2c0fa1017d6ffc6e10e67e2aebb24a42f61b7852
[vpp.git] / src / plugins / nat / test / test_nat.py
1 #!/usr/bin/env python3
2
3 import ipaddress
4 import random
5 import socket
6 import struct
7 import unittest
8 from io import BytesIO
9 from time import sleep
10
11 import scapy.compat
12 from framework import VppTestCase, VppTestRunner, running_extended_tests
13 from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
14 from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \
15     IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \
16     PacketListField
17 from scapy.data import IP_PROTOS
18 from scapy.layers.inet import IP, TCP, UDP, ICMP
19 from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
20 from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
21 from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply, \
22     ICMPv6ND_NS, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr, fragment6
23 from scapy.layers.l2 import Ether, ARP, GRE
24 from scapy.packet import Raw
25 from syslog_rfc5424_parser import SyslogMessage, ParseError
26 from syslog_rfc5424_parser.constants import SyslogSeverity
27 from util import ip4_range
28 from util import ppc, ppp
29 from vpp_acl import AclRule, VppAcl, VppAclInterface
30 from vpp_ip_route import VppIpRoute, VppRoutePath
31 from vpp_neighbor import VppNeighbor
32 from vpp_papi import VppEnum
33
34
35 # NAT HA protocol event data
36 class Event(Packet):
37     name = "Event"
38     fields_desc = [ByteEnumField("event_type", None,
39                                  {1: "add", 2: "del", 3: "refresh"}),
40                    ByteEnumField("protocol", None,
41                                  {0: "udp", 1: "tcp", 2: "icmp"}),
42                    ShortField("flags", 0),
43                    IPField("in_addr", None),
44                    IPField("out_addr", None),
45                    ShortField("in_port", None),
46                    ShortField("out_port", None),
47                    IPField("eh_addr", None),
48                    IPField("ehn_addr", None),
49                    ShortField("eh_port", None),
50                    ShortField("ehn_port", None),
51                    IntField("fib_index", None),
52                    IntField("total_pkts", 0),
53                    LongField("total_bytes", 0)]
54
55     def extract_padding(self, s):
56         return "", s
57
58
59 # NAT HA protocol header
60 class HANATStateSync(Packet):
61     name = "HA NAT state sync"
62     fields_desc = [XByteField("version", 1),
63                    FlagsField("flags", 0, 8, ['ACK']),
64                    FieldLenField("count", None, count_of="events"),
65                    IntField("sequence_number", 1),
66                    IntField("thread_index", 0),
67                    PacketListField("events", [], Event,
68                                    count_from=lambda pkt: pkt.count)]
69
70
71 class MethodHolder(VppTestCase):
72     """ NAT create capture and verify method holder """
73
74     @property
75     def config_flags(self):
76         return VppEnum.vl_api_nat_config_flags_t
77
78     @property
79     def SYSLOG_SEVERITY(self):
80         return VppEnum.vl_api_syslog_severity_t
81
82     def clear_nat44(self):
83         """
84         Clear NAT44 configuration.
85         """
86         if hasattr(self, 'pg7') and hasattr(self, 'pg8'):
87             if self.pg7.has_ip4_config:
88                 self.pg7.unconfig_ip4()
89
90         self.vapi.nat44_forwarding_enable_disable(enable=0)
91
92         interfaces = self.vapi.nat44_interface_addr_dump()
93         for intf in interfaces:
94             self.vapi.nat44_add_del_interface_addr(
95                 is_add=0,
96                 sw_if_index=intf.sw_if_index,
97                 flags=intf.flags)
98
99         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
100                                            src_port=self.ipfix_src_port,
101                                            enable=0)
102         self.ipfix_src_port = 4739
103         self.ipfix_domain_id = 1
104
105         self.vapi.syslog_set_filter(
106             self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_EMERG)
107
108         self.vapi.nat_ha_set_listener(ip_address='0.0.0.0', port=0,
109                                       path_mtu=512)
110         self.vapi.nat_ha_set_failover(ip_address='0.0.0.0', port=0,
111                                       session_refresh_interval=10)
112
113         interfaces = self.vapi.nat44_interface_dump()
114         for intf in interfaces:
115             if intf.flags & self.config_flags.NAT_IS_INSIDE and \
116                     intf.flags & self.config_flags.NAT_IS_OUTSIDE:
117                 self.vapi.nat44_interface_add_del_feature(
118                     sw_if_index=intf.sw_if_index)
119             self.vapi.nat44_interface_add_del_feature(
120                 sw_if_index=intf.sw_if_index,
121                 flags=intf.flags)
122
123         interfaces = self.vapi.nat44_interface_output_feature_dump()
124         for intf in interfaces:
125             self.vapi.nat44_interface_add_del_output_feature(
126                 is_add=0,
127                 flags=intf.flags,
128                 sw_if_index=intf.sw_if_index)
129         static_mappings = self.vapi.nat44_static_mapping_dump()
130         for sm in static_mappings:
131             self.vapi.nat44_add_del_static_mapping(
132                 is_add=0,
133                 local_ip_address=sm.local_ip_address,
134                 external_ip_address=sm.external_ip_address,
135                 external_sw_if_index=sm.external_sw_if_index,
136                 local_port=sm.local_port,
137                 external_port=sm.external_port,
138                 vrf_id=sm.vrf_id,
139                 protocol=sm.protocol,
140                 flags=sm.flags, tag=sm.tag)
141
142         lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
143         for lb_sm in lb_static_mappings:
144             self.vapi.nat44_add_del_lb_static_mapping(
145                 is_add=0,
146                 flags=lb_sm.flags,
147                 external_addr=lb_sm.external_addr,
148                 external_port=lb_sm.external_port,
149                 protocol=lb_sm.protocol,
150                 local_num=0, locals=[],
151                 tag=lb_sm.tag)
152
153         identity_mappings = self.vapi.nat44_identity_mapping_dump()
154         for id_m in identity_mappings:
155             self.vapi.nat44_add_del_identity_mapping(
156                 ip_address=id_m.ip_address,
157                 sw_if_index=id_m.sw_if_index,
158                 port=id_m.port,
159                 flags=id_m.flags,
160                 vrf_id=id_m.vrf_id,
161                 protocol=id_m.protocol)
162
163         addresses = self.vapi.nat44_address_dump()
164         for addr in addresses:
165             self.vapi.nat44_add_del_address_range(
166                 first_ip_address=addr.ip_address,
167                 last_ip_address=addr.ip_address,
168                 vrf_id=0xFFFFFFFF, flags=addr.flags)
169
170         self.verify_no_nat44_user()
171         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
172                                    tcp_transitory=240, icmp=60)
173         self.vapi.nat_set_addr_and_port_alloc_alg()
174         self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
175
176     def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
177                                  local_port=0, external_port=0, vrf_id=0,
178                                  is_add=1, external_sw_if_index=0xFFFFFFFF,
179                                  proto=0, tag="", flags=0):
180         """
181         Add/delete NAT44 static mapping
182
183         :param local_ip: Local IP address
184         :param external_ip: External IP address
185         :param local_port: Local port number (Optional)
186         :param external_port: External port number (Optional)
187         :param vrf_id: VRF ID (Default 0)
188         :param is_add: 1 if add, 0 if delete (Default add)
189         :param external_sw_if_index: External interface instead of IP address
190         :param proto: IP protocol (Mandatory if port specified)
191         :param tag: Opaque string tag
192         :param flags: NAT configuration flags
193         """
194
195         if not (local_port and external_port):
196             flags |= self.config_flags.NAT_IS_ADDR_ONLY
197
198         self.vapi.nat44_add_del_static_mapping(
199             is_add=is_add,
200             local_ip_address=local_ip,
201             external_ip_address=external_ip,
202             external_sw_if_index=external_sw_if_index,
203             local_port=local_port,
204             external_port=external_port,
205             vrf_id=vrf_id, protocol=proto,
206             flags=flags,
207             tag=tag)
208
209     def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
210         """
211         Add/delete NAT44 address
212
213         :param ip: IP address
214         :param is_add: 1 if add, 0 if delete (Default add)
215         :param twice_nat: twice NAT address for external hosts
216         """
217         flags = self.config_flags.NAT_IS_TWICE_NAT if twice_nat else 0
218         self.vapi.nat44_add_del_address_range(first_ip_address=ip,
219                                               last_ip_address=ip,
220                                               vrf_id=vrf_id,
221                                               is_add=is_add,
222                                               flags=flags)
223
224     def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
225         """
226         Create packet stream for inside network
227
228         :param in_if: Inside interface
229         :param out_if: Outside interface
230         :param dst_ip: Destination address
231         :param ttl: TTL of generated packets
232         """
233         if dst_ip is None:
234             dst_ip = out_if.remote_ip4
235
236         pkts = []
237         # TCP
238         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
239              IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
240              TCP(sport=self.tcp_port_in, dport=20))
241         pkts.extend([p, p])
242
243         # UDP
244         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
245              IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
246              UDP(sport=self.udp_port_in, dport=20))
247         pkts.append(p)
248
249         # ICMP
250         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
251              IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
252              ICMP(id=self.icmp_id_in, type='echo-request'))
253         pkts.append(p)
254
255         return pkts
256
257     def compose_ip6(self, ip4, pref, plen):
258         """
259         Compose IPv4-embedded IPv6 addresses
260
261         :param ip4: IPv4 address
262         :param pref: IPv6 prefix
263         :param plen: IPv6 prefix length
264         :returns: IPv4-embedded IPv6 addresses
265         """
266         pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
267         ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
268         if plen == 32:
269             pref_n[4] = ip4_n[0]
270             pref_n[5] = ip4_n[1]
271             pref_n[6] = ip4_n[2]
272             pref_n[7] = ip4_n[3]
273         elif plen == 40:
274             pref_n[5] = ip4_n[0]
275             pref_n[6] = ip4_n[1]
276             pref_n[7] = ip4_n[2]
277             pref_n[9] = ip4_n[3]
278         elif plen == 48:
279             pref_n[6] = ip4_n[0]
280             pref_n[7] = ip4_n[1]
281             pref_n[9] = ip4_n[2]
282             pref_n[10] = ip4_n[3]
283         elif plen == 56:
284             pref_n[7] = ip4_n[0]
285             pref_n[9] = ip4_n[1]
286             pref_n[10] = ip4_n[2]
287             pref_n[11] = ip4_n[3]
288         elif plen == 64:
289             pref_n[9] = ip4_n[0]
290             pref_n[10] = ip4_n[1]
291             pref_n[11] = ip4_n[2]
292             pref_n[12] = ip4_n[3]
293         elif plen == 96:
294             pref_n[12] = ip4_n[0]
295             pref_n[13] = ip4_n[1]
296             pref_n[14] = ip4_n[2]
297             pref_n[15] = ip4_n[3]
298         packed_pref_n = b''.join([scapy.compat.chb(x) for x in pref_n])
299         return socket.inet_ntop(socket.AF_INET6, packed_pref_n)
300
301     def extract_ip4(self, ip6, plen):
302         """
303         Extract IPv4 address embedded in IPv6 addresses
304
305         :param ip6: IPv6 address
306         :param plen: IPv6 prefix length
307         :returns: extracted IPv4 address
308         """
309         ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
310         ip4_n = [None] * 4
311         if plen == 32:
312             ip4_n[0] = ip6_n[4]
313             ip4_n[1] = ip6_n[5]
314             ip4_n[2] = ip6_n[6]
315             ip4_n[3] = ip6_n[7]
316         elif plen == 40:
317             ip4_n[0] = ip6_n[5]
318             ip4_n[1] = ip6_n[6]
319             ip4_n[2] = ip6_n[7]
320             ip4_n[3] = ip6_n[9]
321         elif plen == 48:
322             ip4_n[0] = ip6_n[6]
323             ip4_n[1] = ip6_n[7]
324             ip4_n[2] = ip6_n[9]
325             ip4_n[3] = ip6_n[10]
326         elif plen == 56:
327             ip4_n[0] = ip6_n[7]
328             ip4_n[1] = ip6_n[9]
329             ip4_n[2] = ip6_n[10]
330             ip4_n[3] = ip6_n[11]
331         elif plen == 64:
332             ip4_n[0] = ip6_n[9]
333             ip4_n[1] = ip6_n[10]
334             ip4_n[2] = ip6_n[11]
335             ip4_n[3] = ip6_n[12]
336         elif plen == 96:
337             ip4_n[0] = ip6_n[12]
338             ip4_n[1] = ip6_n[13]
339             ip4_n[2] = ip6_n[14]
340             ip4_n[3] = ip6_n[15]
341         return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
342
343     def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
344         """
345         Create IPv6 packet stream for inside network
346
347         :param in_if: Inside interface
348         :param out_if: Outside interface
349         :param ttl: Hop Limit of generated packets
350         :param pref: NAT64 prefix
351         :param plen: NAT64 prefix length
352         """
353         pkts = []
354         if pref is None:
355             dst = ''.join(['64:ff9b::', out_if.remote_ip4])
356         else:
357             dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
358
359         # TCP
360         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
361              IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
362              TCP(sport=self.tcp_port_in, dport=20))
363         pkts.append(p)
364
365         # UDP
366         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
367              IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
368              UDP(sport=self.udp_port_in, dport=20))
369         pkts.append(p)
370
371         # ICMP
372         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
373              IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
374              ICMPv6EchoRequest(id=self.icmp_id_in))
375         pkts.append(p)
376
377         return pkts
378
379     def create_stream_out(self, out_if, dst_ip=None, ttl=64,
380                           use_inside_ports=False):
381         """
382         Create packet stream for outside network
383
384         :param out_if: Outside interface
385         :param dst_ip: Destination IP address (Default use global NAT address)
386         :param ttl: TTL of generated packets
387         :param use_inside_ports: Use inside NAT ports as destination ports
388                instead of outside ports
389         """
390         if dst_ip is None:
391             dst_ip = self.nat_addr
392         if not use_inside_ports:
393             tcp_port = self.tcp_port_out
394             udp_port = self.udp_port_out
395             icmp_id = self.icmp_id_out
396         else:
397             tcp_port = self.tcp_port_in
398             udp_port = self.udp_port_in
399             icmp_id = self.icmp_id_in
400         pkts = []
401         # TCP
402         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
403              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
404              TCP(dport=tcp_port, sport=20))
405         pkts.extend([p, p])
406
407         # UDP
408         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
409              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
410              UDP(dport=udp_port, sport=20))
411         pkts.append(p)
412
413         # ICMP
414         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
415              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
416              ICMP(id=icmp_id, type='echo-reply'))
417         pkts.append(p)
418
419         return pkts
420
421     def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
422         """
423         Create packet stream for outside network
424
425         :param out_if: Outside interface
426         :param dst_ip: Destination IP address (Default use global NAT address)
427         :param hl: HL of generated packets
428         """
429         pkts = []
430         # TCP
431         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
432              IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
433              TCP(dport=self.tcp_port_out, sport=20))
434         pkts.append(p)
435
436         # UDP
437         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
438              IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
439              UDP(dport=self.udp_port_out, sport=20))
440         pkts.append(p)
441
442         # ICMP
443         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
444              IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
445              ICMPv6EchoReply(id=self.icmp_id_out))
446         pkts.append(p)
447
448         return pkts
449
450     def verify_capture_out(self, capture, nat_ip=None, same_port=False,
451                            dst_ip=None, is_ip6=False):
452         """
453         Verify captured packets on outside network
454
455         :param capture: Captured packets
456         :param nat_ip: Translated IP address (Default use global NAT address)
457         :param same_port: Source port number is not translated (Default False)
458         :param dst_ip: Destination IP address (Default do not verify)
459         :param is_ip6: If L3 protocol is IPv6 (Default False)
460         """
461         if is_ip6:
462             IP46 = IPv6
463             ICMP46 = ICMPv6EchoRequest
464         else:
465             IP46 = IP
466             ICMP46 = ICMP
467         if nat_ip is None:
468             nat_ip = self.nat_addr
469         for packet in capture:
470             try:
471                 if not is_ip6:
472                     self.assert_packet_checksums_valid(packet)
473                 self.assertEqual(packet[IP46].src, nat_ip)
474                 if dst_ip is not None:
475                     self.assertEqual(packet[IP46].dst, dst_ip)
476                 if packet.haslayer(TCP):
477                     if same_port:
478                         self.assertEqual(packet[TCP].sport, self.tcp_port_in)
479                     else:
480                         self.assertNotEqual(
481                             packet[TCP].sport, self.tcp_port_in)
482                     self.tcp_port_out = packet[TCP].sport
483                     self.assert_packet_checksums_valid(packet)
484                 elif packet.haslayer(UDP):
485                     if same_port:
486                         self.assertEqual(packet[UDP].sport, self.udp_port_in)
487                     else:
488                         self.assertNotEqual(
489                             packet[UDP].sport, self.udp_port_in)
490                     self.udp_port_out = packet[UDP].sport
491                 else:
492                     if same_port:
493                         self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
494                     else:
495                         self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
496                     self.icmp_id_out = packet[ICMP46].id
497                     self.assert_packet_checksums_valid(packet)
498             except:
499                 self.logger.error(ppp("Unexpected or invalid packet "
500                                       "(outside network):", packet))
501                 raise
502
503     def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
504                                dst_ip=None):
505         """
506         Verify captured packets on outside network
507
508         :param capture: Captured packets
509         :param nat_ip: Translated IP address
510         :param same_port: Source port number is not translated (Default False)
511         :param dst_ip: Destination IP address (Default do not verify)
512         """
513         return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
514                                        True)
515
516     def verify_capture_in(self, capture, in_if):
517         """
518         Verify captured packets on inside network
519
520         :param capture: Captured packets
521         :param in_if: Inside interface
522         """
523         for packet in capture:
524             try:
525                 self.assert_packet_checksums_valid(packet)
526                 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
527                 if packet.haslayer(TCP):
528                     self.assertEqual(packet[TCP].dport, self.tcp_port_in)
529                 elif packet.haslayer(UDP):
530                     self.assertEqual(packet[UDP].dport, self.udp_port_in)
531                 else:
532                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
533             except:
534                 self.logger.error(ppp("Unexpected or invalid packet "
535                                       "(inside network):", packet))
536                 raise
537
538     def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
539         """
540         Verify captured IPv6 packets on inside network
541
542         :param capture: Captured packets
543         :param src_ip: Source IP
544         :param dst_ip: Destination IP address
545         """
546         for packet in capture:
547             try:
548                 self.assertEqual(packet[IPv6].src, src_ip)
549                 self.assertEqual(packet[IPv6].dst, dst_ip)
550                 self.assert_packet_checksums_valid(packet)
551                 if packet.haslayer(TCP):
552                     self.assertEqual(packet[TCP].dport, self.tcp_port_in)
553                 elif packet.haslayer(UDP):
554                     self.assertEqual(packet[UDP].dport, self.udp_port_in)
555                 else:
556                     self.assertEqual(packet[ICMPv6EchoReply].id,
557                                      self.icmp_id_in)
558             except:
559                 self.logger.error(ppp("Unexpected or invalid packet "
560                                       "(inside network):", packet))
561                 raise
562
563     def verify_capture_no_translation(self, capture, ingress_if, egress_if):
564         """
565         Verify captured packet that don't have to be translated
566
567         :param capture: Captured packets
568         :param ingress_if: Ingress interface
569         :param egress_if: Egress interface
570         """
571         for packet in capture:
572             try:
573                 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
574                 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
575                 if packet.haslayer(TCP):
576                     self.assertEqual(packet[TCP].sport, self.tcp_port_in)
577                 elif packet.haslayer(UDP):
578                     self.assertEqual(packet[UDP].sport, self.udp_port_in)
579                 else:
580                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
581             except:
582                 self.logger.error(ppp("Unexpected or invalid packet "
583                                       "(inside network):", packet))
584                 raise
585
586     def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
587                                             icmp_type=11):
588         """
589         Verify captured packets with ICMP errors on outside network
590
591         :param capture: Captured packets
592         :param src_ip: Translated IP address or IP address of VPP
593                        (Default use global NAT address)
594         :param icmp_type: Type of error ICMP packet
595                           we are expecting (Default 11)
596         """
597         if src_ip is None:
598             src_ip = self.nat_addr
599         for packet in capture:
600             try:
601                 self.assertEqual(packet[IP].src, src_ip)
602                 self.assertEqual(packet.haslayer(ICMP), 1)
603                 icmp = packet[ICMP]
604                 self.assertEqual(icmp.type, icmp_type)
605                 self.assertTrue(icmp.haslayer(IPerror))
606                 inner_ip = icmp[IPerror]
607                 if inner_ip.haslayer(TCPerror):
608                     self.assertEqual(inner_ip[TCPerror].dport,
609                                      self.tcp_port_out)
610                 elif inner_ip.haslayer(UDPerror):
611                     self.assertEqual(inner_ip[UDPerror].dport,
612                                      self.udp_port_out)
613                 else:
614                     self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
615             except:
616                 self.logger.error(ppp("Unexpected or invalid packet "
617                                       "(outside network):", packet))
618                 raise
619
620     def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
621         """
622         Verify captured packets with ICMP errors on inside network
623
624         :param capture: Captured packets
625         :param in_if: Inside interface
626         :param icmp_type: Type of error ICMP packet
627                           we are expecting (Default 11)
628         """
629         for packet in capture:
630             try:
631                 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
632                 self.assertEqual(packet.haslayer(ICMP), 1)
633                 icmp = packet[ICMP]
634                 self.assertEqual(icmp.type, icmp_type)
635                 self.assertTrue(icmp.haslayer(IPerror))
636                 inner_ip = icmp[IPerror]
637                 if inner_ip.haslayer(TCPerror):
638                     self.assertEqual(inner_ip[TCPerror].sport,
639                                      self.tcp_port_in)
640                 elif inner_ip.haslayer(UDPerror):
641                     self.assertEqual(inner_ip[UDPerror].sport,
642                                      self.udp_port_in)
643                 else:
644                     self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
645             except:
646                 self.logger.error(ppp("Unexpected or invalid packet "
647                                       "(inside network):", packet))
648                 raise
649
650     def create_stream_frag(self, src_if, dst, sport, dport, data,
651                            proto=IP_PROTOS.tcp, echo_reply=False):
652         """
653         Create fragmented packet stream
654
655         :param src_if: Source interface
656         :param dst: Destination IPv4 address
657         :param sport: Source port
658         :param dport: Destination port
659         :param data: Payload data
660         :param proto: protocol (TCP, UDP, ICMP)
661         :param echo_reply: use echo_reply if protocol is ICMP
662         :returns: Fragments
663         """
664         if proto == IP_PROTOS.tcp:
665             p = (IP(src=src_if.remote_ip4, dst=dst) /
666                  TCP(sport=sport, dport=dport) /
667                  Raw(data))
668             p = p.__class__(scapy.compat.raw(p))
669             chksum = p[TCP].chksum
670             proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
671         elif proto == IP_PROTOS.udp:
672             proto_header = UDP(sport=sport, dport=dport)
673         elif proto == IP_PROTOS.icmp:
674             if not echo_reply:
675                 proto_header = ICMP(id=sport, type='echo-request')
676             else:
677                 proto_header = ICMP(id=sport, type='echo-reply')
678         else:
679             raise Exception("Unsupported protocol")
680         id = random.randint(0, 65535)
681         pkts = []
682         if proto == IP_PROTOS.tcp:
683             raw = Raw(data[0:4])
684         else:
685             raw = Raw(data[0:16])
686         p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
687              IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
688              proto_header /
689              raw)
690         pkts.append(p)
691         if proto == IP_PROTOS.tcp:
692             raw = Raw(data[4:20])
693         else:
694             raw = Raw(data[16:32])
695         p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
696              IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
697                 proto=proto) /
698              raw)
699         pkts.append(p)
700         if proto == IP_PROTOS.tcp:
701             raw = Raw(data[20:])
702         else:
703             raw = Raw(data[32:])
704         p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
705              IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
706                 id=id) /
707              raw)
708         pkts.append(p)
709         return pkts
710
711     def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
712                                pref=None, plen=0, frag_size=128):
713         """
714         Create fragmented packet stream
715
716         :param src_if: Source interface
717         :param dst: Destination IPv4 address
718         :param sport: Source TCP port
719         :param dport: Destination TCP port
720         :param data: Payload data
721         :param pref: NAT64 prefix
722         :param plen: NAT64 prefix length
723         :param fragsize: size of fragments
724         :returns: Fragments
725         """
726         if pref is None:
727             dst_ip6 = ''.join(['64:ff9b::', dst])
728         else:
729             dst_ip6 = self.compose_ip6(dst, pref, plen)
730
731         p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
732              IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
733              IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
734              TCP(sport=sport, dport=dport) /
735              Raw(data))
736
737         return fragment6(p, frag_size)
738
739     def reass_frags_and_verify(self, frags, src, dst):
740         """
741         Reassemble and verify fragmented packet
742
743         :param frags: Captured fragments
744         :param src: Source IPv4 address to verify
745         :param dst: Destination IPv4 address to verify
746
747         :returns: Reassembled IPv4 packet
748         """
749         buffer = BytesIO()
750         for p in frags:
751             self.assertEqual(p[IP].src, src)
752             self.assertEqual(p[IP].dst, dst)
753             self.assert_ip_checksum_valid(p)
754             buffer.seek(p[IP].frag * 8)
755             buffer.write(bytes(p[IP].payload))
756         ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
757                 proto=frags[0][IP].proto)
758         if ip.proto == IP_PROTOS.tcp:
759             p = (ip / TCP(buffer.getvalue()))
760             self.logger.debug(ppp("Reassembled:", p))
761             self.assert_tcp_checksum_valid(p)
762         elif ip.proto == IP_PROTOS.udp:
763             p = (ip / UDP(buffer.getvalue()[:8]) /
764                  Raw(buffer.getvalue()[8:]))
765         elif ip.proto == IP_PROTOS.icmp:
766             p = (ip / ICMP(buffer.getvalue()))
767         return p
768
769     def reass_frags_and_verify_ip6(self, frags, src, dst):
770         """
771         Reassemble and verify fragmented packet
772
773         :param frags: Captured fragments
774         :param src: Source IPv6 address to verify
775         :param dst: Destination IPv6 address to verify
776
777         :returns: Reassembled IPv6 packet
778         """
779         buffer = BytesIO()
780         for p in frags:
781             self.assertEqual(p[IPv6].src, src)
782             self.assertEqual(p[IPv6].dst, dst)
783             buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
784             buffer.write(bytes(p[IPv6ExtHdrFragment].payload))
785         ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
786                   nh=frags[0][IPv6ExtHdrFragment].nh)
787         if ip.nh == IP_PROTOS.tcp:
788             p = (ip / TCP(buffer.getvalue()))
789         elif ip.nh == IP_PROTOS.udp:
790             p = (ip / UDP(buffer.getvalue()))
791         self.logger.debug(ppp("Reassembled:", p))
792         self.assert_packet_checksums_valid(p)
793         return p
794
795     def initiate_tcp_session(self, in_if, out_if):
796         """
797         Initiates TCP session
798
799         :param in_if: Inside interface
800         :param out_if: Outside interface
801         """
802         try:
803             # SYN packet in->out
804             p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
805                  IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
806                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
807                      flags="S"))
808             in_if.add_stream(p)
809             self.pg_enable_capture(self.pg_interfaces)
810             self.pg_start()
811             capture = out_if.get_capture(1)
812             p = capture[0]
813             self.tcp_port_out = p[TCP].sport
814
815             # SYN + ACK packet out->in
816             p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
817                  IP(src=out_if.remote_ip4, dst=self.nat_addr) /
818                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
819                      flags="SA"))
820             out_if.add_stream(p)
821             self.pg_enable_capture(self.pg_interfaces)
822             self.pg_start()
823             in_if.get_capture(1)
824
825             # ACK packet in->out
826             p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
827                  IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
828                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
829                      flags="A"))
830             in_if.add_stream(p)
831             self.pg_enable_capture(self.pg_interfaces)
832             self.pg_start()
833             out_if.get_capture(1)
834
835         except:
836             self.logger.error("TCP 3 way handshake failed")
837             raise
838
839     def verify_ipfix_nat44_ses(self, data):
840         """
841         Verify IPFIX NAT44 session create/delete event
842
843         :param data: Decoded IPFIX data records
844         """
845         nat44_ses_create_num = 0
846         nat44_ses_delete_num = 0
847         self.assertEqual(6, len(data))
848         for record in data:
849             # natEvent
850             self.assertIn(scapy.compat.orb(record[230]), [4, 5])
851             if scapy.compat.orb(record[230]) == 4:
852                 nat44_ses_create_num += 1
853             else:
854                 nat44_ses_delete_num += 1
855             # sourceIPv4Address
856             self.assertEqual(self.pg0.remote_ip4,
857                              str(ipaddress.IPv4Address(record[8])))
858             # postNATSourceIPv4Address
859             self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
860                              record[225])
861             # ingressVRFID
862             self.assertEqual(struct.pack("!I", 0), record[234])
863             # protocolIdentifier/sourceTransportPort
864             # /postNAPTSourceTransportPort
865             if IP_PROTOS.icmp == scapy.compat.orb(record[4]):
866                 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
867                 self.assertEqual(struct.pack("!H", self.icmp_id_out),
868                                  record[227])
869             elif IP_PROTOS.tcp == scapy.compat.orb(record[4]):
870                 self.assertEqual(struct.pack("!H", self.tcp_port_in),
871                                  record[7])
872                 self.assertEqual(struct.pack("!H", self.tcp_port_out),
873                                  record[227])
874             elif IP_PROTOS.udp == scapy.compat.orb(record[4]):
875                 self.assertEqual(struct.pack("!H", self.udp_port_in),
876                                  record[7])
877                 self.assertEqual(struct.pack("!H", self.udp_port_out),
878                                  record[227])
879             else:
880                 self.fail("Invalid protocol")
881         self.assertEqual(3, nat44_ses_create_num)
882         self.assertEqual(3, nat44_ses_delete_num)
883
884     def verify_ipfix_addr_exhausted(self, data):
885         """
886         Verify IPFIX NAT addresses event
887
888         :param data: Decoded IPFIX data records
889         """
890         self.assertEqual(1, len(data))
891         record = data[0]
892         # natEvent
893         self.assertEqual(scapy.compat.orb(record[230]), 3)
894         # natPoolID
895         self.assertEqual(struct.pack("!I", 0), record[283])
896
897     def verify_ipfix_max_sessions(self, data, limit):
898         """
899         Verify IPFIX maximum session entries exceeded event
900
901         :param data: Decoded IPFIX data records
902         :param limit: Number of maximum session entries that can be created.
903         """
904         self.assertEqual(1, len(data))
905         record = data[0]
906         # natEvent
907         self.assertEqual(scapy.compat.orb(record[230]), 13)
908         # natQuotaExceededEvent
909         self.assertEqual(struct.pack("I", 1), record[466])
910         # maxSessionEntries
911         self.assertEqual(struct.pack("I", limit), record[471])
912
913     def verify_ipfix_max_bibs(self, data, limit):
914         """
915         Verify IPFIX maximum BIB entries exceeded event
916
917         :param data: Decoded IPFIX data records
918         :param limit: Number of maximum BIB entries that can be created.
919         """
920         self.assertEqual(1, len(data))
921         record = data[0]
922         # natEvent
923         self.assertEqual(scapy.compat.orb(record[230]), 13)
924         # natQuotaExceededEvent
925         self.assertEqual(struct.pack("I", 2), record[466])
926         # maxBIBEntries
927         self.assertEqual(struct.pack("I", limit), record[472])
928
929     def verify_ipfix_bib(self, data, is_create, src_addr):
930         """
931         Verify IPFIX NAT64 BIB create and delete events
932
933         :param data: Decoded IPFIX data records
934         :param is_create: Create event if nonzero value otherwise delete event
935         :param src_addr: IPv6 source address
936         """
937         self.assertEqual(1, len(data))
938         record = data[0]
939         # natEvent
940         if is_create:
941             self.assertEqual(scapy.compat.orb(record[230]), 10)
942         else:
943             self.assertEqual(scapy.compat.orb(record[230]), 11)
944         # sourceIPv6Address
945         self.assertEqual(src_addr, str(ipaddress.IPv6Address(record[27])))
946         # postNATSourceIPv4Address
947         self.assertEqual(self.nat_addr_n, record[225])
948         # protocolIdentifier
949         self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
950         # ingressVRFID
951         self.assertEqual(struct.pack("!I", 0), record[234])
952         # sourceTransportPort
953         self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
954         # postNAPTSourceTransportPort
955         self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
956
957     def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
958                                dst_port):
959         """
960         Verify IPFIX NAT64 session create and delete events
961
962         :param data: Decoded IPFIX data records
963         :param is_create: Create event if nonzero value otherwise delete event
964         :param src_addr: IPv6 source address
965         :param dst_addr: IPv4 destination address
966         :param dst_port: destination TCP port
967         """
968         self.assertEqual(1, len(data))
969         record = data[0]
970         # natEvent
971         if is_create:
972             self.assertEqual(scapy.compat.orb(record[230]), 6)
973         else:
974             self.assertEqual(scapy.compat.orb(record[230]), 7)
975         # sourceIPv6Address
976         self.assertEqual(src_addr, str(ipaddress.IPv6Address(record[27])))
977         # destinationIPv6Address
978         self.assertEqual(socket.inet_pton(socket.AF_INET6,
979                                           self.compose_ip6(dst_addr,
980                                                            '64:ff9b::',
981                                                            96)),
982                          record[28])
983         # postNATSourceIPv4Address
984         self.assertEqual(self.nat_addr_n, record[225])
985         # postNATDestinationIPv4Address
986         self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
987                          record[226])
988         # protocolIdentifier
989         self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
990         # ingressVRFID
991         self.assertEqual(struct.pack("!I", 0), record[234])
992         # sourceTransportPort
993         self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
994         # postNAPTSourceTransportPort
995         self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
996         # destinationTransportPort
997         self.assertEqual(struct.pack("!H", dst_port), record[11])
998         # postNAPTDestinationTransportPort
999         self.assertEqual(struct.pack("!H", dst_port), record[228])
1000
1001     def verify_no_nat44_user(self):
1002         """ Verify that there is no NAT44 user """
1003         users = self.vapi.nat44_user_dump()
1004         self.assertEqual(len(users), 0)
1005         users = self.statistics.get_counter('/nat44/total-users')
1006         self.assertEqual(users[0][0], 0)
1007         sessions = self.statistics.get_counter('/nat44/total-sessions')
1008         self.assertEqual(sessions[0][0], 0)
1009
1010     def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
1011         """
1012         Verify IPFIX maximum entries per user exceeded event
1013
1014         :param data: Decoded IPFIX data records
1015         :param limit: Number of maximum entries per user
1016         :param src_addr: IPv4 source address
1017         """
1018         self.assertEqual(1, len(data))
1019         record = data[0]
1020         # natEvent
1021         self.assertEqual(scapy.compat.orb(record[230]), 13)
1022         # natQuotaExceededEvent
1023         self.assertEqual(struct.pack("I", 3), record[466])
1024         # maxEntriesPerUser
1025         self.assertEqual(struct.pack("I", limit), record[473])
1026         # sourceIPv4Address
1027         self.assertEqual(socket.inet_pton(socket.AF_INET, src_addr), record[8])
1028
1029     def verify_syslog_apmap(self, data, is_add=True):
1030         message = data.decode('utf-8')
1031         try:
1032             message = SyslogMessage.parse(message)
1033         except ParseError as e:
1034             self.logger.error(e)
1035             raise
1036         else:
1037             self.assertEqual(message.severity, SyslogSeverity.info)
1038             self.assertEqual(message.appname, 'NAT')
1039             self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
1040             sd_params = message.sd.get('napmap')
1041             self.assertTrue(sd_params is not None)
1042             self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1043             self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1044             self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1045             self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1046             self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1047             self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1048             self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1049             self.assertTrue(sd_params.get('SSUBIX') is not None)
1050             self.assertEqual(sd_params.get('SVLAN'), '0')
1051
1052     def verify_syslog_sess(self, data, is_add=True, is_ip6=False):
1053         message = data.decode('utf-8')
1054         try:
1055             message = SyslogMessage.parse(message)
1056         except ParseError as e:
1057             self.logger.error(e)
1058             raise
1059         else:
1060             self.assertEqual(message.severity, SyslogSeverity.info)
1061             self.assertEqual(message.appname, 'NAT')
1062             self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL')
1063             sd_params = message.sd.get('nsess')
1064             self.assertTrue(sd_params is not None)
1065             if is_ip6:
1066                 self.assertEqual(sd_params.get('IATYP'), 'IPv6')
1067                 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
1068             else:
1069                 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1070                 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1071                 self.assertTrue(sd_params.get('SSUBIX') is not None)
1072             self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1073             self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1074             self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1075             self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1076             self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1077             self.assertEqual(sd_params.get('SVLAN'), '0')
1078             self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
1079             self.assertEqual(sd_params.get('XDPORT'),
1080                              "%d" % self.tcp_external_port)
1081
1082     def verify_mss_value(self, pkt, mss):
1083         """
1084         Verify TCP MSS value
1085
1086         :param pkt:
1087         :param mss:
1088         """
1089         if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
1090             raise TypeError("Not a TCP/IP packet")
1091
1092         for option in pkt[TCP].options:
1093             if option[0] == 'MSS':
1094                 self.assertEqual(option[1], mss)
1095                 self.assert_tcp_checksum_valid(pkt)
1096
1097     @staticmethod
1098     def proto2layer(proto):
1099         if proto == IP_PROTOS.tcp:
1100             return TCP
1101         elif proto == IP_PROTOS.udp:
1102             return UDP
1103         elif proto == IP_PROTOS.icmp:
1104             return ICMP
1105         else:
1106             raise Exception("Unsupported protocol")
1107
1108     def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1109         layer = self.proto2layer(proto)
1110
1111         if proto == IP_PROTOS.tcp:
1112             data = b"A" * 4 + b"B" * 16 + b"C" * 3
1113         else:
1114             data = b"A" * 16 + b"B" * 16 + b"C" * 3
1115         self.port_in = random.randint(1025, 65535)
1116
1117         # in2out
1118         pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
1119                                        self.port_in, 20, data, proto)
1120         self.pg0.add_stream(pkts)
1121         self.pg_enable_capture(self.pg_interfaces)
1122         self.pg_start()
1123         frags = self.pg1.get_capture(len(pkts))
1124         if not dont_translate:
1125             p = self.reass_frags_and_verify(frags,
1126                                             self.nat_addr,
1127                                             self.pg1.remote_ip4)
1128         else:
1129             p = self.reass_frags_and_verify(frags,
1130                                             self.pg0.remote_ip4,
1131                                             self.pg1.remote_ip4)
1132         if proto != IP_PROTOS.icmp:
1133             if not dont_translate:
1134                 self.assertEqual(p[layer].dport, 20)
1135                 self.assertNotEqual(p[layer].sport, self.port_in)
1136             else:
1137                 self.assertEqual(p[layer].sport, self.port_in)
1138         else:
1139             if not dont_translate:
1140                 self.assertNotEqual(p[layer].id, self.port_in)
1141             else:
1142                 self.assertEqual(p[layer].id, self.port_in)
1143         self.assertEqual(data, p[Raw].load)
1144
1145         # out2in
1146         if not dont_translate:
1147             dst_addr = self.nat_addr
1148         else:
1149             dst_addr = self.pg0.remote_ip4
1150         if proto != IP_PROTOS.icmp:
1151             sport = 20
1152             dport = p[layer].sport
1153         else:
1154             sport = p[layer].id
1155             dport = 0
1156         pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport, data,
1157                                        proto, echo_reply=True)
1158         self.pg1.add_stream(pkts)
1159         self.pg_enable_capture(self.pg_interfaces)
1160         self.pg_start()
1161         frags = self.pg0.get_capture(len(pkts))
1162         p = self.reass_frags_and_verify(frags,
1163                                         self.pg1.remote_ip4,
1164                                         self.pg0.remote_ip4)
1165         if proto != IP_PROTOS.icmp:
1166             self.assertEqual(p[layer].sport, 20)
1167             self.assertEqual(p[layer].dport, self.port_in)
1168         else:
1169             self.assertEqual(p[layer].id, self.port_in)
1170         self.assertEqual(data, p[Raw].load)
1171
1172     def frag_in_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1173         layer = self.proto2layer(proto)
1174
1175         if proto == IP_PROTOS.tcp:
1176             data = b"A" * 4 + b"B" * 16 + b"C" * 3
1177         else:
1178             data = b"A" * 16 + b"B" * 16 + b"C" * 3
1179         self.port_in = random.randint(1025, 65535)
1180
1181         for i in range(2):
1182             # out2in
1183             pkts = self.create_stream_frag(self.pg0, self.server_out_addr,
1184                                            self.port_in, self.server_out_port,
1185                                            data, proto)
1186             self.pg0.add_stream(pkts)
1187             self.pg_enable_capture(self.pg_interfaces)
1188             self.pg_start()
1189             frags = self.pg1.get_capture(len(pkts))
1190             p = self.reass_frags_and_verify(frags,
1191                                             self.pg0.remote_ip4,
1192                                             self.server_in_addr)
1193             if proto != IP_PROTOS.icmp:
1194                 self.assertEqual(p[layer].sport, self.port_in)
1195                 self.assertEqual(p[layer].dport, self.server_in_port)
1196             else:
1197                 self.assertEqual(p[layer].id, self.port_in)
1198             self.assertEqual(data, p[Raw].load)
1199
1200             # in2out
1201             if proto != IP_PROTOS.icmp:
1202                 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1203                                                self.server_in_port,
1204                                                p[layer].sport, data, proto)
1205             else:
1206                 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1207                                                p[layer].id, 0, data, proto,
1208                                                echo_reply=True)
1209             self.pg1.add_stream(pkts)
1210             self.pg_enable_capture(self.pg_interfaces)
1211             self.pg_start()
1212             frags = self.pg0.get_capture(len(pkts))
1213             p = self.reass_frags_and_verify(frags,
1214                                             self.server_out_addr,
1215                                             self.pg0.remote_ip4)
1216             if proto != IP_PROTOS.icmp:
1217                 self.assertEqual(p[layer].sport, self.server_out_port)
1218                 self.assertEqual(p[layer].dport, self.port_in)
1219             else:
1220                 self.assertEqual(p[layer].id, self.port_in)
1221             self.assertEqual(data, p[Raw].load)
1222
1223     def reass_hairpinning(self, proto=IP_PROTOS.tcp):
1224         layer = self.proto2layer(proto)
1225
1226         if proto == IP_PROTOS.tcp:
1227             data = b"A" * 4 + b"B" * 16 + b"C" * 3
1228         else:
1229             data = b"A" * 16 + b"B" * 16 + b"C" * 3
1230
1231         # send packet from host to server
1232         pkts = self.create_stream_frag(self.pg0,
1233                                        self.nat_addr,
1234                                        self.host_in_port,
1235                                        self.server_out_port,
1236                                        data,
1237                                        proto)
1238         self.pg0.add_stream(pkts)
1239         self.pg_enable_capture(self.pg_interfaces)
1240         self.pg_start()
1241         frags = self.pg0.get_capture(len(pkts))
1242         p = self.reass_frags_and_verify(frags,
1243                                         self.nat_addr,
1244                                         self.server.ip4)
1245         if proto != IP_PROTOS.icmp:
1246             self.assertNotEqual(p[layer].sport, self.host_in_port)
1247             self.assertEqual(p[layer].dport, self.server_in_port)
1248         else:
1249             self.assertNotEqual(p[layer].id, self.host_in_port)
1250         self.assertEqual(data, p[Raw].load)
1251
1252     def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1253         layer = self.proto2layer(proto)
1254
1255         if proto == IP_PROTOS.tcp:
1256             data = b"A" * 4 + b"B" * 16 + b"C" * 3
1257         else:
1258             data = b"A" * 16 + b"B" * 16 + b"C" * 3
1259         self.port_in = random.randint(1025, 65535)
1260
1261         for i in range(2):
1262             # in2out
1263             pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
1264                                            self.port_in, 20, data, proto)
1265             pkts.reverse()
1266             self.pg0.add_stream(pkts)
1267             self.pg_enable_capture(self.pg_interfaces)
1268             self.pg_start()
1269             frags = self.pg1.get_capture(len(pkts))
1270             if not dont_translate:
1271                 p = self.reass_frags_and_verify(frags,
1272                                                 self.nat_addr,
1273                                                 self.pg1.remote_ip4)
1274             else:
1275                 p = self.reass_frags_and_verify(frags,
1276                                                 self.pg0.remote_ip4,
1277                                                 self.pg1.remote_ip4)
1278             if proto != IP_PROTOS.icmp:
1279                 if not dont_translate:
1280                     self.assertEqual(p[layer].dport, 20)
1281                     self.assertNotEqual(p[layer].sport, self.port_in)
1282                 else:
1283                     self.assertEqual(p[layer].sport, self.port_in)
1284             else:
1285                 if not dont_translate:
1286                     self.assertNotEqual(p[layer].id, self.port_in)
1287                 else:
1288                     self.assertEqual(p[layer].id, self.port_in)
1289             self.assertEqual(data, p[Raw].load)
1290
1291             # out2in
1292             if not dont_translate:
1293                 dst_addr = self.nat_addr
1294             else:
1295                 dst_addr = self.pg0.remote_ip4
1296             if proto != IP_PROTOS.icmp:
1297                 sport = 20
1298                 dport = p[layer].sport
1299             else:
1300                 sport = p[layer].id
1301                 dport = 0
1302             pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport,
1303                                            data, proto, echo_reply=True)
1304             pkts.reverse()
1305             self.pg1.add_stream(pkts)
1306             self.pg_enable_capture(self.pg_interfaces)
1307             self.pg_start()
1308             frags = self.pg0.get_capture(len(pkts))
1309             p = self.reass_frags_and_verify(frags,
1310                                             self.pg1.remote_ip4,
1311                                             self.pg0.remote_ip4)
1312             if proto != IP_PROTOS.icmp:
1313                 self.assertEqual(p[layer].sport, 20)
1314                 self.assertEqual(p[layer].dport, self.port_in)
1315             else:
1316                 self.assertEqual(p[layer].id, self.port_in)
1317             self.assertEqual(data, p[Raw].load)
1318
1319     def frag_out_of_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1320         layer = self.proto2layer(proto)
1321
1322         if proto == IP_PROTOS.tcp:
1323             data = b"A" * 4 + b"B" * 16 + b"C" * 3
1324         else:
1325             data = b"A" * 16 + b"B" * 16 + b"C" * 3
1326         self.port_in = random.randint(1025, 65535)
1327
1328         for i in range(2):
1329             # out2in
1330             pkts = self.create_stream_frag(self.pg0, self.server_out_addr,
1331                                            self.port_in, self.server_out_port,
1332                                            data, proto)
1333             pkts.reverse()
1334             self.pg0.add_stream(pkts)
1335             self.pg_enable_capture(self.pg_interfaces)
1336             self.pg_start()
1337             frags = self.pg1.get_capture(len(pkts))
1338             p = self.reass_frags_and_verify(frags,
1339                                             self.pg0.remote_ip4,
1340                                             self.server_in_addr)
1341             if proto != IP_PROTOS.icmp:
1342                 self.assertEqual(p[layer].dport, self.server_in_port)
1343                 self.assertEqual(p[layer].sport, self.port_in)
1344                 self.assertEqual(p[layer].dport, self.server_in_port)
1345             else:
1346                 self.assertEqual(p[layer].id, self.port_in)
1347             self.assertEqual(data, p[Raw].load)
1348
1349             # in2out
1350             if proto != IP_PROTOS.icmp:
1351                 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1352                                                self.server_in_port,
1353                                                p[layer].sport, data, proto)
1354             else:
1355                 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1356                                                p[layer].id, 0, data, proto,
1357                                                echo_reply=True)
1358             pkts.reverse()
1359             self.pg1.add_stream(pkts)
1360             self.pg_enable_capture(self.pg_interfaces)
1361             self.pg_start()
1362             frags = self.pg0.get_capture(len(pkts))
1363             p = self.reass_frags_and_verify(frags,
1364                                             self.server_out_addr,
1365                                             self.pg0.remote_ip4)
1366             if proto != IP_PROTOS.icmp:
1367                 self.assertEqual(p[layer].sport, self.server_out_port)
1368                 self.assertEqual(p[layer].dport, self.port_in)
1369             else:
1370                 self.assertEqual(p[layer].id, self.port_in)
1371             self.assertEqual(data, p[Raw].load)
1372
1373
1374 class TestNAT44(MethodHolder):
1375     """ NAT44 Test Cases """
1376
1377     @classmethod
1378     def setUpClass(cls):
1379         super(TestNAT44, cls).setUpClass()
1380         cls.vapi.cli("set log class nat level debug")
1381
1382         cls.tcp_port_in = 6303
1383         cls.tcp_port_out = 6303
1384         cls.udp_port_in = 6304
1385         cls.udp_port_out = 6304
1386         cls.icmp_id_in = 6305
1387         cls.icmp_id_out = 6305
1388         cls.nat_addr = '10.0.0.3'
1389         cls.ipfix_src_port = 4739
1390         cls.ipfix_domain_id = 1
1391         cls.tcp_external_port = 80
1392         cls.udp_external_port = 69
1393
1394         cls.create_pg_interfaces(range(10))
1395         cls.interfaces = list(cls.pg_interfaces[0:4])
1396
1397         for i in cls.interfaces:
1398             i.admin_up()
1399             i.config_ip4()
1400             i.resolve_arp()
1401
1402         cls.pg0.generate_remote_hosts(3)
1403         cls.pg0.configure_ipv4_neighbors()
1404
1405         cls.pg1.generate_remote_hosts(1)
1406         cls.pg1.configure_ipv4_neighbors()
1407
1408         cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
1409         cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 10})
1410         cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 20})
1411
1412         cls.pg4._local_ip4 = "172.16.255.1"
1413         cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1414         cls.pg4.set_table_ip4(10)
1415         cls.pg5._local_ip4 = "172.17.255.3"
1416         cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
1417         cls.pg5.set_table_ip4(10)
1418         cls.pg6._local_ip4 = "172.16.255.1"
1419         cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1420         cls.pg6.set_table_ip4(20)
1421         for i in cls.overlapping_interfaces:
1422             i.config_ip4()
1423             i.admin_up()
1424             i.resolve_arp()
1425
1426         cls.pg7.admin_up()
1427         cls.pg8.admin_up()
1428
1429         cls.pg9.generate_remote_hosts(2)
1430         cls.pg9.config_ip4()
1431         cls.vapi.sw_interface_add_del_address(
1432             sw_if_index=cls.pg9.sw_if_index,
1433             prefix="10.0.0.1/24")
1434
1435         cls.pg9.admin_up()
1436         cls.pg9.resolve_arp()
1437         cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1438         cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1439         cls.pg9.resolve_arp()
1440
1441     @classmethod
1442     def tearDownClass(cls):
1443         super(TestNAT44, cls).tearDownClass()
1444
1445     def test_dynamic(self):
1446         """ NAT44 dynamic translation test """
1447         self.nat44_add_address(self.nat_addr)
1448         flags = self.config_flags.NAT_IS_INSIDE
1449         self.vapi.nat44_interface_add_del_feature(
1450             sw_if_index=self.pg0.sw_if_index,
1451             flags=flags, is_add=1)
1452         self.vapi.nat44_interface_add_del_feature(
1453             sw_if_index=self.pg1.sw_if_index,
1454             is_add=1)
1455
1456         # in2out
1457         tcpn = self.statistics.get_err_counter(
1458             '/err/nat44-in2out-slowpath/TCP packets')
1459         udpn = self.statistics.get_err_counter(
1460             '/err/nat44-in2out-slowpath/UDP packets')
1461         icmpn = self.statistics.get_err_counter(
1462             '/err/nat44-in2out-slowpath/ICMP packets')
1463         totaln = self.statistics.get_err_counter(
1464             '/err/nat44-in2out-slowpath/good in2out packets processed')
1465
1466         pkts = self.create_stream_in(self.pg0, self.pg1)
1467         self.pg0.add_stream(pkts)
1468         self.pg_enable_capture(self.pg_interfaces)
1469         self.pg_start()
1470         capture = self.pg1.get_capture(len(pkts))
1471         self.verify_capture_out(capture)
1472
1473         err = self.statistics.get_err_counter(
1474             '/err/nat44-in2out-slowpath/TCP packets')
1475         self.assertEqual(err - tcpn, 2)
1476         err = self.statistics.get_err_counter(
1477             '/err/nat44-in2out-slowpath/UDP packets')
1478         self.assertEqual(err - udpn, 1)
1479         err = self.statistics.get_err_counter(
1480             '/err/nat44-in2out-slowpath/ICMP packets')
1481         self.assertEqual(err - icmpn, 1)
1482         err = self.statistics.get_err_counter(
1483             '/err/nat44-in2out-slowpath/good in2out packets processed')
1484         self.assertEqual(err - totaln, 4)
1485
1486         # out2in
1487         tcpn = self.statistics.get_err_counter('/err/nat44-out2in/TCP packets')
1488         udpn = self.statistics.get_err_counter('/err/nat44-out2in/UDP packets')
1489         icmpn = self.statistics.get_err_counter(
1490             '/err/nat44-out2in/ICMP packets')
1491         totaln = self.statistics.get_err_counter(
1492             '/err/nat44-out2in/good out2in packets processed')
1493
1494         pkts = self.create_stream_out(self.pg1)
1495         self.pg1.add_stream(pkts)
1496         self.pg_enable_capture(self.pg_interfaces)
1497         self.pg_start()
1498         capture = self.pg0.get_capture(len(pkts))
1499         self.verify_capture_in(capture, self.pg0)
1500
1501         err = self.statistics.get_err_counter('/err/nat44-out2in/TCP packets')
1502         self.assertEqual(err - tcpn, 2)
1503         err = self.statistics.get_err_counter('/err/nat44-out2in/UDP packets')
1504         self.assertEqual(err - udpn, 1)
1505         err = self.statistics.get_err_counter('/err/nat44-out2in/ICMP packets')
1506         self.assertEqual(err - icmpn, 1)
1507         err = self.statistics.get_err_counter(
1508             '/err/nat44-out2in/good out2in packets processed')
1509         self.assertEqual(err - totaln, 4)
1510
1511         users = self.statistics.get_counter('/nat44/total-users')
1512         self.assertEqual(users[0][0], 1)
1513         sessions = self.statistics.get_counter('/nat44/total-sessions')
1514         self.assertEqual(sessions[0][0], 3)
1515
1516     def test_dynamic_icmp_errors_in2out_ttl_1(self):
1517         """ NAT44 handling of client packets with TTL=1 """
1518
1519         self.nat44_add_address(self.nat_addr)
1520         flags = self.config_flags.NAT_IS_INSIDE
1521         self.vapi.nat44_interface_add_del_feature(
1522             sw_if_index=self.pg0.sw_if_index,
1523             flags=flags, is_add=1)
1524         self.vapi.nat44_interface_add_del_feature(
1525             sw_if_index=self.pg1.sw_if_index,
1526             is_add=1)
1527
1528         # Client side - generate traffic
1529         pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1530         self.pg0.add_stream(pkts)
1531         self.pg_enable_capture(self.pg_interfaces)
1532         self.pg_start()
1533
1534         # Client side - verify ICMP type 11 packets
1535         capture = self.pg0.get_capture(len(pkts))
1536         self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1537
1538     def test_dynamic_icmp_errors_out2in_ttl_1(self):
1539         """ NAT44 handling of server packets with TTL=1 """
1540
1541         self.nat44_add_address(self.nat_addr)
1542         flags = self.config_flags.NAT_IS_INSIDE
1543         self.vapi.nat44_interface_add_del_feature(
1544             sw_if_index=self.pg0.sw_if_index,
1545             flags=flags, is_add=1)
1546         self.vapi.nat44_interface_add_del_feature(
1547             sw_if_index=self.pg1.sw_if_index,
1548             is_add=1)
1549
1550         # Client side - create sessions
1551         pkts = self.create_stream_in(self.pg0, self.pg1)
1552         self.pg0.add_stream(pkts)
1553         self.pg_enable_capture(self.pg_interfaces)
1554         self.pg_start()
1555
1556         # Server side - generate traffic
1557         capture = self.pg1.get_capture(len(pkts))
1558         self.verify_capture_out(capture)
1559         pkts = self.create_stream_out(self.pg1, ttl=1)
1560         self.pg1.add_stream(pkts)
1561         self.pg_enable_capture(self.pg_interfaces)
1562         self.pg_start()
1563
1564         # Server side - verify ICMP type 11 packets
1565         capture = self.pg1.get_capture(len(pkts))
1566         self.verify_capture_out_with_icmp_errors(capture,
1567                                                  src_ip=self.pg1.local_ip4)
1568
1569     def test_dynamic_icmp_errors_in2out_ttl_2(self):
1570         """ NAT44 handling of error responses to client packets with TTL=2 """
1571
1572         self.nat44_add_address(self.nat_addr)
1573         flags = self.config_flags.NAT_IS_INSIDE
1574         self.vapi.nat44_interface_add_del_feature(
1575             sw_if_index=self.pg0.sw_if_index,
1576             flags=flags, is_add=1)
1577         self.vapi.nat44_interface_add_del_feature(
1578             sw_if_index=self.pg1.sw_if_index,
1579             is_add=1)
1580
1581         # Client side - generate traffic
1582         pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1583         self.pg0.add_stream(pkts)
1584         self.pg_enable_capture(self.pg_interfaces)
1585         self.pg_start()
1586
1587         # Server side - simulate ICMP type 11 response
1588         capture = self.pg1.get_capture(len(pkts))
1589         pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1590                 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1591                 ICMP(type=11) / packet[IP] for packet in capture]
1592         self.pg1.add_stream(pkts)
1593         self.pg_enable_capture(self.pg_interfaces)
1594         self.pg_start()
1595
1596         # Client side - verify ICMP type 11 packets
1597         capture = self.pg0.get_capture(len(pkts))
1598         self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1599
1600     def test_dynamic_icmp_errors_out2in_ttl_2(self):
1601         """ NAT44 handling of error responses to server packets with TTL=2 """
1602
1603         self.nat44_add_address(self.nat_addr)
1604         flags = self.config_flags.NAT_IS_INSIDE
1605         self.vapi.nat44_interface_add_del_feature(
1606             sw_if_index=self.pg0.sw_if_index,
1607             flags=flags, is_add=1)
1608         self.vapi.nat44_interface_add_del_feature(
1609             sw_if_index=self.pg1.sw_if_index,
1610             is_add=1)
1611
1612         # Client side - create sessions
1613         pkts = self.create_stream_in(self.pg0, self.pg1)
1614         self.pg0.add_stream(pkts)
1615         self.pg_enable_capture(self.pg_interfaces)
1616         self.pg_start()
1617
1618         # Server side - generate traffic
1619         capture = self.pg1.get_capture(len(pkts))
1620         self.verify_capture_out(capture)
1621         pkts = self.create_stream_out(self.pg1, ttl=2)
1622         self.pg1.add_stream(pkts)
1623         self.pg_enable_capture(self.pg_interfaces)
1624         self.pg_start()
1625
1626         # Client side - simulate ICMP type 11 response
1627         capture = self.pg0.get_capture(len(pkts))
1628         pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1629                 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1630                 ICMP(type=11) / packet[IP] for packet in capture]
1631         self.pg0.add_stream(pkts)
1632         self.pg_enable_capture(self.pg_interfaces)
1633         self.pg_start()
1634
1635         # Server side - verify ICMP type 11 packets
1636         capture = self.pg1.get_capture(len(pkts))
1637         self.verify_capture_out_with_icmp_errors(capture)
1638
1639     def test_ping_out_interface_from_outside(self):
1640         """ Ping NAT44 out interface from outside network """
1641
1642         self.nat44_add_address(self.nat_addr)
1643         flags = self.config_flags.NAT_IS_INSIDE
1644         self.vapi.nat44_interface_add_del_feature(
1645             sw_if_index=self.pg0.sw_if_index,
1646             flags=flags, is_add=1)
1647         self.vapi.nat44_interface_add_del_feature(
1648             sw_if_index=self.pg1.sw_if_index,
1649             is_add=1)
1650
1651         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1652              IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1653              ICMP(id=self.icmp_id_out, type='echo-request'))
1654         pkts = [p]
1655         self.pg1.add_stream(pkts)
1656         self.pg_enable_capture(self.pg_interfaces)
1657         self.pg_start()
1658         capture = self.pg1.get_capture(len(pkts))
1659         packet = capture[0]
1660         try:
1661             self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1662             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1663             self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1664             self.assertEqual(packet[ICMP].type, 0)  # echo reply
1665         except:
1666             self.logger.error(ppp("Unexpected or invalid packet "
1667                                   "(outside network):", packet))
1668             raise
1669
1670     def test_ping_internal_host_from_outside(self):
1671         """ Ping internal host from outside network """
1672
1673         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1674         flags = self.config_flags.NAT_IS_INSIDE
1675         self.vapi.nat44_interface_add_del_feature(
1676             sw_if_index=self.pg0.sw_if_index,
1677             flags=flags, is_add=1)
1678         self.vapi.nat44_interface_add_del_feature(
1679             sw_if_index=self.pg1.sw_if_index,
1680             is_add=1)
1681
1682         # out2in
1683         pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1684                IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
1685                ICMP(id=self.icmp_id_out, type='echo-request'))
1686         self.pg1.add_stream(pkt)
1687         self.pg_enable_capture(self.pg_interfaces)
1688         self.pg_start()
1689         capture = self.pg0.get_capture(1)
1690         self.verify_capture_in(capture, self.pg0)
1691         self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1692
1693         # in2out
1694         pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1695                IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1696                ICMP(id=self.icmp_id_in, type='echo-reply'))
1697         self.pg0.add_stream(pkt)
1698         self.pg_enable_capture(self.pg_interfaces)
1699         self.pg_start()
1700         capture = self.pg1.get_capture(1)
1701         self.verify_capture_out(capture, same_port=True)
1702         self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1703
1704     def test_forwarding(self):
1705         """ NAT44 forwarding test """
1706
1707         flags = self.config_flags.NAT_IS_INSIDE
1708         self.vapi.nat44_interface_add_del_feature(
1709             sw_if_index=self.pg0.sw_if_index,
1710             flags=flags, is_add=1)
1711         self.vapi.nat44_interface_add_del_feature(
1712             sw_if_index=self.pg1.sw_if_index,
1713             is_add=1)
1714         self.vapi.nat44_forwarding_enable_disable(enable=1)
1715
1716         real_ip = self.pg0.remote_ip4
1717         alias_ip = self.nat_addr
1718         flags = self.config_flags.NAT_IS_ADDR_ONLY
1719         self.vapi.nat44_add_del_static_mapping(is_add=1,
1720                                                local_ip_address=real_ip,
1721                                                external_ip_address=alias_ip,
1722                                                external_sw_if_index=0xFFFFFFFF,
1723                                                flags=flags)
1724
1725         try:
1726             # static mapping match
1727
1728             pkts = self.create_stream_out(self.pg1)
1729             self.pg1.add_stream(pkts)
1730             self.pg_enable_capture(self.pg_interfaces)
1731             self.pg_start()
1732             capture = self.pg0.get_capture(len(pkts))
1733             self.verify_capture_in(capture, self.pg0)
1734
1735             pkts = self.create_stream_in(self.pg0, self.pg1)
1736             self.pg0.add_stream(pkts)
1737             self.pg_enable_capture(self.pg_interfaces)
1738             self.pg_start()
1739             capture = self.pg1.get_capture(len(pkts))
1740             self.verify_capture_out(capture, same_port=True)
1741
1742             # no static mapping match
1743
1744             host0 = self.pg0.remote_hosts[0]
1745             self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1746             try:
1747                 pkts = self.create_stream_out(self.pg1,
1748                                               dst_ip=self.pg0.remote_ip4,
1749                                               use_inside_ports=True)
1750                 self.pg1.add_stream(pkts)
1751                 self.pg_enable_capture(self.pg_interfaces)
1752                 self.pg_start()
1753                 capture = self.pg0.get_capture(len(pkts))
1754                 self.verify_capture_in(capture, self.pg0)
1755
1756                 pkts = self.create_stream_in(self.pg0, self.pg1)
1757                 self.pg0.add_stream(pkts)
1758                 self.pg_enable_capture(self.pg_interfaces)
1759                 self.pg_start()
1760                 capture = self.pg1.get_capture(len(pkts))
1761                 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1762                                         same_port=True)
1763             finally:
1764                 self.pg0.remote_hosts[0] = host0
1765
1766         finally:
1767             self.vapi.nat44_forwarding_enable_disable(enable=0)
1768             flags = self.config_flags.NAT_IS_ADDR_ONLY
1769             self.vapi.nat44_add_del_static_mapping(
1770                 is_add=0,
1771                 local_ip_address=real_ip,
1772                 external_ip_address=alias_ip,
1773                 external_sw_if_index=0xFFFFFFFF,
1774                 flags=flags)
1775
1776     def test_static_in(self):
1777         """ 1:1 NAT initialized from inside network """
1778
1779         nat_ip = "10.0.0.10"
1780         self.tcp_port_out = 6303
1781         self.udp_port_out = 6304
1782         self.icmp_id_out = 6305
1783
1784         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1785         flags = self.config_flags.NAT_IS_INSIDE
1786         self.vapi.nat44_interface_add_del_feature(
1787             sw_if_index=self.pg0.sw_if_index,
1788             flags=flags, is_add=1)
1789         self.vapi.nat44_interface_add_del_feature(
1790             sw_if_index=self.pg1.sw_if_index,
1791             is_add=1)
1792         sm = self.vapi.nat44_static_mapping_dump()
1793         self.assertEqual(len(sm), 1)
1794         self.assertEqual(sm[0].tag, '')
1795         self.assertEqual(sm[0].protocol, 0)
1796         self.assertEqual(sm[0].local_port, 0)
1797         self.assertEqual(sm[0].external_port, 0)
1798
1799         # in2out
1800         pkts = self.create_stream_in(self.pg0, self.pg1)
1801         self.pg0.add_stream(pkts)
1802         self.pg_enable_capture(self.pg_interfaces)
1803         self.pg_start()
1804         capture = self.pg1.get_capture(len(pkts))
1805         self.verify_capture_out(capture, nat_ip, True)
1806
1807         # out2in
1808         pkts = self.create_stream_out(self.pg1, nat_ip)
1809         self.pg1.add_stream(pkts)
1810         self.pg_enable_capture(self.pg_interfaces)
1811         self.pg_start()
1812         capture = self.pg0.get_capture(len(pkts))
1813         self.verify_capture_in(capture, self.pg0)
1814
1815     def test_static_out(self):
1816         """ 1:1 NAT initialized from outside network """
1817
1818         nat_ip = "10.0.0.20"
1819         self.tcp_port_out = 6303
1820         self.udp_port_out = 6304
1821         self.icmp_id_out = 6305
1822         tag = "testTAG"
1823
1824         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
1825         flags = self.config_flags.NAT_IS_INSIDE
1826         self.vapi.nat44_interface_add_del_feature(
1827             sw_if_index=self.pg0.sw_if_index,
1828             flags=flags, is_add=1)
1829         self.vapi.nat44_interface_add_del_feature(
1830             sw_if_index=self.pg1.sw_if_index,
1831             is_add=1)
1832         sm = self.vapi.nat44_static_mapping_dump()
1833         self.assertEqual(len(sm), 1)
1834         self.assertEqual(sm[0].tag, tag)
1835
1836         # out2in
1837         pkts = self.create_stream_out(self.pg1, nat_ip)
1838         self.pg1.add_stream(pkts)
1839         self.pg_enable_capture(self.pg_interfaces)
1840         self.pg_start()
1841         capture = self.pg0.get_capture(len(pkts))
1842         self.verify_capture_in(capture, self.pg0)
1843
1844         # in2out
1845         pkts = self.create_stream_in(self.pg0, self.pg1)
1846         self.pg0.add_stream(pkts)
1847         self.pg_enable_capture(self.pg_interfaces)
1848         self.pg_start()
1849         capture = self.pg1.get_capture(len(pkts))
1850         self.verify_capture_out(capture, nat_ip, True)
1851
1852     def test_static_with_port_in(self):
1853         """ 1:1 NAPT initialized from inside network """
1854
1855         self.tcp_port_out = 3606
1856         self.udp_port_out = 3607
1857         self.icmp_id_out = 3608
1858
1859         self.nat44_add_address(self.nat_addr)
1860         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1861                                       self.tcp_port_in, self.tcp_port_out,
1862                                       proto=IP_PROTOS.tcp)
1863         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1864                                       self.udp_port_in, self.udp_port_out,
1865                                       proto=IP_PROTOS.udp)
1866         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1867                                       self.icmp_id_in, self.icmp_id_out,
1868                                       proto=IP_PROTOS.icmp)
1869         flags = self.config_flags.NAT_IS_INSIDE
1870         self.vapi.nat44_interface_add_del_feature(
1871             sw_if_index=self.pg0.sw_if_index,
1872             flags=flags, is_add=1)
1873         self.vapi.nat44_interface_add_del_feature(
1874             sw_if_index=self.pg1.sw_if_index,
1875             is_add=1)
1876
1877         # in2out
1878         pkts = self.create_stream_in(self.pg0, self.pg1)
1879         self.pg0.add_stream(pkts)
1880         self.pg_enable_capture(self.pg_interfaces)
1881         self.pg_start()
1882         capture = self.pg1.get_capture(len(pkts))
1883         self.verify_capture_out(capture)
1884
1885         # out2in
1886         pkts = self.create_stream_out(self.pg1)
1887         self.pg1.add_stream(pkts)
1888         self.pg_enable_capture(self.pg_interfaces)
1889         self.pg_start()
1890         capture = self.pg0.get_capture(len(pkts))
1891         self.verify_capture_in(capture, self.pg0)
1892
1893     def test_static_with_port_out(self):
1894         """ 1:1 NAPT initialized from outside network """
1895
1896         self.tcp_port_out = 30606
1897         self.udp_port_out = 30607
1898         self.icmp_id_out = 30608
1899
1900         self.nat44_add_address(self.nat_addr)
1901         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1902                                       self.tcp_port_in, self.tcp_port_out,
1903                                       proto=IP_PROTOS.tcp)
1904         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1905                                       self.udp_port_in, self.udp_port_out,
1906                                       proto=IP_PROTOS.udp)
1907         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1908                                       self.icmp_id_in, self.icmp_id_out,
1909                                       proto=IP_PROTOS.icmp)
1910         flags = self.config_flags.NAT_IS_INSIDE
1911         self.vapi.nat44_interface_add_del_feature(
1912             sw_if_index=self.pg0.sw_if_index,
1913             flags=flags, is_add=1)
1914         self.vapi.nat44_interface_add_del_feature(
1915             sw_if_index=self.pg1.sw_if_index,
1916             is_add=1)
1917
1918         # out2in
1919         pkts = self.create_stream_out(self.pg1)
1920         self.pg1.add_stream(pkts)
1921         self.pg_enable_capture(self.pg_interfaces)
1922         self.pg_start()
1923         capture = self.pg0.get_capture(len(pkts))
1924         self.verify_capture_in(capture, self.pg0)
1925
1926         # in2out
1927         pkts = self.create_stream_in(self.pg0, self.pg1)
1928         self.pg0.add_stream(pkts)
1929         self.pg_enable_capture(self.pg_interfaces)
1930         self.pg_start()
1931         capture = self.pg1.get_capture(len(pkts))
1932         self.verify_capture_out(capture)
1933
1934     def test_static_vrf_aware(self):
1935         """ 1:1 NAT VRF awareness """
1936
1937         nat_ip1 = "10.0.0.30"
1938         nat_ip2 = "10.0.0.40"
1939         self.tcp_port_out = 6303
1940         self.udp_port_out = 6304
1941         self.icmp_id_out = 6305
1942
1943         self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1944                                       vrf_id=10)
1945         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1946                                       vrf_id=10)
1947         flags = self.config_flags.NAT_IS_INSIDE
1948         self.vapi.nat44_interface_add_del_feature(
1949             sw_if_index=self.pg3.sw_if_index,
1950             is_add=1)
1951         self.vapi.nat44_interface_add_del_feature(
1952             sw_if_index=self.pg0.sw_if_index,
1953             flags=flags, is_add=1)
1954         self.vapi.nat44_interface_add_del_feature(
1955             sw_if_index=self.pg4.sw_if_index,
1956             flags=flags, is_add=1)
1957
1958         # inside interface VRF match NAT44 static mapping VRF
1959         pkts = self.create_stream_in(self.pg4, self.pg3)
1960         self.pg4.add_stream(pkts)
1961         self.pg_enable_capture(self.pg_interfaces)
1962         self.pg_start()
1963         capture = self.pg3.get_capture(len(pkts))
1964         self.verify_capture_out(capture, nat_ip1, True)
1965
1966         # inside interface VRF don't match NAT44 static mapping VRF (packets
1967         # are dropped)
1968         pkts = self.create_stream_in(self.pg0, self.pg3)
1969         self.pg0.add_stream(pkts)
1970         self.pg_enable_capture(self.pg_interfaces)
1971         self.pg_start()
1972         self.pg3.assert_nothing_captured()
1973
1974     def test_dynamic_to_static(self):
1975         """ Switch from dynamic translation to 1:1NAT """
1976         nat_ip = "10.0.0.10"
1977         self.tcp_port_out = 6303
1978         self.udp_port_out = 6304
1979         self.icmp_id_out = 6305
1980
1981         self.nat44_add_address(self.nat_addr)
1982         flags = self.config_flags.NAT_IS_INSIDE
1983         self.vapi.nat44_interface_add_del_feature(
1984             sw_if_index=self.pg0.sw_if_index,
1985             flags=flags, is_add=1)
1986         self.vapi.nat44_interface_add_del_feature(
1987             sw_if_index=self.pg1.sw_if_index,
1988             is_add=1)
1989
1990         # dynamic
1991         pkts = self.create_stream_in(self.pg0, self.pg1)
1992         self.pg0.add_stream(pkts)
1993         self.pg_enable_capture(self.pg_interfaces)
1994         self.pg_start()
1995         capture = self.pg1.get_capture(len(pkts))
1996         self.verify_capture_out(capture)
1997
1998         # 1:1NAT
1999         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2000         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
2001         self.assertEqual(len(sessions), 0)
2002         pkts = self.create_stream_in(self.pg0, self.pg1)
2003         self.pg0.add_stream(pkts)
2004         self.pg_enable_capture(self.pg_interfaces)
2005         self.pg_start()
2006         capture = self.pg1.get_capture(len(pkts))
2007         self.verify_capture_out(capture, nat_ip, True)
2008
2009     def test_identity_nat(self):
2010         """ Identity NAT """
2011         flags = self.config_flags.NAT_IS_ADDR_ONLY
2012         self.vapi.nat44_add_del_identity_mapping(
2013             ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
2014             flags=flags, is_add=1)
2015         flags = self.config_flags.NAT_IS_INSIDE
2016         self.vapi.nat44_interface_add_del_feature(
2017             sw_if_index=self.pg0.sw_if_index,
2018             flags=flags, is_add=1)
2019         self.vapi.nat44_interface_add_del_feature(
2020             sw_if_index=self.pg1.sw_if_index,
2021             is_add=1)
2022
2023         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2024              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2025              TCP(sport=12345, dport=56789))
2026         self.pg1.add_stream(p)
2027         self.pg_enable_capture(self.pg_interfaces)
2028         self.pg_start()
2029         capture = self.pg0.get_capture(1)
2030         p = capture[0]
2031         try:
2032             ip = p[IP]
2033             tcp = p[TCP]
2034             self.assertEqual(ip.dst, self.pg0.remote_ip4)
2035             self.assertEqual(ip.src, self.pg1.remote_ip4)
2036             self.assertEqual(tcp.dport, 56789)
2037             self.assertEqual(tcp.sport, 12345)
2038             self.assert_packet_checksums_valid(p)
2039         except:
2040             self.logger.error(ppp("Unexpected or invalid packet:", p))
2041             raise
2042
2043         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
2044         self.assertEqual(len(sessions), 0)
2045         flags = self.config_flags.NAT_IS_ADDR_ONLY
2046         self.vapi.nat44_add_del_identity_mapping(
2047             ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
2048             flags=flags, vrf_id=1, is_add=1)
2049         identity_mappings = self.vapi.nat44_identity_mapping_dump()
2050         self.assertEqual(len(identity_mappings), 2)
2051
2052     def test_multiple_inside_interfaces(self):
2053         """ NAT44 multiple non-overlapping address space inside interfaces """
2054
2055         self.nat44_add_address(self.nat_addr)
2056         flags = self.config_flags.NAT_IS_INSIDE
2057         self.vapi.nat44_interface_add_del_feature(
2058             sw_if_index=self.pg0.sw_if_index,
2059             flags=flags, is_add=1)
2060         self.vapi.nat44_interface_add_del_feature(
2061             sw_if_index=self.pg1.sw_if_index,
2062             flags=flags, is_add=1)
2063         self.vapi.nat44_interface_add_del_feature(
2064             sw_if_index=self.pg3.sw_if_index,
2065             is_add=1)
2066
2067         # between two NAT44 inside interfaces (no translation)
2068         pkts = self.create_stream_in(self.pg0, self.pg1)
2069         self.pg0.add_stream(pkts)
2070         self.pg_enable_capture(self.pg_interfaces)
2071         self.pg_start()
2072         capture = self.pg1.get_capture(len(pkts))
2073         self.verify_capture_no_translation(capture, self.pg0, self.pg1)
2074
2075         # from NAT44 inside to interface without NAT44 feature (no translation)
2076         pkts = self.create_stream_in(self.pg0, self.pg2)
2077         self.pg0.add_stream(pkts)
2078         self.pg_enable_capture(self.pg_interfaces)
2079         self.pg_start()
2080         capture = self.pg2.get_capture(len(pkts))
2081         self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2082
2083         # in2out 1st interface
2084         pkts = self.create_stream_in(self.pg0, self.pg3)
2085         self.pg0.add_stream(pkts)
2086         self.pg_enable_capture(self.pg_interfaces)
2087         self.pg_start()
2088         capture = self.pg3.get_capture(len(pkts))
2089         self.verify_capture_out(capture)
2090
2091         # out2in 1st interface
2092         pkts = self.create_stream_out(self.pg3)
2093         self.pg3.add_stream(pkts)
2094         self.pg_enable_capture(self.pg_interfaces)
2095         self.pg_start()
2096         capture = self.pg0.get_capture(len(pkts))
2097         self.verify_capture_in(capture, self.pg0)
2098
2099         # in2out 2nd interface
2100         pkts = self.create_stream_in(self.pg1, self.pg3)
2101         self.pg1.add_stream(pkts)
2102         self.pg_enable_capture(self.pg_interfaces)
2103         self.pg_start()
2104         capture = self.pg3.get_capture(len(pkts))
2105         self.verify_capture_out(capture)
2106
2107         # out2in 2nd interface
2108         pkts = self.create_stream_out(self.pg3)
2109         self.pg3.add_stream(pkts)
2110         self.pg_enable_capture(self.pg_interfaces)
2111         self.pg_start()
2112         capture = self.pg1.get_capture(len(pkts))
2113         self.verify_capture_in(capture, self.pg1)
2114
2115     def test_inside_overlapping_interfaces(self):
2116         """ NAT44 multiple inside interfaces with overlapping address space """
2117
2118         static_nat_ip = "10.0.0.10"
2119         self.nat44_add_address(self.nat_addr)
2120         flags = self.config_flags.NAT_IS_INSIDE
2121         self.vapi.nat44_interface_add_del_feature(
2122             sw_if_index=self.pg3.sw_if_index,
2123             is_add=1)
2124         self.vapi.nat44_interface_add_del_feature(
2125             sw_if_index=self.pg4.sw_if_index,
2126             flags=flags, is_add=1)
2127         self.vapi.nat44_interface_add_del_feature(
2128             sw_if_index=self.pg5.sw_if_index,
2129             flags=flags, is_add=1)
2130         self.vapi.nat44_interface_add_del_feature(
2131             sw_if_index=self.pg6.sw_if_index,
2132             flags=flags, is_add=1)
2133         self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2134                                       vrf_id=20)
2135
2136         # between NAT44 inside interfaces with same VRF (no translation)
2137         pkts = self.create_stream_in(self.pg4, self.pg5)
2138         self.pg4.add_stream(pkts)
2139         self.pg_enable_capture(self.pg_interfaces)
2140         self.pg_start()
2141         capture = self.pg5.get_capture(len(pkts))
2142         self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2143
2144         # between NAT44 inside interfaces with different VRF (hairpinning)
2145         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2146              IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2147              TCP(sport=1234, dport=5678))
2148         self.pg4.add_stream(p)
2149         self.pg_enable_capture(self.pg_interfaces)
2150         self.pg_start()
2151         capture = self.pg6.get_capture(1)
2152         p = capture[0]
2153         try:
2154             ip = p[IP]
2155             tcp = p[TCP]
2156             self.assertEqual(ip.src, self.nat_addr)
2157             self.assertEqual(ip.dst, self.pg6.remote_ip4)
2158             self.assertNotEqual(tcp.sport, 1234)
2159             self.assertEqual(tcp.dport, 5678)
2160         except:
2161             self.logger.error(ppp("Unexpected or invalid packet:", p))
2162             raise
2163
2164         # in2out 1st interface
2165         pkts = self.create_stream_in(self.pg4, self.pg3)
2166         self.pg4.add_stream(pkts)
2167         self.pg_enable_capture(self.pg_interfaces)
2168         self.pg_start()
2169         capture = self.pg3.get_capture(len(pkts))
2170         self.verify_capture_out(capture)
2171
2172         # out2in 1st interface
2173         pkts = self.create_stream_out(self.pg3)
2174         self.pg3.add_stream(pkts)
2175         self.pg_enable_capture(self.pg_interfaces)
2176         self.pg_start()
2177         capture = self.pg4.get_capture(len(pkts))
2178         self.verify_capture_in(capture, self.pg4)
2179
2180         # in2out 2nd interface
2181         pkts = self.create_stream_in(self.pg5, self.pg3)
2182         self.pg5.add_stream(pkts)
2183         self.pg_enable_capture(self.pg_interfaces)
2184         self.pg_start()
2185         capture = self.pg3.get_capture(len(pkts))
2186         self.verify_capture_out(capture)
2187
2188         # out2in 2nd interface
2189         pkts = self.create_stream_out(self.pg3)
2190         self.pg3.add_stream(pkts)
2191         self.pg_enable_capture(self.pg_interfaces)
2192         self.pg_start()
2193         capture = self.pg5.get_capture(len(pkts))
2194         self.verify_capture_in(capture, self.pg5)
2195
2196         # pg5 session dump
2197         addresses = self.vapi.nat44_address_dump()
2198         self.assertEqual(len(addresses), 1)
2199         sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4, 10)
2200         self.assertEqual(len(sessions), 3)
2201         for session in sessions:
2202             self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2203             self.assertEqual(str(session.inside_ip_address),
2204                              self.pg5.remote_ip4)
2205             self.assertEqual(session.outside_ip_address,
2206                              addresses[0].ip_address)
2207         self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2208         self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2209         self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2210         self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2211         self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2212         self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2213         self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2214         self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2215         self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2216
2217         # in2out 3rd interface
2218         pkts = self.create_stream_in(self.pg6, self.pg3)
2219         self.pg6.add_stream(pkts)
2220         self.pg_enable_capture(self.pg_interfaces)
2221         self.pg_start()
2222         capture = self.pg3.get_capture(len(pkts))
2223         self.verify_capture_out(capture, static_nat_ip, True)
2224
2225         # out2in 3rd interface
2226         pkts = self.create_stream_out(self.pg3, static_nat_ip)
2227         self.pg3.add_stream(pkts)
2228         self.pg_enable_capture(self.pg_interfaces)
2229         self.pg_start()
2230         capture = self.pg6.get_capture(len(pkts))
2231         self.verify_capture_in(capture, self.pg6)
2232
2233         # general user and session dump verifications
2234         users = self.vapi.nat44_user_dump()
2235         self.assertGreaterEqual(len(users), 3)
2236         addresses = self.vapi.nat44_address_dump()
2237         self.assertEqual(len(addresses), 1)
2238         for user in users:
2239             sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2240                                                          user.vrf_id)
2241             for session in sessions:
2242                 self.assertEqual(user.ip_address, session.inside_ip_address)
2243                 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2244                 self.assertTrue(session.protocol in
2245                                 [IP_PROTOS.tcp, IP_PROTOS.udp,
2246                                  IP_PROTOS.icmp])
2247                 self.assertFalse(session.flags &
2248                                  self.config_flags.NAT_IS_EXT_HOST_VALID)
2249
2250         # pg4 session dump
2251         sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4, 10)
2252         self.assertGreaterEqual(len(sessions), 4)
2253         for session in sessions:
2254             self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2255             self.assertEqual(str(session.inside_ip_address),
2256                              self.pg4.remote_ip4)
2257             self.assertEqual(session.outside_ip_address,
2258                              addresses[0].ip_address)
2259
2260         # pg6 session dump
2261         sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4, 20)
2262         self.assertGreaterEqual(len(sessions), 3)
2263         for session in sessions:
2264             self.assertTrue(session.flags & self.config_flags.NAT_IS_STATIC)
2265             self.assertEqual(str(session.inside_ip_address),
2266                              self.pg6.remote_ip4)
2267             self.assertEqual(str(session.outside_ip_address),
2268                              static_nat_ip)
2269             self.assertTrue(session.inside_port in
2270                             [self.tcp_port_in, self.udp_port_in,
2271                              self.icmp_id_in])
2272
2273     def test_hairpinning(self):
2274         """ NAT44 hairpinning - 1:1 NAPT """
2275
2276         host = self.pg0.remote_hosts[0]
2277         server = self.pg0.remote_hosts[1]
2278         host_in_port = 1234
2279         host_out_port = 0
2280         server_in_port = 5678
2281         server_out_port = 8765
2282
2283         self.nat44_add_address(self.nat_addr)
2284         flags = self.config_flags.NAT_IS_INSIDE
2285         self.vapi.nat44_interface_add_del_feature(
2286             sw_if_index=self.pg0.sw_if_index,
2287             flags=flags, is_add=1)
2288         self.vapi.nat44_interface_add_del_feature(
2289             sw_if_index=self.pg1.sw_if_index,
2290             is_add=1)
2291
2292         # add static mapping for server
2293         self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2294                                       server_in_port, server_out_port,
2295                                       proto=IP_PROTOS.tcp)
2296
2297         # send packet from host to server
2298         p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2299              IP(src=host.ip4, dst=self.nat_addr) /
2300              TCP(sport=host_in_port, dport=server_out_port))
2301         self.pg0.add_stream(p)
2302         self.pg_enable_capture(self.pg_interfaces)
2303         self.pg_start()
2304         capture = self.pg0.get_capture(1)
2305         p = capture[0]
2306         try:
2307             ip = p[IP]
2308             tcp = p[TCP]
2309             self.assertEqual(ip.src, self.nat_addr)
2310             self.assertEqual(ip.dst, server.ip4)
2311             self.assertNotEqual(tcp.sport, host_in_port)
2312             self.assertEqual(tcp.dport, server_in_port)
2313             self.assert_packet_checksums_valid(p)
2314             host_out_port = tcp.sport
2315         except:
2316             self.logger.error(ppp("Unexpected or invalid packet:", p))
2317             raise
2318
2319         # send reply from server to host
2320         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2321              IP(src=server.ip4, dst=self.nat_addr) /
2322              TCP(sport=server_in_port, dport=host_out_port))
2323         self.pg0.add_stream(p)
2324         self.pg_enable_capture(self.pg_interfaces)
2325         self.pg_start()
2326         capture = self.pg0.get_capture(1)
2327         p = capture[0]
2328         try:
2329             ip = p[IP]
2330             tcp = p[TCP]
2331             self.assertEqual(ip.src, self.nat_addr)
2332             self.assertEqual(ip.dst, host.ip4)
2333             self.assertEqual(tcp.sport, server_out_port)
2334             self.assertEqual(tcp.dport, host_in_port)
2335             self.assert_packet_checksums_valid(p)
2336         except:
2337             self.logger.error(ppp("Unexpected or invalid packet:", p))
2338             raise
2339
2340     def test_hairpinning2(self):
2341         """ NAT44 hairpinning - 1:1 NAT"""
2342
2343         server1_nat_ip = "10.0.0.10"
2344         server2_nat_ip = "10.0.0.11"
2345         host = self.pg0.remote_hosts[0]
2346         server1 = self.pg0.remote_hosts[1]
2347         server2 = self.pg0.remote_hosts[2]
2348         server_tcp_port = 22
2349         server_udp_port = 20
2350
2351         self.nat44_add_address(self.nat_addr)
2352         flags = self.config_flags.NAT_IS_INSIDE
2353         self.vapi.nat44_interface_add_del_feature(
2354             sw_if_index=self.pg0.sw_if_index,
2355             flags=flags, is_add=1)
2356         self.vapi.nat44_interface_add_del_feature(
2357             sw_if_index=self.pg1.sw_if_index,
2358             is_add=1)
2359
2360         # add static mapping for servers
2361         self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2362         self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
2363
2364         # host to server1
2365         pkts = []
2366         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2367              IP(src=host.ip4, dst=server1_nat_ip) /
2368              TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2369         pkts.append(p)
2370         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2371              IP(src=host.ip4, dst=server1_nat_ip) /
2372              UDP(sport=self.udp_port_in, dport=server_udp_port))
2373         pkts.append(p)
2374         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2375              IP(src=host.ip4, dst=server1_nat_ip) /
2376              ICMP(id=self.icmp_id_in, type='echo-request'))
2377         pkts.append(p)
2378         self.pg0.add_stream(pkts)
2379         self.pg_enable_capture(self.pg_interfaces)
2380         self.pg_start()
2381         capture = self.pg0.get_capture(len(pkts))
2382         for packet in capture:
2383             try:
2384                 self.assertEqual(packet[IP].src, self.nat_addr)
2385                 self.assertEqual(packet[IP].dst, server1.ip4)
2386                 if packet.haslayer(TCP):
2387                     self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2388                     self.assertEqual(packet[TCP].dport, server_tcp_port)
2389                     self.tcp_port_out = packet[TCP].sport
2390                     self.assert_packet_checksums_valid(packet)
2391                 elif packet.haslayer(UDP):
2392                     self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2393                     self.assertEqual(packet[UDP].dport, server_udp_port)
2394                     self.udp_port_out = packet[UDP].sport
2395                 else:
2396                     self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2397                     self.icmp_id_out = packet[ICMP].id
2398             except:
2399                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2400                 raise
2401
2402         # server1 to host
2403         pkts = []
2404         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2405              IP(src=server1.ip4, dst=self.nat_addr) /
2406              TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2407         pkts.append(p)
2408         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2409              IP(src=server1.ip4, dst=self.nat_addr) /
2410              UDP(sport=server_udp_port, dport=self.udp_port_out))
2411         pkts.append(p)
2412         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2413              IP(src=server1.ip4, dst=self.nat_addr) /
2414              ICMP(id=self.icmp_id_out, type='echo-reply'))
2415         pkts.append(p)
2416         self.pg0.add_stream(pkts)
2417         self.pg_enable_capture(self.pg_interfaces)
2418         self.pg_start()
2419         capture = self.pg0.get_capture(len(pkts))
2420         for packet in capture:
2421             try:
2422                 self.assertEqual(packet[IP].src, server1_nat_ip)
2423                 self.assertEqual(packet[IP].dst, host.ip4)
2424                 if packet.haslayer(TCP):
2425                     self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2426                     self.assertEqual(packet[TCP].sport, server_tcp_port)
2427                     self.assert_packet_checksums_valid(packet)
2428                 elif packet.haslayer(UDP):
2429                     self.assertEqual(packet[UDP].dport, self.udp_port_in)
2430                     self.assertEqual(packet[UDP].sport, server_udp_port)
2431                 else:
2432                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2433             except:
2434                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2435                 raise
2436
2437         # server2 to server1
2438         pkts = []
2439         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2440              IP(src=server2.ip4, dst=server1_nat_ip) /
2441              TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2442         pkts.append(p)
2443         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2444              IP(src=server2.ip4, dst=server1_nat_ip) /
2445              UDP(sport=self.udp_port_in, dport=server_udp_port))
2446         pkts.append(p)
2447         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2448              IP(src=server2.ip4, dst=server1_nat_ip) /
2449              ICMP(id=self.icmp_id_in, type='echo-request'))
2450         pkts.append(p)
2451         self.pg0.add_stream(pkts)
2452         self.pg_enable_capture(self.pg_interfaces)
2453         self.pg_start()
2454         capture = self.pg0.get_capture(len(pkts))
2455         for packet in capture:
2456             try:
2457                 self.assertEqual(packet[IP].src, server2_nat_ip)
2458                 self.assertEqual(packet[IP].dst, server1.ip4)
2459                 if packet.haslayer(TCP):
2460                     self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2461                     self.assertEqual(packet[TCP].dport, server_tcp_port)
2462                     self.tcp_port_out = packet[TCP].sport
2463                     self.assert_packet_checksums_valid(packet)
2464                 elif packet.haslayer(UDP):
2465                     self.assertEqual(packet[UDP].sport, self.udp_port_in)
2466                     self.assertEqual(packet[UDP].dport, server_udp_port)
2467                     self.udp_port_out = packet[UDP].sport
2468                 else:
2469                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2470                     self.icmp_id_out = packet[ICMP].id
2471             except:
2472                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2473                 raise
2474
2475         # server1 to server2
2476         pkts = []
2477         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2478              IP(src=server1.ip4, dst=server2_nat_ip) /
2479              TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2480         pkts.append(p)
2481         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2482              IP(src=server1.ip4, dst=server2_nat_ip) /
2483              UDP(sport=server_udp_port, dport=self.udp_port_out))
2484         pkts.append(p)
2485         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2486              IP(src=server1.ip4, dst=server2_nat_ip) /
2487              ICMP(id=self.icmp_id_out, type='echo-reply'))
2488         pkts.append(p)
2489         self.pg0.add_stream(pkts)
2490         self.pg_enable_capture(self.pg_interfaces)
2491         self.pg_start()
2492         capture = self.pg0.get_capture(len(pkts))
2493         for packet in capture:
2494             try:
2495                 self.assertEqual(packet[IP].src, server1_nat_ip)
2496                 self.assertEqual(packet[IP].dst, server2.ip4)
2497                 if packet.haslayer(TCP):
2498                     self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2499                     self.assertEqual(packet[TCP].sport, server_tcp_port)
2500                     self.assert_packet_checksums_valid(packet)
2501                 elif packet.haslayer(UDP):
2502                     self.assertEqual(packet[UDP].dport, self.udp_port_in)
2503                     self.assertEqual(packet[UDP].sport, server_udp_port)
2504                 else:
2505                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2506             except:
2507                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2508                 raise
2509
2510     def test_interface_addr(self):
2511         """ Acquire NAT44 addresses from interface """
2512         self.vapi.nat44_add_del_interface_addr(
2513             is_add=1,
2514             sw_if_index=self.pg7.sw_if_index)
2515
2516         # no address in NAT pool
2517         addresses = self.vapi.nat44_address_dump()
2518         self.assertEqual(0, len(addresses))
2519
2520         # configure interface address and check NAT address pool
2521         self.pg7.config_ip4()
2522         addresses = self.vapi.nat44_address_dump()
2523         self.assertEqual(1, len(addresses))
2524         self.assertEqual(str(addresses[0].ip_address), self.pg7.local_ip4)
2525
2526         # remove interface address and check NAT address pool
2527         self.pg7.unconfig_ip4()
2528         addresses = self.vapi.nat44_address_dump()
2529         self.assertEqual(0, len(addresses))
2530
2531     def test_interface_addr_static_mapping(self):
2532         """ Static mapping with addresses from interface """
2533         tag = "testTAG"
2534
2535         self.vapi.nat44_add_del_interface_addr(
2536             is_add=1,
2537             sw_if_index=self.pg7.sw_if_index)
2538         self.nat44_add_static_mapping(
2539             '1.2.3.4',
2540             external_sw_if_index=self.pg7.sw_if_index,
2541             tag=tag)
2542
2543         # static mappings with external interface
2544         static_mappings = self.vapi.nat44_static_mapping_dump()
2545         self.assertEqual(1, len(static_mappings))
2546         self.assertEqual(self.pg7.sw_if_index,
2547                          static_mappings[0].external_sw_if_index)
2548         self.assertEqual(static_mappings[0].tag, tag)
2549
2550         # configure interface address and check static mappings
2551         self.pg7.config_ip4()
2552         static_mappings = self.vapi.nat44_static_mapping_dump()
2553         self.assertEqual(2, len(static_mappings))
2554         resolved = False
2555         for sm in static_mappings:
2556             if sm.external_sw_if_index == 0xFFFFFFFF:
2557                 self.assertEqual(str(sm.external_ip_address),
2558                                  self.pg7.local_ip4)
2559                 self.assertEqual(sm.tag, tag)
2560                 resolved = True
2561         self.assertTrue(resolved)
2562
2563         # remove interface address and check static mappings
2564         self.pg7.unconfig_ip4()
2565         static_mappings = self.vapi.nat44_static_mapping_dump()
2566         self.assertEqual(1, len(static_mappings))
2567         self.assertEqual(self.pg7.sw_if_index,
2568                          static_mappings[0].external_sw_if_index)
2569         self.assertEqual(static_mappings[0].tag, tag)
2570
2571         # configure interface address again and check static mappings
2572         self.pg7.config_ip4()
2573         static_mappings = self.vapi.nat44_static_mapping_dump()
2574         self.assertEqual(2, len(static_mappings))
2575         resolved = False
2576         for sm in static_mappings:
2577             if sm.external_sw_if_index == 0xFFFFFFFF:
2578                 self.assertEqual(str(sm.external_ip_address),
2579                                  self.pg7.local_ip4)
2580                 self.assertEqual(sm.tag, tag)
2581                 resolved = True
2582         self.assertTrue(resolved)
2583
2584         # remove static mapping
2585         self.nat44_add_static_mapping(
2586             '1.2.3.4',
2587             external_sw_if_index=self.pg7.sw_if_index,
2588             tag=tag,
2589             is_add=0)
2590         static_mappings = self.vapi.nat44_static_mapping_dump()
2591         self.assertEqual(0, len(static_mappings))
2592
2593     def test_interface_addr_identity_nat(self):
2594         """ Identity NAT with addresses from interface """
2595
2596         port = 53053
2597         self.vapi.nat44_add_del_interface_addr(
2598             is_add=1,
2599             sw_if_index=self.pg7.sw_if_index)
2600         self.vapi.nat44_add_del_identity_mapping(
2601             ip_address=b'0',
2602             sw_if_index=self.pg7.sw_if_index,
2603             port=port,
2604             protocol=IP_PROTOS.tcp,
2605             is_add=1)
2606
2607         # identity mappings with external interface
2608         identity_mappings = self.vapi.nat44_identity_mapping_dump()
2609         self.assertEqual(1, len(identity_mappings))
2610         self.assertEqual(self.pg7.sw_if_index,
2611                          identity_mappings[0].sw_if_index)
2612
2613         # configure interface address and check identity mappings
2614         self.pg7.config_ip4()
2615         identity_mappings = self.vapi.nat44_identity_mapping_dump()
2616         resolved = False
2617         self.assertEqual(2, len(identity_mappings))
2618         for sm in identity_mappings:
2619             if sm.sw_if_index == 0xFFFFFFFF:
2620                 self.assertEqual(str(identity_mappings[0].ip_address),
2621                                  self.pg7.local_ip4)
2622                 self.assertEqual(port, identity_mappings[0].port)
2623                 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2624                 resolved = True
2625         self.assertTrue(resolved)
2626
2627         # remove interface address and check identity mappings
2628         self.pg7.unconfig_ip4()
2629         identity_mappings = self.vapi.nat44_identity_mapping_dump()
2630         self.assertEqual(1, len(identity_mappings))
2631         self.assertEqual(self.pg7.sw_if_index,
2632                          identity_mappings[0].sw_if_index)
2633
2634     def test_ipfix_nat44_sess(self):
2635         """ IPFIX logging NAT44 session created/deleted """
2636         self.ipfix_domain_id = 10
2637         self.ipfix_src_port = 20202
2638         collector_port = 30303
2639         bind_layers(UDP, IPFIX, dport=30303)
2640         self.nat44_add_address(self.nat_addr)
2641         flags = self.config_flags.NAT_IS_INSIDE
2642         self.vapi.nat44_interface_add_del_feature(
2643             sw_if_index=self.pg0.sw_if_index,
2644             flags=flags, is_add=1)
2645         self.vapi.nat44_interface_add_del_feature(
2646             sw_if_index=self.pg1.sw_if_index,
2647             is_add=1)
2648         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2649                                      src_address=self.pg3.local_ip4,
2650                                      path_mtu=512,
2651                                      template_interval=10,
2652                                      collector_port=collector_port)
2653         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2654                                            src_port=self.ipfix_src_port,
2655                                            enable=1)
2656
2657         pkts = self.create_stream_in(self.pg0, self.pg1)
2658         self.pg0.add_stream(pkts)
2659         self.pg_enable_capture(self.pg_interfaces)
2660         self.pg_start()
2661         capture = self.pg1.get_capture(len(pkts))
2662         self.verify_capture_out(capture)
2663         self.nat44_add_address(self.nat_addr, is_add=0)
2664         self.vapi.ipfix_flush()
2665         capture = self.pg3.get_capture(7)
2666         ipfix = IPFIXDecoder()
2667         # first load template
2668         for p in capture:
2669             self.assertTrue(p.haslayer(IPFIX))
2670             self.assertEqual(p[IP].src, self.pg3.local_ip4)
2671             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2672             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2673             self.assertEqual(p[UDP].dport, collector_port)
2674             self.assertEqual(p[IPFIX].observationDomainID,
2675                              self.ipfix_domain_id)
2676             if p.haslayer(Template):
2677                 ipfix.add_template(p.getlayer(Template))
2678         # verify events in data set
2679         for p in capture:
2680             if p.haslayer(Data):
2681                 data = ipfix.decode_data_set(p.getlayer(Set))
2682                 self.verify_ipfix_nat44_ses(data)
2683
2684     def test_ipfix_addr_exhausted(self):
2685         """ IPFIX logging NAT addresses exhausted """
2686         flags = self.config_flags.NAT_IS_INSIDE
2687         self.vapi.nat44_interface_add_del_feature(
2688             sw_if_index=self.pg0.sw_if_index,
2689             flags=flags, is_add=1)
2690         self.vapi.nat44_interface_add_del_feature(
2691             sw_if_index=self.pg1.sw_if_index,
2692             is_add=1)
2693         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2694                                      src_address=self.pg3.local_ip4,
2695                                      path_mtu=512,
2696                                      template_interval=10)
2697         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2698                                            src_port=self.ipfix_src_port,
2699                                            enable=1)
2700
2701         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2702              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2703              TCP(sport=3025))
2704         self.pg0.add_stream(p)
2705         self.pg_enable_capture(self.pg_interfaces)
2706         self.pg_start()
2707         self.pg1.assert_nothing_captured()
2708         sleep(1)
2709         self.vapi.ipfix_flush()
2710         capture = self.pg3.get_capture(7)
2711         ipfix = IPFIXDecoder()
2712         # first load template
2713         for p in capture:
2714             self.assertTrue(p.haslayer(IPFIX))
2715             self.assertEqual(p[IP].src, self.pg3.local_ip4)
2716             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2717             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2718             self.assertEqual(p[UDP].dport, 4739)
2719             self.assertEqual(p[IPFIX].observationDomainID,
2720                              self.ipfix_domain_id)
2721             if p.haslayer(Template):
2722                 ipfix.add_template(p.getlayer(Template))
2723         # verify events in data set
2724         for p in capture:
2725             if p.haslayer(Data):
2726                 data = ipfix.decode_data_set(p.getlayer(Set))
2727                 self.verify_ipfix_addr_exhausted(data)
2728
2729     @unittest.skipUnless(running_extended_tests, "part of extended tests")
2730     def test_ipfix_max_sessions(self):
2731         """ IPFIX logging maximum session entries exceeded """
2732         self.nat44_add_address(self.nat_addr)
2733         flags = self.config_flags.NAT_IS_INSIDE
2734         self.vapi.nat44_interface_add_del_feature(
2735             sw_if_index=self.pg0.sw_if_index,
2736             flags=flags, is_add=1)
2737         self.vapi.nat44_interface_add_del_feature(
2738             sw_if_index=self.pg1.sw_if_index,
2739             is_add=1)
2740
2741         nat44_config = self.vapi.nat_show_config()
2742         max_sessions = 10 * nat44_config.translation_buckets
2743
2744         pkts = []
2745         for i in range(0, max_sessions):
2746             src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2747             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2748                  IP(src=src, dst=self.pg1.remote_ip4) /
2749                  TCP(sport=1025))
2750             pkts.append(p)
2751         self.pg0.add_stream(pkts)
2752         self.pg_enable_capture(self.pg_interfaces)
2753         self.pg_start()
2754
2755         self.pg1.get_capture(max_sessions)
2756         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2757                                      src_address=self.pg3.local_ip4,
2758                                      path_mtu=512,
2759                                      template_interval=10)
2760         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2761                                            src_port=self.ipfix_src_port,
2762                                            enable=1)
2763
2764         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2765              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2766              TCP(sport=1025))
2767         self.pg0.add_stream(p)
2768         self.pg_enable_capture(self.pg_interfaces)
2769         self.pg_start()
2770         self.pg1.assert_nothing_captured()
2771         sleep(1)
2772         self.vapi.ipfix_flush()
2773         capture = self.pg3.get_capture(7)
2774         ipfix = IPFIXDecoder()
2775         # first load template
2776         for p in capture:
2777             self.assertTrue(p.haslayer(IPFIX))
2778             self.assertEqual(p[IP].src, self.pg3.local_ip4)
2779             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2780             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2781             self.assertEqual(p[UDP].dport, 4739)
2782             self.assertEqual(p[IPFIX].observationDomainID,
2783                              self.ipfix_domain_id)
2784             if p.haslayer(Template):
2785                 ipfix.add_template(p.getlayer(Template))
2786         # verify events in data set
2787         for p in capture:
2788             if p.haslayer(Data):
2789                 data = ipfix.decode_data_set(p.getlayer(Set))
2790                 self.verify_ipfix_max_sessions(data, max_sessions)
2791
2792     def test_syslog_apmap(self):
2793         """ Test syslog address and port mapping creation and deletion """
2794         self.vapi.syslog_set_filter(
2795             self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
2796         self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
2797         self.nat44_add_address(self.nat_addr)
2798         flags = self.config_flags.NAT_IS_INSIDE
2799         self.vapi.nat44_interface_add_del_feature(
2800             sw_if_index=self.pg0.sw_if_index,
2801             flags=flags, is_add=1)
2802         self.vapi.nat44_interface_add_del_feature(
2803             sw_if_index=self.pg1.sw_if_index,
2804             is_add=1)
2805
2806         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2807              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2808              TCP(sport=self.tcp_port_in, dport=20))
2809         self.pg0.add_stream(p)
2810         self.pg_enable_capture(self.pg_interfaces)
2811         self.pg_start()
2812         capture = self.pg1.get_capture(1)
2813         self.tcp_port_out = capture[0][TCP].sport
2814         capture = self.pg3.get_capture(1)
2815         self.verify_syslog_apmap(capture[0][Raw].load)
2816
2817         self.pg_enable_capture(self.pg_interfaces)
2818         self.pg_start()
2819         self.nat44_add_address(self.nat_addr, is_add=0)
2820         capture = self.pg3.get_capture(1)
2821         self.verify_syslog_apmap(capture[0][Raw].load, False)
2822
2823     def test_pool_addr_fib(self):
2824         """ NAT44 add pool addresses to FIB """
2825         static_addr = '10.0.0.10'
2826         self.nat44_add_address(self.nat_addr)
2827         flags = self.config_flags.NAT_IS_INSIDE
2828         self.vapi.nat44_interface_add_del_feature(
2829             sw_if_index=self.pg0.sw_if_index,
2830             flags=flags, is_add=1)
2831         self.vapi.nat44_interface_add_del_feature(
2832             sw_if_index=self.pg1.sw_if_index,
2833             is_add=1)
2834         self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
2835
2836         # NAT44 address
2837         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2838              ARP(op=ARP.who_has, pdst=self.nat_addr,
2839                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2840         self.pg1.add_stream(p)
2841         self.pg_enable_capture(self.pg_interfaces)
2842         self.pg_start()
2843         capture = self.pg1.get_capture(1)
2844         self.assertTrue(capture[0].haslayer(ARP))
2845         self.assertTrue(capture[0][ARP].op, ARP.is_at)
2846
2847         # 1:1 NAT address
2848         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2849              ARP(op=ARP.who_has, pdst=static_addr,
2850                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2851         self.pg1.add_stream(p)
2852         self.pg_enable_capture(self.pg_interfaces)
2853         self.pg_start()
2854         capture = self.pg1.get_capture(1)
2855         self.assertTrue(capture[0].haslayer(ARP))
2856         self.assertTrue(capture[0][ARP].op, ARP.is_at)
2857
2858         # send ARP to non-NAT44 interface
2859         p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2860              ARP(op=ARP.who_has, pdst=self.nat_addr,
2861                  psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2862         self.pg2.add_stream(p)
2863         self.pg_enable_capture(self.pg_interfaces)
2864         self.pg_start()
2865         self.pg1.assert_nothing_captured()
2866
2867         # remove addresses and verify
2868         self.nat44_add_address(self.nat_addr, is_add=0)
2869         self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2870                                       is_add=0)
2871
2872         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2873              ARP(op=ARP.who_has, pdst=self.nat_addr,
2874                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2875         self.pg1.add_stream(p)
2876         self.pg_enable_capture(self.pg_interfaces)
2877         self.pg_start()
2878         self.pg1.assert_nothing_captured()
2879
2880         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2881              ARP(op=ARP.who_has, pdst=static_addr,
2882                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2883         self.pg1.add_stream(p)
2884         self.pg_enable_capture(self.pg_interfaces)
2885         self.pg_start()
2886         self.pg1.assert_nothing_captured()
2887
2888     def test_vrf_mode(self):
2889         """ NAT44 tenant VRF aware address pool mode """
2890
2891         vrf_id1 = 1
2892         vrf_id2 = 2
2893         nat_ip1 = "10.0.0.10"
2894         nat_ip2 = "10.0.0.11"
2895
2896         self.pg0.unconfig_ip4()
2897         self.pg1.unconfig_ip4()
2898         self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
2899         self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
2900         self.pg0.set_table_ip4(vrf_id1)
2901         self.pg1.set_table_ip4(vrf_id2)
2902         self.pg0.config_ip4()
2903         self.pg1.config_ip4()
2904         self.pg0.resolve_arp()
2905         self.pg1.resolve_arp()
2906
2907         self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2908         self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2909         flags = self.config_flags.NAT_IS_INSIDE
2910         self.vapi.nat44_interface_add_del_feature(
2911             sw_if_index=self.pg0.sw_if_index,
2912             flags=flags, is_add=1)
2913         self.vapi.nat44_interface_add_del_feature(
2914             sw_if_index=self.pg1.sw_if_index,
2915             flags=flags, is_add=1)
2916         self.vapi.nat44_interface_add_del_feature(
2917             sw_if_index=self.pg2.sw_if_index,
2918             is_add=1)
2919
2920         try:
2921             # first VRF
2922             pkts = self.create_stream_in(self.pg0, self.pg2)
2923             self.pg0.add_stream(pkts)
2924             self.pg_enable_capture(self.pg_interfaces)
2925             self.pg_start()
2926             capture = self.pg2.get_capture(len(pkts))
2927             self.verify_capture_out(capture, nat_ip1)
2928
2929             # second VRF
2930             pkts = self.create_stream_in(self.pg1, self.pg2)
2931             self.pg1.add_stream(pkts)
2932             self.pg_enable_capture(self.pg_interfaces)
2933             self.pg_start()
2934             capture = self.pg2.get_capture(len(pkts))
2935             self.verify_capture_out(capture, nat_ip2)
2936
2937         finally:
2938             self.pg0.unconfig_ip4()
2939             self.pg1.unconfig_ip4()
2940             self.pg0.set_table_ip4(0)
2941             self.pg1.set_table_ip4(0)
2942             self.pg0.config_ip4()
2943             self.pg1.config_ip4()
2944             self.pg0.resolve_arp()
2945             self.pg1.resolve_arp()
2946             self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id1})
2947             self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id2})
2948
2949     def test_vrf_feature_independent(self):
2950         """ NAT44 tenant VRF independent address pool mode """
2951
2952         nat_ip1 = "10.0.0.10"
2953         nat_ip2 = "10.0.0.11"
2954
2955         self.nat44_add_address(nat_ip1)
2956         self.nat44_add_address(nat_ip2, vrf_id=99)
2957         flags = self.config_flags.NAT_IS_INSIDE
2958         self.vapi.nat44_interface_add_del_feature(
2959             sw_if_index=self.pg0.sw_if_index,
2960             flags=flags, is_add=1)
2961         self.vapi.nat44_interface_add_del_feature(
2962             sw_if_index=self.pg1.sw_if_index,
2963             flags=flags, is_add=1)
2964         self.vapi.nat44_interface_add_del_feature(
2965             sw_if_index=self.pg2.sw_if_index,
2966             is_add=1)
2967
2968         # first VRF
2969         pkts = self.create_stream_in(self.pg0, self.pg2)
2970         self.pg0.add_stream(pkts)
2971         self.pg_enable_capture(self.pg_interfaces)
2972         self.pg_start()
2973         capture = self.pg2.get_capture(len(pkts))
2974         self.verify_capture_out(capture, nat_ip1)
2975
2976         # second VRF
2977         pkts = self.create_stream_in(self.pg1, self.pg2)
2978         self.pg1.add_stream(pkts)
2979         self.pg_enable_capture(self.pg_interfaces)
2980         self.pg_start()
2981         capture = self.pg2.get_capture(len(pkts))
2982         self.verify_capture_out(capture, nat_ip1)
2983
2984     def create_routes_and_neigbors(self):
2985         r1 = VppIpRoute(self, self.pg7.remote_ip4, 32,
2986                         [VppRoutePath(self.pg7.remote_ip4,
2987                                       self.pg7.sw_if_index)])
2988         r2 = VppIpRoute(self, self.pg8.remote_ip4, 32,
2989                         [VppRoutePath(self.pg8.remote_ip4,
2990                                       self.pg8.sw_if_index)])
2991         r1.add_vpp_config()
2992         r2.add_vpp_config()
2993
2994         n1 = VppNeighbor(self,
2995                          self.pg7.sw_if_index,
2996                          self.pg7.remote_mac,
2997                          self.pg7.remote_ip4,
2998                          is_static=1)
2999         n2 = VppNeighbor(self,
3000                          self.pg8.sw_if_index,
3001                          self.pg8.remote_mac,
3002                          self.pg8.remote_ip4,
3003                          is_static=1)
3004         n1.add_vpp_config()
3005         n2.add_vpp_config()
3006
3007     def test_dynamic_ipless_interfaces(self):
3008         """ NAT44 interfaces without configured IP address """
3009         self.create_routes_and_neigbors()
3010         self.nat44_add_address(self.nat_addr)
3011         flags = self.config_flags.NAT_IS_INSIDE
3012         self.vapi.nat44_interface_add_del_feature(
3013             sw_if_index=self.pg7.sw_if_index,
3014             flags=flags, is_add=1)
3015         self.vapi.nat44_interface_add_del_feature(
3016             sw_if_index=self.pg8.sw_if_index,
3017             is_add=1)
3018
3019         # in2out
3020         pkts = self.create_stream_in(self.pg7, self.pg8)
3021         self.pg7.add_stream(pkts)
3022         self.pg_enable_capture(self.pg_interfaces)
3023         self.pg_start()
3024         capture = self.pg8.get_capture(len(pkts))
3025         self.verify_capture_out(capture)
3026
3027         # out2in
3028         pkts = self.create_stream_out(self.pg8, self.nat_addr)
3029         self.pg8.add_stream(pkts)
3030         self.pg_enable_capture(self.pg_interfaces)
3031         self.pg_start()
3032         capture = self.pg7.get_capture(len(pkts))
3033         self.verify_capture_in(capture, self.pg7)
3034
3035     def test_static_ipless_interfaces(self):
3036         """ NAT44 interfaces without configured IP address - 1:1 NAT """
3037
3038         self.create_routes_and_neigbors()
3039         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
3040         flags = self.config_flags.NAT_IS_INSIDE
3041         self.vapi.nat44_interface_add_del_feature(
3042             sw_if_index=self.pg7.sw_if_index,
3043             flags=flags, is_add=1)
3044         self.vapi.nat44_interface_add_del_feature(
3045             sw_if_index=self.pg8.sw_if_index,
3046             is_add=1)
3047
3048         # out2in
3049         pkts = self.create_stream_out(self.pg8)
3050         self.pg8.add_stream(pkts)
3051         self.pg_enable_capture(self.pg_interfaces)
3052         self.pg_start()
3053         capture = self.pg7.get_capture(len(pkts))
3054         self.verify_capture_in(capture, self.pg7)
3055
3056         # in2out
3057         pkts = self.create_stream_in(self.pg7, self.pg8)
3058         self.pg7.add_stream(pkts)
3059         self.pg_enable_capture(self.pg_interfaces)
3060         self.pg_start()
3061         capture = self.pg8.get_capture(len(pkts))
3062         self.verify_capture_out(capture, self.nat_addr, True)
3063
3064     def test_static_with_port_ipless_interfaces(self):
3065         """ NAT44 interfaces without configured IP address - 1:1 NAPT """
3066
3067         self.tcp_port_out = 30606
3068         self.udp_port_out = 30607
3069         self.icmp_id_out = 30608
3070
3071         self.create_routes_and_neigbors()
3072         self.nat44_add_address(self.nat_addr)
3073         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3074                                       self.tcp_port_in, self.tcp_port_out,
3075                                       proto=IP_PROTOS.tcp)
3076         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3077                                       self.udp_port_in, self.udp_port_out,
3078                                       proto=IP_PROTOS.udp)
3079         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3080                                       self.icmp_id_in, self.icmp_id_out,
3081                                       proto=IP_PROTOS.icmp)
3082         flags = self.config_flags.NAT_IS_INSIDE
3083         self.vapi.nat44_interface_add_del_feature(
3084             sw_if_index=self.pg7.sw_if_index,
3085             flags=flags, is_add=1)
3086         self.vapi.nat44_interface_add_del_feature(
3087             sw_if_index=self.pg8.sw_if_index,
3088             is_add=1)
3089
3090         # out2in
3091         pkts = self.create_stream_out(self.pg8)
3092         self.pg8.add_stream(pkts)
3093         self.pg_enable_capture(self.pg_interfaces)
3094         self.pg_start()
3095         capture = self.pg7.get_capture(len(pkts))
3096         self.verify_capture_in(capture, self.pg7)
3097
3098         # in2out
3099         pkts = self.create_stream_in(self.pg7, self.pg8)
3100         self.pg7.add_stream(pkts)
3101         self.pg_enable_capture(self.pg_interfaces)
3102         self.pg_start()
3103         capture = self.pg8.get_capture(len(pkts))
3104         self.verify_capture_out(capture)
3105
3106     def test_static_unknown_proto(self):
3107         """ 1:1 NAT translate packet with unknown protocol """
3108         nat_ip = "10.0.0.10"
3109         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
3110         flags = self.config_flags.NAT_IS_INSIDE
3111         self.vapi.nat44_interface_add_del_feature(
3112             sw_if_index=self.pg0.sw_if_index,
3113             flags=flags, is_add=1)
3114         self.vapi.nat44_interface_add_del_feature(
3115             sw_if_index=self.pg1.sw_if_index,
3116             is_add=1)
3117
3118         # in2out
3119         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3120              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3121              GRE() /
3122              IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3123              TCP(sport=1234, dport=1234))
3124         self.pg0.add_stream(p)
3125         self.pg_enable_capture(self.pg_interfaces)
3126         self.pg_start()
3127         p = self.pg1.get_capture(1)
3128         packet = p[0]
3129         try:
3130             self.assertEqual(packet[IP].src, nat_ip)
3131             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3132             self.assertEqual(packet.haslayer(GRE), 1)
3133             self.assert_packet_checksums_valid(packet)
3134         except:
3135             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3136             raise
3137
3138         # out2in
3139         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3140              IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3141              GRE() /
3142              IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3143              TCP(sport=1234, dport=1234))
3144         self.pg1.add_stream(p)
3145         self.pg_enable_capture(self.pg_interfaces)
3146         self.pg_start()
3147         p = self.pg0.get_capture(1)
3148         packet = p[0]
3149         try:
3150             self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3151             self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3152             self.assertEqual(packet.haslayer(GRE), 1)
3153             self.assert_packet_checksums_valid(packet)
3154         except:
3155             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3156             raise
3157
3158     def test_hairpinning_static_unknown_proto(self):
3159         """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3160
3161         host = self.pg0.remote_hosts[0]
3162         server = self.pg0.remote_hosts[1]
3163
3164         host_nat_ip = "10.0.0.10"
3165         server_nat_ip = "10.0.0.11"
3166
3167         self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3168         self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3169         flags = self.config_flags.NAT_IS_INSIDE
3170         self.vapi.nat44_interface_add_del_feature(
3171             sw_if_index=self.pg0.sw_if_index,
3172             flags=flags, is_add=1)
3173         self.vapi.nat44_interface_add_del_feature(
3174             sw_if_index=self.pg1.sw_if_index,
3175             is_add=1)
3176
3177         # host to server
3178         p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3179              IP(src=host.ip4, dst=server_nat_ip) /
3180              GRE() /
3181              IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3182              TCP(sport=1234, dport=1234))
3183         self.pg0.add_stream(p)
3184         self.pg_enable_capture(self.pg_interfaces)
3185         self.pg_start()
3186         p = self.pg0.get_capture(1)
3187         packet = p[0]
3188         try:
3189             self.assertEqual(packet[IP].src, host_nat_ip)
3190             self.assertEqual(packet[IP].dst, server.ip4)
3191             self.assertEqual(packet.haslayer(GRE), 1)
3192             self.assert_packet_checksums_valid(packet)
3193         except:
3194             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3195             raise
3196
3197         # server to host
3198         p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3199              IP(src=server.ip4, dst=host_nat_ip) /
3200              GRE() /
3201              IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3202              TCP(sport=1234, dport=1234))
3203         self.pg0.add_stream(p)
3204         self.pg_enable_capture(self.pg_interfaces)
3205         self.pg_start()
3206         p = self.pg0.get_capture(1)
3207         packet = p[0]
3208         try:
3209             self.assertEqual(packet[IP].src, server_nat_ip)
3210             self.assertEqual(packet[IP].dst, host.ip4)
3211             self.assertEqual(packet.haslayer(GRE), 1)
3212             self.assert_packet_checksums_valid(packet)
3213         except:
3214             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3215             raise
3216
3217     def test_output_feature(self):
3218         """ NAT44 interface output feature (in2out postrouting) """
3219         self.nat44_add_address(self.nat_addr)
3220         flags = self.config_flags.NAT_IS_INSIDE
3221         self.vapi.nat44_interface_add_del_output_feature(
3222             is_add=1, flags=flags,
3223             sw_if_index=self.pg0.sw_if_index)
3224         self.vapi.nat44_interface_add_del_output_feature(
3225             is_add=1, flags=flags,
3226             sw_if_index=self.pg1.sw_if_index)
3227         self.vapi.nat44_interface_add_del_output_feature(
3228             is_add=1,
3229             sw_if_index=self.pg3.sw_if_index)
3230
3231         # in2out
3232         pkts = self.create_stream_in(self.pg0, self.pg3)
3233         self.pg0.add_stream(pkts)
3234         self.pg_enable_capture(self.pg_interfaces)
3235         self.pg_start()
3236         capture = self.pg3.get_capture(len(pkts))
3237         self.verify_capture_out(capture)
3238
3239         # out2in
3240         pkts = self.create_stream_out(self.pg3)
3241         self.pg3.add_stream(pkts)
3242         self.pg_enable_capture(self.pg_interfaces)
3243         self.pg_start()
3244         capture = self.pg0.get_capture(len(pkts))
3245         self.verify_capture_in(capture, self.pg0)
3246
3247         # from non-NAT interface to NAT inside interface
3248         pkts = self.create_stream_in(self.pg2, self.pg0)
3249         self.pg2.add_stream(pkts)
3250         self.pg_enable_capture(self.pg_interfaces)
3251         self.pg_start()
3252         capture = self.pg0.get_capture(len(pkts))
3253         self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3254
3255     def test_output_feature_vrf_aware(self):
3256         """ NAT44 interface output feature VRF aware (in2out postrouting) """
3257         nat_ip_vrf10 = "10.0.0.10"
3258         nat_ip_vrf20 = "10.0.0.20"
3259
3260         r1 = VppIpRoute(self, self.pg3.remote_ip4, 32,
3261                         [VppRoutePath(self.pg3.remote_ip4,
3262                                       self.pg3.sw_if_index)],
3263                         table_id=10)
3264         r2 = VppIpRoute(self, self.pg3.remote_ip4, 32,
3265                         [VppRoutePath(self.pg3.remote_ip4,
3266                                       self.pg3.sw_if_index)],
3267                         table_id=20)
3268         r1.add_vpp_config()
3269         r2.add_vpp_config()
3270
3271         self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3272         self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3273         flags = self.config_flags.NAT_IS_INSIDE
3274         self.vapi.nat44_interface_add_del_output_feature(
3275             is_add=1, flags=flags,
3276             sw_if_index=self.pg4.sw_if_index)
3277         self.vapi.nat44_interface_add_del_output_feature(
3278             is_add=1, flags=flags,
3279             sw_if_index=self.pg6.sw_if_index)
3280         self.vapi.nat44_interface_add_del_output_feature(
3281             is_add=1,
3282             sw_if_index=self.pg3.sw_if_index)
3283
3284         # in2out VRF 10
3285         pkts = self.create_stream_in(self.pg4, self.pg3)
3286         self.pg4.add_stream(pkts)
3287         self.pg_enable_capture(self.pg_interfaces)
3288         self.pg_start()
3289         capture = self.pg3.get_capture(len(pkts))
3290         self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3291
3292         # out2in VRF 10
3293         pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3294         self.pg3.add_stream(pkts)
3295         self.pg_enable_capture(self.pg_interfaces)
3296         self.pg_start()
3297         capture = self.pg4.get_capture(len(pkts))
3298         self.verify_capture_in(capture, self.pg4)
3299
3300         # in2out VRF 20
3301         pkts = self.create_stream_in(self.pg6, self.pg3)
3302         self.pg6.add_stream(pkts)
3303         self.pg_enable_capture(self.pg_interfaces)
3304         self.pg_start()
3305         capture = self.pg3.get_capture(len(pkts))
3306         self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3307
3308         # out2in VRF 20
3309         pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3310         self.pg3.add_stream(pkts)
3311         self.pg_enable_capture(self.pg_interfaces)
3312         self.pg_start()
3313         capture = self.pg6.get_capture(len(pkts))
3314         self.verify_capture_in(capture, self.pg6)
3315
3316     def test_output_feature_hairpinning(self):
3317         """ NAT44 interface output feature hairpinning (in2out postrouting) """
3318         host = self.pg0.remote_hosts[0]
3319         server = self.pg0.remote_hosts[1]
3320         host_in_port = 1234
3321         host_out_port = 0
3322         server_in_port = 5678
3323         server_out_port = 8765
3324
3325         self.nat44_add_address(self.nat_addr)
3326         flags = self.config_flags.NAT_IS_INSIDE
3327         self.vapi.nat44_interface_add_del_output_feature(
3328             is_add=1, flags=flags,
3329             sw_if_index=self.pg0.sw_if_index)
3330         self.vapi.nat44_interface_add_del_output_feature(
3331             is_add=1,
3332             sw_if_index=self.pg1.sw_if_index)
3333
3334         # add static mapping for server
3335         self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3336                                       server_in_port, server_out_port,
3337                                       proto=IP_PROTOS.tcp)
3338
3339         # send packet from host to server
3340         p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3341              IP(src=host.ip4, dst=self.nat_addr) /
3342              TCP(sport=host_in_port, dport=server_out_port))
3343         self.pg0.add_stream(p)
3344         self.pg_enable_capture(self.pg_interfaces)
3345         self.pg_start()
3346         capture = self.pg0.get_capture(1)
3347         p = capture[0]
3348         try:
3349             ip = p[IP]
3350             tcp = p[TCP]
3351             self.assertEqual(ip.src, self.nat_addr)
3352             self.assertEqual(ip.dst, server.ip4)
3353             self.assertNotEqual(tcp.sport, host_in_port)
3354             self.assertEqual(tcp.dport, server_in_port)
3355             self.assert_packet_checksums_valid(p)
3356             host_out_port = tcp.sport
3357         except:
3358             self.logger.error(ppp("Unexpected or invalid packet:", p))
3359             raise
3360
3361         # send reply from server to host
3362         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3363              IP(src=server.ip4, dst=self.nat_addr) /
3364              TCP(sport=server_in_port, dport=host_out_port))
3365         self.pg0.add_stream(p)
3366         self.pg_enable_capture(self.pg_interfaces)
3367         self.pg_start()
3368         capture = self.pg0.get_capture(1)
3369         p = capture[0]
3370         try:
3371             ip = p[IP]
3372             tcp = p[TCP]
3373             self.assertEqual(ip.src, self.nat_addr)
3374             self.assertEqual(ip.dst, host.ip4)
3375             self.assertEqual(tcp.sport, server_out_port)
3376             self.assertEqual(tcp.dport, host_in_port)
3377             self.assert_packet_checksums_valid(p)
3378         except:
3379             self.logger.error(ppp("Unexpected or invalid packet:", p))
3380             raise
3381
3382     def test_one_armed_nat44(self):
3383         """ One armed NAT44 """
3384         remote_host = self.pg9.remote_hosts[0]
3385         local_host = self.pg9.remote_hosts[1]
3386         external_port = 0
3387
3388         self.nat44_add_address(self.nat_addr)
3389         flags = self.config_flags.NAT_IS_INSIDE
3390         self.vapi.nat44_interface_add_del_feature(
3391             sw_if_index=self.pg9.sw_if_index,
3392             is_add=1)
3393         self.vapi.nat44_interface_add_del_feature(
3394             sw_if_index=self.pg9.sw_if_index,
3395             flags=flags, is_add=1)
3396
3397         # in2out
3398         p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3399              IP(src=local_host.ip4, dst=remote_host.ip4) /
3400              TCP(sport=12345, dport=80))
3401         self.pg9.add_stream(p)
3402         self.pg_enable_capture(self.pg_interfaces)
3403         self.pg_start()
3404         capture = self.pg9.get_capture(1)
3405         p = capture[0]
3406         try:
3407             ip = p[IP]
3408             tcp = p[TCP]
3409             self.assertEqual(ip.src, self.nat_addr)
3410             self.assertEqual(ip.dst, remote_host.ip4)
3411             self.assertNotEqual(tcp.sport, 12345)
3412             external_port = tcp.sport
3413             self.assertEqual(tcp.dport, 80)
3414             self.assert_packet_checksums_valid(p)
3415         except:
3416             self.logger.error(ppp("Unexpected or invalid packet:", p))
3417             raise
3418
3419         # out2in
3420         p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3421              IP(src=remote_host.ip4, dst=self.nat_addr) /
3422              TCP(sport=80, dport=external_port))
3423         self.pg9.add_stream(p)
3424         self.pg_enable_capture(self.pg_interfaces)
3425         self.pg_start()
3426         capture = self.pg9.get_capture(1)
3427         p = capture[0]
3428         try:
3429             ip = p[IP]
3430             tcp = p[TCP]
3431             self.assertEqual(ip.src, remote_host.ip4)
3432             self.assertEqual(ip.dst, local_host.ip4)
3433             self.assertEqual(tcp.sport, 80)
3434             self.assertEqual(tcp.dport, 12345)
3435             self.assert_packet_checksums_valid(p)
3436         except:
3437             self.logger.error(ppp("Unexpected or invalid packet:", p))
3438             raise
3439
3440         err = self.statistics.get_err_counter(
3441             '/err/nat44-classify/next in2out')
3442         self.assertEqual(err, 1)
3443         err = self.statistics.get_err_counter(
3444             '/err/nat44-classify/next out2in')
3445         self.assertEqual(err, 1)
3446
3447     def test_del_session(self):
3448         """ Delete NAT44 session """
3449         self.nat44_add_address(self.nat_addr)
3450         flags = self.config_flags.NAT_IS_INSIDE
3451         self.vapi.nat44_interface_add_del_feature(
3452             sw_if_index=self.pg0.sw_if_index,
3453             flags=flags, is_add=1)
3454         self.vapi.nat44_interface_add_del_feature(
3455             sw_if_index=self.pg1.sw_if_index,
3456             is_add=1)
3457
3458         pkts = self.create_stream_in(self.pg0, self.pg1)
3459         self.pg0.add_stream(pkts)
3460         self.pg_enable_capture(self.pg_interfaces)
3461         self.pg_start()
3462         self.pg1.get_capture(len(pkts))
3463
3464         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3465         nsessions = len(sessions)
3466
3467         self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3468                                     port=sessions[0].inside_port,
3469                                     protocol=sessions[0].protocol,
3470                                     flags=self.config_flags.NAT_IS_INSIDE)
3471         self.vapi.nat44_del_session(address=sessions[1].outside_ip_address,
3472                                     port=sessions[1].outside_port,
3473                                     protocol=sessions[1].protocol)
3474
3475         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3476         self.assertEqual(nsessions - len(sessions), 2)
3477
3478         self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3479                                     port=sessions[0].inside_port,
3480                                     protocol=sessions[0].protocol,
3481                                     flags=self.config_flags.NAT_IS_INSIDE)
3482
3483         self.verify_no_nat44_user()
3484
3485     def test_frag_in_order(self):
3486         """ NAT44 translate fragments arriving in order """
3487
3488         self.nat44_add_address(self.nat_addr)
3489         flags = self.config_flags.NAT_IS_INSIDE
3490         self.vapi.nat44_interface_add_del_feature(
3491             sw_if_index=self.pg0.sw_if_index,
3492             flags=flags, is_add=1)
3493         self.vapi.nat44_interface_add_del_feature(
3494             sw_if_index=self.pg1.sw_if_index,
3495             is_add=1)
3496
3497         self.frag_in_order(proto=IP_PROTOS.tcp)
3498         self.frag_in_order(proto=IP_PROTOS.udp)
3499         self.frag_in_order(proto=IP_PROTOS.icmp)
3500
3501     def test_frag_forwarding(self):
3502         """ NAT44 forwarding fragment test """
3503         self.vapi.nat44_add_del_interface_addr(
3504             is_add=1,
3505             sw_if_index=self.pg1.sw_if_index)
3506         flags = self.config_flags.NAT_IS_INSIDE
3507         self.vapi.nat44_interface_add_del_feature(
3508             sw_if_index=self.pg0.sw_if_index,
3509             flags=flags, is_add=1)
3510         self.vapi.nat44_interface_add_del_feature(
3511             sw_if_index=self.pg1.sw_if_index,
3512             is_add=1)
3513         self.vapi.nat44_forwarding_enable_disable(enable=1)
3514
3515         data = b"A" * 16 + b"B" * 16 + b"C" * 3
3516         pkts = self.create_stream_frag(self.pg1,
3517                                        self.pg0.remote_ip4,
3518                                        4789,
3519                                        4789,
3520                                        data,
3521                                        proto=IP_PROTOS.udp)
3522         self.pg1.add_stream(pkts)
3523         self.pg_enable_capture(self.pg_interfaces)
3524         self.pg_start()
3525         frags = self.pg0.get_capture(len(pkts))
3526         p = self.reass_frags_and_verify(frags,
3527                                         self.pg1.remote_ip4,
3528                                         self.pg0.remote_ip4)
3529         self.assertEqual(p[UDP].sport, 4789)
3530         self.assertEqual(p[UDP].dport, 4789)
3531         self.assertEqual(data, p[Raw].load)
3532
3533     def test_reass_hairpinning(self):
3534         """ NAT44 fragments hairpinning """
3535
3536         self.server = self.pg0.remote_hosts[1]
3537         self.host_in_port = random.randint(1025, 65535)
3538         self.server_in_port = random.randint(1025, 65535)
3539         self.server_out_port = random.randint(1025, 65535)
3540
3541         self.nat44_add_address(self.nat_addr)
3542         flags = self.config_flags.NAT_IS_INSIDE
3543         self.vapi.nat44_interface_add_del_feature(
3544             sw_if_index=self.pg0.sw_if_index,
3545             flags=flags, is_add=1)
3546         self.vapi.nat44_interface_add_del_feature(
3547             sw_if_index=self.pg1.sw_if_index,
3548             is_add=1)
3549         # add static mapping for server
3550         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3551                                       self.server_in_port,
3552                                       self.server_out_port,
3553                                       proto=IP_PROTOS.tcp)
3554         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3555                                       self.server_in_port,
3556                                       self.server_out_port,
3557                                       proto=IP_PROTOS.udp)
3558         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
3559
3560         self.reass_hairpinning(proto=IP_PROTOS.tcp)
3561         self.reass_hairpinning(proto=IP_PROTOS.udp)
3562         self.reass_hairpinning(proto=IP_PROTOS.icmp)
3563
3564     def test_frag_out_of_order(self):
3565         """ NAT44 translate fragments arriving out of order """
3566
3567         self.nat44_add_address(self.nat_addr)
3568         flags = self.config_flags.NAT_IS_INSIDE
3569         self.vapi.nat44_interface_add_del_feature(
3570             sw_if_index=self.pg0.sw_if_index,
3571             flags=flags, is_add=1)
3572         self.vapi.nat44_interface_add_del_feature(
3573             sw_if_index=self.pg1.sw_if_index,
3574             is_add=1)
3575
3576         self.frag_out_of_order(proto=IP_PROTOS.tcp)
3577         self.frag_out_of_order(proto=IP_PROTOS.udp)
3578         self.frag_out_of_order(proto=IP_PROTOS.icmp)
3579
3580     def test_port_restricted(self):
3581         """ Port restricted NAT44 (MAP-E CE) """
3582         self.nat44_add_address(self.nat_addr)
3583         flags = self.config_flags.NAT_IS_INSIDE
3584         self.vapi.nat44_interface_add_del_feature(
3585             sw_if_index=self.pg0.sw_if_index,
3586             flags=flags, is_add=1)
3587         self.vapi.nat44_interface_add_del_feature(
3588             sw_if_index=self.pg1.sw_if_index,
3589             is_add=1)
3590         self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3591                                                   psid_offset=6,
3592                                                   psid_length=6,
3593                                                   psid=10)
3594
3595         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3596              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3597              TCP(sport=4567, dport=22))
3598         self.pg0.add_stream(p)
3599         self.pg_enable_capture(self.pg_interfaces)
3600         self.pg_start()
3601         capture = self.pg1.get_capture(1)
3602         p = capture[0]
3603         try:
3604             ip = p[IP]
3605             tcp = p[TCP]
3606             self.assertEqual(ip.dst, self.pg1.remote_ip4)
3607             self.assertEqual(ip.src, self.nat_addr)
3608             self.assertEqual(tcp.dport, 22)
3609             self.assertNotEqual(tcp.sport, 4567)
3610             self.assertEqual((tcp.sport >> 6) & 63, 10)
3611             self.assert_packet_checksums_valid(p)
3612         except:
3613             self.logger.error(ppp("Unexpected or invalid packet:", p))
3614             raise
3615
3616     def test_port_range(self):
3617         """ External address port range """
3618         self.nat44_add_address(self.nat_addr)
3619         flags = self.config_flags.NAT_IS_INSIDE
3620         self.vapi.nat44_interface_add_del_feature(
3621             sw_if_index=self.pg0.sw_if_index,
3622             flags=flags, is_add=1)
3623         self.vapi.nat44_interface_add_del_feature(
3624             sw_if_index=self.pg1.sw_if_index,
3625             is_add=1)
3626         self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3627                                                   start_port=1025,
3628                                                   end_port=1027)
3629
3630         pkts = []
3631         for port in range(0, 5):
3632             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3633                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3634                  TCP(sport=1125 + port))
3635             pkts.append(p)
3636         self.pg0.add_stream(pkts)
3637         self.pg_enable_capture(self.pg_interfaces)
3638         self.pg_start()
3639         capture = self.pg1.get_capture(3)
3640         for p in capture:
3641             tcp = p[TCP]
3642             self.assertGreaterEqual(tcp.sport, 1025)
3643             self.assertLessEqual(tcp.sport, 1027)
3644
3645     def test_multiple_outside_vrf(self):
3646         """ Multiple outside VRF """
3647         vrf_id1 = 1
3648         vrf_id2 = 2
3649
3650         self.pg1.unconfig_ip4()
3651         self.pg2.unconfig_ip4()
3652         self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
3653         self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
3654         self.pg1.set_table_ip4(vrf_id1)
3655         self.pg2.set_table_ip4(vrf_id2)
3656         self.pg1.config_ip4()
3657         self.pg2.config_ip4()
3658         self.pg1.resolve_arp()
3659         self.pg2.resolve_arp()
3660
3661         self.nat44_add_address(self.nat_addr)
3662         flags = self.config_flags.NAT_IS_INSIDE
3663         self.vapi.nat44_interface_add_del_feature(
3664             sw_if_index=self.pg0.sw_if_index,
3665             flags=flags, is_add=1)
3666         self.vapi.nat44_interface_add_del_feature(
3667             sw_if_index=self.pg1.sw_if_index,
3668             is_add=1)
3669         self.vapi.nat44_interface_add_del_feature(
3670             sw_if_index=self.pg2.sw_if_index,
3671             is_add=1)
3672
3673         try:
3674             # first VRF
3675             pkts = self.create_stream_in(self.pg0, self.pg1)
3676             self.pg0.add_stream(pkts)
3677             self.pg_enable_capture(self.pg_interfaces)
3678             self.pg_start()
3679             capture = self.pg1.get_capture(len(pkts))
3680             self.verify_capture_out(capture, self.nat_addr)
3681
3682             pkts = self.create_stream_out(self.pg1, self.nat_addr)
3683             self.pg1.add_stream(pkts)
3684             self.pg_enable_capture(self.pg_interfaces)
3685             self.pg_start()
3686             capture = self.pg0.get_capture(len(pkts))
3687             self.verify_capture_in(capture, self.pg0)
3688
3689             self.tcp_port_in = 60303
3690             self.udp_port_in = 60304
3691             self.icmp_id_in = 60305
3692
3693             # second VRF
3694             pkts = self.create_stream_in(self.pg0, self.pg2)
3695             self.pg0.add_stream(pkts)
3696             self.pg_enable_capture(self.pg_interfaces)
3697             self.pg_start()
3698             capture = self.pg2.get_capture(len(pkts))
3699             self.verify_capture_out(capture, self.nat_addr)
3700
3701             pkts = self.create_stream_out(self.pg2, self.nat_addr)
3702             self.pg2.add_stream(pkts)
3703             self.pg_enable_capture(self.pg_interfaces)
3704             self.pg_start()
3705             capture = self.pg0.get_capture(len(pkts))
3706             self.verify_capture_in(capture, self.pg0)
3707
3708         finally:
3709             self.nat44_add_address(self.nat_addr, is_add=0)
3710             self.pg1.unconfig_ip4()
3711             self.pg2.unconfig_ip4()
3712             self.pg1.set_table_ip4(0)
3713             self.pg2.set_table_ip4(0)
3714             self.pg1.config_ip4()
3715             self.pg2.config_ip4()
3716             self.pg1.resolve_arp()
3717             self.pg2.resolve_arp()
3718
3719     @unittest.skipUnless(running_extended_tests, "part of extended tests")
3720     def test_session_timeout(self):
3721         """ NAT44 session timeouts """
3722         self.nat44_add_address(self.nat_addr)
3723         flags = self.config_flags.NAT_IS_INSIDE
3724         self.vapi.nat44_interface_add_del_feature(
3725             sw_if_index=self.pg0.sw_if_index,
3726             flags=flags, is_add=1)
3727         self.vapi.nat44_interface_add_del_feature(
3728             sw_if_index=self.pg1.sw_if_index,
3729             is_add=1)
3730         self.vapi.nat_set_timeouts(udp=5, tcp_established=7440,
3731                                    tcp_transitory=240, icmp=60)
3732
3733         max_sessions = 1000
3734         pkts = []
3735         for i in range(0, max_sessions):
3736             src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3737             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3738                  IP(src=src, dst=self.pg1.remote_ip4) /
3739                  UDP(sport=1025, dport=53))
3740             pkts.append(p)
3741         self.pg0.add_stream(pkts)
3742         self.pg_enable_capture(self.pg_interfaces)
3743         self.pg_start()
3744         self.pg1.get_capture(max_sessions)
3745
3746         sleep(6)
3747
3748         pkts = []
3749         for i in range(0, max_sessions):
3750             src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3751             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3752                  IP(src=src, dst=self.pg1.remote_ip4) /
3753                  UDP(sport=1026, dport=53))
3754             pkts.append(p)
3755         self.pg0.add_stream(pkts)
3756         self.pg_enable_capture(self.pg_interfaces)
3757         self.pg_start()
3758         self.pg1.get_capture(max_sessions)
3759
3760         nsessions = 0
3761         users = self.vapi.nat44_user_dump()
3762         for user in users:
3763             nsessions = nsessions + user.nsessions
3764         self.assertLess(nsessions, 2 * max_sessions)
3765
3766     def test_mss_clamping(self):
3767         """ TCP MSS clamping """
3768         self.nat44_add_address(self.nat_addr)
3769         flags = self.config_flags.NAT_IS_INSIDE
3770         self.vapi.nat44_interface_add_del_feature(
3771             sw_if_index=self.pg0.sw_if_index,
3772             flags=flags, is_add=1)
3773         self.vapi.nat44_interface_add_del_feature(
3774             sw_if_index=self.pg1.sw_if_index,
3775             is_add=1)
3776
3777         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3778              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3779              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3780                  flags="S", options=[('MSS', 1400)]))
3781
3782         self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3783         self.pg0.add_stream(p)
3784         self.pg_enable_capture(self.pg_interfaces)
3785         self.pg_start()
3786         capture = self.pg1.get_capture(1)
3787         # Negotiated MSS value greater than configured - changed
3788         self.verify_mss_value(capture[0], 1000)
3789
3790         self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
3791         self.pg0.add_stream(p)
3792         self.pg_enable_capture(self.pg_interfaces)
3793         self.pg_start()
3794         capture = self.pg1.get_capture(1)
3795         # MSS clamping disabled - negotiated MSS unchanged
3796         self.verify_mss_value(capture[0], 1400)
3797
3798         self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3799         self.pg0.add_stream(p)
3800         self.pg_enable_capture(self.pg_interfaces)
3801         self.pg_start()
3802         capture = self.pg1.get_capture(1)
3803         # Negotiated MSS value smaller than configured - unchanged
3804         self.verify_mss_value(capture[0], 1400)
3805
3806     @unittest.skipUnless(running_extended_tests, "part of extended tests")
3807     def test_ha_send(self):
3808         """ Send HA session synchronization events (active) """
3809         self.nat44_add_address(self.nat_addr)
3810         flags = self.config_flags.NAT_IS_INSIDE
3811         self.vapi.nat44_interface_add_del_feature(
3812             sw_if_index=self.pg0.sw_if_index,
3813             flags=flags, is_add=1)
3814         self.vapi.nat44_interface_add_del_feature(
3815             sw_if_index=self.pg1.sw_if_index,
3816             is_add=1)
3817         self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
3818                                       port=12345,
3819                                       path_mtu=512)
3820         self.vapi.nat_ha_set_failover(ip_address=self.pg3.remote_ip4,
3821                                       port=12346, session_refresh_interval=10)
3822         bind_layers(UDP, HANATStateSync, sport=12345)
3823
3824         # create sessions
3825         pkts = self.create_stream_in(self.pg0, self.pg1)
3826         self.pg0.add_stream(pkts)
3827         self.pg_enable_capture(self.pg_interfaces)
3828         self.pg_start()
3829         capture = self.pg1.get_capture(len(pkts))
3830         self.verify_capture_out(capture)
3831         # active send HA events
3832         self.vapi.nat_ha_flush()
3833         stats = self.statistics.get_counter('/nat44/ha/add-event-send')
3834         self.assertEqual(stats[0][0], 3)
3835         capture = self.pg3.get_capture(1)
3836         p = capture[0]
3837         self.assert_packet_checksums_valid(p)
3838         try:
3839             ip = p[IP]
3840             udp = p[UDP]
3841             hanat = p[HANATStateSync]
3842         except IndexError:
3843             self.logger.error(ppp("Invalid packet:", p))
3844             raise
3845         else:
3846             self.assertEqual(ip.src, self.pg3.local_ip4)
3847             self.assertEqual(ip.dst, self.pg3.remote_ip4)
3848             self.assertEqual(udp.sport, 12345)
3849             self.assertEqual(udp.dport, 12346)
3850             self.assertEqual(hanat.version, 1)
3851             self.assertEqual(hanat.thread_index, 0)
3852             self.assertEqual(hanat.count, 3)
3853             seq = hanat.sequence_number
3854             for event in hanat.events:
3855                 self.assertEqual(event.event_type, 1)
3856                 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
3857                 self.assertEqual(event.out_addr, self.nat_addr)
3858                 self.assertEqual(event.fib_index, 0)
3859
3860         # ACK received events
3861         ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3862                IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3863                UDP(sport=12346, dport=12345) /
3864                HANATStateSync(sequence_number=seq, flags='ACK'))
3865         self.pg3.add_stream(ack)
3866         self.pg_start()
3867         stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3868         self.assertEqual(stats[0][0], 1)
3869
3870         # delete one session
3871         self.pg_enable_capture(self.pg_interfaces)
3872         self.vapi.nat44_del_session(address=self.pg0.remote_ip4,
3873                                     port=self.tcp_port_in,
3874                                     protocol=IP_PROTOS.tcp,
3875                                     flags=self.config_flags.NAT_IS_INSIDE)
3876         self.vapi.nat_ha_flush()
3877         stats = self.statistics.get_counter('/nat44/ha/del-event-send')
3878         self.assertEqual(stats[0][0], 1)
3879         capture = self.pg3.get_capture(1)
3880         p = capture[0]
3881         try:
3882             hanat = p[HANATStateSync]
3883         except IndexError:
3884             self.logger.error(ppp("Invalid packet:", p))
3885             raise
3886         else:
3887             self.assertGreater(hanat.sequence_number, seq)
3888
3889         # do not send ACK, active retry send HA event again
3890         self.pg_enable_capture(self.pg_interfaces)
3891         sleep(12)
3892         stats = self.statistics.get_counter('/nat44/ha/retry-count')
3893         self.assertEqual(stats[0][0], 3)
3894         stats = self.statistics.get_counter('/nat44/ha/missed-count')
3895         self.assertEqual(stats[0][0], 1)
3896         capture = self.pg3.get_capture(3)
3897         for packet in capture:
3898             self.assertEqual(packet, p)
3899
3900         # session counters refresh
3901         pkts = self.create_stream_out(self.pg1)
3902         self.pg1.add_stream(pkts)
3903         self.pg_enable_capture(self.pg_interfaces)
3904         self.pg_start()
3905         self.pg0.get_capture(2)
3906         self.vapi.nat_ha_flush()
3907         stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
3908         self.assertEqual(stats[0][0], 2)
3909         capture = self.pg3.get_capture(1)
3910         p = capture[0]
3911         self.assert_packet_checksums_valid(p)
3912         try:
3913             ip = p[IP]
3914             udp = p[UDP]
3915             hanat = p[HANATStateSync]
3916         except IndexError:
3917             self.logger.error(ppp("Invalid packet:", p))
3918             raise
3919         else:
3920             self.assertEqual(ip.src, self.pg3.local_ip4)
3921             self.assertEqual(ip.dst, self.pg3.remote_ip4)
3922             self.assertEqual(udp.sport, 12345)
3923             self.assertEqual(udp.dport, 12346)
3924             self.assertEqual(hanat.version, 1)
3925             self.assertEqual(hanat.count, 2)
3926             seq = hanat.sequence_number
3927             for event in hanat.events:
3928                 self.assertEqual(event.event_type, 3)
3929                 self.assertEqual(event.out_addr, self.nat_addr)
3930                 self.assertEqual(event.fib_index, 0)
3931                 self.assertEqual(event.total_pkts, 2)
3932                 self.assertGreater(event.total_bytes, 0)
3933
3934         ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3935                IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3936                UDP(sport=12346, dport=12345) /
3937                HANATStateSync(sequence_number=seq, flags='ACK'))
3938         self.pg3.add_stream(ack)
3939         self.pg_start()
3940         stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3941         self.assertEqual(stats[0][0], 2)
3942
3943     def test_ha_recv(self):
3944         """ Receive HA session synchronization events (passive) """
3945         self.nat44_add_address(self.nat_addr)
3946         flags = self.config_flags.NAT_IS_INSIDE
3947         self.vapi.nat44_interface_add_del_feature(
3948             sw_if_index=self.pg0.sw_if_index,
3949             flags=flags, is_add=1)
3950         self.vapi.nat44_interface_add_del_feature(
3951             sw_if_index=self.pg1.sw_if_index,
3952             is_add=1)
3953         self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
3954                                       port=12345,
3955                                       path_mtu=512)
3956         bind_layers(UDP, HANATStateSync, sport=12345)
3957
3958         self.tcp_port_out = random.randint(1025, 65535)
3959         self.udp_port_out = random.randint(1025, 65535)
3960
3961         # send HA session add events to failover/passive
3962         p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3963              IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3964              UDP(sport=12346, dport=12345) /
3965              HANATStateSync(sequence_number=1, events=[
3966                  Event(event_type='add', protocol='tcp',
3967                        in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3968                        in_port=self.tcp_port_in, out_port=self.tcp_port_out,
3969                        eh_addr=self.pg1.remote_ip4,
3970                        ehn_addr=self.pg1.remote_ip4,
3971                        eh_port=self.tcp_external_port,
3972                        ehn_port=self.tcp_external_port, fib_index=0),
3973                  Event(event_type='add', protocol='udp',
3974                        in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3975                        in_port=self.udp_port_in, out_port=self.udp_port_out,
3976                        eh_addr=self.pg1.remote_ip4,
3977                        ehn_addr=self.pg1.remote_ip4,
3978                        eh_port=self.udp_external_port,
3979                        ehn_port=self.udp_external_port, fib_index=0)]))
3980
3981         self.pg3.add_stream(p)
3982         self.pg_enable_capture(self.pg_interfaces)
3983         self.pg_start()
3984         # receive ACK
3985         capture = self.pg3.get_capture(1)
3986         p = capture[0]
3987         try:
3988             hanat = p[HANATStateSync]
3989         except IndexError:
3990             self.logger.error(ppp("Invalid packet:", p))
3991             raise
3992         else:
3993             self.assertEqual(hanat.sequence_number, 1)
3994             self.assertEqual(hanat.flags, 'ACK')
3995             self.assertEqual(hanat.version, 1)
3996             self.assertEqual(hanat.thread_index, 0)
3997         stats = self.statistics.get_counter('/nat44/ha/ack-send')
3998         self.assertEqual(stats[0][0], 1)
3999         stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
4000         self.assertEqual(stats[0][0], 2)
4001         users = self.statistics.get_counter('/nat44/total-users')
4002         self.assertEqual(users[0][0], 1)
4003         sessions = self.statistics.get_counter('/nat44/total-sessions')
4004         self.assertEqual(sessions[0][0], 2)
4005         users = self.vapi.nat44_user_dump()
4006         self.assertEqual(len(users), 1)
4007         self.assertEqual(str(users[0].ip_address),
4008                          self.pg0.remote_ip4)
4009         # there should be 2 sessions created by HA
4010         sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4011                                                      users[0].vrf_id)
4012         self.assertEqual(len(sessions), 2)
4013         for session in sessions:
4014             self.assertEqual(str(session.inside_ip_address),
4015                              self.pg0.remote_ip4)
4016             self.assertEqual(str(session.outside_ip_address),
4017                              self.nat_addr)
4018             self.assertIn(session.inside_port,
4019                           [self.tcp_port_in, self.udp_port_in])
4020             self.assertIn(session.outside_port,
4021                           [self.tcp_port_out, self.udp_port_out])
4022             self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
4023
4024         # send HA session delete event to failover/passive
4025         p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4026              IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4027              UDP(sport=12346, dport=12345) /
4028              HANATStateSync(sequence_number=2, events=[
4029                  Event(event_type='del', protocol='udp',
4030                        in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4031                        in_port=self.udp_port_in, out_port=self.udp_port_out,
4032                        eh_addr=self.pg1.remote_ip4,
4033                        ehn_addr=self.pg1.remote_ip4,
4034                        eh_port=self.udp_external_port,
4035                        ehn_port=self.udp_external_port, fib_index=0)]))
4036
4037         self.pg3.add_stream(p)
4038         self.pg_enable_capture(self.pg_interfaces)
4039         self.pg_start()
4040         # receive ACK
4041         capture = self.pg3.get_capture(1)
4042         p = capture[0]
4043         try:
4044             hanat = p[HANATStateSync]
4045         except IndexError:
4046             self.logger.error(ppp("Invalid packet:", p))
4047             raise
4048         else:
4049             self.assertEqual(hanat.sequence_number, 2)
4050             self.assertEqual(hanat.flags, 'ACK')
4051             self.assertEqual(hanat.version, 1)
4052         users = self.vapi.nat44_user_dump()
4053         self.assertEqual(len(users), 1)
4054         self.assertEqual(str(users[0].ip_address),
4055                          self.pg0.remote_ip4)
4056         # now we should have only 1 session, 1 deleted by HA
4057         sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4058                                                      users[0].vrf_id)
4059         self.assertEqual(len(sessions), 1)
4060         stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
4061         self.assertEqual(stats[0][0], 1)
4062
4063         stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
4064         self.assertEqual(stats, 2)
4065
4066         # send HA session refresh event to failover/passive
4067         p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4068              IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4069              UDP(sport=12346, dport=12345) /
4070              HANATStateSync(sequence_number=3, events=[
4071                  Event(event_type='refresh', protocol='tcp',
4072                        in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4073                        in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4074                        eh_addr=self.pg1.remote_ip4,
4075                        ehn_addr=self.pg1.remote_ip4,
4076                        eh_port=self.tcp_external_port,
4077                        ehn_port=self.tcp_external_port, fib_index=0,
4078                        total_bytes=1024, total_pkts=2)]))
4079         self.pg3.add_stream(p)
4080         self.pg_enable_capture(self.pg_interfaces)
4081         self.pg_start()
4082         # receive ACK
4083         capture = self.pg3.get_capture(1)
4084         p = capture[0]
4085         try:
4086             hanat = p[HANATStateSync]
4087         except IndexError:
4088             self.logger.error(ppp("Invalid packet:", p))
4089             raise
4090         else:
4091             self.assertEqual(hanat.sequence_number, 3)
4092             self.assertEqual(hanat.flags, 'ACK')
4093             self.assertEqual(hanat.version, 1)
4094         users = self.vapi.nat44_user_dump()
4095         self.assertEqual(len(users), 1)
4096         self.assertEqual(str(users[0].ip_address),
4097                          self.pg0.remote_ip4)
4098         sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4099                                                      users[0].vrf_id)
4100         self.assertEqual(len(sessions), 1)
4101         session = sessions[0]
4102         self.assertEqual(session.total_bytes, 1024)
4103         self.assertEqual(session.total_pkts, 2)
4104         stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
4105         self.assertEqual(stats[0][0], 1)
4106
4107         stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
4108         self.assertEqual(stats, 3)
4109
4110         # send packet to test session created by HA
4111         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4112              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4113              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
4114         self.pg1.add_stream(p)
4115         self.pg_enable_capture(self.pg_interfaces)
4116         self.pg_start()
4117         capture = self.pg0.get_capture(1)
4118         p = capture[0]
4119         try:
4120             ip = p[IP]
4121             tcp = p[TCP]
4122         except IndexError:
4123             self.logger.error(ppp("Invalid packet:", p))
4124             raise
4125         else:
4126             self.assertEqual(ip.src, self.pg1.remote_ip4)
4127             self.assertEqual(ip.dst, self.pg0.remote_ip4)
4128             self.assertEqual(tcp.sport, self.tcp_external_port)
4129             self.assertEqual(tcp.dport, self.tcp_port_in)
4130
4131     def tearDown(self):
4132         super(TestNAT44, self).tearDown()
4133         self.clear_nat44()
4134         self.vapi.cli("clear logging")
4135
4136     def show_commands_at_teardown(self):
4137         self.logger.info(self.vapi.cli("show nat44 addresses"))
4138         self.logger.info(self.vapi.cli("show nat44 interfaces"))
4139         self.logger.info(self.vapi.cli("show nat44 static mappings"))
4140         self.logger.info(self.vapi.cli("show nat44 interface address"))
4141         self.logger.info(self.vapi.cli("show nat44 sessions detail"))
4142         self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
4143         self.logger.info(self.vapi.cli("show nat timeouts"))
4144         self.logger.info(
4145             self.vapi.cli("show nat addr-port-assignment-alg"))
4146         self.logger.info(self.vapi.cli("show nat ha"))
4147
4148
4149 class TestNAT44EndpointDependent2(MethodHolder):
4150     """ Endpoint-Dependent mapping and filtering test cases """
4151
4152     @classmethod
4153     def setUpConstants(cls):
4154         super(TestNAT44EndpointDependent2, cls).setUpConstants()
4155         cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4156
4157     @classmethod
4158     def tearDownClass(cls):
4159         super(TestNAT44EndpointDependent2, cls).tearDownClass()
4160
4161     def tearDown(self):
4162         super(TestNAT44EndpointDependent2, self).tearDown()
4163
4164     @classmethod
4165     def create_and_add_ip4_table(cls, i, table_id):
4166         cls.vapi.ip_table_add_del(is_add=1, table={'table_id': table_id})
4167         i.set_table_ip4(table_id)
4168
4169     @classmethod
4170     def setUpClass(cls):
4171         super(TestNAT44EndpointDependent2, cls).setUpClass()
4172
4173         cls.create_pg_interfaces(range(3))
4174         cls.interfaces = list(cls.pg_interfaces)
4175
4176         cls.create_and_add_ip4_table(cls.pg1, 10)
4177
4178         for i in cls.interfaces:
4179             i.admin_up()
4180             i.config_ip4()
4181             i.resolve_arp()
4182
4183             i.generate_remote_hosts(1)
4184             i.configure_ipv4_neighbors()
4185
4186     def setUp(self):
4187         super(TestNAT44EndpointDependent2, self).setUp()
4188
4189         nat_config = self.vapi.nat_show_config()
4190         self.assertEqual(1, nat_config.endpoint_dependent)
4191
4192     def nat_add_inside_interface(self, i):
4193         self.vapi.nat44_interface_add_del_feature(
4194             flags=self.config_flags.NAT_IS_INSIDE,
4195             sw_if_index=i.sw_if_index, is_add=1)
4196
4197     def nat_add_outside_interface(self, i):
4198         self.vapi.nat44_interface_add_del_feature(
4199             flags=self.config_flags.NAT_IS_OUTSIDE,
4200             sw_if_index=i.sw_if_index, is_add=1)
4201
4202     def nat_add_interface_address(self, i):
4203         self.nat_addr = i.local_ip4
4204         self.vapi.nat44_add_del_interface_addr(
4205             sw_if_index=i.sw_if_index, is_add=1)
4206
4207     def nat_add_address(self, address, vrf_id=0xFFFFFFFF):
4208         self.nat_addr = address
4209         self.nat44_add_address(address, vrf_id=vrf_id)
4210
4211     def cli(self, command):
4212         result = self.vapi.cli(command)
4213         self.logger.info(result)
4214         # print(result)
4215
4216     def show_configuration(self):
4217         self.cli("show interface")
4218         self.cli("show interface address")
4219         self.cli("show nat44 addresses")
4220         self.cli("show nat44 interfaces")
4221
4222     def create_tcp_stream(self, in_if, out_if, count):
4223         """
4224         Create tcp packet stream
4225
4226         :param in_if: Inside interface
4227         :param out_if: Outside interface
4228         :param count: count of packets to generate
4229         """
4230         pkts = []
4231         port = 6303
4232
4233         for i in range(count):
4234             p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4235                  IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=64) /
4236                  TCP(sport=port + i, dport=20))
4237             pkts.append(p)
4238
4239         return pkts
4240
4241     def test_session_limit_per_vrf(self):
4242
4243         inside = self.pg0
4244         inside_vrf10 = self.pg1
4245         outside = self.pg2
4246
4247         limit = 5
4248
4249         # 2 interfaces pg0, pg1 (vrf10, limit 1 tcp session)
4250         # non existing vrf_id makes process core dump
4251         self.vapi.nat44_set_session_limit(session_limit=limit, vrf_id=10)
4252
4253         self.nat_add_inside_interface(inside)
4254         self.nat_add_inside_interface(inside_vrf10)
4255         self.nat_add_outside_interface(outside)
4256
4257         # vrf independent
4258         self.nat_add_interface_address(outside)
4259
4260         # BUG: causing core dump - when bad vrf_id is specified
4261         # self.nat44_add_address(outside.local_ip4, vrf_id=20)
4262
4263         self.show_configuration()
4264
4265         stream = self.create_tcp_stream(inside_vrf10, outside, limit * 2)
4266         inside_vrf10.add_stream(stream)
4267
4268         self.pg_enable_capture(self.pg_interfaces)
4269         self.pg_start()
4270
4271         capture = outside.get_capture(limit)
4272
4273         stream = self.create_tcp_stream(inside, outside, limit * 2)
4274         inside.add_stream(stream)
4275
4276         self.pg_enable_capture(self.pg_interfaces)
4277         self.pg_start()
4278
4279         capture = outside.get_capture(len(stream))
4280
4281
4282 class TestNAT44EndpointDependent(MethodHolder):
4283     """ Endpoint-Dependent mapping and filtering test cases """
4284
4285     @classmethod
4286     def setUpConstants(cls):
4287         super(TestNAT44EndpointDependent, cls).setUpConstants()
4288         cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4289
4290     @classmethod
4291     def setUpClass(cls):
4292         super(TestNAT44EndpointDependent, cls).setUpClass()
4293         cls.vapi.cli("set log class nat level debug")
4294
4295         cls.tcp_port_in = 6303
4296         cls.tcp_port_out = 6303
4297         cls.udp_port_in = 6304
4298         cls.udp_port_out = 6304
4299         cls.icmp_id_in = 6305
4300         cls.icmp_id_out = 6305
4301         cls.nat_addr = '10.0.0.3'
4302         cls.ipfix_src_port = 4739
4303         cls.ipfix_domain_id = 1
4304         cls.tcp_external_port = 80
4305
4306         cls.create_pg_interfaces(range(9))
4307         cls.interfaces = list(cls.pg_interfaces[0:3])
4308
4309         for i in cls.interfaces:
4310             i.admin_up()
4311             i.config_ip4()
4312             i.resolve_arp()
4313
4314         cls.pg0.generate_remote_hosts(3)
4315         cls.pg0.configure_ipv4_neighbors()
4316
4317         cls.pg3.admin_up()
4318
4319         cls.pg4.generate_remote_hosts(2)
4320         cls.pg4.config_ip4()
4321         cls.vapi.sw_interface_add_del_address(
4322             sw_if_index=cls.pg4.sw_if_index,
4323             prefix="10.0.0.1/24")
4324
4325         cls.pg4.admin_up()
4326         cls.pg4.resolve_arp()
4327         cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4328         cls.pg4.resolve_arp()
4329
4330         zero_ip4 = socket.inet_pton(socket.AF_INET, "0.0.0.0")
4331         cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 1})
4332
4333         cls.pg5._local_ip4 = "10.1.1.1"
4334         cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4335         cls.pg5.set_table_ip4(1)
4336         cls.pg5.config_ip4()
4337         cls.pg5.admin_up()
4338         r1 = VppIpRoute(cls, cls.pg5.remote_ip4, 32,
4339                         [VppRoutePath("0.0.0.0",
4340                                       cls.pg5.sw_if_index)],
4341                         table_id=1,
4342                         register=False)
4343         r1.add_vpp_config()
4344
4345         cls.pg6._local_ip4 = "10.1.2.1"
4346         cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4347         cls.pg6.set_table_ip4(1)
4348         cls.pg6.config_ip4()
4349         cls.pg6.admin_up()
4350
4351         r2 = VppIpRoute(cls, cls.pg6.remote_ip4, 32,
4352                         [VppRoutePath("0.0.0.0",
4353                                       cls.pg6.sw_if_index)],
4354                         table_id=1,
4355                         register=False)
4356         r3 = VppIpRoute(cls, cls.pg6.remote_ip4, 16,
4357                         [VppRoutePath("0.0.0.0",
4358                                       0xffffffff,
4359                                       nh_table_id=1)],
4360                         table_id=0,
4361                         register=False)
4362         r4 = VppIpRoute(cls, "0.0.0.0", 0,
4363                         [VppRoutePath("0.0.0.0", 0xffffffff,
4364                                       nh_table_id=0)],
4365                         table_id=1,
4366                         register=False)
4367         r5 = VppIpRoute(cls, "0.0.0.0", 0,
4368                         [VppRoutePath(cls.pg1.local_ip4,
4369                                       cls.pg1.sw_if_index)],
4370                         register=False)
4371         r2.add_vpp_config()
4372         r3.add_vpp_config()
4373         r4.add_vpp_config()
4374         r5.add_vpp_config()
4375
4376         cls.pg5.resolve_arp()
4377         cls.pg6.resolve_arp()
4378
4379         cls.pg7.admin_up()
4380         cls.pg7.config_ip4()
4381         cls.pg7.resolve_arp()
4382         cls.pg7.generate_remote_hosts(3)
4383         cls.pg7.configure_ipv4_neighbors()
4384
4385         cls.pg8.admin_up()
4386         cls.pg8.config_ip4()
4387         cls.pg8.resolve_arp()
4388
4389     def setUp(self):
4390         super(TestNAT44EndpointDependent, self).setUp()
4391         self.vapi.nat_set_timeouts(
4392             udp=300, tcp_established=7440, tcp_transitory=240, icmp=60)
4393
4394     @classmethod
4395     def tearDownClass(cls):
4396         super(TestNAT44EndpointDependent, cls).tearDownClass()
4397
4398     def test_frag_in_order(self):
4399         """ NAT44 translate fragments arriving in order """
4400         self.nat44_add_address(self.nat_addr)
4401         flags = self.config_flags.NAT_IS_INSIDE
4402         self.vapi.nat44_interface_add_del_feature(
4403             sw_if_index=self.pg0.sw_if_index,
4404             flags=flags, is_add=1)
4405         self.vapi.nat44_interface_add_del_feature(
4406             sw_if_index=self.pg1.sw_if_index,
4407             is_add=1)
4408         self.frag_in_order(proto=IP_PROTOS.tcp)
4409         self.frag_in_order(proto=IP_PROTOS.udp)
4410         self.frag_in_order(proto=IP_PROTOS.icmp)
4411
4412     def test_frag_in_order_dont_translate(self):
4413         """ NAT44 don't translate fragments arriving in order """
4414         flags = self.config_flags.NAT_IS_INSIDE
4415         self.vapi.nat44_interface_add_del_feature(
4416             sw_if_index=self.pg0.sw_if_index,
4417             flags=flags, is_add=1)
4418         self.vapi.nat44_interface_add_del_feature(
4419             sw_if_index=self.pg1.sw_if_index,
4420             is_add=1)
4421         self.vapi.nat44_forwarding_enable_disable(enable=True)
4422         self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4423
4424     def test_frag_out_of_order(self):
4425         """ NAT44 translate fragments arriving out of order """
4426         self.nat44_add_address(self.nat_addr)
4427         flags = self.config_flags.NAT_IS_INSIDE
4428         self.vapi.nat44_interface_add_del_feature(
4429             sw_if_index=self.pg0.sw_if_index,
4430             flags=flags, is_add=1)
4431         self.vapi.nat44_interface_add_del_feature(
4432             sw_if_index=self.pg1.sw_if_index,
4433             is_add=1)
4434         self.frag_out_of_order(proto=IP_PROTOS.tcp)
4435         self.frag_out_of_order(proto=IP_PROTOS.udp)
4436         self.frag_out_of_order(proto=IP_PROTOS.icmp)
4437
4438     def test_frag_out_of_order_dont_translate(self):
4439         """ NAT44 don't translate fragments arriving out of order """
4440         flags = self.config_flags.NAT_IS_INSIDE
4441         self.vapi.nat44_interface_add_del_feature(
4442             sw_if_index=self.pg0.sw_if_index,
4443             flags=flags, is_add=1)
4444         self.vapi.nat44_interface_add_del_feature(
4445             sw_if_index=self.pg1.sw_if_index,
4446             is_add=1)
4447         self.vapi.nat44_forwarding_enable_disable(enable=True)
4448         self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4449
4450     def test_frag_in_order_in_plus_out(self):
4451         """ in+out interface fragments in order """
4452         flags = self.config_flags.NAT_IS_INSIDE
4453         self.vapi.nat44_interface_add_del_feature(
4454             sw_if_index=self.pg0.sw_if_index,
4455             is_add=1)
4456         self.vapi.nat44_interface_add_del_feature(
4457             sw_if_index=self.pg0.sw_if_index,
4458             flags=flags, is_add=1)
4459         self.vapi.nat44_interface_add_del_feature(
4460             sw_if_index=self.pg1.sw_if_index,
4461             is_add=1)
4462         self.vapi.nat44_interface_add_del_feature(
4463             sw_if_index=self.pg1.sw_if_index,
4464             flags=flags, is_add=1)
4465
4466         self.server = self.pg1.remote_hosts[0]
4467
4468         self.server_in_addr = self.server.ip4
4469         self.server_out_addr = '11.11.11.11'
4470         self.server_in_port = random.randint(1025, 65535)
4471         self.server_out_port = random.randint(1025, 65535)
4472
4473         self.nat44_add_address(self.server_out_addr)
4474
4475         # add static mappings for server
4476         self.nat44_add_static_mapping(self.server_in_addr,
4477                                       self.server_out_addr,
4478                                       self.server_in_port,
4479                                       self.server_out_port,
4480                                       proto=IP_PROTOS.tcp)
4481         self.nat44_add_static_mapping(self.server_in_addr,
4482                                       self.server_out_addr,
4483                                       self.server_in_port,
4484                                       self.server_out_port,
4485                                       proto=IP_PROTOS.udp)
4486         self.nat44_add_static_mapping(self.server_in_addr,
4487                                       self.server_out_addr,
4488                                       proto=IP_PROTOS.icmp)
4489
4490         self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4491         self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4492         self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4493
4494     def test_frag_out_of_order_in_plus_out(self):
4495         """ in+out interface fragments out of order """
4496         flags = self.config_flags.NAT_IS_INSIDE
4497         self.vapi.nat44_interface_add_del_feature(
4498             sw_if_index=self.pg0.sw_if_index,
4499             is_add=1)
4500         self.vapi.nat44_interface_add_del_feature(
4501             sw_if_index=self.pg0.sw_if_index,
4502             flags=flags, is_add=1)
4503         self.vapi.nat44_interface_add_del_feature(
4504             sw_if_index=self.pg1.sw_if_index,
4505             is_add=1)
4506         self.vapi.nat44_interface_add_del_feature(
4507             sw_if_index=self.pg1.sw_if_index,
4508             flags=flags, is_add=1)
4509
4510         self.server = self.pg1.remote_hosts[0]
4511
4512         self.server_in_addr = self.server.ip4
4513         self.server_out_addr = '11.11.11.11'
4514         self.server_in_port = random.randint(1025, 65535)
4515         self.server_out_port = random.randint(1025, 65535)
4516
4517         self.nat44_add_address(self.server_out_addr)
4518
4519         # add static mappings for server
4520         self.nat44_add_static_mapping(self.server_in_addr,
4521                                       self.server_out_addr,
4522                                       self.server_in_port,
4523                                       self.server_out_port,
4524                                       proto=IP_PROTOS.tcp)
4525         self.nat44_add_static_mapping(self.server_in_addr,
4526                                       self.server_out_addr,
4527                                       self.server_in_port,
4528                                       self.server_out_port,
4529                                       proto=IP_PROTOS.udp)
4530         self.nat44_add_static_mapping(self.server_in_addr,
4531                                       self.server_out_addr,
4532                                       proto=IP_PROTOS.icmp)
4533
4534         self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4535         self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4536         self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4537
4538     def test_reass_hairpinning(self):
4539         """ NAT44 fragments hairpinning """
4540         self.server = self.pg0.remote_hosts[1]
4541         self.host_in_port = random.randint(1025, 65535)
4542         self.server_in_port = random.randint(1025, 65535)
4543         self.server_out_port = random.randint(1025, 65535)
4544
4545         self.nat44_add_address(self.nat_addr)
4546         flags = self.config_flags.NAT_IS_INSIDE
4547         self.vapi.nat44_interface_add_del_feature(
4548             sw_if_index=self.pg0.sw_if_index,
4549             flags=flags, is_add=1)
4550         self.vapi.nat44_interface_add_del_feature(
4551             sw_if_index=self.pg1.sw_if_index,
4552             is_add=1)
4553         # add static mapping for server
4554         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4555                                       self.server_in_port,
4556                                       self.server_out_port,
4557                                       proto=IP_PROTOS.tcp)
4558         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4559                                       self.server_in_port,
4560                                       self.server_out_port,
4561                                       proto=IP_PROTOS.udp)
4562         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
4563
4564         self.reass_hairpinning(proto=IP_PROTOS.tcp)
4565         self.reass_hairpinning(proto=IP_PROTOS.udp)
4566         self.reass_hairpinning(proto=IP_PROTOS.icmp)
4567
4568     def test_dynamic(self):
4569         """ NAT44 dynamic translation test """
4570
4571         self.nat44_add_address(self.nat_addr)
4572         flags = self.config_flags.NAT_IS_INSIDE
4573         self.vapi.nat44_interface_add_del_feature(
4574             sw_if_index=self.pg0.sw_if_index,
4575             flags=flags, is_add=1)
4576         self.vapi.nat44_interface_add_del_feature(
4577             sw_if_index=self.pg1.sw_if_index,
4578             is_add=1)
4579
4580         nat_config = self.vapi.nat_show_config()
4581         self.assertEqual(1, nat_config.endpoint_dependent)
4582
4583         # in2out
4584         tcpn = self.statistics.get_err_counter(
4585             '/err/nat44-ed-in2out-slowpath/TCP packets')
4586         udpn = self.statistics.get_err_counter(
4587             '/err/nat44-ed-in2out-slowpath/UDP packets')
4588         icmpn = self.statistics.get_err_counter(
4589             '/err/nat44-ed-in2out-slowpath/ICMP packets')
4590         totaln = self.statistics.get_err_counter(
4591             '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4592
4593         pkts = self.create_stream_in(self.pg0, self.pg1)
4594         self.pg0.add_stream(pkts)
4595         self.pg_enable_capture(self.pg_interfaces)
4596         self.pg_start()
4597         capture = self.pg1.get_capture(len(pkts))
4598         self.verify_capture_out(capture)
4599
4600         err = self.statistics.get_err_counter(
4601             '/err/nat44-ed-in2out-slowpath/TCP packets')
4602         self.assertEqual(err - tcpn, 2)
4603         err = self.statistics.get_err_counter(
4604             '/err/nat44-ed-in2out-slowpath/UDP packets')
4605         self.assertEqual(err - udpn, 1)
4606         err = self.statistics.get_err_counter(
4607             '/err/nat44-ed-in2out-slowpath/ICMP packets')
4608         self.assertEqual(err - icmpn, 1)
4609         err = self.statistics.get_err_counter(
4610             '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4611         self.assertEqual(err - totaln, 4)
4612
4613         # out2in
4614         tcpn = self.statistics.get_err_counter(
4615             '/err/nat44-ed-out2in/TCP packets')
4616         udpn = self.statistics.get_err_counter(
4617             '/err/nat44-ed-out2in/UDP packets')
4618         icmpn = self.statistics.get_err_counter(
4619             '/err/nat44-ed-out2in-slowpath/ICMP packets')
4620         totaln = self.statistics.get_err_counter(
4621             '/err/nat44-ed-out2in/good out2in packets processed')
4622
4623         pkts = self.create_stream_out(self.pg1)
4624         self.pg1.add_stream(pkts)
4625         self.pg_enable_capture(self.pg_interfaces)
4626         self.pg_start()
4627         capture = self.pg0.get_capture(len(pkts))
4628         self.verify_capture_in(capture, self.pg0)
4629
4630         err = self.statistics.get_err_counter(
4631             '/err/nat44-ed-out2in/TCP packets')
4632         self.assertEqual(err - tcpn, 2)
4633         err = self.statistics.get_err_counter(
4634             '/err/nat44-ed-out2in/UDP packets')
4635         self.assertEqual(err - udpn, 1)
4636         err = self.statistics.get_err_counter(
4637             '/err/nat44-ed-out2in-slowpath/ICMP packets')
4638         self.assertEqual(err - icmpn, 1)
4639         err = self.statistics.get_err_counter(
4640             '/err/nat44-ed-out2in/good out2in packets processed')
4641         self.assertEqual(err - totaln, 3)
4642
4643         sessions = self.statistics.get_counter('/nat44/total-sessions')
4644         self.assertEqual(sessions[0][0], 3)
4645
4646     def test_dynamic_output_feature_vrf(self):
4647         """ NAT44 dynamic translation test: output-feature, VRF"""
4648
4649         # other then default (0)
4650         new_vrf_id = 22
4651
4652         self.nat44_add_address(self.nat_addr)
4653         flags = self.config_flags.NAT_IS_INSIDE
4654         self.vapi.nat44_interface_add_del_output_feature(
4655             sw_if_index=self.pg7.sw_if_index,
4656             flags=flags, is_add=1)
4657         self.vapi.nat44_interface_add_del_output_feature(
4658             sw_if_index=self.pg8.sw_if_index,
4659             is_add=1)
4660
4661         try:
4662             self.vapi.ip_table_add_del(is_add=1,
4663                                        table={'table_id': new_vrf_id})
4664
4665             self.pg7.unconfig_ip4()
4666             self.pg7.set_table_ip4(new_vrf_id)
4667             self.pg7.config_ip4()
4668             self.pg7.resolve_arp()
4669
4670             self.pg8.unconfig_ip4()
4671             self.pg8.set_table_ip4(new_vrf_id)
4672             self.pg8.config_ip4()
4673             self.pg8.resolve_arp()
4674
4675             nat_config = self.vapi.nat_show_config()
4676             self.assertEqual(1, nat_config.endpoint_dependent)
4677
4678             # in2out
4679             tcpn = self.statistics.get_err_counter(
4680                 '/err/nat44-ed-in2out-slowpath/TCP packets')
4681             udpn = self.statistics.get_err_counter(
4682                 '/err/nat44-ed-in2out-slowpath/UDP packets')
4683             icmpn = self.statistics.get_err_counter(
4684                 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4685             totaln = self.statistics.get_err_counter(
4686                 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4687
4688             pkts = self.create_stream_in(self.pg7, self.pg8)
4689             self.pg7.add_stream(pkts)
4690             self.pg_enable_capture(self.pg_interfaces)
4691             self.pg_start()
4692             capture = self.pg8.get_capture(len(pkts))
4693             self.verify_capture_out(capture)
4694
4695             err = self.statistics.get_err_counter(
4696                 '/err/nat44-ed-in2out-slowpath/TCP packets')
4697             self.assertEqual(err - tcpn, 2)
4698             err = self.statistics.get_err_counter(
4699                 '/err/nat44-ed-in2out-slowpath/UDP packets')
4700             self.assertEqual(err - udpn, 1)
4701             err = self.statistics.get_err_counter(
4702                 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4703             self.assertEqual(err - icmpn, 1)
4704             err = self.statistics.get_err_counter(
4705                 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4706             self.assertEqual(err - totaln, 4)
4707
4708             # out2in
4709             tcpn = self.statistics.get_err_counter(
4710                 '/err/nat44-ed-out2in/TCP packets')
4711             udpn = self.statistics.get_err_counter(
4712                 '/err/nat44-ed-out2in/UDP packets')
4713             icmpn = self.statistics.get_err_counter(
4714                 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4715             totaln = self.statistics.get_err_counter(
4716                 '/err/nat44-ed-out2in/good out2in packets processed')
4717
4718             pkts = self.create_stream_out(self.pg8)
4719             self.pg8.add_stream(pkts)
4720             self.pg_enable_capture(self.pg_interfaces)
4721             self.pg_start()
4722             capture = self.pg7.get_capture(len(pkts))
4723             self.verify_capture_in(capture, self.pg7)
4724
4725             err = self.statistics.get_err_counter(
4726                 '/err/nat44-ed-out2in/TCP packets')
4727             self.assertEqual(err - tcpn, 2)
4728             err = self.statistics.get_err_counter(
4729                 '/err/nat44-ed-out2in/UDP packets')
4730             self.assertEqual(err - udpn, 1)
4731             err = self.statistics.get_err_counter(
4732                 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4733             self.assertEqual(err - icmpn, 1)
4734             err = self.statistics.get_err_counter(
4735                 '/err/nat44-ed-out2in/good out2in packets processed')
4736             self.assertEqual(err - totaln, 3)
4737
4738             sessions = self.statistics.get_counter('/nat44/total-sessions')
4739             self.assertEqual(sessions[0][0], 3)
4740
4741         finally:
4742             self.pg7.unconfig_ip4()
4743             self.pg7.set_table_ip4(1)
4744             self.pg7.config_ip4()
4745             self.pg7.resolve_arp()
4746
4747             self.pg8.unconfig_ip4()
4748             self.pg8.set_table_ip4(1)
4749             self.pg8.config_ip4()
4750             self.pg8.resolve_arp()
4751
4752             self.vapi.ip_table_add_del(is_add=0,
4753                                        table={'table_id': new_vrf_id})
4754
4755     def test_forwarding(self):
4756         """ NAT44 forwarding test """
4757
4758         flags = self.config_flags.NAT_IS_INSIDE
4759         self.vapi.nat44_interface_add_del_feature(
4760             sw_if_index=self.pg0.sw_if_index,
4761             flags=flags, is_add=1)
4762         self.vapi.nat44_interface_add_del_feature(
4763             sw_if_index=self.pg1.sw_if_index,
4764             is_add=1)
4765         self.vapi.nat44_forwarding_enable_disable(enable=1)
4766
4767         real_ip = self.pg0.remote_ip4
4768         alias_ip = self.nat_addr
4769         flags = self.config_flags.NAT_IS_ADDR_ONLY
4770         self.vapi.nat44_add_del_static_mapping(is_add=1,
4771                                                local_ip_address=real_ip,
4772                                                external_ip_address=alias_ip,
4773                                                external_sw_if_index=0xFFFFFFFF,
4774                                                flags=flags)
4775
4776         try:
4777             # in2out - static mapping match
4778
4779             pkts = self.create_stream_out(self.pg1)
4780             self.pg1.add_stream(pkts)
4781             self.pg_enable_capture(self.pg_interfaces)
4782             self.pg_start()
4783             capture = self.pg0.get_capture(len(pkts))
4784             self.verify_capture_in(capture, self.pg0)
4785
4786             pkts = self.create_stream_in(self.pg0, self.pg1)
4787             self.pg0.add_stream(pkts)
4788             self.pg_enable_capture(self.pg_interfaces)
4789             self.pg_start()
4790             capture = self.pg1.get_capture(len(pkts))
4791             self.verify_capture_out(capture, same_port=True)
4792
4793             # in2out - no static mapping match
4794
4795             host0 = self.pg0.remote_hosts[0]
4796             self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4797             try:
4798                 pkts = self.create_stream_out(self.pg1,
4799                                               dst_ip=self.pg0.remote_ip4,
4800                                               use_inside_ports=True)
4801                 self.pg1.add_stream(pkts)
4802                 self.pg_enable_capture(self.pg_interfaces)
4803                 self.pg_start()
4804                 capture = self.pg0.get_capture(len(pkts))
4805                 self.verify_capture_in(capture, self.pg0)
4806
4807                 pkts = self.create_stream_in(self.pg0, self.pg1)
4808                 self.pg0.add_stream(pkts)
4809                 self.pg_enable_capture(self.pg_interfaces)
4810                 self.pg_start()
4811                 capture = self.pg1.get_capture(len(pkts))
4812                 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4813                                         same_port=True)
4814             finally:
4815                 self.pg0.remote_hosts[0] = host0
4816
4817             user = self.pg0.remote_hosts[1]
4818             sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4819             self.assertEqual(len(sessions), 3)
4820             self.assertTrue(sessions[0].flags &
4821                             self.config_flags.NAT_IS_EXT_HOST_VALID)
4822             self.vapi.nat44_del_session(
4823                 address=sessions[0].inside_ip_address,
4824                 port=sessions[0].inside_port,
4825                 protocol=sessions[0].protocol,
4826                 flags=(self.config_flags.NAT_IS_INSIDE |
4827                        self.config_flags.NAT_IS_EXT_HOST_VALID),
4828                 ext_host_address=sessions[0].ext_host_address,
4829                 ext_host_port=sessions[0].ext_host_port)
4830             sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4831             self.assertEqual(len(sessions), 2)
4832
4833         finally:
4834             self.vapi.nat44_forwarding_enable_disable(enable=0)
4835             flags = self.config_flags.NAT_IS_ADDR_ONLY
4836             self.vapi.nat44_add_del_static_mapping(
4837                 is_add=0,
4838                 local_ip_address=real_ip,
4839                 external_ip_address=alias_ip,
4840                 external_sw_if_index=0xFFFFFFFF,
4841                 flags=flags)
4842
4843     def test_static_lb(self):
4844         """ NAT44 local service load balancing """
4845         external_addr_n = self.nat_addr
4846         external_port = 80
4847         local_port = 8080
4848         server1 = self.pg0.remote_hosts[0]
4849         server2 = self.pg0.remote_hosts[1]
4850
4851         locals = [{'addr': server1.ip4,
4852                    'port': local_port,
4853                    'probability': 70,
4854                    'vrf_id': 0},
4855                   {'addr': server2.ip4,
4856                    'port': local_port,
4857                    'probability': 30,
4858                    'vrf_id': 0}]
4859
4860         self.nat44_add_address(self.nat_addr)
4861         self.vapi.nat44_add_del_lb_static_mapping(
4862             is_add=1,
4863             external_addr=external_addr_n,
4864             external_port=external_port,
4865             protocol=IP_PROTOS.tcp,
4866             local_num=len(locals),
4867             locals=locals)
4868         flags = self.config_flags.NAT_IS_INSIDE
4869         self.vapi.nat44_interface_add_del_feature(
4870             sw_if_index=self.pg0.sw_if_index,
4871             flags=flags, is_add=1)
4872         self.vapi.nat44_interface_add_del_feature(
4873             sw_if_index=self.pg1.sw_if_index,
4874             is_add=1)
4875
4876         # from client to service
4877         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4878              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4879              TCP(sport=12345, dport=external_port))
4880         self.pg1.add_stream(p)
4881         self.pg_enable_capture(self.pg_interfaces)
4882         self.pg_start()
4883         capture = self.pg0.get_capture(1)
4884         p = capture[0]
4885         server = None
4886         try:
4887             ip = p[IP]
4888             tcp = p[TCP]
4889             self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4890             if ip.dst == server1.ip4:
4891                 server = server1
4892             else:
4893                 server = server2
4894             self.assertEqual(tcp.dport, local_port)
4895             self.assert_packet_checksums_valid(p)
4896         except:
4897             self.logger.error(ppp("Unexpected or invalid packet:", p))
4898             raise
4899
4900         # from service back to client
4901         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4902              IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4903              TCP(sport=local_port, dport=12345))
4904         self.pg0.add_stream(p)
4905         self.pg_enable_capture(self.pg_interfaces)
4906         self.pg_start()
4907         capture = self.pg1.get_capture(1)
4908         p = capture[0]
4909         try:
4910             ip = p[IP]
4911             tcp = p[TCP]
4912             self.assertEqual(ip.src, self.nat_addr)
4913             self.assertEqual(tcp.sport, external_port)
4914             self.assert_packet_checksums_valid(p)
4915         except:
4916             self.logger.error(ppp("Unexpected or invalid packet:", p))
4917             raise
4918
4919         sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
4920         self.assertEqual(len(sessions), 1)
4921         self.assertTrue(sessions[0].flags &
4922                         self.config_flags.NAT_IS_EXT_HOST_VALID)
4923         self.vapi.nat44_del_session(
4924             address=sessions[0].inside_ip_address,
4925             port=sessions[0].inside_port,
4926             protocol=sessions[0].protocol,
4927             flags=(self.config_flags.NAT_IS_INSIDE |
4928                    self.config_flags.NAT_IS_EXT_HOST_VALID),
4929             ext_host_address=sessions[0].ext_host_address,
4930             ext_host_port=sessions[0].ext_host_port)
4931         sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
4932         self.assertEqual(len(sessions), 0)
4933
4934     @unittest.skipUnless(running_extended_tests, "part of extended tests")
4935     def test_static_lb_multi_clients(self):
4936         """ NAT44 local service load balancing - multiple clients"""
4937
4938         external_addr = self.nat_addr
4939         external_port = 80
4940         local_port = 8080
4941         server1 = self.pg0.remote_hosts[0]
4942         server2 = self.pg0.remote_hosts[1]
4943         server3 = self.pg0.remote_hosts[2]
4944
4945         locals = [{'addr': server1.ip4,
4946                    'port': local_port,
4947                    'probability': 90,
4948                    'vrf_id': 0},
4949                   {'addr': server2.ip4,
4950                    'port': local_port,
4951                    'probability': 10,
4952                    'vrf_id': 0}]
4953
4954         self.nat44_add_address(self.nat_addr)
4955         self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
4956                                                   external_addr=external_addr,
4957                                                   external_port=external_port,
4958                                                   protocol=IP_PROTOS.tcp,
4959                                                   local_num=len(locals),
4960                                                   locals=locals)
4961         flags = self.config_flags.NAT_IS_INSIDE
4962         self.vapi.nat44_interface_add_del_feature(
4963             sw_if_index=self.pg0.sw_if_index,
4964             flags=flags, is_add=1)
4965         self.vapi.nat44_interface_add_del_feature(
4966             sw_if_index=self.pg1.sw_if_index,
4967             is_add=1)
4968
4969         server1_n = 0
4970         server2_n = 0
4971         clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4972         pkts = []
4973         for client in clients:
4974             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4975                  IP(src=client, dst=self.nat_addr) /
4976                  TCP(sport=12345, dport=external_port))
4977             pkts.append(p)
4978         self.pg1.add_stream(pkts)
4979         self.pg_enable_capture(self.pg_interfaces)
4980         self.pg_start()
4981         capture = self.pg0.get_capture(len(pkts))
4982         for p in capture:
4983             if p[IP].dst == server1.ip4:
4984                 server1_n += 1
4985             else:
4986                 server2_n += 1
4987         self.assertGreater(server1_n, server2_n)
4988
4989         local = {
4990             'addr': server3.ip4,
4991             'port': local_port,
4992             'probability': 20,
4993             'vrf_id': 0
4994         }
4995
4996         # add new back-end
4997         self.vapi.nat44_lb_static_mapping_add_del_local(
4998             is_add=1,
4999             external_addr=external_addr,
5000             external_port=external_port,
5001             local=local,
5002             protocol=IP_PROTOS.tcp)
5003         server1_n = 0
5004         server2_n = 0
5005         server3_n = 0
5006         clients = ip4_range(self.pg1.remote_ip4, 60, 110)
5007         pkts = []
5008         for client in clients:
5009             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5010                  IP(src=client, dst=self.nat_addr) /
5011                  TCP(sport=12346, dport=external_port))
5012             pkts.append(p)
5013         self.assertGreater(len(pkts), 0)
5014         self.pg1.add_stream(pkts)
5015         self.pg_enable_capture(self.pg_interfaces)
5016         self.pg_start()
5017         capture = self.pg0.get_capture(len(pkts))
5018         for p in capture:
5019             if p[IP].dst == server1.ip4:
5020                 server1_n += 1
5021             elif p[IP].dst == server2.ip4:
5022                 server2_n += 1
5023             else:
5024                 server3_n += 1
5025         self.assertGreater(server1_n, 0)
5026         self.assertGreater(server2_n, 0)
5027         self.assertGreater(server3_n, 0)
5028
5029         local = {
5030             'addr': server2.ip4,
5031             'port': local_port,
5032             'probability': 10,
5033             'vrf_id': 0
5034         }
5035
5036         # remove one back-end
5037         self.vapi.nat44_lb_static_mapping_add_del_local(
5038             is_add=0,
5039             external_addr=external_addr,
5040             external_port=external_port,
5041             local=local,
5042             protocol=IP_PROTOS.tcp)
5043         server1_n = 0
5044         server2_n = 0
5045         server3_n = 0
5046         self.pg1.add_stream(pkts)
5047         self.pg_enable_capture(self.pg_interfaces)
5048         self.pg_start()
5049         capture = self.pg0.get_capture(len(pkts))
5050         for p in capture:
5051             if p[IP].dst == server1.ip4:
5052                 server1_n += 1
5053             elif p[IP].dst == server2.ip4:
5054                 server2_n += 1
5055             else:
5056                 server3_n += 1
5057         self.assertGreater(server1_n, 0)
5058         self.assertEqual(server2_n, 0)
5059         self.assertGreater(server3_n, 0)
5060
5061     def test_static_lb_2(self):
5062         """ NAT44 local service load balancing (asymmetrical rule) """
5063         external_addr = self.nat_addr
5064         external_port = 80
5065         local_port = 8080
5066         server1 = self.pg0.remote_hosts[0]
5067         server2 = self.pg0.remote_hosts[1]
5068
5069         locals = [{'addr': server1.ip4,
5070                    'port': local_port,
5071                    'probability': 70,
5072                    'vrf_id': 0},
5073                   {'addr': server2.ip4,
5074                    'port': local_port,
5075                    'probability': 30,
5076                    'vrf_id': 0}]
5077
5078         self.vapi.nat44_forwarding_enable_disable(enable=1)
5079         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5080         self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5081                                                   external_addr=external_addr,
5082                                                   external_port=external_port,
5083                                                   protocol=IP_PROTOS.tcp,
5084                                                   local_num=len(locals),
5085                                                   locals=locals)
5086         flags = self.config_flags.NAT_IS_INSIDE
5087         self.vapi.nat44_interface_add_del_feature(
5088             sw_if_index=self.pg0.sw_if_index,
5089             flags=flags, is_add=1)
5090         self.vapi.nat44_interface_add_del_feature(
5091             sw_if_index=self.pg1.sw_if_index,
5092             is_add=1)
5093
5094         # from client to service
5095         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5096              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5097              TCP(sport=12345, dport=external_port))
5098         self.pg1.add_stream(p)
5099         self.pg_enable_capture(self.pg_interfaces)
5100         self.pg_start()
5101         capture = self.pg0.get_capture(1)
5102         p = capture[0]
5103         server = None
5104         try:
5105             ip = p[IP]
5106             tcp = p[TCP]
5107             self.assertIn(ip.dst, [server1.ip4, server2.ip4])
5108             if ip.dst == server1.ip4:
5109                 server = server1
5110             else:
5111                 server = server2
5112             self.assertEqual(tcp.dport, local_port)
5113             self.assert_packet_checksums_valid(p)
5114         except:
5115             self.logger.error(ppp("Unexpected or invalid packet:", p))
5116             raise
5117
5118         # from service back to client
5119         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
5120              IP(src=server.ip4, dst=self.pg1.remote_ip4) /
5121              TCP(sport=local_port, dport=12345))
5122         self.pg0.add_stream(p)
5123         self.pg_enable_capture(self.pg_interfaces)
5124         self.pg_start()
5125         capture = self.pg1.get_capture(1)
5126         p = capture[0]
5127         try:
5128             ip = p[IP]
5129             tcp = p[TCP]
5130             self.assertEqual(ip.src, self.nat_addr)
5131             self.assertEqual(tcp.sport, external_port)
5132             self.assert_packet_checksums_valid(p)
5133         except:
5134             self.logger.error(ppp("Unexpected or invalid packet:", p))
5135             raise
5136
5137         # from client to server (no translation)
5138         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5139              IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
5140              TCP(sport=12346, dport=local_port))
5141         self.pg1.add_stream(p)
5142         self.pg_enable_capture(self.pg_interfaces)
5143         self.pg_start()
5144         capture = self.pg0.get_capture(1)
5145         p = capture[0]
5146         server = None
5147         try:
5148             ip = p[IP]
5149             tcp = p[TCP]
5150             self.assertEqual(ip.dst, server1.ip4)
5151             self.assertEqual(tcp.dport, local_port)
5152             self.assert_packet_checksums_valid(p)
5153         except:
5154             self.logger.error(ppp("Unexpected or invalid packet:", p))
5155             raise
5156
5157         # from service back to client (no translation)
5158         p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
5159              IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
5160              TCP(sport=local_port, dport=12346))
5161         self.pg0.add_stream(p)
5162         self.pg_enable_capture(self.pg_interfaces)
5163         self.pg_start()
5164         capture = self.pg1.get_capture(1)
5165         p = capture[0]
5166         try:
5167             ip = p[IP]
5168             tcp = p[TCP]
5169             self.assertEqual(ip.src, server1.ip4)
5170             self.assertEqual(tcp.sport, local_port)
5171             self.assert_packet_checksums_valid(p)
5172         except:
5173             self.logger.error(ppp("Unexpected or invalid packet:", p))
5174             raise
5175
5176     def test_lb_affinity(self):
5177         """ NAT44 local service load balancing affinity """
5178         external_addr = self.nat_addr
5179         external_port = 80
5180         local_port = 8080
5181         server1 = self.pg0.remote_hosts[0]
5182         server2 = self.pg0.remote_hosts[1]
5183
5184         locals = [{'addr': server1.ip4,
5185                    'port': local_port,
5186                    'probability': 50,
5187                    'vrf_id': 0},
5188                   {'addr': server2.ip4,
5189                    'port': local_port,
5190                    'probability': 50,
5191                    'vrf_id': 0}]
5192
5193         self.nat44_add_address(self.nat_addr)
5194         self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
5195                                                   external_addr=external_addr,
5196                                                   external_port=external_port,
5197                                                   protocol=IP_PROTOS.tcp,
5198                                                   affinity=10800,
5199                                                   local_num=len(locals),
5200                                                   locals=locals)
5201         flags = self.config_flags.NAT_IS_INSIDE
5202         self.vapi.nat44_interface_add_del_feature(
5203             sw_if_index=self.pg0.sw_if_index,
5204             flags=flags, is_add=1)
5205         self.vapi.nat44_interface_add_del_feature(
5206             sw_if_index=self.pg1.sw_if_index,
5207             is_add=1)
5208
5209         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5210              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5211              TCP(sport=1025, dport=external_port))
5212         self.pg1.add_stream(p)
5213         self.pg_enable_capture(self.pg_interfaces)
5214         self.pg_start()
5215         capture = self.pg0.get_capture(1)
5216         backend = capture[0][IP].dst
5217
5218         sessions = self.vapi.nat44_user_session_dump(backend, 0)
5219         self.assertEqual(len(sessions), 1)
5220         self.assertTrue(sessions[0].flags &
5221                         self.config_flags.NAT_IS_EXT_HOST_VALID)
5222         self.vapi.nat44_del_session(
5223             address=sessions[0].inside_ip_address,
5224             port=sessions[0].inside_port,
5225             protocol=sessions[0].protocol,
5226             flags=(self.config_flags.NAT_IS_INSIDE |
5227                    self.config_flags.NAT_IS_EXT_HOST_VALID),
5228             ext_host_address=sessions[0].ext_host_address,
5229             ext_host_port=sessions[0].ext_host_port)
5230
5231         pkts = []
5232         for port in range(1030, 1100):
5233             p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5234                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5235                  TCP(sport=port, dport=external_port))
5236             pkts.append(p)
5237         self.pg1.add_stream(pkts)
5238         self.pg_enable_capture(self.pg_interfaces)
5239         self.pg_start()
5240         capture = self.pg0.get_capture(len(pkts))
5241         for p in capture:
5242             self.assertEqual(p[IP].dst, backend)
5243
5244     def test_unknown_proto(self):
5245         """ NAT44 translate packet with unknown protocol """
5246         self.nat44_add_address(self.nat_addr)
5247         flags = self.config_flags.NAT_IS_INSIDE
5248         self.vapi.nat44_interface_add_del_feature(
5249             sw_if_index=self.pg0.sw_if_index,
5250             flags=flags, is_add=1)
5251         self.vapi.nat44_interface_add_del_feature(
5252             sw_if_index=self.pg1.sw_if_index,
5253             is_add=1)
5254
5255         # in2out
5256         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5257              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5258              TCP(sport=self.tcp_port_in, dport=20))
5259         self.pg0.add_stream(p)
5260         self.pg_enable_capture(self.pg_interfaces)
5261         self.pg_start()
5262         p = self.pg1.get_capture(1)
5263
5264         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5265              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5266              GRE() /
5267              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5268              TCP(sport=1234, dport=1234))
5269         self.pg0.add_stream(p)
5270         self.pg_enable_capture(self.pg_interfaces)
5271         self.pg_start()
5272         p = self.pg1.get_capture(1)
5273         packet = p[0]
5274         try:
5275             self.assertEqual(packet[IP].src, self.nat_addr)
5276             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5277             self.assertEqual(packet.haslayer(GRE), 1)
5278             self.assert_packet_checksums_valid(packet)
5279         except:
5280             self.logger.error(ppp("Unexpected or invalid packet:", packet))
5281             raise
5282
5283         # out2in
5284         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5285              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5286              GRE() /
5287              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5288              TCP(sport=1234, dport=1234))
5289         self.pg1.add_stream(p)
5290         self.pg_enable_capture(self.pg_interfaces)
5291         self.pg_start()
5292         p = self.pg0.get_capture(1)
5293         packet = p[0]
5294         try:
5295             self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
5296             self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
5297             self.assertEqual(packet.haslayer(GRE), 1)
5298             self.assert_packet_checksums_valid(packet)
5299         except:
5300             self.logger.error(ppp("Unexpected or invalid packet:", packet))
5301             raise
5302
5303     def test_hairpinning_unknown_proto(self):
5304         """ NAT44 translate packet with unknown protocol - hairpinning """
5305         host = self.pg0.remote_hosts[0]
5306         server = self.pg0.remote_hosts[1]
5307         host_in_port = 1234
5308         server_out_port = 8765
5309         server_nat_ip = "10.0.0.11"
5310
5311         self.nat44_add_address(self.nat_addr)
5312         flags = self.config_flags.NAT_IS_INSIDE
5313         self.vapi.nat44_interface_add_del_feature(
5314             sw_if_index=self.pg0.sw_if_index,
5315             flags=flags, is_add=1)
5316         self.vapi.nat44_interface_add_del_feature(
5317             sw_if_index=self.pg1.sw_if_index,
5318             is_add=1)
5319
5320         # add static mapping for server
5321         self.nat44_add_static_mapping(server.ip4, server_nat_ip)
5322
5323         # host to server
5324         p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
5325              IP(src=host.ip4, dst=server_nat_ip) /
5326              TCP(sport=host_in_port, dport=server_out_port))
5327         self.pg0.add_stream(p)
5328         self.pg_enable_capture(self.pg_interfaces)
5329         self.pg_start()
5330         self.pg0.get_capture(1)
5331
5332         p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5333              IP(src=host.ip4, dst=server_nat_ip) /
5334              GRE() /
5335              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5336              TCP(sport=1234, dport=1234))
5337         self.pg0.add_stream(p)
5338         self.pg_enable_capture(self.pg_interfaces)
5339         self.pg_start()
5340         p = self.pg0.get_capture(1)
5341         packet = p[0]
5342         try:
5343             self.assertEqual(packet[IP].src, self.nat_addr)
5344             self.assertEqual(packet[IP].dst, server.ip4)
5345             self.assertEqual(packet.haslayer(GRE), 1)
5346             self.assert_packet_checksums_valid(packet)
5347         except:
5348             self.logger.error(ppp("Unexpected or invalid packet:", packet))
5349             raise
5350
5351         # server to host
5352         p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5353              IP(src=server.ip4, dst=self.nat_addr) /
5354              GRE() /
5355              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5356              TCP(sport=1234, dport=1234))
5357         self.pg0.add_stream(p)
5358         self.pg_enable_capture(self.pg_interfaces)
5359         self.pg_start()
5360         p = self.pg0.get_capture(1)
5361         packet = p[0]
5362         try:
5363             self.assertEqual(packet[IP].src, server_nat_ip)
5364             self.assertEqual(packet[IP].dst, host.ip4)
5365             self.assertEqual(packet.haslayer(GRE), 1)
5366             self.assert_packet_checksums_valid(packet)
5367         except:
5368             self.logger.error(ppp("Unexpected or invalid packet:", packet))
5369             raise
5370
5371     def test_output_feature_and_service(self):
5372         """ NAT44 interface output feature and services """
5373         external_addr = '1.2.3.4'
5374         external_port = 80
5375         local_port = 8080
5376
5377         self.vapi.nat44_forwarding_enable_disable(enable=1)
5378         self.nat44_add_address(self.nat_addr)
5379         flags = self.config_flags.NAT_IS_ADDR_ONLY
5380         self.vapi.nat44_add_del_identity_mapping(
5381             ip_address=self.pg1.remote_ip4, sw_if_index=0xFFFFFFFF,
5382             flags=flags, is_add=1)
5383         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5384         self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5385                                       local_port, external_port,
5386                                       proto=IP_PROTOS.tcp, flags=flags)
5387         flags = self.config_flags.NAT_IS_INSIDE
5388         self.vapi.nat44_interface_add_del_feature(
5389             sw_if_index=self.pg0.sw_if_index,
5390             is_add=1)
5391         self.vapi.nat44_interface_add_del_feature(
5392             sw_if_index=self.pg0.sw_if_index,
5393             flags=flags, is_add=1)
5394         self.vapi.nat44_interface_add_del_output_feature(
5395             is_add=1,
5396             sw_if_index=self.pg1.sw_if_index)
5397
5398         # from client to service
5399         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5400              IP(src=self.pg1.remote_ip4, dst=external_addr) /
5401              TCP(sport=12345, dport=external_port))
5402         self.pg1.add_stream(p)
5403         self.pg_enable_capture(self.pg_interfaces)
5404         self.pg_start()
5405         capture = self.pg0.get_capture(1)
5406         p = capture[0]
5407         try:
5408             ip = p[IP]
5409             tcp = p[TCP]
5410             self.assertEqual(ip.dst, self.pg0.remote_ip4)
5411             self.assertEqual(tcp.dport, local_port)
5412             self.assert_packet_checksums_valid(p)
5413         except:
5414             self.logger.error(ppp("Unexpected or invalid packet:", p))
5415             raise
5416
5417         # from service back to client
5418         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5419              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5420              TCP(sport=local_port, dport=12345))
5421         self.pg0.add_stream(p)
5422         self.pg_enable_capture(self.pg_interfaces)
5423         self.pg_start()
5424         capture = self.pg1.get_capture(1)
5425         p = capture[0]
5426         try:
5427             ip = p[IP]
5428             tcp = p[TCP]
5429             self.assertEqual(ip.src, external_addr)
5430             self.assertEqual(tcp.sport, external_port)
5431             self.assert_packet_checksums_valid(p)
5432         except:
5433             self.logger.error(ppp("Unexpected or invalid packet:", p))
5434             raise
5435
5436         # from local network host to external network
5437         pkts = self.create_stream_in(self.pg0, self.pg1)
5438         self.pg0.add_stream(pkts)
5439         self.pg_enable_capture(self.pg_interfaces)
5440         self.pg_start()
5441         capture = self.pg1.get_capture(len(pkts))
5442         self.verify_capture_out(capture)
5443         pkts = self.create_stream_in(self.pg0, self.pg1)
5444         self.pg0.add_stream(pkts)
5445         self.pg_enable_capture(self.pg_interfaces)
5446         self.pg_start()
5447         capture = self.pg1.get_capture(len(pkts))
5448         self.verify_capture_out(capture)
5449
5450         # from external network back to local network host
5451         pkts = self.create_stream_out(self.pg1)
5452         self.pg1.add_stream(pkts)
5453         self.pg_enable_capture(self.pg_interfaces)
5454         self.pg_start()
5455         capture = self.pg0.get_capture(len(pkts))
5456         self.verify_capture_in(capture, self.pg0)
5457
5458     def test_output_feature_and_service2(self):
5459         """ NAT44 interface output feature and service host direct access """
5460         self.vapi.nat44_forwarding_enable_disable(enable=1)
5461         self.nat44_add_address(self.nat_addr)
5462         self.vapi.nat44_interface_add_del_output_feature(
5463             is_add=1,
5464             sw_if_index=self.pg1.sw_if_index)
5465
5466         # session initiated from service host - translate
5467         pkts = self.create_stream_in(self.pg0, self.pg1)
5468         self.pg0.add_stream(pkts)
5469         self.pg_enable_capture(self.pg_interfaces)
5470         self.pg_start()
5471         capture = self.pg1.get_capture(len(pkts))
5472         self.verify_capture_out(capture)
5473
5474         pkts = self.create_stream_out(self.pg1)
5475         self.pg1.add_stream(pkts)
5476         self.pg_enable_capture(self.pg_interfaces)
5477         self.pg_start()
5478         capture = self.pg0.get_capture(len(pkts))
5479         self.verify_capture_in(capture, self.pg0)
5480
5481         # session initiated from remote host - do not translate
5482         self.tcp_port_in = 60303
5483         self.udp_port_in = 60304
5484         self.icmp_id_in = 60305
5485         pkts = self.create_stream_out(self.pg1,
5486                                       self.pg0.remote_ip4,
5487                                       use_inside_ports=True)
5488         self.pg1.add_stream(pkts)
5489         self.pg_enable_capture(self.pg_interfaces)
5490         self.pg_start()
5491         capture = self.pg0.get_capture(len(pkts))
5492         self.verify_capture_in(capture, self.pg0)
5493
5494         pkts = self.create_stream_in(self.pg0, self.pg1)
5495         self.pg0.add_stream(pkts)
5496         self.pg_enable_capture(self.pg_interfaces)
5497         self.pg_start()
5498         capture = self.pg1.get_capture(len(pkts))
5499         self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5500                                 same_port=True)
5501
5502     def test_output_feature_and_service3(self):
5503         """ NAT44 interface output feature and DST NAT """
5504         external_addr = '1.2.3.4'
5505         external_port = 80
5506         local_port = 8080
5507
5508         self.vapi.nat44_forwarding_enable_disable(enable=1)
5509         self.nat44_add_address(self.nat_addr)
5510         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5511         self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5512                                       local_port, external_port,
5513                                       proto=IP_PROTOS.tcp, flags=flags)
5514         flags = self.config_flags.NAT_IS_INSIDE
5515         self.vapi.nat44_interface_add_del_feature(
5516             sw_if_index=self.pg0.sw_if_index,
5517             is_add=1)
5518         self.vapi.nat44_interface_add_del_feature(
5519             sw_if_index=self.pg0.sw_if_index,
5520             flags=flags, is_add=1)
5521         self.vapi.nat44_interface_add_del_output_feature(
5522             is_add=1,
5523             sw_if_index=self.pg1.sw_if_index)
5524
5525         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5526              IP(src=self.pg0.remote_ip4, dst=external_addr) /
5527              TCP(sport=12345, dport=external_port))
5528         self.pg0.add_stream(p)
5529         self.pg_enable_capture(self.pg_interfaces)
5530         self.pg_start()
5531         capture = self.pg1.get_capture(1)
5532         p = capture[0]
5533         try:
5534             ip = p[IP]
5535             tcp = p[TCP]
5536             self.assertEqual(ip.src, self.pg0.remote_ip4)
5537             self.assertEqual(tcp.sport, 12345)
5538             self.assertEqual(ip.dst, self.pg1.remote_ip4)
5539             self.assertEqual(tcp.dport, local_port)
5540             self.assert_packet_checksums_valid(p)
5541         except:
5542             self.logger.error(ppp("Unexpected or invalid packet:", p))
5543             raise
5544
5545         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5546              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5547              TCP(sport=local_port, dport=12345))
5548         self.pg1.add_stream(p)
5549         self.pg_enable_capture(self.pg_interfaces)
5550         self.pg_start()
5551         capture = self.pg0.get_capture(1)
5552         p = capture[0]
5553         try:
5554             ip = p[IP]
5555             tcp = p[TCP]
5556             self.assertEqual(ip.src, external_addr)
5557             self.assertEqual(tcp.sport, external_port)
5558             self.assertEqual(ip.dst, self.pg0.remote_ip4)
5559             self.assertEqual(tcp.dport, 12345)
5560             self.assert_packet_checksums_valid(p)
5561         except:
5562             self.logger.error(ppp("Unexpected or invalid packet:", p))
5563             raise
5564
5565     def test_next_src_nat(self):
5566         """ On way back forward packet to nat44-in2out node. """
5567         twice_nat_addr = '10.0.1.3'
5568         external_port = 80
5569         local_port = 8080
5570         post_twice_nat_port = 0
5571
5572         self.vapi.nat44_forwarding_enable_disable(enable=1)
5573         self.nat44_add_address(twice_nat_addr, twice_nat=1)
5574         flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5575                  self.config_flags.NAT_IS_SELF_TWICE_NAT)
5576         self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5577                                       local_port, external_port,
5578                                       proto=IP_PROTOS.tcp, vrf_id=1,
5579                                       flags=flags)
5580         self.vapi.nat44_interface_add_del_feature(
5581             sw_if_index=self.pg6.sw_if_index,
5582             is_add=1)
5583
5584         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5585              IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5586              TCP(sport=12345, dport=external_port))
5587         self.pg6.add_stream(p)
5588         self.pg_enable_capture(self.pg_interfaces)
5589         self.pg_start()
5590         capture = self.pg6.get_capture(1)
5591         p = capture[0]
5592         try:
5593             ip = p[IP]
5594             tcp = p[TCP]
5595             self.assertEqual(ip.src, twice_nat_addr)
5596             self.assertNotEqual(tcp.sport, 12345)
5597             post_twice_nat_port = tcp.sport
5598             self.assertEqual(ip.dst, self.pg6.remote_ip4)
5599             self.assertEqual(tcp.dport, local_port)
5600             self.assert_packet_checksums_valid(p)
5601         except:
5602             self.logger.error(ppp("Unexpected or invalid packet:", p))
5603             raise
5604
5605         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5606              IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5607              TCP(sport=local_port, dport=post_twice_nat_port))
5608         self.pg6.add_stream(p)
5609         self.pg_enable_capture(self.pg_interfaces)
5610         self.pg_start()
5611         capture = self.pg6.get_capture(1)
5612         p = capture[0]
5613         try:
5614             ip = p[IP]
5615             tcp = p[TCP]
5616             self.assertEqual(ip.src, self.pg1.remote_ip4)
5617             self.assertEqual(tcp.sport, external_port)
5618             self.assertEqual(ip.dst, self.pg6.remote_ip4)
5619             self.assertEqual(tcp.dport, 12345)
5620             self.assert_packet_checksums_valid(p)
5621         except:
5622             self.logger.error(ppp("Unexpected or invalid packet:", p))
5623             raise
5624
5625     def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5626                          client_id=None):
5627         twice_nat_addr = '10.0.1.3'
5628
5629         port_in = 8080
5630         if lb:
5631             if not same_pg:
5632                 port_in1 = port_in
5633                 port_in2 = port_in
5634             else:
5635                 port_in1 = port_in + 1
5636                 port_in2 = port_in + 2
5637
5638         port_out = 80
5639         eh_port_out = 4567
5640
5641         server1 = self.pg0.remote_hosts[0]
5642         server2 = self.pg0.remote_hosts[1]
5643         if lb and same_pg:
5644             server2 = server1
5645         if not lb:
5646             server = server1
5647
5648         pg0 = self.pg0
5649         if same_pg:
5650             pg1 = self.pg0
5651         else:
5652             pg1 = self.pg1
5653
5654         eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5655                         client_id == 1)
5656
5657         self.nat44_add_address(self.nat_addr)
5658         self.nat44_add_address(twice_nat_addr, twice_nat=1)
5659
5660         flags = 0
5661         if self_twice_nat:
5662             flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
5663         else:
5664             flags |= self.config_flags.NAT_IS_TWICE_NAT
5665
5666         if not lb:
5667             self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5668                                           port_in, port_out,
5669                                           proto=IP_PROTOS.tcp,
5670                                           flags=flags)
5671         else:
5672             locals = [{'addr': server1.ip4,
5673                        'port': port_in1,
5674                        'probability': 50,
5675                        'vrf_id': 0},
5676                       {'addr': server2.ip4,
5677                        'port': port_in2,
5678                        'probability': 50,
5679                        'vrf_id': 0}]
5680             out_addr = self.nat_addr
5681
5682             self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5683                                                       external_addr=out_addr,
5684                                                       external_port=port_out,
5685                                                       protocol=IP_PROTOS.tcp,
5686                                                       local_num=len(locals),
5687                                                       locals=locals)
5688         flags = self.config_flags.NAT_IS_INSIDE
5689         self.vapi.nat44_interface_add_del_feature(
5690             sw_if_index=pg0.sw_if_index,
5691             flags=flags, is_add=1)
5692         self.vapi.nat44_interface_add_del_feature(
5693             sw_if_index=pg1.sw_if_index,
5694             is_add=1)
5695
5696         if same_pg:
5697             if not lb:
5698                 client = server
5699             else:
5700                 assert client_id is not None
5701                 if client_id == 1:
5702                     client = self.pg0.remote_hosts[0]
5703                 elif client_id == 2:
5704                     client = self.pg0.remote_hosts[1]
5705         else:
5706             client = pg1.remote_hosts[0]
5707         p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5708              IP(src=client.ip4, dst=self.nat_addr) /
5709              TCP(sport=eh_port_out, dport=port_out))
5710         pg1.add_stream(p)
5711         self.pg_enable_capture(self.pg_interfaces)
5712         self.pg_start()
5713         capture = pg0.get_capture(1)
5714         p = capture[0]
5715         try:
5716             ip = p[IP]
5717             tcp = p[TCP]
5718             if lb:
5719                 if ip.dst == server1.ip4:
5720                     server = server1
5721                     port_in = port_in1
5722                 else:
5723                     server = server2
5724                     port_in = port_in2
5725             self.assertEqual(ip.dst, server.ip4)
5726             if lb and same_pg:
5727                 self.assertIn(tcp.dport, [port_in1, port_in2])
5728             else:
5729                 self.assertEqual(tcp.dport, port_in)
5730             if eh_translate:
5731                 self.assertEqual(ip.src, twice_nat_addr)
5732                 self.assertNotEqual(tcp.sport, eh_port_out)
5733             else:
5734                 self.assertEqual(ip.src, client.ip4)
5735                 self.assertEqual(tcp.sport, eh_port_out)
5736             eh_addr_in = ip.src
5737             eh_port_in = tcp.sport
5738             saved_port_in = tcp.dport
5739             self.assert_packet_checksums_valid(p)
5740         except:
5741             self.logger.error(ppp("Unexpected or invalid packet:", p))
5742             raise
5743
5744         p = (Ether(src=server.mac, dst=pg0.local_mac) /
5745              IP(src=server.ip4, dst=eh_addr_in) /
5746              TCP(sport=saved_port_in, dport=eh_port_in))
5747         pg0.add_stream(p)
5748         self.pg_enable_capture(self.pg_interfaces)
5749         self.pg_start()
5750         capture = pg1.get_capture(1)
5751         p = capture[0]
5752         try:
5753             ip = p[IP]
5754             tcp = p[TCP]
5755             self.assertEqual(ip.dst, client.ip4)
5756             self.assertEqual(ip.src, self.nat_addr)
5757             self.assertEqual(tcp.dport, eh_port_out)
5758             self.assertEqual(tcp.sport, port_out)
5759             self.assert_packet_checksums_valid(p)
5760         except:
5761             self.logger.error(ppp("Unexpected or invalid packet:", p))
5762             raise
5763
5764         if eh_translate:
5765             sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5766             self.assertEqual(len(sessions), 1)
5767             self.assertTrue(sessions[0].flags &
5768                             self.config_flags.NAT_IS_EXT_HOST_VALID)
5769             self.assertTrue(sessions[0].flags &
5770                             self.config_flags.NAT_IS_TWICE_NAT)
5771             self.logger.info(self.vapi.cli("show nat44 sessions detail"))
5772             self.vapi.nat44_del_session(
5773                 address=sessions[0].inside_ip_address,
5774                 port=sessions[0].inside_port,
5775                 protocol=sessions[0].protocol,
5776                 flags=(self.config_flags.NAT_IS_INSIDE |
5777                        self.config_flags.NAT_IS_EXT_HOST_VALID),
5778                 ext_host_address=sessions[0].ext_host_nat_address,
5779                 ext_host_port=sessions[0].ext_host_nat_port)
5780             sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5781             self.assertEqual(len(sessions), 0)
5782
5783     def test_twice_nat(self):
5784         """ Twice NAT44 """
5785         self.twice_nat_common()
5786
5787     def test_self_twice_nat_positive(self):
5788         """ Self Twice NAT44 (positive test) """
5789         self.twice_nat_common(self_twice_nat=True, same_pg=True)
5790
5791     def test_self_twice_nat_negative(self):
5792         """ Self Twice NAT44 (negative test) """
5793         self.twice_nat_common(self_twice_nat=True)
5794
5795     def test_twice_nat_lb(self):
5796         """ Twice NAT44 local service load balancing """
5797         self.twice_nat_common(lb=True)
5798
5799     def test_self_twice_nat_lb_positive(self):
5800         """ Self Twice NAT44 local service load balancing (positive test) """
5801         self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5802                               client_id=1)
5803
5804     def test_self_twice_nat_lb_negative(self):
5805         """ Self Twice NAT44 local service load balancing (negative test) """
5806         self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5807                               client_id=2)
5808
5809     def test_twice_nat_interface_addr(self):
5810         """ Acquire twice NAT44 addresses from interface """
5811         flags = self.config_flags.NAT_IS_TWICE_NAT
5812         self.vapi.nat44_add_del_interface_addr(
5813             is_add=1,
5814             sw_if_index=self.pg3.sw_if_index,
5815             flags=flags)
5816
5817         # no address in NAT pool
5818         adresses = self.vapi.nat44_address_dump()
5819         self.assertEqual(0, len(adresses))
5820
5821         # configure interface address and check NAT address pool
5822         self.pg3.config_ip4()
5823         adresses = self.vapi.nat44_address_dump()
5824         self.assertEqual(1, len(adresses))
5825         self.assertEqual(str(adresses[0].ip_address),
5826                          self.pg3.local_ip4)
5827         self.assertEqual(adresses[0].flags, flags)
5828
5829         # remove interface address and check NAT address pool
5830         self.pg3.unconfig_ip4()
5831         adresses = self.vapi.nat44_address_dump()
5832         self.assertEqual(0, len(adresses))
5833
5834     def test_tcp_close(self):
5835         """ Close TCP session from inside network - output feature """
5836         self.vapi.nat44_forwarding_enable_disable(enable=1)
5837         self.nat44_add_address(self.pg1.local_ip4)
5838         twice_nat_addr = '10.0.1.3'
5839         service_ip = '192.168.16.150'
5840         self.nat44_add_address(twice_nat_addr, twice_nat=1)
5841         flags = self.config_flags.NAT_IS_INSIDE
5842         self.vapi.nat44_interface_add_del_feature(
5843             sw_if_index=self.pg0.sw_if_index,
5844             is_add=1)
5845         self.vapi.nat44_interface_add_del_feature(
5846             sw_if_index=self.pg0.sw_if_index,
5847             flags=flags, is_add=1)
5848         self.vapi.nat44_interface_add_del_output_feature(
5849             is_add=1,
5850             sw_if_index=self.pg1.sw_if_index)
5851         flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5852                  self.config_flags.NAT_IS_TWICE_NAT)
5853         self.nat44_add_static_mapping(self.pg0.remote_ip4,
5854                                       service_ip,
5855                                       80,
5856                                       80,
5857                                       proto=IP_PROTOS.tcp,
5858                                       flags=flags)
5859         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5860         start_sessnum = len(sessions)
5861
5862         # SYN packet out->in
5863         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5864              IP(src=self.pg1.remote_ip4, dst=service_ip) /
5865              TCP(sport=33898, dport=80, flags="S"))
5866         self.pg1.add_stream(p)
5867         self.pg_enable_capture(self.pg_interfaces)
5868         self.pg_start()
5869         capture = self.pg0.get_capture(1)
5870         p = capture[0]
5871         tcp_port = p[TCP].sport
5872
5873         # SYN + ACK packet in->out
5874         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5875              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5876              TCP(sport=80, dport=tcp_port, flags="SA"))
5877         self.pg0.add_stream(p)
5878         self.pg_enable_capture(self.pg_interfaces)
5879         self.pg_start()
5880         self.pg1.get_capture(1)
5881
5882         # ACK packet out->in
5883         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5884              IP(src=self.pg1.remote_ip4, dst=service_ip) /
5885              TCP(sport=33898, dport=80, flags="A"))
5886         self.pg1.add_stream(p)
5887         self.pg_enable_capture(self.pg_interfaces)
5888         self.pg_start()
5889         self.pg0.get_capture(1)
5890
5891         # FIN packet in -> out
5892         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5893              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5894              TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5895         self.pg0.add_stream(p)
5896         self.pg_enable_capture(self.pg_interfaces)
5897         self.pg_start()
5898         self.pg1.get_capture(1)
5899
5900         # FIN+ACK packet out -> in
5901         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5902              IP(src=self.pg1.remote_ip4, dst=service_ip) /
5903              TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5904         self.pg1.add_stream(p)
5905         self.pg_enable_capture(self.pg_interfaces)
5906         self.pg_start()
5907         self.pg0.get_capture(1)
5908
5909         # ACK packet in -> out
5910         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5911              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5912              TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5913         self.pg0.add_stream(p)
5914         self.pg_enable_capture(self.pg_interfaces)
5915         self.pg_start()
5916         self.pg1.get_capture(1)
5917
5918         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4,
5919                                                      0)
5920         self.assertEqual(len(sessions) - start_sessnum, 0)
5921
5922     def test_tcp_session_close_in(self):
5923         """ Close TCP session from inside network """
5924         self.tcp_port_out = 10505
5925         self.nat44_add_address(self.nat_addr)
5926         flags = self.config_flags.NAT_IS_TWICE_NAT
5927         self.nat44_add_static_mapping(self.pg0.remote_ip4,
5928                                       self.nat_addr,
5929                                       self.tcp_port_in,
5930                                       self.tcp_port_out,
5931                                       proto=IP_PROTOS.tcp,
5932                                       flags=flags)
5933         flags = self.config_flags.NAT_IS_INSIDE
5934         self.vapi.nat44_interface_add_del_feature(
5935             sw_if_index=self.pg0.sw_if_index,
5936             flags=flags, is_add=1)
5937         self.vapi.nat44_interface_add_del_feature(
5938             sw_if_index=self.pg1.sw_if_index,
5939             is_add=1)
5940
5941         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5942         start_sessnum = len(sessions)
5943
5944         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
5945                                    tcp_transitory=2, icmp=5)
5946
5947         self.initiate_tcp_session(self.pg0, self.pg1)
5948
5949         # FIN packet in -> out
5950         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5951              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5952              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5953                  flags="FA", seq=100, ack=300))
5954         self.pg0.add_stream(p)
5955         self.pg_enable_capture(self.pg_interfaces)
5956         self.pg_start()
5957         self.pg1.get_capture(1)
5958
5959         pkts = []
5960
5961         # ACK packet out -> in
5962         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5963              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5964              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5965                  flags="A", seq=300, ack=101))
5966         pkts.append(p)
5967
5968         # FIN packet out -> in
5969         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5970              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5971              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5972                  flags="FA", seq=300, ack=101))
5973         pkts.append(p)
5974
5975         self.pg1.add_stream(pkts)
5976         self.pg_enable_capture(self.pg_interfaces)
5977         self.pg_start()
5978         self.pg0.get_capture(2)
5979
5980         # ACK packet in -> out
5981         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5982              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5983              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5984                  flags="A", seq=101, ack=301))
5985         self.pg0.add_stream(p)
5986         self.pg_enable_capture(self.pg_interfaces)
5987         self.pg_start()
5988         self.pg1.get_capture(1)
5989
5990         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5991         self.assertEqual(len(sessions) - start_sessnum, 1)
5992
5993         stats = self.statistics.get_counter(
5994             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
5995         out2in_drops = stats[0]
5996         stats = self.statistics.get_counter(
5997             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
5998         in2out_drops = stats[0]
5999
6000         # extra FIN packet out -> in - this should be dropped
6001         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6002              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6003              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6004                  flags="FA", seq=300, ack=101))
6005
6006         self.pg1.add_stream(p)
6007         self.pg_enable_capture(self.pg_interfaces)
6008         self.pg_start()
6009         self.pg0.assert_nothing_captured()
6010
6011         # extra ACK packet in -> out - this should be dropped
6012         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6013              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6014              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6015                  flags="A", seq=101, ack=301))
6016         self.pg0.add_stream(p)
6017         self.pg_enable_capture(self.pg_interfaces)
6018         self.pg_start()
6019         self.pg1.assert_nothing_captured()
6020
6021         stats = self.statistics.get_counter(
6022             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6023         self.assertEqual(stats[0] - out2in_drops, 1)
6024         stats = self.statistics.get_counter(
6025             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6026         self.assertEqual(stats[0] - in2out_drops, 1)
6027
6028         self.sleep(3)
6029         # extra ACK packet in -> out - this will cause session to be wiped
6030         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6031              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6032              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6033                  flags="A", seq=101, ack=301))
6034         self.pg0.add_stream(p)
6035         self.pg_enable_capture(self.pg_interfaces)
6036         self.pg_start()
6037         self.pg1.assert_nothing_captured()
6038         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6039         self.assertEqual(len(sessions) - start_sessnum, 0)
6040
6041     def test_tcp_session_close_out(self):
6042         """ Close TCP session from outside network """
6043         self.tcp_port_out = 10505
6044         self.nat44_add_address(self.nat_addr)
6045         flags = self.config_flags.NAT_IS_TWICE_NAT
6046         self.nat44_add_static_mapping(self.pg0.remote_ip4,
6047                                       self.nat_addr,
6048                                       self.tcp_port_in,
6049                                       self.tcp_port_out,
6050                                       proto=IP_PROTOS.tcp,
6051                                       flags=flags)
6052         flags = self.config_flags.NAT_IS_INSIDE
6053         self.vapi.nat44_interface_add_del_feature(
6054             sw_if_index=self.pg0.sw_if_index,
6055             flags=flags, is_add=1)
6056         self.vapi.nat44_interface_add_del_feature(
6057             sw_if_index=self.pg1.sw_if_index,
6058             is_add=1)
6059
6060         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6061         start_sessnum = len(sessions)
6062
6063         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6064                                    tcp_transitory=2, icmp=5)
6065
6066         self.initiate_tcp_session(self.pg0, self.pg1)
6067
6068         # FIN packet out -> in
6069         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6070              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6071              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6072                  flags="FA", seq=100, ack=300))
6073         self.pg1.add_stream(p)
6074         self.pg_enable_capture(self.pg_interfaces)
6075         self.pg_start()
6076         self.pg0.get_capture(1)
6077
6078         # FIN+ACK packet in -> out
6079         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6080              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6081              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6082                  flags="FA", seq=300, ack=101))
6083
6084         self.pg0.add_stream(p)
6085         self.pg_enable_capture(self.pg_interfaces)
6086         self.pg_start()
6087         self.pg1.get_capture(1)
6088
6089         # ACK packet out -> in
6090         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6091              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6092              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6093                  flags="A", seq=101, ack=301))
6094         self.pg1.add_stream(p)
6095         self.pg_enable_capture(self.pg_interfaces)
6096         self.pg_start()
6097         self.pg0.get_capture(1)
6098
6099         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6100         self.assertEqual(len(sessions) - start_sessnum, 1)
6101
6102         stats = self.statistics.get_counter(
6103             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6104         out2in_drops = stats[0]
6105         stats = self.statistics.get_counter(
6106             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6107         in2out_drops = stats[0]
6108
6109         # extra FIN packet out -> in - this should be dropped
6110         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6111              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6112              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6113                  flags="FA", seq=300, ack=101))
6114
6115         self.pg1.add_stream(p)
6116         self.pg_enable_capture(self.pg_interfaces)
6117         self.pg_start()
6118         self.pg0.assert_nothing_captured()
6119
6120         # extra ACK packet in -> out - this should be dropped
6121         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6122              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6123              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6124                  flags="A", seq=101, ack=301))
6125         self.pg0.add_stream(p)
6126         self.pg_enable_capture(self.pg_interfaces)
6127         self.pg_start()
6128         self.pg1.assert_nothing_captured()
6129
6130         stats = self.statistics.get_counter(
6131             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6132         self.assertEqual(stats[0] - out2in_drops, 1)
6133         stats = self.statistics.get_counter(
6134             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6135         self.assertEqual(stats[0] - in2out_drops, 1)
6136
6137         self.sleep(3)
6138         # extra ACK packet in -> out - this will cause session to be wiped
6139         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6140              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6141              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6142                  flags="A", seq=101, ack=301))
6143         self.pg0.add_stream(p)
6144         self.pg_enable_capture(self.pg_interfaces)
6145         self.pg_start()
6146         self.pg1.assert_nothing_captured()
6147         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6148         self.assertEqual(len(sessions) - start_sessnum, 0)
6149
6150     def test_tcp_session_close_simultaneous(self):
6151         """ Close TCP session from inside network """
6152         self.tcp_port_out = 10505
6153         self.nat44_add_address(self.nat_addr)
6154         flags = self.config_flags.NAT_IS_TWICE_NAT
6155         self.nat44_add_static_mapping(self.pg0.remote_ip4,
6156                                       self.nat_addr,
6157                                       self.tcp_port_in,
6158                                       self.tcp_port_out,
6159                                       proto=IP_PROTOS.tcp,
6160                                       flags=flags)
6161         flags = self.config_flags.NAT_IS_INSIDE
6162         self.vapi.nat44_interface_add_del_feature(
6163             sw_if_index=self.pg0.sw_if_index,
6164             flags=flags, is_add=1)
6165         self.vapi.nat44_interface_add_del_feature(
6166             sw_if_index=self.pg1.sw_if_index,
6167             is_add=1)
6168
6169         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6170         start_sessnum = len(sessions)
6171
6172         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6173                                    tcp_transitory=2, icmp=5)
6174
6175         self.initiate_tcp_session(self.pg0, self.pg1)
6176
6177         # FIN packet in -> out
6178         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6179              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6180              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6181                  flags="FA", seq=100, ack=300))
6182         self.pg0.add_stream(p)
6183         self.pg_enable_capture(self.pg_interfaces)
6184         self.pg_start()
6185         self.pg1.get_capture(1)
6186
6187         # FIN packet out -> in
6188         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6189              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6190              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6191                  flags="FA", seq=300, ack=100))
6192         self.pg1.add_stream(p)
6193         self.pg_enable_capture(self.pg_interfaces)
6194         self.pg_start()
6195         self.pg0.get_capture(1)
6196
6197         # ACK packet in -> out
6198         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6199              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6200              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6201                  flags="A", seq=101, ack=301))
6202         self.pg0.add_stream(p)
6203         self.pg_enable_capture(self.pg_interfaces)
6204         self.pg_start()
6205         self.pg1.get_capture(1)
6206
6207         # ACK packet out -> in
6208         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6209              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6210              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6211                  flags="A", seq=301, ack=101))
6212         self.pg1.add_stream(p)
6213         self.pg_enable_capture(self.pg_interfaces)
6214         self.pg_start()
6215         self.pg0.get_capture(1)
6216
6217         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6218         self.assertEqual(len(sessions) - start_sessnum, 1)
6219
6220         stats = self.statistics.get_counter(
6221             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6222         out2in_drops = stats[0]
6223         stats = self.statistics.get_counter(
6224             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6225         in2out_drops = stats[0]
6226
6227         # extra FIN packet out -> in - this should be dropped
6228         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6229              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6230              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6231                  flags="FA", seq=300, ack=101))
6232
6233         self.pg1.add_stream(p)
6234         self.pg_enable_capture(self.pg_interfaces)
6235         self.pg_start()
6236         self.pg0.assert_nothing_captured()
6237
6238         # extra ACK packet in -> out - this should be dropped
6239         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6240              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6241              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6242                  flags="A", seq=101, ack=301))
6243         self.pg0.add_stream(p)
6244         self.pg_enable_capture(self.pg_interfaces)
6245         self.pg_start()
6246         self.pg1.assert_nothing_captured()
6247
6248         stats = self.statistics.get_counter(
6249             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6250         self.assertEqual(stats[0] - out2in_drops, 1)
6251         stats = self.statistics.get_counter(
6252             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6253         self.assertEqual(stats[0] - in2out_drops, 1)
6254
6255         self.sleep(3)
6256         # extra ACK packet in -> out - this will cause session to be wiped
6257         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6258              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6259              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6260                  flags="A", seq=101, ack=301))
6261         self.pg0.add_stream(p)
6262         self.pg_enable_capture(self.pg_interfaces)
6263         self.pg_start()
6264         self.pg1.assert_nothing_captured()
6265         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6266         self.assertEqual(len(sessions) - start_sessnum, 0)
6267
6268     def test_one_armed_nat44_static(self):
6269         """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
6270         remote_host = self.pg4.remote_hosts[0]
6271         local_host = self.pg4.remote_hosts[1]
6272         external_port = 80
6273         local_port = 8080
6274         eh_port_in = 0
6275
6276         self.vapi.nat44_forwarding_enable_disable(enable=1)
6277         self.nat44_add_address(self.nat_addr, twice_nat=1)
6278         flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
6279                  self.config_flags.NAT_IS_TWICE_NAT)
6280         self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
6281                                       local_port, external_port,
6282                                       proto=IP_PROTOS.tcp, flags=flags)
6283         flags = self.config_flags.NAT_IS_INSIDE
6284         self.vapi.nat44_interface_add_del_feature(
6285             sw_if_index=self.pg4.sw_if_index,
6286             is_add=1)
6287         self.vapi.nat44_interface_add_del_feature(
6288             sw_if_index=self.pg4.sw_if_index,
6289             flags=flags, is_add=1)
6290
6291         # from client to service
6292         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6293              IP(src=remote_host.ip4, dst=self.nat_addr) /
6294              TCP(sport=12345, dport=external_port))
6295         self.pg4.add_stream(p)
6296         self.pg_enable_capture(self.pg_interfaces)
6297         self.pg_start()
6298         capture = self.pg4.get_capture(1)
6299         p = capture[0]
6300         try:
6301             ip = p[IP]
6302             tcp = p[TCP]
6303             self.assertEqual(ip.dst, local_host.ip4)
6304             self.assertEqual(ip.src, self.nat_addr)
6305             self.assertEqual(tcp.dport, local_port)
6306             self.assertNotEqual(tcp.sport, 12345)
6307             eh_port_in = tcp.sport
6308             self.assert_packet_checksums_valid(p)
6309         except:
6310             self.logger.error(ppp("Unexpected or invalid packet:", p))
6311             raise
6312
6313         # from service back to client
6314         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6315              IP(src=local_host.ip4, dst=self.nat_addr) /
6316              TCP(sport=local_port, dport=eh_port_in))
6317         self.pg4.add_stream(p)
6318         self.pg_enable_capture(self.pg_interfaces)
6319         self.pg_start()
6320         capture = self.pg4.get_capture(1)
6321         p = capture[0]
6322         try:
6323             ip = p[IP]
6324             tcp = p[TCP]
6325             self.assertEqual(ip.src, self.nat_addr)
6326             self.assertEqual(ip.dst, remote_host.ip4)
6327             self.assertEqual(tcp.sport, external_port)
6328             self.assertEqual(tcp.dport, 12345)
6329             self.assert_packet_checksums_valid(p)
6330         except:
6331             self.logger.error(ppp("Unexpected or invalid packet:", p))
6332             raise
6333
6334     def test_static_with_port_out2(self):
6335         """ 1:1 NAPT asymmetrical rule """
6336
6337         external_port = 80
6338         local_port = 8080
6339
6340         self.vapi.nat44_forwarding_enable_disable(enable=1)
6341         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6342         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
6343                                       local_port, external_port,
6344                                       proto=IP_PROTOS.tcp, flags=flags)
6345         flags = self.config_flags.NAT_IS_INSIDE
6346         self.vapi.nat44_interface_add_del_feature(
6347             sw_if_index=self.pg0.sw_if_index,
6348             flags=flags, is_add=1)
6349         self.vapi.nat44_interface_add_del_feature(
6350             sw_if_index=self.pg1.sw_if_index,
6351             is_add=1)
6352
6353         # from client to service
6354         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6355              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6356              TCP(sport=12345, dport=external_port))
6357         self.pg1.add_stream(p)
6358         self.pg_enable_capture(self.pg_interfaces)
6359         self.pg_start()
6360         capture = self.pg0.get_capture(1)
6361         p = capture[0]
6362         try:
6363             ip = p[IP]
6364             tcp = p[TCP]
6365             self.assertEqual(ip.dst, self.pg0.remote_ip4)
6366             self.assertEqual(tcp.dport, local_port)
6367             self.assert_packet_checksums_valid(p)
6368         except:
6369             self.logger.error(ppp("Unexpected or invalid packet:", p))
6370             raise
6371
6372         # ICMP error
6373         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6374              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6375              ICMP(type=11) / capture[0][IP])
6376         self.pg0.add_stream(p)
6377         self.pg_enable_capture(self.pg_interfaces)
6378         self.pg_start()
6379         capture = self.pg1.get_capture(1)
6380         p = capture[0]
6381         try:
6382             self.assertEqual(p[IP].src, self.nat_addr)
6383             inner = p[IPerror]
6384             self.assertEqual(inner.dst, self.nat_addr)
6385             self.assertEqual(inner[TCPerror].dport, external_port)
6386         except:
6387             self.logger.error(ppp("Unexpected or invalid packet:", p))
6388             raise
6389
6390         # from service back to client
6391         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6392              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6393              TCP(sport=local_port, dport=12345))
6394         self.pg0.add_stream(p)
6395         self.pg_enable_capture(self.pg_interfaces)
6396         self.pg_start()
6397         capture = self.pg1.get_capture(1)
6398         p = capture[0]
6399         try:
6400             ip = p[IP]
6401             tcp = p[TCP]
6402             self.assertEqual(ip.src, self.nat_addr)
6403             self.assertEqual(tcp.sport, external_port)
6404             self.assert_packet_checksums_valid(p)
6405         except:
6406             self.logger.error(ppp("Unexpected or invalid packet:", p))
6407             raise
6408
6409         # ICMP error
6410         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6411              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6412              ICMP(type=11) / capture[0][IP])
6413         self.pg1.add_stream(p)
6414         self.pg_enable_capture(self.pg_interfaces)
6415         self.pg_start()
6416         capture = self.pg0.get_capture(1)
6417         p = capture[0]
6418         try:
6419             self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
6420             inner = p[IPerror]
6421             self.assertEqual(inner.src, self.pg0.remote_ip4)
6422             self.assertEqual(inner[TCPerror].sport, local_port)
6423         except:
6424             self.logger.error(ppp("Unexpected or invalid packet:", p))
6425             raise
6426
6427         # from client to server (no translation)
6428         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6429              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
6430              TCP(sport=12346, dport=local_port))
6431         self.pg1.add_stream(p)
6432         self.pg_enable_capture(self.pg_interfaces)
6433         self.pg_start()
6434         capture = self.pg0.get_capture(1)
6435         p = capture[0]
6436         try:
6437             ip = p[IP]
6438             tcp = p[TCP]
6439             self.assertEqual(ip.dst, self.pg0.remote_ip4)
6440             self.assertEqual(tcp.dport, local_port)
6441             self.assert_packet_checksums_valid(p)
6442         except:
6443             self.logger.error(ppp("Unexpected or invalid packet:", p))
6444             raise
6445
6446         # from service back to client (no translation)
6447         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6448              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6449              TCP(sport=local_port, dport=12346))
6450         self.pg0.add_stream(p)
6451         self.pg_enable_capture(self.pg_interfaces)
6452         self.pg_start()
6453         capture = self.pg1.get_capture(1)
6454         p = capture[0]
6455         try:
6456             ip = p[IP]
6457             tcp = p[TCP]
6458             self.assertEqual(ip.src, self.pg0.remote_ip4)
6459             self.assertEqual(tcp.sport, local_port)
6460             self.assert_packet_checksums_valid(p)
6461         except:
6462             self.logger.error(ppp("Unexpected or invalid packet:", p))
6463             raise
6464
6465     def test_output_feature(self):
6466         """ NAT44 interface output feature (in2out postrouting) """
6467         self.vapi.nat44_forwarding_enable_disable(enable=1)
6468         self.nat44_add_address(self.nat_addr)
6469         self.vapi.nat44_interface_add_del_feature(
6470             sw_if_index=self.pg0.sw_if_index,
6471             is_add=1)
6472         self.vapi.nat44_interface_add_del_output_feature(
6473             is_add=1,
6474             sw_if_index=self.pg1.sw_if_index)
6475
6476         # in2out
6477         pkts = self.create_stream_in(self.pg0, self.pg1)
6478         self.pg0.add_stream(pkts)
6479         self.pg_enable_capture(self.pg_interfaces)
6480         self.pg_start()
6481         capture = self.pg1.get_capture(len(pkts))
6482         self.verify_capture_out(capture)
6483
6484         # out2in
6485         pkts = self.create_stream_out(self.pg1)
6486         self.pg1.add_stream(pkts)
6487         self.pg_enable_capture(self.pg_interfaces)
6488         self.pg_start()
6489         capture = self.pg0.get_capture(len(pkts))
6490         self.verify_capture_in(capture, self.pg0)
6491
6492     def test_output_feature_stateful_acl(self):
6493         """ NAT44 endpoint-dependent output feature works with stateful ACL """
6494         self.nat44_add_address(self.nat_addr)
6495         self.vapi.nat44_interface_add_del_output_feature(
6496             sw_if_index=self.pg0.sw_if_index,
6497             flags=self.config_flags.NAT_IS_INSIDE,
6498             is_add=1)
6499         self.vapi.nat44_interface_add_del_output_feature(
6500             sw_if_index=self.pg1.sw_if_index,
6501             flags=self.config_flags.NAT_IS_OUTSIDE,
6502             is_add=1)
6503
6504         # First ensure that the NAT is working sans ACL
6505
6506         # send packets out2in, no sessions yet so packets should drop
6507         pkts_out2in = self.create_stream_out(self.pg1)
6508         self.send_and_assert_no_replies(self.pg1, pkts_out2in)
6509
6510         # send packets into inside intf, ensure received via outside intf
6511         pkts_in2out = self.create_stream_in(self.pg0, self.pg1)
6512         capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
6513                                        len(pkts_in2out))
6514         self.verify_capture_out(capture)
6515
6516         # send out2in again, with sessions created it should work now
6517         pkts_out2in = self.create_stream_out(self.pg1)
6518         capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
6519                                        len(pkts_out2in))
6520         self.verify_capture_in(capture, self.pg0)
6521
6522         # Create an ACL blocking everything
6523         out2in_deny_rule = AclRule(is_permit=0)
6524         out2in_acl = VppAcl(self, rules=[out2in_deny_rule])
6525         out2in_acl.add_vpp_config()
6526
6527         # create an ACL to permit/reflect everything
6528         in2out_reflect_rule = AclRule(is_permit=2)
6529         in2out_acl = VppAcl(self, rules=[in2out_reflect_rule])
6530         in2out_acl.add_vpp_config()
6531
6532         # apply as input acl on interface and confirm it blocks everything
6533         acl_if = VppAclInterface(self, sw_if_index=self.pg1.sw_if_index,
6534                                  n_input=1, acls=[out2in_acl])
6535         acl_if.add_vpp_config()
6536         self.send_and_assert_no_replies(self.pg1, pkts_out2in)
6537
6538         # apply output acl
6539         acl_if.acls = [out2in_acl, in2out_acl]
6540         acl_if.add_vpp_config()
6541         # send in2out to generate ACL state (NAT state was created earlier)
6542         capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
6543                                        len(pkts_in2out))
6544         self.verify_capture_out(capture)
6545
6546         # send out2in again. ACL state exists so it should work now.
6547         # TCP packets with the syn flag set also need the ack flag
6548         for p in pkts_out2in:
6549             if p.haslayer(TCP) and p[TCP].flags & 0x02:
6550                 p[TCP].flags |= 0x10
6551         capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
6552                                        len(pkts_out2in))
6553         self.verify_capture_in(capture, self.pg0)
6554         self.logger.info(self.vapi.cli("show trace"))
6555
6556     def test_multiple_vrf(self):
6557         """ Multiple VRF setup """
6558         external_addr = '1.2.3.4'
6559         external_port = 80
6560         local_port = 8080
6561         port = 0
6562
6563         self.vapi.nat44_forwarding_enable_disable(enable=1)
6564         self.nat44_add_address(self.nat_addr)
6565         flags = self.config_flags.NAT_IS_INSIDE
6566         self.vapi.nat44_interface_add_del_feature(
6567             sw_if_index=self.pg0.sw_if_index,
6568             is_add=1)
6569         self.vapi.nat44_interface_add_del_feature(
6570             sw_if_index=self.pg0.sw_if_index,
6571             flags=flags, is_add=1)
6572         self.vapi.nat44_interface_add_del_output_feature(
6573             is_add=1,
6574             sw_if_index=self.pg1.sw_if_index)
6575         self.vapi.nat44_interface_add_del_feature(
6576             sw_if_index=self.pg5.sw_if_index,
6577             is_add=1)
6578         self.vapi.nat44_interface_add_del_feature(
6579             sw_if_index=self.pg5.sw_if_index,
6580             flags=flags, is_add=1)
6581         self.vapi.nat44_interface_add_del_feature(
6582             sw_if_index=self.pg6.sw_if_index,
6583             is_add=1)
6584         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6585         self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
6586                                       local_port, external_port, vrf_id=1,
6587                                       proto=IP_PROTOS.tcp, flags=flags)
6588         self.nat44_add_static_mapping(
6589             self.pg0.remote_ip4,
6590             external_sw_if_index=self.pg0.sw_if_index,
6591             local_port=local_port,
6592             vrf_id=0,
6593             external_port=external_port,
6594             proto=IP_PROTOS.tcp,
6595             flags=flags
6596         )
6597
6598         # from client to service (both VRF1)
6599         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6600              IP(src=self.pg6.remote_ip4, dst=external_addr) /
6601              TCP(sport=12345, dport=external_port))
6602         self.pg6.add_stream(p)
6603         self.pg_enable_capture(self.pg_interfaces)
6604         self.pg_start()
6605         capture = self.pg5.get_capture(1)
6606         p = capture[0]
6607         try:
6608             ip = p[IP]
6609             tcp = p[TCP]
6610             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6611             self.assertEqual(tcp.dport, local_port)
6612             self.assert_packet_checksums_valid(p)
6613         except:
6614             self.logger.error(ppp("Unexpected or invalid packet:", p))
6615             raise
6616
6617         # from service back to client (both VRF1)
6618         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6619              IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6620              TCP(sport=local_port, dport=12345))
6621         self.pg5.add_stream(p)
6622         self.pg_enable_capture(self.pg_interfaces)
6623         self.pg_start()
6624         capture = self.pg6.get_capture(1)
6625         p = capture[0]
6626         try:
6627             ip = p[IP]
6628             tcp = p[TCP]
6629             self.assertEqual(ip.src, external_addr)
6630             self.assertEqual(tcp.sport, external_port)
6631             self.assert_packet_checksums_valid(p)
6632         except:
6633             self.logger.error(ppp("Unexpected or invalid packet:", p))
6634             raise
6635
6636         # dynamic NAT from VRF1 to VRF0 (output-feature)
6637         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6638              IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6639              TCP(sport=2345, dport=22))
6640         self.pg5.add_stream(p)
6641         self.pg_enable_capture(self.pg_interfaces)
6642         self.pg_start()
6643         capture = self.pg1.get_capture(1)
6644         p = capture[0]
6645         try:
6646             ip = p[IP]
6647             tcp = p[TCP]
6648             self.assertEqual(ip.src, self.nat_addr)
6649             self.assertNotEqual(tcp.sport, 2345)
6650             self.assert_packet_checksums_valid(p)
6651             port = tcp.sport
6652         except:
6653             self.logger.error(ppp("Unexpected or invalid packet:", p))
6654             raise
6655
6656         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6657              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6658              TCP(sport=22, dport=port))
6659         self.pg1.add_stream(p)
6660         self.pg_enable_capture(self.pg_interfaces)
6661         self.pg_start()
6662         capture = self.pg5.get_capture(1)
6663         p = capture[0]
6664         try:
6665             ip = p[IP]
6666             tcp = p[TCP]
6667             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6668             self.assertEqual(tcp.dport, 2345)
6669             self.assert_packet_checksums_valid(p)
6670         except:
6671             self.logger.error(ppp("Unexpected or invalid packet:", p))
6672             raise
6673
6674         # from client VRF1 to service VRF0
6675         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6676              IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6677              TCP(sport=12346, dport=external_port))
6678         self.pg6.add_stream(p)
6679         self.pg_enable_capture(self.pg_interfaces)
6680         self.pg_start()
6681         capture = self.pg0.get_capture(1)
6682         p = capture[0]
6683         try:
6684             ip = p[IP]
6685             tcp = p[TCP]
6686             self.assertEqual(ip.dst, self.pg0.remote_ip4)
6687             self.assertEqual(tcp.dport, local_port)
6688             self.assert_packet_checksums_valid(p)
6689         except:
6690             self.logger.error(ppp("Unexpected or invalid packet:", p))
6691             raise
6692
6693         # from service VRF0 back to client VRF1
6694         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6695              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6696              TCP(sport=local_port, dport=12346))
6697         self.pg0.add_stream(p)
6698         self.pg_enable_capture(self.pg_interfaces)
6699         self.pg_start()
6700         capture = self.pg6.get_capture(1)
6701         p = capture[0]
6702         try:
6703             ip = p[IP]
6704             tcp = p[TCP]
6705             self.assertEqual(ip.src, self.pg0.local_ip4)
6706             self.assertEqual(tcp.sport, external_port)
6707             self.assert_packet_checksums_valid(p)
6708         except:
6709             self.logger.error(ppp("Unexpected or invalid packet:", p))
6710             raise
6711
6712         # from client VRF0 to service VRF1
6713         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6714              IP(src=self.pg0.remote_ip4, dst=external_addr) /
6715              TCP(sport=12347, dport=external_port))
6716         self.pg0.add_stream(p)
6717         self.pg_enable_capture(self.pg_interfaces)
6718         self.pg_start()
6719         capture = self.pg5.get_capture(1)
6720         p = capture[0]
6721         try:
6722             ip = p[IP]
6723             tcp = p[TCP]
6724             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6725             self.assertEqual(tcp.dport, local_port)
6726             self.assert_packet_checksums_valid(p)
6727         except:
6728             self.logger.error(ppp("Unexpected or invalid packet:", p))
6729             raise
6730
6731         # from service VRF1 back to client VRF0
6732         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6733              IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6734              TCP(sport=local_port, dport=12347))
6735         self.pg5.add_stream(p)
6736         self.pg_enable_capture(self.pg_interfaces)
6737         self.pg_start()
6738         capture = self.pg0.get_capture(1)
6739         p = capture[0]
6740         try:
6741             ip = p[IP]
6742             tcp = p[TCP]
6743             self.assertEqual(ip.src, external_addr)
6744             self.assertEqual(tcp.sport, external_port)
6745             self.assert_packet_checksums_valid(p)
6746         except:
6747             self.logger.error(ppp("Unexpected or invalid packet:", p))
6748             raise
6749
6750         # from client to server (both VRF1, no translation)
6751         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6752              IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6753              TCP(sport=12348, dport=local_port))
6754         self.pg6.add_stream(p)
6755         self.pg_enable_capture(self.pg_interfaces)
6756         self.pg_start()
6757         capture = self.pg5.get_capture(1)
6758         p = capture[0]
6759         try:
6760             ip = p[IP]
6761             tcp = p[TCP]
6762             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6763             self.assertEqual(tcp.dport, local_port)
6764             self.assert_packet_checksums_valid(p)
6765         except:
6766             self.logger.error(ppp("Unexpected or invalid packet:", p))
6767             raise
6768
6769         # from server back to client (both VRF1, no translation)
6770         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6771              IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6772              TCP(sport=local_port, dport=12348))
6773         self.pg5.add_stream(p)
6774         self.pg_enable_capture(self.pg_interfaces)
6775         self.pg_start()
6776         capture = self.pg6.get_capture(1)
6777         p = capture[0]
6778         try:
6779             ip = p[IP]
6780             tcp = p[TCP]
6781             self.assertEqual(ip.src, self.pg5.remote_ip4)
6782             self.assertEqual(tcp.sport, local_port)
6783             self.assert_packet_checksums_valid(p)
6784         except:
6785             self.logger.error(ppp("Unexpected or invalid packet:", p))
6786             raise
6787
6788         # from client VRF1 to server VRF0 (no translation)
6789         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6790              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6791              TCP(sport=local_port, dport=12349))
6792         self.pg0.add_stream(p)
6793         self.pg_enable_capture(self.pg_interfaces)
6794         self.pg_start()
6795         capture = self.pg6.get_capture(1)
6796         p = capture[0]
6797         try:
6798             ip = p[IP]
6799             tcp = p[TCP]
6800             self.assertEqual(ip.src, self.pg0.remote_ip4)
6801             self.assertEqual(tcp.sport, local_port)
6802             self.assert_packet_checksums_valid(p)
6803         except:
6804             self.logger.error(ppp("Unexpected or invalid packet:", p))
6805             raise
6806
6807         # from server VRF0 back to client VRF1 (no translation)
6808         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6809              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6810              TCP(sport=local_port, dport=12349))
6811         self.pg0.add_stream(p)
6812         self.pg_enable_capture(self.pg_interfaces)
6813         self.pg_start()
6814         capture = self.pg6.get_capture(1)
6815         p = capture[0]
6816         try:
6817             ip = p[IP]
6818             tcp = p[TCP]
6819             self.assertEqual(ip.src, self.pg0.remote_ip4)
6820             self.assertEqual(tcp.sport, local_port)
6821             self.assert_packet_checksums_valid(p)
6822         except:
6823             self.logger.error(ppp("Unexpected or invalid packet:", p))
6824             raise
6825
6826         # from client VRF0 to server VRF1 (no translation)
6827         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6828              IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6829              TCP(sport=12344, dport=local_port))
6830         self.pg0.add_stream(p)
6831         self.pg_enable_capture(self.pg_interfaces)
6832         self.pg_start()
6833         capture = self.pg5.get_capture(1)
6834         p = capture[0]
6835         try:
6836             ip = p[IP]
6837             tcp = p[TCP]
6838             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6839             self.assertEqual(tcp.dport, local_port)
6840             self.assert_packet_checksums_valid(p)
6841         except:
6842             self.logger.error(ppp("Unexpected or invalid packet:", p))
6843             raise
6844
6845         # from server VRF1 back to client VRF0 (no translation)
6846         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6847              IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6848              TCP(sport=local_port, dport=12344))
6849         self.pg5.add_stream(p)
6850         self.pg_enable_capture(self.pg_interfaces)
6851         self.pg_start()
6852         capture = self.pg0.get_capture(1)
6853         p = capture[0]
6854         try:
6855             ip = p[IP]
6856             tcp = p[TCP]
6857             self.assertEqual(ip.src, self.pg5.remote_ip4)
6858             self.assertEqual(tcp.sport, local_port)
6859             self.assert_packet_checksums_valid(p)
6860         except:
6861             self.logger.error(ppp("Unexpected or invalid packet:", p))
6862             raise
6863
6864     @unittest.skipUnless(running_extended_tests, "part of extended tests")
6865     def test_session_timeout(self):
6866         """ NAT44 session timeouts """
6867         self.nat44_add_address(self.nat_addr)
6868         flags = self.config_flags.NAT_IS_INSIDE
6869         self.vapi.nat44_interface_add_del_feature(
6870             sw_if_index=self.pg0.sw_if_index,
6871             flags=flags, is_add=1)
6872         self.vapi.nat44_interface_add_del_feature(
6873             sw_if_index=self.pg1.sw_if_index,
6874             is_add=1)
6875         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6876                                    tcp_transitory=240, icmp=5)
6877
6878         max_sessions = 1000
6879         pkts = []
6880         for i in range(0, max_sessions):
6881             src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6882             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6883                  IP(src=src, dst=self.pg1.remote_ip4) /
6884                  ICMP(id=1025, type='echo-request'))
6885             pkts.append(p)
6886         self.pg0.add_stream(pkts)
6887         self.pg_enable_capture(self.pg_interfaces)
6888         self.pg_start()
6889         self.pg1.get_capture(max_sessions)
6890
6891         sleep(10)
6892
6893         pkts = []
6894         for i in range(0, max_sessions):
6895             src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6896             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6897                  IP(src=src, dst=self.pg1.remote_ip4) /
6898                  ICMP(id=1026, type='echo-request'))
6899             pkts.append(p)
6900         self.pg0.add_stream(pkts)
6901         self.pg_enable_capture(self.pg_interfaces)
6902         self.pg_start()
6903         self.pg1.get_capture(max_sessions)
6904
6905         nsessions = 0
6906         users = self.vapi.nat44_user_dump()
6907         for user in users:
6908             nsessions = nsessions + user.nsessions
6909         self.assertLess(nsessions, 2 * max_sessions)
6910
6911     @unittest.skipUnless(running_extended_tests, "part of extended tests")
6912     def test_session_rst_timeout(self):
6913         """ NAT44 session RST timeouts """
6914         self.nat44_add_address(self.nat_addr)
6915         flags = self.config_flags.NAT_IS_INSIDE
6916         self.vapi.nat44_interface_add_del_feature(
6917             sw_if_index=self.pg0.sw_if_index,
6918             flags=flags, is_add=1)
6919         self.vapi.nat44_interface_add_del_feature(
6920             sw_if_index=self.pg1.sw_if_index,
6921             is_add=1)
6922         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6923                                    tcp_transitory=5, icmp=60)
6924
6925         self.initiate_tcp_session(self.pg0, self.pg1)
6926         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6927              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6928              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6929                  flags="R"))
6930         self.pg0.add_stream(p)
6931         self.pg_enable_capture(self.pg_interfaces)
6932         self.pg_start()
6933         self.pg1.get_capture(1)
6934
6935         sleep(6)
6936
6937         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6938              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6939              TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6940                  flags="S"))
6941         self.pg0.add_stream(p)
6942         self.pg_enable_capture(self.pg_interfaces)
6943         self.pg_start()
6944         self.pg1.get_capture(1)
6945
6946     def test_syslog_sess(self):
6947         """ Test syslog session creation and deletion """
6948         self.vapi.syslog_set_filter(
6949             self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
6950         self.vapi.syslog_set_sender(self.pg2.local_ip4, self.pg2.remote_ip4)
6951         self.nat44_add_address(self.nat_addr)
6952         flags = self.config_flags.NAT_IS_INSIDE
6953         self.vapi.nat44_interface_add_del_feature(
6954             sw_if_index=self.pg0.sw_if_index,
6955             flags=flags, is_add=1)
6956         self.vapi.nat44_interface_add_del_feature(
6957             sw_if_index=self.pg1.sw_if_index,
6958             is_add=1)
6959
6960         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6961              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6962              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6963         self.pg0.add_stream(p)
6964         self.pg_enable_capture(self.pg_interfaces)
6965         self.pg_start()
6966         capture = self.pg1.get_capture(1)
6967         self.tcp_port_out = capture[0][TCP].sport
6968         capture = self.pg2.get_capture(1)
6969         self.verify_syslog_sess(capture[0][Raw].load)
6970
6971         self.pg_enable_capture(self.pg_interfaces)
6972         self.pg_start()
6973         self.nat44_add_address(self.nat_addr, is_add=0)
6974         capture = self.pg2.get_capture(1)
6975         self.verify_syslog_sess(capture[0][Raw].load, False)
6976
6977     def tearDown(self):
6978         super(TestNAT44EndpointDependent, self).tearDown()
6979         if not self.vpp_dead:
6980             self.clear_nat44()
6981             self.vapi.cli("clear logging")
6982
6983     def show_commands_at_teardown(self):
6984         self.logger.info(self.vapi.cli("show nat44 addresses"))
6985         self.logger.info(self.vapi.cli("show nat44 interfaces"))
6986         self.logger.info(self.vapi.cli("show nat44 static mappings"))
6987         self.logger.info(self.vapi.cli("show nat44 interface address"))
6988         self.logger.info(self.vapi.cli("show nat44 sessions detail"))
6989         self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
6990         self.logger.info(self.vapi.cli("show nat timeouts"))
6991
6992
6993 class TestNAT44Out2InDPO(MethodHolder):
6994     """ NAT44 Test Cases using out2in DPO """
6995
6996     @classmethod
6997     def setUpConstants(cls):
6998         super(TestNAT44Out2InDPO, cls).setUpConstants()
6999         cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
7000
7001     @classmethod
7002     def setUpClass(cls):
7003         super(TestNAT44Out2InDPO, cls).setUpClass()
7004         cls.vapi.cli("set log class nat level debug")
7005
7006         cls.tcp_port_in = 6303
7007         cls.tcp_port_out = 6303
7008         cls.udp_port_in = 6304
7009         cls.udp_port_out = 6304
7010         cls.icmp_id_in = 6305
7011         cls.icmp_id_out = 6305
7012         cls.nat_addr = '10.0.0.3'
7013         cls.dst_ip4 = '192.168.70.1'
7014
7015         cls.create_pg_interfaces(range(2))
7016
7017         cls.pg0.admin_up()
7018         cls.pg0.config_ip4()
7019         cls.pg0.resolve_arp()
7020
7021         cls.pg1.admin_up()
7022         cls.pg1.config_ip6()
7023         cls.pg1.resolve_ndp()
7024
7025         r1 = VppIpRoute(cls, "::", 0,
7026                         [VppRoutePath(cls.pg1.remote_ip6,
7027                                       cls.pg1.sw_if_index)],
7028                         register=False)
7029         r1.add_vpp_config()
7030
7031     @classmethod
7032     def tearDownClass(cls):
7033         super(TestNAT44Out2InDPO, cls).tearDownClass()
7034
7035     def configure_xlat(self):
7036         self.dst_ip6_pfx = '1:2:3::'
7037         self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
7038                                               self.dst_ip6_pfx)
7039         self.dst_ip6_pfx_len = 96
7040         self.src_ip6_pfx = '4:5:6::'
7041         self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
7042                                               self.src_ip6_pfx)
7043         self.src_ip6_pfx_len = 96
7044         self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
7045                                  self.src_ip6_pfx_n, self.src_ip6_pfx_len,
7046                                  '\x00\x00\x00\x00', 0)
7047
7048     @unittest.skip('Temporary disabled')
7049     def test_464xlat_ce(self):
7050         """ Test 464XLAT CE with NAT44 """
7051
7052         nat_config = self.vapi.nat_show_config()
7053         self.assertEqual(1, nat_config.out2in_dpo)
7054
7055         self.configure_xlat()
7056
7057         flags = self.config_flags.NAT_IS_INSIDE
7058         self.vapi.nat44_interface_add_del_feature(
7059             sw_if_index=self.pg0.sw_if_index,
7060             flags=flags, is_add=1)
7061         self.vapi.nat44_add_del_address_range(first_ip_address=self.nat_addr_n,
7062                                               last_ip_address=self.nat_addr_n,
7063                                               vrf_id=0xFFFFFFFF, is_add=1)
7064
7065         out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7066                                        self.dst_ip6_pfx_len)
7067         out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
7068                                        self.src_ip6_pfx_len)
7069
7070         try:
7071             pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7072             self.pg0.add_stream(pkts)
7073             self.pg_enable_capture(self.pg_interfaces)
7074             self.pg_start()
7075             capture = self.pg1.get_capture(len(pkts))
7076             self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
7077                                         dst_ip=out_src_ip6)
7078
7079             pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
7080                                               out_dst_ip6)
7081             self.pg1.add_stream(pkts)
7082             self.pg_enable_capture(self.pg_interfaces)
7083             self.pg_start()
7084             capture = self.pg0.get_capture(len(pkts))
7085             self.verify_capture_in(capture, self.pg0)
7086         finally:
7087             self.vapi.nat44_interface_add_del_feature(
7088                 sw_if_index=self.pg0.sw_if_index,
7089                 flags=flags)
7090             self.vapi.nat44_add_del_address_range(
7091                 first_ip_address=self.nat_addr_n,
7092                 last_ip_address=self.nat_addr_n,
7093                 vrf_id=0xFFFFFFFF)
7094
7095     @unittest.skip('Temporary disabled')
7096     def test_464xlat_ce_no_nat(self):
7097         """ Test 464XLAT CE without NAT44 """
7098
7099         self.configure_xlat()
7100
7101         out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7102                                        self.dst_ip6_pfx_len)
7103         out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
7104                                        self.src_ip6_pfx_len)
7105
7106         pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7107         self.pg0.add_stream(pkts)
7108         self.pg_enable_capture(self.pg_interfaces)
7109         self.pg_start()
7110         capture = self.pg1.get_capture(len(pkts))
7111         self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
7112                                     nat_ip=out_dst_ip6, same_port=True)
7113
7114         pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
7115         self.pg1.add_stream(pkts)
7116         self.pg_enable_capture(self.pg_interfaces)
7117         self.pg_start()
7118         capture = self.pg0.get_capture(len(pkts))
7119         self.verify_capture_in(capture, self.pg0)
7120
7121
7122 class TestDeterministicNAT(MethodHolder):
7123     """ Deterministic NAT Test Cases """
7124
7125     @classmethod
7126     def setUpConstants(cls):
7127         super(TestDeterministicNAT, cls).setUpConstants()
7128         cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
7129
7130     @classmethod
7131     def setUpClass(cls):
7132         super(TestDeterministicNAT, cls).setUpClass()
7133         cls.vapi.cli("set log class nat level debug")
7134
7135         cls.tcp_port_in = 6303
7136         cls.tcp_external_port = 6303
7137         cls.udp_port_in = 6304
7138         cls.udp_external_port = 6304
7139         cls.icmp_id_in = 6305
7140         cls.nat_addr = '10.0.0.3'
7141
7142         cls.create_pg_interfaces(range(3))
7143         cls.interfaces = list(cls.pg_interfaces)
7144
7145         for i in cls.interfaces:
7146             i.admin_up()
7147             i.config_ip4()
7148             i.resolve_arp()
7149
7150         cls.pg0.generate_remote_hosts(2)
7151         cls.pg0.configure_ipv4_neighbors()
7152
7153     @classmethod
7154     def tearDownClass(cls):
7155         super(TestDeterministicNAT, cls).tearDownClass()
7156
7157     def create_stream_in(self, in_if, out_if, ttl=64):
7158         """
7159         Create packet stream for inside network
7160
7161         :param in_if: Inside interface
7162         :param out_if: Outside interface
7163         :param ttl: TTL of generated packets
7164         """
7165         pkts = []
7166         # TCP
7167         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7168              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7169              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
7170         pkts.append(p)
7171
7172         # UDP
7173         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7174              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7175              UDP(sport=self.udp_port_in, dport=self.udp_external_port))
7176         pkts.append(p)
7177
7178         # ICMP
7179         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7180              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7181              ICMP(id=self.icmp_id_in, type='echo-request'))
7182         pkts.append(p)
7183
7184         return pkts
7185
7186     def create_stream_out(self, out_if, dst_ip=None, ttl=64):
7187         """
7188         Create packet stream for outside network
7189
7190         :param out_if: Outside interface
7191         :param dst_ip: Destination IP address (Default use global NAT address)
7192         :param ttl: TTL of generated packets
7193         """
7194         if dst_ip is None:
7195             dst_ip = self.nat_addr
7196         pkts = []
7197         # TCP
7198         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7199              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7200              TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
7201         pkts.append(p)
7202
7203         # UDP
7204         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7205              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7206              UDP(dport=self.udp_port_out, sport=self.udp_external_port))
7207         pkts.append(p)
7208
7209         # ICMP
7210         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7211              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7212              ICMP(id=self.icmp_external_id, type='echo-reply'))
7213         pkts.append(p)
7214
7215         return pkts
7216
7217     def verify_capture_out(self, capture, nat_ip=None):
7218         """
7219         Verify captured packets on outside network
7220
7221         :param capture: Captured packets
7222         :param nat_ip: Translated IP address (Default use global NAT address)
7223         :param same_port: Source port number is not translated (Default False)
7224         """
7225         if nat_ip is None:
7226             nat_ip = self.nat_addr
7227         for packet in capture:
7228             try:
7229                 self.assertEqual(packet[IP].src, nat_ip)
7230                 if packet.haslayer(TCP):
7231                     self.tcp_port_out = packet[TCP].sport
7232                 elif packet.haslayer(UDP):
7233                     self.udp_port_out = packet[UDP].sport
7234                 else:
7235                     self.icmp_external_id = packet[ICMP].id
7236             except:
7237                 self.logger.error(ppp("Unexpected or invalid packet "
7238                                       "(outside network):", packet))
7239                 raise
7240
7241     def test_deterministic_mode(self):
7242         """ NAT plugin run deterministic mode """
7243         in_addr = '172.16.255.0'
7244         out_addr = '172.17.255.50'
7245         in_addr_t = '172.16.255.20'
7246         in_plen = 24
7247         out_plen = 32
7248
7249         nat_config = self.vapi.nat_show_config()
7250         self.assertEqual(1, nat_config.deterministic)
7251
7252         self.vapi.nat_det_add_del_map(is_add=1, in_addr=in_addr,
7253                                       in_plen=in_plen, out_addr=out_addr,
7254                                       out_plen=out_plen)
7255
7256         rep1 = self.vapi.nat_det_forward(in_addr_t)
7257         self.assertEqual(str(rep1.out_addr), out_addr)
7258         rep2 = self.vapi.nat_det_reverse(rep1.out_port_hi, out_addr)
7259
7260         self.assertEqual(str(rep2.in_addr), in_addr_t)
7261
7262         deterministic_mappings = self.vapi.nat_det_map_dump()
7263         self.assertEqual(len(deterministic_mappings), 1)
7264         dsm = deterministic_mappings[0]
7265         self.assertEqual(in_addr, str(dsm.in_addr))
7266         self.assertEqual(in_plen, dsm.in_plen)
7267         self.assertEqual(out_addr, str(dsm.out_addr))
7268         self.assertEqual(out_plen, dsm.out_plen)
7269
7270         self.clear_nat_det()
7271         deterministic_mappings = self.vapi.nat_det_map_dump()
7272         self.assertEqual(len(deterministic_mappings), 0)
7273
7274     def test_set_timeouts(self):
7275         """ Set deterministic NAT timeouts """
7276         timeouts_before = self.vapi.nat_get_timeouts()
7277
7278         self.vapi.nat_set_timeouts(
7279             udp=timeouts_before.udp + 10,
7280             tcp_established=timeouts_before.tcp_established + 10,
7281             tcp_transitory=timeouts_before.tcp_transitory + 10,
7282             icmp=timeouts_before.icmp + 10)
7283
7284         timeouts_after = self.vapi.nat_get_timeouts()
7285
7286         self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
7287         self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
7288         self.assertNotEqual(timeouts_before.tcp_established,
7289                             timeouts_after.tcp_established)
7290         self.assertNotEqual(timeouts_before.tcp_transitory,
7291                             timeouts_after.tcp_transitory)
7292
7293     def test_det_in(self):
7294         """ Deterministic NAT translation test (TCP, UDP, ICMP) """
7295
7296         nat_ip = "10.0.0.10"
7297
7298         self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7299                                       in_plen=32,
7300                                       out_addr=socket.inet_aton(nat_ip),
7301                                       out_plen=32)
7302
7303         flags = self.config_flags.NAT_IS_INSIDE
7304         self.vapi.nat44_interface_add_del_feature(
7305             sw_if_index=self.pg0.sw_if_index,
7306             flags=flags, is_add=1)
7307         self.vapi.nat44_interface_add_del_feature(
7308             sw_if_index=self.pg1.sw_if_index,
7309             is_add=1)
7310
7311         # in2out
7312         pkts = self.create_stream_in(self.pg0, self.pg1)
7313         self.pg0.add_stream(pkts)
7314         self.pg_enable_capture(self.pg_interfaces)
7315         self.pg_start()
7316         capture = self.pg1.get_capture(len(pkts))
7317         self.verify_capture_out(capture, nat_ip)
7318
7319         # out2in
7320         pkts = self.create_stream_out(self.pg1, nat_ip)
7321         self.pg1.add_stream(pkts)
7322         self.pg_enable_capture(self.pg_interfaces)
7323         self.pg_start()
7324         capture = self.pg0.get_capture(len(pkts))
7325         self.verify_capture_in(capture, self.pg0)
7326
7327         # session dump test
7328         sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4)
7329         self.assertEqual(len(sessions), 3)
7330
7331         # TCP session
7332         s = sessions[0]
7333         self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7334         self.assertEqual(s.in_port, self.tcp_port_in)
7335         self.assertEqual(s.out_port, self.tcp_port_out)
7336         self.assertEqual(s.ext_port, self.tcp_external_port)
7337
7338         # UDP session
7339         s = sessions[1]
7340         self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7341         self.assertEqual(s.in_port, self.udp_port_in)
7342         self.assertEqual(s.out_port, self.udp_port_out)
7343         self.assertEqual(s.ext_port, self.udp_external_port)
7344
7345         # ICMP session
7346         s = sessions[2]
7347         self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7348         self.assertEqual(s.in_port, self.icmp_id_in)
7349         self.assertEqual(s.out_port, self.icmp_external_id)
7350
7351     def test_multiple_users(self):
7352         """ Deterministic NAT multiple users """
7353
7354         nat_ip = "10.0.0.10"
7355         port_in = 80
7356         external_port = 6303
7357
7358         host0 = self.pg0.remote_hosts[0]
7359         host1 = self.pg0.remote_hosts[1]
7360
7361         self.vapi.nat_det_add_del_map(is_add=1, in_addr=host0.ip4, in_plen=24,
7362                                       out_addr=socket.inet_aton(nat_ip),
7363                                       out_plen=32)
7364         flags = self.config_flags.NAT_IS_INSIDE
7365         self.vapi.nat44_interface_add_del_feature(
7366             sw_if_index=self.pg0.sw_if_index,
7367             flags=flags, is_add=1)
7368         self.vapi.nat44_interface_add_del_feature(
7369             sw_if_index=self.pg1.sw_if_index,
7370             is_add=1)
7371
7372         # host0 to out
7373         p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
7374              IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
7375              TCP(sport=port_in, dport=external_port))
7376         self.pg0.add_stream(p)
7377         self.pg_enable_capture(self.pg_interfaces)
7378         self.pg_start()
7379         capture = self.pg1.get_capture(1)
7380         p = capture[0]
7381         try:
7382             ip = p[IP]
7383             tcp = p[TCP]
7384             self.assertEqual(ip.src, nat_ip)
7385             self.assertEqual(ip.dst, self.pg1.remote_ip4)
7386             self.assertEqual(tcp.dport, external_port)
7387             port_out0 = tcp.sport
7388         except:
7389             self.logger.error(ppp("Unexpected or invalid packet:", p))
7390             raise
7391
7392         # host1 to out
7393         p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
7394              IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
7395              TCP(sport=port_in, dport=external_port))
7396         self.pg0.add_stream(p)
7397         self.pg_enable_capture(self.pg_interfaces)
7398         self.pg_start()
7399         capture = self.pg1.get_capture(1)
7400         p = capture[0]
7401         try:
7402             ip = p[IP]
7403             tcp = p[TCP]
7404             self.assertEqual(ip.src, nat_ip)
7405             self.assertEqual(ip.dst, self.pg1.remote_ip4)
7406             self.assertEqual(tcp.dport, external_port)
7407             port_out1 = tcp.sport
7408         except:
7409             self.logger.error(ppp("Unexpected or invalid packet:", p))
7410             raise
7411
7412         dms = self.vapi.nat_det_map_dump()
7413         self.assertEqual(1, len(dms))
7414         self.assertEqual(2, dms[0].ses_num)
7415
7416         # out to host0
7417         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7418              IP(src=self.pg1.remote_ip4, dst=nat_ip) /
7419              TCP(sport=external_port, dport=port_out0))
7420         self.pg1.add_stream(p)
7421         self.pg_enable_capture(self.pg_interfaces)
7422         self.pg_start()
7423         capture = self.pg0.get_capture(1)
7424         p = capture[0]
7425         try:
7426             ip = p[IP]
7427             tcp = p[TCP]
7428             self.assertEqual(ip.src, self.pg1.remote_ip4)
7429             self.assertEqual(ip.dst, host0.ip4)
7430             self.assertEqual(tcp.dport, port_in)
7431             self.assertEqual(tcp.sport, external_port)
7432         except:
7433             self.logger.error(ppp("Unexpected or invalid packet:", p))
7434             raise
7435
7436         # out to host1
7437         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7438              IP(src=self.pg1.remote_ip4, dst=nat_ip) /
7439              TCP(sport=external_port, dport=port_out1))
7440         self.pg1.add_stream(p)
7441         self.pg_enable_capture(self.pg_interfaces)
7442         self.pg_start()
7443         capture = self.pg0.get_capture(1)
7444         p = capture[0]
7445         try:
7446             ip = p[IP]
7447             tcp = p[TCP]
7448             self.assertEqual(ip.src, self.pg1.remote_ip4)
7449             self.assertEqual(ip.dst, host1.ip4)
7450             self.assertEqual(tcp.dport, port_in)
7451             self.assertEqual(tcp.sport, external_port)
7452         except:
7453             self.logger.error(ppp("Unexpected or invalid packet", p))
7454             raise
7455
7456         # session close api test
7457         self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
7458                                             port_out1,
7459                                             self.pg1.remote_ip4,
7460                                             external_port)
7461         dms = self.vapi.nat_det_map_dump()
7462         self.assertEqual(dms[0].ses_num, 1)
7463
7464         self.vapi.nat_det_close_session_in(host0.ip4,
7465                                            port_in,
7466                                            self.pg1.remote_ip4,
7467                                            external_port)
7468         dms = self.vapi.nat_det_map_dump()
7469         self.assertEqual(dms[0].ses_num, 0)
7470
7471     def test_tcp_session_close_detection_in(self):
7472         """ Deterministic NAT TCP session close from inside network """
7473         self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7474                                       in_plen=32,
7475                                       out_addr=socket.inet_aton(self.nat_addr),
7476                                       out_plen=32)
7477         flags = self.config_flags.NAT_IS_INSIDE
7478         self.vapi.nat44_interface_add_del_feature(
7479             sw_if_index=self.pg0.sw_if_index,
7480             flags=flags, is_add=1)
7481         self.vapi.nat44_interface_add_del_feature(
7482             sw_if_index=self.pg1.sw_if_index,
7483             is_add=1)
7484
7485         self.initiate_tcp_session(self.pg0, self.pg1)
7486
7487         # close the session from inside
7488         try:
7489             # FIN packet in -> out
7490             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7491                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7492                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7493                      flags="F"))
7494             self.pg0.add_stream(p)
7495             self.pg_enable_capture(self.pg_interfaces)
7496             self.pg_start()
7497             self.pg1.get_capture(1)
7498
7499             pkts = []
7500
7501             # ACK packet out -> in
7502             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7503                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7504                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7505                      flags="A"))
7506             pkts.append(p)
7507
7508             # FIN packet out -> in
7509             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7510                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7511                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7512                      flags="F"))
7513             pkts.append(p)
7514
7515             self.pg1.add_stream(pkts)
7516             self.pg_enable_capture(self.pg_interfaces)
7517             self.pg_start()
7518             self.pg0.get_capture(2)
7519
7520             # ACK packet in -> out
7521             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7522                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7523                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7524                      flags="A"))
7525             self.pg0.add_stream(p)
7526             self.pg_enable_capture(self.pg_interfaces)
7527             self.pg_start()
7528             self.pg1.get_capture(1)
7529
7530             # Check if deterministic NAT44 closed the session
7531             dms = self.vapi.nat_det_map_dump()
7532             self.assertEqual(0, dms[0].ses_num)
7533         except:
7534             self.logger.error("TCP session termination failed")
7535             raise
7536
7537     def test_tcp_session_close_detection_out(self):
7538         """ Deterministic NAT TCP session close from outside network """
7539         self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7540                                       in_plen=32,
7541                                       out_addr=socket.inet_aton(self.nat_addr),
7542                                       out_plen=32)
7543         flags = self.config_flags.NAT_IS_INSIDE
7544         self.vapi.nat44_interface_add_del_feature(
7545             sw_if_index=self.pg0.sw_if_index,
7546             flags=flags, is_add=1)
7547         self.vapi.nat44_interface_add_del_feature(
7548             sw_if_index=self.pg1.sw_if_index,
7549             is_add=1)
7550
7551         self.initiate_tcp_session(self.pg0, self.pg1)
7552
7553         # close the session from outside
7554         try:
7555             # FIN packet out -> in
7556             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7557                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7558                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7559                      flags="F"))
7560             self.pg1.add_stream(p)
7561             self.pg_enable_capture(self.pg_interfaces)
7562             self.pg_start()
7563             self.pg0.get_capture(1)
7564
7565             pkts = []
7566
7567             # ACK packet in -> out
7568             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7569                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7570                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7571                      flags="A"))
7572             pkts.append(p)
7573
7574             # ACK packet in -> out
7575             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7576                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7577                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7578                      flags="F"))
7579             pkts.append(p)
7580
7581             self.pg0.add_stream(pkts)
7582             self.pg_enable_capture(self.pg_interfaces)
7583             self.pg_start()
7584             self.pg1.get_capture(2)
7585
7586             # ACK packet out -> in
7587             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7588                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7589                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7590                      flags="A"))
7591             self.pg1.add_stream(p)
7592             self.pg_enable_capture(self.pg_interfaces)
7593             self.pg_start()
7594             self.pg0.get_capture(1)
7595
7596             # Check if deterministic NAT44 closed the session
7597             dms = self.vapi.nat_det_map_dump()
7598             self.assertEqual(0, dms[0].ses_num)
7599         except:
7600             self.logger.error("TCP session termination failed")
7601             raise
7602
7603     @unittest.skipUnless(running_extended_tests, "part of extended tests")
7604     def test_session_timeout(self):
7605         """ Deterministic NAT session timeouts """
7606         self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7607                                       in_plen=32,
7608                                       out_addr=socket.inet_aton(self.nat_addr),
7609                                       out_plen=32)
7610         flags = self.config_flags.NAT_IS_INSIDE
7611         self.vapi.nat44_interface_add_del_feature(
7612             sw_if_index=self.pg0.sw_if_index,
7613             flags=flags, is_add=1)
7614         self.vapi.nat44_interface_add_del_feature(
7615             sw_if_index=self.pg1.sw_if_index,
7616             is_add=1)
7617
7618         self.initiate_tcp_session(self.pg0, self.pg1)
7619         self.vapi.nat_set_timeouts(udp=5, tcp_established=5, tcp_transitory=5,
7620                                    icmp=5)
7621         pkts = self.create_stream_in(self.pg0, self.pg1)
7622         self.pg0.add_stream(pkts)
7623         self.pg_enable_capture(self.pg_interfaces)
7624         self.pg_start()
7625         capture = self.pg1.get_capture(len(pkts))
7626         sleep(15)
7627
7628         dms = self.vapi.nat_det_map_dump()
7629         self.assertEqual(0, dms[0].ses_num)
7630
7631     @unittest.skipUnless(running_extended_tests, "part of extended tests")
7632     def test_session_limit_per_user(self):
7633         """ Deterministic NAT maximum sessions per user limit """
7634         self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7635                                       in_plen=32,
7636                                       out_addr=socket.inet_aton(self.nat_addr),
7637                                       out_plen=32)
7638         flags = self.config_flags.NAT_IS_INSIDE
7639         self.vapi.nat44_interface_add_del_feature(
7640             sw_if_index=self.pg0.sw_if_index,
7641             flags=flags, is_add=1)
7642         self.vapi.nat44_interface_add_del_feature(
7643             sw_if_index=self.pg1.sw_if_index,
7644             is_add=1)
7645         self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4,
7646                                      src_address=self.pg2.local_ip4,
7647                                      path_mtu=512,
7648                                      template_interval=10)
7649         self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7650                                            enable=1)
7651
7652         pkts = []
7653         for port in range(1025, 2025):
7654             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7655                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7656                  UDP(sport=port, dport=port))
7657             pkts.append(p)
7658
7659         self.pg0.add_stream(pkts)
7660         self.pg_enable_capture(self.pg_interfaces)
7661         self.pg_start()
7662         capture = self.pg1.get_capture(len(pkts))
7663
7664         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7665              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7666              UDP(sport=3001, dport=3002))
7667         self.pg0.add_stream(p)
7668         self.pg_enable_capture(self.pg_interfaces)
7669         self.pg_start()
7670         capture = self.pg1.assert_nothing_captured()
7671
7672         # verify ICMP error packet
7673         capture = self.pg0.get_capture(1)
7674         p = capture[0]
7675         self.assertTrue(p.haslayer(ICMP))
7676         icmp = p[ICMP]
7677         self.assertEqual(icmp.type, 3)
7678         self.assertEqual(icmp.code, 1)
7679         self.assertTrue(icmp.haslayer(IPerror))
7680         inner_ip = icmp[IPerror]
7681         self.assertEqual(inner_ip[UDPerror].sport, 3001)
7682         self.assertEqual(inner_ip[UDPerror].dport, 3002)
7683
7684         dms = self.vapi.nat_det_map_dump()
7685
7686         self.assertEqual(1000, dms[0].ses_num)
7687
7688         # verify IPFIX logging
7689         self.vapi.ipfix_flush()
7690         sleep(1)
7691         capture = self.pg2.get_capture(2)
7692         ipfix = IPFIXDecoder()
7693         # first load template
7694         for p in capture:
7695             self.assertTrue(p.haslayer(IPFIX))
7696             if p.haslayer(Template):
7697                 ipfix.add_template(p.getlayer(Template))
7698         # verify events in data set
7699         for p in capture:
7700             if p.haslayer(Data):
7701                 data = ipfix.decode_data_set(p.getlayer(Set))
7702                 self.verify_ipfix_max_entries_per_user(data,
7703                                                        1000,
7704                                                        self.pg0.remote_ip4)
7705
7706     def clear_nat_det(self):
7707         """
7708         Clear deterministic NAT configuration.
7709         """
7710         self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7711                                            enable=0)
7712         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
7713                                    tcp_transitory=240, icmp=60)
7714         deterministic_mappings = self.vapi.nat_det_map_dump()
7715         for dsm in deterministic_mappings:
7716             self.vapi.nat_det_add_del_map(is_add=0, in_addr=dsm.in_addr,
7717                                           in_plen=dsm.in_plen,
7718                                           out_addr=dsm.out_addr,
7719                                           out_plen=dsm.out_plen)
7720
7721         interfaces = self.vapi.nat44_interface_dump()
7722         for intf in interfaces:
7723             self.vapi.nat44_interface_add_del_feature(
7724                 sw_if_index=intf.sw_if_index,
7725                 flags=intf.flags)
7726
7727     def tearDown(self):
7728         super(TestDeterministicNAT, self).tearDown()
7729         if not self.vpp_dead:
7730             self.clear_nat_det()
7731
7732     def show_commands_at_teardown(self):
7733         self.logger.info(self.vapi.cli("show nat44 interfaces"))
7734         self.logger.info(self.vapi.cli("show nat timeouts"))
7735         self.logger.info(
7736             self.vapi.cli("show nat44 deterministic mappings"))
7737         self.logger.info(
7738             self.vapi.cli("show nat44 deterministic sessions"))
7739
7740
7741 class TestNAT64(MethodHolder):
7742     """ NAT64 Test Cases """
7743
7744     @classmethod
7745     def setUpConstants(cls):
7746         super(TestNAT64, cls).setUpConstants()
7747         cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
7748                                 "nat64 st hash buckets 256", "}"])
7749
7750     @classmethod
7751     def setUpClass(cls):
7752         super(TestNAT64, cls).setUpClass()
7753
7754         cls.tcp_port_in = 6303
7755         cls.tcp_port_out = 6303
7756         cls.udp_port_in = 6304
7757         cls.udp_port_out = 6304
7758         cls.icmp_id_in = 6305
7759         cls.icmp_id_out = 6305
7760         cls.tcp_external_port = 80
7761         cls.nat_addr = '10.0.0.3'
7762         cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
7763         cls.vrf1_id = 10
7764         cls.vrf1_nat_addr = '10.0.10.3'
7765         cls.ipfix_src_port = 4739
7766         cls.ipfix_domain_id = 1
7767
7768         cls.create_pg_interfaces(range(6))
7769         cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
7770         cls.ip6_interfaces.append(cls.pg_interfaces[2])
7771         cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
7772
7773         cls.vapi.ip_table_add_del(is_add=1,
7774                                   table={'table_id': cls.vrf1_id,
7775                                          'is_ip6': 1})
7776
7777         cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
7778
7779         cls.pg0.generate_remote_hosts(2)
7780
7781         for i in cls.ip6_interfaces:
7782             i.admin_up()
7783             i.config_ip6()
7784             i.configure_ipv6_neighbors()
7785
7786         for i in cls.ip4_interfaces:
7787             i.admin_up()
7788             i.config_ip4()
7789             i.resolve_arp()
7790
7791         cls.pg3.admin_up()
7792         cls.pg3.config_ip4()
7793         cls.pg3.resolve_arp()
7794         cls.pg3.config_ip6()
7795         cls.pg3.configure_ipv6_neighbors()
7796
7797         cls.pg5.admin_up()
7798         cls.pg5.config_ip6()
7799
7800     @classmethod
7801     def tearDownClass(cls):
7802         super(TestNAT64, cls).tearDownClass()
7803
7804     def test_nat64_inside_interface_handles_neighbor_advertisement(self):
7805         """ NAT64 inside interface handles Neighbor Advertisement """
7806
7807         flags = self.config_flags.NAT_IS_INSIDE
7808         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7809                                           sw_if_index=self.pg5.sw_if_index)
7810
7811         # Try to send ping
7812         ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7813                 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7814                 ICMPv6EchoRequest())
7815         pkts = [ping]
7816         self.pg5.add_stream(pkts)
7817         self.pg_enable_capture(self.pg_interfaces)
7818         self.pg_start()
7819
7820         # Wait for Neighbor Solicitation
7821         capture = self.pg5.get_capture(len(pkts))
7822         packet = capture[0]
7823         try:
7824             self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7825             self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
7826             tgt = packet[ICMPv6ND_NS].tgt
7827         except:
7828             self.logger.error(ppp("Unexpected or invalid packet:", packet))
7829             raise
7830
7831         # Send Neighbor Advertisement
7832         p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7833              IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7834              ICMPv6ND_NA(tgt=tgt) /
7835              ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
7836         pkts = [p]
7837         self.pg5.add_stream(pkts)
7838         self.pg_enable_capture(self.pg_interfaces)
7839         self.pg_start()
7840
7841         # Try to send ping again
7842         pkts = [ping]
7843         self.pg5.add_stream(pkts)
7844         self.pg_enable_capture(self.pg_interfaces)
7845         self.pg_start()
7846
7847         # Wait for ping reply
7848         capture = self.pg5.get_capture(len(pkts))
7849         packet = capture[0]
7850         try:
7851             self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7852             self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
7853             self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
7854         except:
7855             self.logger.error(ppp("Unexpected or invalid packet:", packet))
7856             raise
7857
7858     def test_pool(self):
7859         """ Add/delete address to NAT64 pool """
7860         nat_addr = '1.2.3.4'
7861
7862         self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7863                                                 end_addr=nat_addr,
7864                                                 vrf_id=0xFFFFFFFF, is_add=1)
7865
7866         addresses = self.vapi.nat64_pool_addr_dump()
7867         self.assertEqual(len(addresses), 1)
7868         self.assertEqual(str(addresses[0].address), nat_addr)
7869
7870         self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7871                                                 end_addr=nat_addr,
7872                                                 vrf_id=0xFFFFFFFF, is_add=0)
7873
7874         addresses = self.vapi.nat64_pool_addr_dump()
7875         self.assertEqual(len(addresses), 0)
7876
7877     def test_interface(self):
7878         """ Enable/disable NAT64 feature on the interface """
7879         flags = self.config_flags.NAT_IS_INSIDE
7880         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7881                                           sw_if_index=self.pg0.sw_if_index)
7882         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7883                                           sw_if_index=self.pg1.sw_if_index)
7884
7885         interfaces = self.vapi.nat64_interface_dump()
7886         self.assertEqual(len(interfaces), 2)
7887         pg0_found = False
7888         pg1_found = False
7889         for intf in interfaces:
7890             if intf.sw_if_index == self.pg0.sw_if_index:
7891                 self.assertEqual(intf.flags, self.config_flags.NAT_IS_INSIDE)
7892                 pg0_found = True
7893             elif intf.sw_if_index == self.pg1.sw_if_index:
7894                 self.assertEqual(intf.flags, self.config_flags.NAT_IS_OUTSIDE)
7895                 pg1_found = True
7896         self.assertTrue(pg0_found)
7897         self.assertTrue(pg1_found)
7898
7899         features = self.vapi.cli("show interface features pg0")
7900         self.assertIn('nat64-in2out', features)
7901         features = self.vapi.cli("show interface features pg1")
7902         self.assertIn('nat64-out2in', features)
7903
7904         self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7905                                           sw_if_index=self.pg0.sw_if_index)
7906         self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7907                                           sw_if_index=self.pg1.sw_if_index)
7908
7909         interfaces = self.vapi.nat64_interface_dump()
7910         self.assertEqual(len(interfaces), 0)
7911
7912     def test_static_bib(self):
7913         """ Add/delete static BIB entry """
7914         in_addr = '2001:db8:85a3::8a2e:370:7334'
7915         out_addr = '10.1.1.3'
7916         in_port = 1234
7917         out_port = 5678
7918         proto = IP_PROTOS.tcp
7919
7920         self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7921                                            i_port=in_port, o_port=out_port,
7922                                            proto=proto, vrf_id=0, is_add=1)
7923         bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
7924         static_bib_num = 0
7925         for bibe in bib:
7926             if bibe.flags & self.config_flags.NAT_IS_STATIC:
7927                 static_bib_num += 1
7928                 self.assertEqual(str(bibe.i_addr), in_addr)
7929                 self.assertEqual(str(bibe.o_addr), out_addr)
7930                 self.assertEqual(bibe.i_port, in_port)
7931                 self.assertEqual(bibe.o_port, out_port)
7932         self.assertEqual(static_bib_num, 1)
7933         bibs = self.statistics.get_counter('/nat64/total-bibs')
7934         self.assertEqual(bibs[0][0], 1)
7935
7936         self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7937                                            i_port=in_port, o_port=out_port,
7938                                            proto=proto, vrf_id=0, is_add=0)
7939         bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
7940         static_bib_num = 0
7941         for bibe in bib:
7942             if bibe.flags & self.config_flags.NAT_IS_STATIC:
7943                 static_bib_num += 1
7944         self.assertEqual(static_bib_num, 0)
7945         bibs = self.statistics.get_counter('/nat64/total-bibs')
7946         self.assertEqual(bibs[0][0], 0)
7947
7948     def test_set_timeouts(self):
7949         """ Set NAT64 timeouts """
7950         # verify default values
7951         timeouts = self.vapi.nat_get_timeouts()
7952         self.assertEqual(timeouts.udp, 300)
7953         self.assertEqual(timeouts.icmp, 60)
7954         self.assertEqual(timeouts.tcp_transitory, 240)
7955         self.assertEqual(timeouts.tcp_established, 7440)
7956
7957         # set and verify custom values
7958         self.vapi.nat_set_timeouts(udp=200, tcp_established=7450,
7959                                    tcp_transitory=250, icmp=30)
7960         timeouts = self.vapi.nat_get_timeouts()
7961         self.assertEqual(timeouts.udp, 200)
7962         self.assertEqual(timeouts.icmp, 30)
7963         self.assertEqual(timeouts.tcp_transitory, 250)
7964         self.assertEqual(timeouts.tcp_established, 7450)
7965
7966     def test_dynamic(self):
7967         """ NAT64 dynamic translation test """
7968         self.tcp_port_in = 6303
7969         self.udp_port_in = 6304
7970         self.icmp_id_in = 6305
7971
7972         ses_num_start = self.nat64_get_ses_num()
7973
7974         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
7975                                                 end_addr=self.nat_addr,
7976                                                 vrf_id=0xFFFFFFFF,
7977                                                 is_add=1)
7978         flags = self.config_flags.NAT_IS_INSIDE
7979         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7980                                           sw_if_index=self.pg0.sw_if_index)
7981         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7982                                           sw_if_index=self.pg1.sw_if_index)
7983
7984         # in2out
7985         tcpn = self.statistics.get_err_counter('/err/nat64-in2out/TCP packets')
7986         udpn = self.statistics.get_err_counter('/err/nat64-in2out/UDP packets')
7987         icmpn = self.statistics.get_err_counter(
7988             '/err/nat64-in2out/ICMP packets')
7989         totaln = self.statistics.get_err_counter(
7990             '/err/nat64-in2out/good in2out packets processed')
7991
7992         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7993         self.pg0.add_stream(pkts)
7994         self.pg_enable_capture(self.pg_interfaces)
7995         self.pg_start()
7996         capture = self.pg1.get_capture(len(pkts))
7997         self.verify_capture_out(capture, nat_ip=self.nat_addr,
7998                                 dst_ip=self.pg1.remote_ip4)
7999
8000         err = self.statistics.get_err_counter('/err/nat64-in2out/TCP packets')
8001         self.assertEqual(err - tcpn, 1)
8002         err = self.statistics.get_err_counter('/err/nat64-in2out/UDP packets')
8003         self.assertEqual(err - udpn, 1)
8004         err = self.statistics.get_err_counter('/err/nat64-in2out/ICMP packets')
8005         self.assertEqual(err - icmpn, 1)
8006         err = self.statistics.get_err_counter(
8007             '/err/nat64-in2out/good in2out packets processed')
8008         self.assertEqual(err - totaln, 3)
8009
8010         # out2in
8011         tcpn = self.statistics.get_err_counter('/err/nat64-out2in/TCP packets')
8012         udpn = self.statistics.get_err_counter('/err/nat64-out2in/UDP packets')
8013         icmpn = self.statistics.get_err_counter(
8014             '/err/nat64-out2in/ICMP packets')
8015         totaln = self.statistics.get_err_counter(
8016             '/err/nat64-out2in/good out2in packets processed')
8017
8018         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8019         self.pg1.add_stream(pkts)
8020         self.pg_enable_capture(self.pg_interfaces)
8021         self.pg_start()
8022         capture = self.pg0.get_capture(len(pkts))
8023         ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8024         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8025
8026         err = self.statistics.get_err_counter('/err/nat64-out2in/TCP packets')
8027         self.assertEqual(err - tcpn, 2)
8028         err = self.statistics.get_err_counter('/err/nat64-out2in/UDP packets')
8029         self.assertEqual(err - udpn, 1)
8030         err = self.statistics.get_err_counter('/err/nat64-out2in/ICMP packets')
8031         self.assertEqual(err - icmpn, 1)
8032         err = self.statistics.get_err_counter(
8033             '/err/nat64-out2in/good out2in packets processed')
8034         self.assertEqual(err - totaln, 4)
8035
8036         bibs = self.statistics.get_counter('/nat64/total-bibs')
8037         self.assertEqual(bibs[0][0], 3)
8038         sessions = self.statistics.get_counter('/nat64/total-sessions')
8039         self.assertEqual(sessions[0][0], 3)
8040
8041         # in2out
8042         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8043         self.pg0.add_stream(pkts)
8044         self.pg_enable_capture(self.pg_interfaces)
8045         self.pg_start()
8046         capture = self.pg1.get_capture(len(pkts))
8047         self.verify_capture_out(capture, nat_ip=self.nat_addr,
8048                                 dst_ip=self.pg1.remote_ip4)
8049
8050         # out2in
8051         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8052         self.pg1.add_stream(pkts)
8053         self.pg_enable_capture(self.pg_interfaces)
8054         self.pg_start()
8055         capture = self.pg0.get_capture(len(pkts))
8056         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8057
8058         ses_num_end = self.nat64_get_ses_num()
8059
8060         self.assertEqual(ses_num_end - ses_num_start, 3)
8061
8062         # tenant with specific VRF
8063         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
8064                                                 end_addr=self.vrf1_nat_addr,
8065                                                 vrf_id=self.vrf1_id, is_add=1)
8066         flags = self.config_flags.NAT_IS_INSIDE
8067         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8068                                           sw_if_index=self.pg2.sw_if_index)
8069
8070         pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
8071         self.pg2.add_stream(pkts)
8072         self.pg_enable_capture(self.pg_interfaces)
8073         self.pg_start()
8074         capture = self.pg1.get_capture(len(pkts))
8075         self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
8076                                 dst_ip=self.pg1.remote_ip4)
8077
8078         pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
8079         self.pg1.add_stream(pkts)
8080         self.pg_enable_capture(self.pg_interfaces)
8081         self.pg_start()
8082         capture = self.pg2.get_capture(len(pkts))
8083         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
8084
8085     def test_static(self):
8086         """ NAT64 static translation test """
8087         self.tcp_port_in = 60303
8088         self.udp_port_in = 60304
8089         self.icmp_id_in = 60305
8090         self.tcp_port_out = 60303
8091         self.udp_port_out = 60304
8092         self.icmp_id_out = 60305
8093
8094         ses_num_start = self.nat64_get_ses_num()
8095
8096         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8097                                                 end_addr=self.nat_addr,
8098                                                 vrf_id=0xFFFFFFFF,
8099                                                 is_add=1)
8100         flags = self.config_flags.NAT_IS_INSIDE
8101         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8102                                           sw_if_index=self.pg0.sw_if_index)
8103         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8104                                           sw_if_index=self.pg1.sw_if_index)
8105
8106         self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6,
8107                                            o_addr=self.nat_addr,
8108                                            i_port=self.tcp_port_in,
8109                                            o_port=self.tcp_port_out,
8110                                            proto=IP_PROTOS.tcp, vrf_id=0,
8111                                            is_add=1)
8112         self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6,
8113                                            o_addr=self.nat_addr,
8114                                            i_port=self.udp_port_in,
8115                                            o_port=self.udp_port_out,
8116                                            proto=IP_PROTOS.udp, vrf_id=0,
8117                                            is_add=1)
8118         self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6,
8119                                            o_addr=self.nat_addr,
8120                                            i_port=self.icmp_id_in,
8121                                            o_port=self.icmp_id_out,
8122                                            proto=IP_PROTOS.icmp, vrf_id=0,
8123                                            is_add=1)
8124
8125         # in2out
8126         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8127         self.pg0.add_stream(pkts)
8128         self.pg_enable_capture(self.pg_interfaces)
8129         self.pg_start()
8130         capture = self.pg1.get_capture(len(pkts))
8131         self.verify_capture_out(capture, nat_ip=self.nat_addr,
8132                                 dst_ip=self.pg1.remote_ip4, same_port=True)
8133
8134         # out2in
8135         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8136         self.pg1.add_stream(pkts)
8137         self.pg_enable_capture(self.pg_interfaces)
8138         self.pg_start()
8139         capture = self.pg0.get_capture(len(pkts))
8140         ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8141         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8142
8143         ses_num_end = self.nat64_get_ses_num()
8144
8145         self.assertEqual(ses_num_end - ses_num_start, 3)
8146
8147     @unittest.skipUnless(running_extended_tests, "part of extended tests")
8148     def test_session_timeout(self):
8149         """ NAT64 session timeout """
8150         self.icmp_id_in = 1234
8151         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8152                                                 end_addr=self.nat_addr,
8153                                                 vrf_id=0xFFFFFFFF,
8154                                                 is_add=1)
8155         flags = self.config_flags.NAT_IS_INSIDE
8156         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8157                                           sw_if_index=self.pg0.sw_if_index)
8158         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8159                                           sw_if_index=self.pg1.sw_if_index)
8160         self.vapi.nat_set_timeouts(udp=300, tcp_established=5,
8161                                    tcp_transitory=5,
8162                                    icmp=5)
8163
8164         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8165         self.pg0.add_stream(pkts)
8166         self.pg_enable_capture(self.pg_interfaces)
8167         self.pg_start()
8168         capture = self.pg1.get_capture(len(pkts))
8169
8170         ses_num_before_timeout = self.nat64_get_ses_num()
8171
8172         sleep(15)
8173
8174         # ICMP and TCP session after timeout
8175         ses_num_after_timeout = self.nat64_get_ses_num()
8176         self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
8177
8178     def test_icmp_error(self):
8179         """ NAT64 ICMP Error message translation """
8180         self.tcp_port_in = 6303
8181         self.udp_port_in = 6304
8182         self.icmp_id_in = 6305
8183
8184         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8185                                                 end_addr=self.nat_addr,
8186                                                 vrf_id=0xFFFFFFFF,
8187                                                 is_add=1)
8188         flags = self.config_flags.NAT_IS_INSIDE
8189         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8190                                           sw_if_index=self.pg0.sw_if_index)
8191         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8192                                           sw_if_index=self.pg1.sw_if_index)
8193
8194         # send some packets to create sessions
8195         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8196         self.pg0.add_stream(pkts)
8197         self.pg_enable_capture(self.pg_interfaces)
8198         self.pg_start()
8199         capture_ip4 = self.pg1.get_capture(len(pkts))
8200         self.verify_capture_out(capture_ip4,
8201                                 nat_ip=self.nat_addr,
8202                                 dst_ip=self.pg1.remote_ip4)
8203
8204         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8205         self.pg1.add_stream(pkts)
8206         self.pg_enable_capture(self.pg_interfaces)
8207         self.pg_start()
8208         capture_ip6 = self.pg0.get_capture(len(pkts))
8209         ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8210         self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
8211                                    self.pg0.remote_ip6)
8212
8213         # in2out
8214         pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8215                 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
8216                 ICMPv6DestUnreach(code=1) /
8217                 packet[IPv6] for packet in capture_ip6]
8218         self.pg0.add_stream(pkts)
8219         self.pg_enable_capture(self.pg_interfaces)
8220         self.pg_start()
8221         capture = self.pg1.get_capture(len(pkts))
8222         for packet in capture:
8223             try:
8224                 self.assertEqual(packet[IP].src, self.nat_addr)
8225                 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
8226                 self.assertEqual(packet[ICMP].type, 3)
8227                 self.assertEqual(packet[ICMP].code, 13)
8228                 inner = packet[IPerror]
8229                 self.assertEqual(inner.src, self.pg1.remote_ip4)
8230                 self.assertEqual(inner.dst, self.nat_addr)
8231                 self.assert_packet_checksums_valid(packet)
8232                 if inner.haslayer(TCPerror):
8233                     self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
8234                 elif inner.haslayer(UDPerror):
8235                     self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
8236                 else:
8237                     self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
8238             except:
8239                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8240                 raise
8241
8242         # out2in
8243         pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8244                 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8245                 ICMP(type=3, code=13) /
8246                 packet[IP] for packet in capture_ip4]
8247         self.pg1.add_stream(pkts)
8248         self.pg_enable_capture(self.pg_interfaces)
8249         self.pg_start()
8250         capture = self.pg0.get_capture(len(pkts))
8251         for packet in capture:
8252             try:
8253                 self.assertEqual(packet[IPv6].src, ip.src)
8254                 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8255                 icmp = packet[ICMPv6DestUnreach]
8256                 self.assertEqual(icmp.code, 1)
8257                 inner = icmp[IPerror6]
8258                 self.assertEqual(inner.src, self.pg0.remote_ip6)
8259                 self.assertEqual(inner.dst, ip.src)
8260                 self.assert_icmpv6_checksum_valid(packet)
8261                 if inner.haslayer(TCPerror):
8262                     self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
8263                 elif inner.haslayer(UDPerror):
8264                     self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
8265                 else:
8266                     self.assertEqual(inner[ICMPv6EchoRequest].id,
8267                                      self.icmp_id_in)
8268             except:
8269                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8270                 raise
8271
8272     def test_hairpinning(self):
8273         """ NAT64 hairpinning """
8274
8275         client = self.pg0.remote_hosts[0]
8276         server = self.pg0.remote_hosts[1]
8277         server_tcp_in_port = 22
8278         server_tcp_out_port = 4022
8279         server_udp_in_port = 23
8280         server_udp_out_port = 4023
8281         client_tcp_in_port = 1234
8282         client_udp_in_port = 1235
8283         client_tcp_out_port = 0
8284         client_udp_out_port = 0
8285         ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8286         nat_addr_ip6 = ip.src
8287
8288         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8289                                                 end_addr=self.nat_addr,
8290                                                 vrf_id=0xFFFFFFFF,
8291                                                 is_add=1)
8292         flags = self.config_flags.NAT_IS_INSIDE
8293         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8294                                           sw_if_index=self.pg0.sw_if_index)
8295         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8296                                           sw_if_index=self.pg1.sw_if_index)
8297
8298         self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8299                                            o_addr=self.nat_addr,
8300                                            i_port=server_tcp_in_port,
8301                                            o_port=server_tcp_out_port,
8302                                            proto=IP_PROTOS.tcp, vrf_id=0,
8303                                            is_add=1)
8304         self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8305                                            o_addr=self.nat_addr,
8306                                            i_port=server_udp_in_port,
8307                                            o_port=server_udp_out_port,
8308                                            proto=IP_PROTOS.udp, vrf_id=0,
8309                                            is_add=1)
8310
8311         # client to server
8312         pkts = []
8313         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8314              IPv6(src=client.ip6, dst=nat_addr_ip6) /
8315              TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8316         pkts.append(p)
8317         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8318              IPv6(src=client.ip6, dst=nat_addr_ip6) /
8319              UDP(sport=client_udp_in_port, dport=server_udp_out_port))
8320         pkts.append(p)
8321         self.pg0.add_stream(pkts)
8322         self.pg_enable_capture(self.pg_interfaces)
8323         self.pg_start()
8324         capture = self.pg0.get_capture(len(pkts))
8325         for packet in capture:
8326             try:
8327                 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8328                 self.assertEqual(packet[IPv6].dst, server.ip6)
8329                 self.assert_packet_checksums_valid(packet)
8330                 if packet.haslayer(TCP):
8331                     self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
8332                     self.assertEqual(packet[TCP].dport, server_tcp_in_port)
8333                     client_tcp_out_port = packet[TCP].sport
8334                 else:
8335                     self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
8336                     self.assertEqual(packet[UDP].dport, server_udp_in_port)
8337                     client_udp_out_port = packet[UDP].sport
8338             except:
8339                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8340                 raise
8341
8342         # server to client
8343         pkts = []
8344         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8345              IPv6(src=server.ip6, dst=nat_addr_ip6) /
8346              TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
8347         pkts.append(p)
8348         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8349              IPv6(src=server.ip6, dst=nat_addr_ip6) /
8350              UDP(sport=server_udp_in_port, dport=client_udp_out_port))
8351         pkts.append(p)
8352         self.pg0.add_stream(pkts)
8353         self.pg_enable_capture(self.pg_interfaces)
8354         self.pg_start()
8355         capture = self.pg0.get_capture(len(pkts))
8356         for packet in capture:
8357             try:
8358                 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8359                 self.assertEqual(packet[IPv6].dst, client.ip6)
8360                 self.assert_packet_checksums_valid(packet)
8361                 if packet.haslayer(TCP):
8362                     self.assertEqual(packet[TCP].sport, server_tcp_out_port)
8363                     self.assertEqual(packet[TCP].dport, client_tcp_in_port)
8364                 else:
8365                     self.assertEqual(packet[UDP].sport, server_udp_out_port)
8366                     self.assertEqual(packet[UDP].dport, client_udp_in_port)
8367             except:
8368                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8369                 raise
8370
8371         # ICMP error
8372         pkts = []
8373         pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8374                 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8375                 ICMPv6DestUnreach(code=1) /
8376                 packet[IPv6] for packet in capture]
8377         self.pg0.add_stream(pkts)
8378         self.pg_enable_capture(self.pg_interfaces)
8379         self.pg_start()
8380         capture = self.pg0.get_capture(len(pkts))
8381         for packet in capture:
8382             try:
8383                 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8384                 self.assertEqual(packet[IPv6].dst, server.ip6)
8385                 icmp = packet[ICMPv6DestUnreach]
8386                 self.assertEqual(icmp.code, 1)
8387                 inner = icmp[IPerror6]
8388                 self.assertEqual(inner.src, server.ip6)
8389                 self.assertEqual(inner.dst, nat_addr_ip6)
8390                 self.assert_packet_checksums_valid(packet)
8391                 if inner.haslayer(TCPerror):
8392                     self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
8393                     self.assertEqual(inner[TCPerror].dport,
8394                                      client_tcp_out_port)
8395                 else:
8396                     self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
8397                     self.assertEqual(inner[UDPerror].dport,
8398                                      client_udp_out_port)
8399             except:
8400                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8401                 raise
8402
8403     def test_prefix(self):
8404         """ NAT64 Network-Specific Prefix """
8405
8406         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8407                                                 end_addr=self.nat_addr,
8408                                                 vrf_id=0xFFFFFFFF,
8409                                                 is_add=1)
8410         flags = self.config_flags.NAT_IS_INSIDE
8411         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8412                                           sw_if_index=self.pg0.sw_if_index)
8413         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8414                                           sw_if_index=self.pg1.sw_if_index)
8415         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
8416                                                 end_addr=self.vrf1_nat_addr,
8417                                                 vrf_id=self.vrf1_id, is_add=1)
8418         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8419                                           sw_if_index=self.pg2.sw_if_index)
8420
8421         # Add global prefix
8422         global_pref64 = "2001:db8::"
8423         global_pref64_len = 32
8424         global_pref64_str = "{}/{}".format(global_pref64, global_pref64_len)
8425         self.vapi.nat64_add_del_prefix(prefix=global_pref64_str, vrf_id=0,
8426                                        is_add=1)
8427
8428         prefix = self.vapi.nat64_prefix_dump()
8429         self.assertEqual(len(prefix), 1)
8430         self.assertEqual(str(prefix[0].prefix), global_pref64_str)
8431         self.assertEqual(prefix[0].vrf_id, 0)
8432
8433         # Add tenant specific prefix
8434         vrf1_pref64 = "2001:db8:122:300::"
8435         vrf1_pref64_len = 56
8436         vrf1_pref64_str = "{}/{}".format(vrf1_pref64, vrf1_pref64_len)
8437         self.vapi.nat64_add_del_prefix(prefix=vrf1_pref64_str,
8438                                        vrf_id=self.vrf1_id, is_add=1)
8439
8440         prefix = self.vapi.nat64_prefix_dump()
8441         self.assertEqual(len(prefix), 2)
8442
8443         # Global prefix
8444         pkts = self.create_stream_in_ip6(self.pg0,
8445                                          self.pg1,
8446                                          pref=global_pref64,
8447                                          plen=global_pref64_len)
8448         self.pg0.add_stream(pkts)
8449         self.pg_enable_capture(self.pg_interfaces)
8450         self.pg_start()
8451         capture = self.pg1.get_capture(len(pkts))
8452         self.verify_capture_out(capture, nat_ip=self.nat_addr,
8453                                 dst_ip=self.pg1.remote_ip4)
8454
8455         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8456         self.pg1.add_stream(pkts)
8457         self.pg_enable_capture(self.pg_interfaces)
8458         self.pg_start()
8459         capture = self.pg0.get_capture(len(pkts))
8460         dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8461                                   global_pref64,
8462                                   global_pref64_len)
8463         self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
8464
8465         # Tenant specific prefix
8466         pkts = self.create_stream_in_ip6(self.pg2,
8467                                          self.pg1,
8468                                          pref=vrf1_pref64,
8469                                          plen=vrf1_pref64_len)
8470         self.pg2.add_stream(pkts)
8471         self.pg_enable_capture(self.pg_interfaces)
8472         self.pg_start()
8473         capture = self.pg1.get_capture(len(pkts))
8474         self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
8475                                 dst_ip=self.pg1.remote_ip4)
8476
8477         pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
8478         self.pg1.add_stream(pkts)
8479         self.pg_enable_capture(self.pg_interfaces)
8480         self.pg_start()
8481         capture = self.pg2.get_capture(len(pkts))
8482         dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8483                                   vrf1_pref64,
8484                                   vrf1_pref64_len)
8485         self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
8486
8487     def test_unknown_proto(self):
8488         """ NAT64 translate packet with unknown protocol """
8489
8490         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8491                                                 end_addr=self.nat_addr,
8492                                                 vrf_id=0xFFFFFFFF,
8493                                                 is_add=1)
8494         flags = self.config_flags.NAT_IS_INSIDE
8495         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8496                                           sw_if_index=self.pg0.sw_if_index)
8497         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8498                                           sw_if_index=self.pg1.sw_if_index)
8499         remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8500
8501         # in2out
8502         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8503              IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
8504              TCP(sport=self.tcp_port_in, dport=20))
8505         self.pg0.add_stream(p)
8506         self.pg_enable_capture(self.pg_interfaces)
8507         self.pg_start()
8508         p = self.pg1.get_capture(1)
8509
8510         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8511              IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
8512              GRE() /
8513              IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8514              TCP(sport=1234, dport=1234))
8515         self.pg0.add_stream(p)
8516         self.pg_enable_capture(self.pg_interfaces)
8517         self.pg_start()
8518         p = self.pg1.get_capture(1)
8519         packet = p[0]
8520         try:
8521             self.assertEqual(packet[IP].src, self.nat_addr)
8522             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
8523             self.assertEqual(packet.haslayer(GRE), 1)
8524             self.assert_packet_checksums_valid(packet)
8525         except:
8526             self.logger.error(ppp("Unexpected or invalid packet:", packet))
8527             raise
8528
8529         # out2in
8530         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8531              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8532              GRE() /
8533              IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8534              TCP(sport=1234, dport=1234))
8535         self.pg1.add_stream(p)
8536         self.pg_enable_capture(self.pg_interfaces)
8537         self.pg_start()
8538         p = self.pg0.get_capture(1)
8539         packet = p[0]
8540         try:
8541             self.assertEqual(packet[IPv6].src, remote_ip6)
8542             self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8543             self.assertEqual(packet[IPv6].nh, 47)
8544         except:
8545             self.logger.error(ppp("Unexpected or invalid packet:", packet))
8546             raise
8547
8548     def test_hairpinning_unknown_proto(self):
8549         """ NAT64 translate packet with unknown protocol - hairpinning """
8550
8551         client = self.pg0.remote_hosts[0]
8552         server = self.pg0.remote_hosts[1]
8553         server_tcp_in_port = 22
8554         server_tcp_out_port = 4022
8555         client_tcp_in_port = 1234
8556         client_tcp_out_port = 1235
8557         server_nat_ip = "10.0.0.100"
8558         client_nat_ip = "10.0.0.110"
8559         server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
8560         client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
8561
8562         self.vapi.nat64_add_del_pool_addr_range(start_addr=server_nat_ip,
8563                                                 end_addr=client_nat_ip,
8564                                                 vrf_id=0xFFFFFFFF,
8565                                                 is_add=1)
8566         flags = self.config_flags.NAT_IS_INSIDE
8567         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8568                                           sw_if_index=self.pg0.sw_if_index)
8569         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8570                                           sw_if_index=self.pg1.sw_if_index)
8571
8572         self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8573                                            o_addr=server_nat_ip,
8574                                            i_port=server_tcp_in_port,
8575                                            o_port=server_tcp_out_port,
8576                                            proto=IP_PROTOS.tcp, vrf_id=0,
8577                                            is_add=1)
8578
8579         self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8580                                            o_addr=server_nat_ip, i_port=0,
8581                                            o_port=0,
8582                                            proto=IP_PROTOS.gre, vrf_id=0,
8583                                            is_add=1)
8584
8585         self.vapi.nat64_add_del_static_bib(i_addr=client.ip6n,
8586                                            o_addr=client_nat_ip,
8587                                            i_port=client_tcp_in_port,
8588                                            o_port=client_tcp_out_port,
8589                                            proto=IP_PROTOS.tcp, vrf_id=0,
8590                                            is_add=1)
8591
8592         # client to server
8593         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8594              IPv6(src=client.ip6, dst=server_nat_ip6) /
8595              TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8596         self.pg0.add_stream(p)
8597         self.pg_enable_capture(self.pg_interfaces)
8598         self.pg_start()
8599         p = self.pg0.get_capture(1)
8600
8601         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8602              IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
8603              GRE() /
8604              IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8605              TCP(sport=1234, dport=1234))
8606         self.pg0.add_stream(p)
8607         self.pg_enable_capture(self.pg_interfaces)
8608         self.pg_start()
8609         p = self.pg0.get_capture(1)
8610         packet = p[0]
8611         try:
8612             self.assertEqual(packet[IPv6].src, client_nat_ip6)
8613             self.assertEqual(packet[IPv6].dst, server.ip6)
8614             self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
8615         except:
8616             self.logger.error(ppp("Unexpected or invalid packet:", packet))
8617             raise
8618
8619         # server to client
8620         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8621              IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
8622              GRE() /
8623              IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8624              TCP(sport=1234, dport=1234))
8625         self.pg0.add_stream(p)
8626         self.pg_enable_capture(self.pg_interfaces)
8627         self.pg_start()
8628         p = self.pg0.get_capture(1)
8629         packet = p[0]
8630         try:
8631             self.assertEqual(packet[IPv6].src, server_nat_ip6)
8632             self.assertEqual(packet[IPv6].dst, client.ip6)
8633             self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
8634         except:
8635             self.logger.error(ppp("Unexpected or invalid packet:", packet))
8636             raise
8637
8638     def test_one_armed_nat64(self):
8639         """ One armed NAT64 """
8640         external_port = 0
8641         remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
8642                                            '64:ff9b::',
8643                                            96)
8644
8645         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8646                                                 end_addr=self.nat_addr,
8647                                                 vrf_id=0xFFFFFFFF,
8648                                                 is_add=1)
8649         flags = self.config_flags.NAT_IS_INSIDE
8650         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8651                                           sw_if_index=self.pg3.sw_if_index)
8652         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8653                                           sw_if_index=self.pg3.sw_if_index)
8654
8655         # in2out
8656         p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8657              IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
8658              TCP(sport=12345, dport=80))
8659         self.pg3.add_stream(p)
8660         self.pg_enable_capture(self.pg_interfaces)
8661         self.pg_start()
8662         capture = self.pg3.get_capture(1)
8663         p = capture[0]
8664         try:
8665             ip = p[IP]
8666             tcp = p[TCP]
8667             self.assertEqual(ip.src, self.nat_addr)
8668             self.assertEqual(ip.dst, self.pg3.remote_ip4)
8669             self.assertNotEqual(tcp.sport, 12345)
8670             external_port = tcp.sport
8671             self.assertEqual(tcp.dport, 80)
8672             self.assert_packet_checksums_valid(p)
8673         except:
8674             self.logger.error(ppp("Unexpected or invalid packet:", p))
8675             raise
8676
8677         # out2in
8678         p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8679              IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
8680              TCP(sport=80, dport=external_port))
8681         self.pg3.add_stream(p)
8682         self.pg_enable_capture(self.pg_interfaces)
8683         self.pg_start()
8684         capture = self.pg3.get_capture(1)
8685         p = capture[0]
8686         try:
8687             ip = p[IPv6]
8688             tcp = p[TCP]
8689             self.assertEqual(ip.src, remote_host_ip6)
8690             self.assertEqual(ip.dst, self.pg3.remote_ip6)
8691             self.assertEqual(tcp.sport, 80)
8692             self.assertEqual(tcp.dport, 12345)
8693             self.assert_packet_checksums_valid(p)
8694         except:
8695             self.logger.error(ppp("Unexpected or invalid packet:", p))
8696             raise
8697
8698     def test_frag_in_order(self):
8699         """ NAT64 translate fragments arriving in order """
8700         self.tcp_port_in = random.randint(1025, 65535)
8701
8702         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8703                                                 end_addr=self.nat_addr,
8704                                                 vrf_id=0xFFFFFFFF,
8705                                                 is_add=1)
8706         flags = self.config_flags.NAT_IS_INSIDE
8707         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8708                                           sw_if_index=self.pg0.sw_if_index)
8709         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8710                                           sw_if_index=self.pg1.sw_if_index)
8711
8712         # in2out
8713         data = b'a' * 200
8714         pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8715                                            self.tcp_port_in, 20, data)
8716         self.pg0.add_stream(pkts)
8717         self.pg_enable_capture(self.pg_interfaces)
8718         self.pg_start()
8719         frags = self.pg1.get_capture(len(pkts))
8720         p = self.reass_frags_and_verify(frags,
8721                                         self.nat_addr,
8722                                         self.pg1.remote_ip4)
8723         self.assertEqual(p[TCP].dport, 20)
8724         self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8725         self.tcp_port_out = p[TCP].sport
8726         self.assertEqual(data, p[Raw].load)
8727
8728         # out2in
8729         data = b"A" * 4 + b"b" * 16 + b"C" * 3
8730         pkts = self.create_stream_frag(self.pg1,
8731                                        self.nat_addr,
8732                                        20,
8733                                        self.tcp_port_out,
8734                                        data)
8735         self.pg1.add_stream(pkts)
8736         self.pg_enable_capture(self.pg_interfaces)
8737         self.pg_start()
8738         frags = self.pg0.get_capture(len(pkts))
8739         self.logger.debug(ppc("Captured:", frags))
8740         src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8741         p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8742         self.assertEqual(p[TCP].sport, 20)
8743         self.assertEqual(p[TCP].dport, self.tcp_port_in)
8744         self.assertEqual(data, p[Raw].load)
8745
8746     def test_reass_hairpinning(self):
8747         """ NAT64 fragments hairpinning """
8748         data = b'a' * 200
8749         server = self.pg0.remote_hosts[1]
8750         server_in_port = random.randint(1025, 65535)
8751         server_out_port = random.randint(1025, 65535)
8752         client_in_port = random.randint(1025, 65535)
8753         ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8754         nat_addr_ip6 = ip.src
8755
8756         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8757                                                 end_addr=self.nat_addr,
8758                                                 vrf_id=0xFFFFFFFF,
8759                                                 is_add=1)
8760         flags = self.config_flags.NAT_IS_INSIDE
8761         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8762                                           sw_if_index=self.pg0.sw_if_index)
8763         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8764                                           sw_if_index=self.pg1.sw_if_index)
8765
8766         # add static BIB entry for server
8767         self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8768                                            o_addr=self.nat_addr,
8769                                            i_port=server_in_port,
8770                                            o_port=server_out_port,
8771                                            proto=IP_PROTOS.tcp, vrf_id=0,
8772                                            is_add=1)
8773
8774         # send packet from host to server
8775         pkts = self.create_stream_frag_ip6(self.pg0,
8776                                            self.nat_addr,
8777                                            client_in_port,
8778                                            server_out_port,
8779                                            data)
8780         self.pg0.add_stream(pkts)
8781         self.pg_enable_capture(self.pg_interfaces)
8782         self.pg_start()
8783         frags = self.pg0.get_capture(len(pkts))
8784         self.logger.debug(ppc("Captured:", frags))
8785         p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
8786         self.assertNotEqual(p[TCP].sport, client_in_port)
8787         self.assertEqual(p[TCP].dport, server_in_port)
8788         self.assertEqual(data, p[Raw].load)
8789
8790     def test_frag_out_of_order(self):
8791         """ NAT64 translate fragments arriving out of order """
8792         self.tcp_port_in = random.randint(1025, 65535)
8793
8794         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8795                                                 end_addr=self.nat_addr,
8796                                                 vrf_id=0xFFFFFFFF,
8797                                                 is_add=1)
8798         flags = self.config_flags.NAT_IS_INSIDE
8799         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8800                                           sw_if_index=self.pg0.sw_if_index)
8801         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8802                                           sw_if_index=self.pg1.sw_if_index)
8803
8804         # in2out
8805         data = b'a' * 200
8806         pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8807                                            self.tcp_port_in, 20, data)
8808         pkts.reverse()
8809         self.pg0.add_stream(pkts)
8810         self.pg_enable_capture(self.pg_interfaces)
8811         self.pg_start()
8812         frags = self.pg1.get_capture(len(pkts))
8813         p = self.reass_frags_and_verify(frags,
8814                                         self.nat_addr,
8815                                         self.pg1.remote_ip4)
8816         self.assertEqual(p[TCP].dport, 20)
8817         self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8818         self.tcp_port_out = p[TCP].sport
8819         self.assertEqual(data, p[Raw].load)
8820
8821         # out2in
8822         data = b"A" * 4 + b"B" * 16 + b"C" * 3
8823         pkts = self.create_stream_frag(self.pg1,
8824                                        self.nat_addr,
8825                                        20,
8826                                        self.tcp_port_out,
8827                                        data)
8828         pkts.reverse()
8829         self.pg1.add_stream(pkts)
8830         self.pg_enable_capture(self.pg_interfaces)
8831         self.pg_start()
8832         frags = self.pg0.get_capture(len(pkts))
8833         src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8834         p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8835         self.assertEqual(p[TCP].sport, 20)
8836         self.assertEqual(p[TCP].dport, self.tcp_port_in)
8837         self.assertEqual(data, p[Raw].load)
8838
8839     def test_interface_addr(self):
8840         """ Acquire NAT64 pool addresses from interface """
8841         self.vapi.nat64_add_del_interface_addr(
8842             is_add=1,
8843             sw_if_index=self.pg4.sw_if_index)
8844
8845         # no address in NAT64 pool
8846         addresses = self.vapi.nat44_address_dump()
8847         self.assertEqual(0, len(addresses))
8848
8849         # configure interface address and check NAT64 address pool
8850         self.pg4.config_ip4()
8851         addresses = self.vapi.nat64_pool_addr_dump()
8852         self.assertEqual(len(addresses), 1)
8853
8854         self.assertEqual(str(addresses[0].address),
8855                          self.pg4.local_ip4)
8856
8857         # remove interface address and check NAT64 address pool
8858         self.pg4.unconfig_ip4()
8859         addresses = self.vapi.nat64_pool_addr_dump()
8860         self.assertEqual(0, len(addresses))
8861
8862     @unittest.skipUnless(running_extended_tests, "part of extended tests")
8863     def test_ipfix_max_bibs_sessions(self):
8864         """ IPFIX logging maximum session and BIB entries exceeded """
8865         max_bibs = 1280
8866         max_sessions = 2560
8867         remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8868                                            '64:ff9b::',
8869                                            96)
8870
8871         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8872                                                 end_addr=self.nat_addr,
8873                                                 vrf_id=0xFFFFFFFF,
8874                                                 is_add=1)
8875         flags = self.config_flags.NAT_IS_INSIDE
8876         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8877                                           sw_if_index=self.pg0.sw_if_index)
8878         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8879                                           sw_if_index=self.pg1.sw_if_index)
8880
8881         pkts = []
8882         src = ""
8883         for i in range(0, max_bibs):
8884             src = "fd01:aa::%x" % (i)
8885             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8886                  IPv6(src=src, dst=remote_host_ip6) /
8887                  TCP(sport=12345, dport=80))
8888             pkts.append(p)
8889             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8890                  IPv6(src=src, dst=remote_host_ip6) /
8891                  TCP(sport=12345, dport=22))
8892             pkts.append(p)
8893         self.pg0.add_stream(pkts)
8894         self.pg_enable_capture(self.pg_interfaces)
8895         self.pg_start()
8896         self.pg1.get_capture(max_sessions)
8897
8898         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
8899                                      src_address=self.pg3.local_ip4,
8900                                      path_mtu=512,
8901                                      template_interval=10)
8902         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8903                                            src_port=self.ipfix_src_port,
8904                                            enable=1)
8905
8906         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8907              IPv6(src=src, dst=remote_host_ip6) /
8908              TCP(sport=12345, dport=25))
8909         self.pg0.add_stream(p)
8910         self.pg_enable_capture(self.pg_interfaces)
8911         self.pg_start()
8912         self.pg1.assert_nothing_captured()
8913         sleep(1)
8914         self.vapi.ipfix_flush()
8915         capture = self.pg3.get_capture(7)
8916         ipfix = IPFIXDecoder()
8917         # first load template
8918         for p in capture:
8919             self.assertTrue(p.haslayer(IPFIX))
8920             self.assertEqual(p[IP].src, self.pg3.local_ip4)
8921             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8922             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8923             self.assertEqual(p[UDP].dport, 4739)
8924             self.assertEqual(p[IPFIX].observationDomainID,
8925                              self.ipfix_domain_id)
8926             if p.haslayer(Template):
8927                 ipfix.add_template(p.getlayer(Template))
8928         # verify events in data set
8929         for p in capture:
8930             if p.haslayer(Data):
8931                 data = ipfix.decode_data_set(p.getlayer(Set))
8932                 self.verify_ipfix_max_sessions(data, max_sessions)
8933
8934         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8935              IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8936              TCP(sport=12345, dport=80))
8937         self.pg0.add_stream(p)
8938         self.pg_enable_capture(self.pg_interfaces)
8939         self.pg_start()
8940         self.pg1.assert_nothing_captured()
8941         sleep(1)
8942         self.vapi.ipfix_flush()
8943         capture = self.pg3.get_capture(1)
8944         # verify events in data set
8945         for p in capture:
8946             self.assertTrue(p.haslayer(IPFIX))
8947             self.assertEqual(p[IP].src, self.pg3.local_ip4)
8948             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8949             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8950             self.assertEqual(p[UDP].dport, 4739)
8951             self.assertEqual(p[IPFIX].observationDomainID,
8952                              self.ipfix_domain_id)
8953             if p.haslayer(Data):
8954                 data = ipfix.decode_data_set(p.getlayer(Set))
8955                 self.verify_ipfix_max_bibs(data, max_bibs)
8956
8957     def test_ipfix_bib_ses(self):
8958         """ IPFIX logging NAT64 BIB/session create and delete events """
8959         self.tcp_port_in = random.randint(1025, 65535)
8960         remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8961                                            '64:ff9b::',
8962                                            96)
8963
8964         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8965                                                 end_addr=self.nat_addr,
8966                                                 vrf_id=0xFFFFFFFF,
8967                                                 is_add=1)
8968         flags = self.config_flags.NAT_IS_INSIDE
8969         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8970                                           sw_if_index=self.pg0.sw_if_index)
8971         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8972                                           sw_if_index=self.pg1.sw_if_index)
8973         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
8974                                      src_address=self.pg3.local_ip4,
8975                                      path_mtu=512,
8976                                      template_interval=10)
8977         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8978                                            src_port=self.ipfix_src_port,
8979                                            enable=1)
8980
8981         # Create
8982         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8983              IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8984              TCP(sport=self.tcp_port_in, dport=25))
8985         self.pg0.add_stream(p)
8986         self.pg_enable_capture(self.pg_interfaces)
8987         self.pg_start()
8988         p = self.pg1.get_capture(1)
8989         self.tcp_port_out = p[0][TCP].sport
8990         self.vapi.ipfix_flush()
8991         capture = self.pg3.get_capture(8)
8992         ipfix = IPFIXDecoder()
8993         # first load template
8994         for p in capture:
8995             self.assertTrue(p.haslayer(IPFIX))
8996             self.assertEqual(p[IP].src, self.pg3.local_ip4)
8997             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8998             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8999             self.assertEqual(p[UDP].dport, 4739)
9000             self.assertEqual(p[IPFIX].observationDomainID,
9001                              self.ipfix_domain_id)
9002             if p.haslayer(Template):
9003                 ipfix.add_template(p.getlayer(Template))
9004         # verify events in data set
9005         for p in capture:
9006             if p.haslayer(Data):
9007                 data = ipfix.decode_data_set(p.getlayer(Set))
9008                 if scapy.compat.orb(data[0][230]) == 10:
9009                     self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6)
9010                 elif scapy.compat.orb(data[0][230]) == 6:
9011                     self.verify_ipfix_nat64_ses(data,
9012                                                 1,
9013                                                 self.pg0.remote_ip6,
9014                                                 self.pg1.remote_ip4,
9015                                                 25)
9016                 else:
9017                     self.logger.error(ppp("Unexpected or invalid packet: ", p))
9018
9019         # Delete
9020         self.pg_enable_capture(self.pg_interfaces)
9021         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9022                                                 end_addr=self.nat_addr,
9023                                                 vrf_id=0xFFFFFFFF,
9024                                                 is_add=0)
9025         self.vapi.ipfix_flush()
9026         capture = self.pg3.get_capture(2)
9027         # verify events in data set
9028         for p in capture:
9029             self.assertTrue(p.haslayer(IPFIX))
9030             self.assertEqual(p[IP].src, self.pg3.local_ip4)
9031             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
9032             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
9033             self.assertEqual(p[UDP].dport, 4739)
9034             self.assertEqual(p[IPFIX].observationDomainID,
9035                              self.ipfix_domain_id)
9036             if p.haslayer(Data):
9037                 data = ipfix.decode_data_set(p.getlayer(Set))
9038                 if scapy.compat.orb(data[0][230]) == 11:
9039                     self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6)
9040                 elif scapy.compat.orb(data[0][230]) == 7:
9041                     self.verify_ipfix_nat64_ses(data,
9042                                                 0,
9043                                                 self.pg0.remote_ip6,
9044                                                 self.pg1.remote_ip4,
9045                                                 25)
9046                 else:
9047                     self.logger.error(ppp("Unexpected or invalid packet: ", p))
9048
9049     def test_syslog_sess(self):
9050         """ Test syslog session creation and deletion """
9051         self.tcp_port_in = random.randint(1025, 65535)
9052         remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
9053                                            '64:ff9b::',
9054                                            96)
9055
9056         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9057                                                 end_addr=self.nat_addr,
9058                                                 vrf_id=0xFFFFFFFF,
9059                                                 is_add=1)
9060         flags = self.config_flags.NAT_IS_INSIDE
9061         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
9062                                           sw_if_index=self.pg0.sw_if_index)
9063         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
9064                                           sw_if_index=self.pg1.sw_if_index)
9065         self.vapi.syslog_set_filter(
9066             self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
9067         self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
9068
9069         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
9070              IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
9071              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
9072         self.pg0.add_stream(p)
9073         self.pg_enable_capture(self.pg_interfaces)
9074         self.pg_start()
9075         p = self.pg1.get_capture(1)
9076         self.tcp_port_out = p[0][TCP].sport
9077         capture = self.pg3.get_capture(1)
9078         self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
9079
9080         self.pg_enable_capture(self.pg_interfaces)
9081         self.pg_start()
9082         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9083                                                 end_addr=self.nat_addr,
9084                                                 vrf_id=0xFFFFFFFF,
9085                                                 is_add=0)
9086         capture = self.pg3.get_capture(1)
9087         self.verify_syslog_sess(capture[0][Raw].load, False, True)
9088
9089     def nat64_get_ses_num(self):
9090         """
9091         Return number of active NAT64 sessions.
9092         """
9093         st = self.vapi.nat64_st_dump(proto=255)
9094         return len(st)
9095
9096     def clear_nat64(self):
9097         """
9098         Clear NAT64 configuration.
9099         """
9100         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
9101                                            src_port=self.ipfix_src_port,
9102                                            enable=0)
9103         self.ipfix_src_port = 4739
9104         self.ipfix_domain_id = 1
9105
9106         self.vapi.syslog_set_filter(
9107             self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_EMERG)
9108
9109         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
9110                                    tcp_transitory=240, icmp=60)
9111
9112         interfaces = self.vapi.nat64_interface_dump()
9113         for intf in interfaces:
9114             self.vapi.nat64_add_del_interface(is_add=0, flags=intf.flags,
9115                                               sw_if_index=intf.sw_if_index)
9116
9117         bib = self.vapi.nat64_bib_dump(proto=255)
9118         for bibe in bib:
9119             if bibe.flags & self.config_flags.NAT_IS_STATIC:
9120                 self.vapi.nat64_add_del_static_bib(i_addr=bibe.i_addr,
9121                                                    o_addr=bibe.o_addr,
9122                                                    i_port=bibe.i_port,
9123                                                    o_port=bibe.o_port,
9124                                                    proto=bibe.proto,
9125                                                    vrf_id=bibe.vrf_id,
9126                                                    is_add=0)
9127
9128         adresses = self.vapi.nat64_pool_addr_dump()
9129         for addr in adresses:
9130             self.vapi.nat64_add_del_pool_addr_range(start_addr=addr.address,
9131                                                     end_addr=addr.address,
9132                                                     vrf_id=addr.vrf_id,
9133                                                     is_add=0)
9134
9135         prefixes = self.vapi.nat64_prefix_dump()
9136         for prefix in prefixes:
9137             self.vapi.nat64_add_del_prefix(prefix=str(prefix.prefix),
9138                                            vrf_id=prefix.vrf_id, is_add=0)
9139
9140         bibs = self.statistics.get_counter('/nat64/total-bibs')
9141         self.assertEqual(bibs[0][0], 0)
9142         sessions = self.statistics.get_counter('/nat64/total-sessions')
9143         self.assertEqual(sessions[0][0], 0)
9144
9145     def tearDown(self):
9146         super(TestNAT64, self).tearDown()
9147         if not self.vpp_dead:
9148             self.clear_nat64()
9149
9150     def show_commands_at_teardown(self):
9151         self.logger.info(self.vapi.cli("show nat64 pool"))
9152         self.logger.info(self.vapi.cli("show nat64 interfaces"))
9153         self.logger.info(self.vapi.cli("show nat64 prefix"))
9154         self.logger.info(self.vapi.cli("show nat64 bib all"))
9155         self.logger.info(self.vapi.cli("show nat64 session table all"))
9156
9157
9158 class TestNAT66(MethodHolder):
9159     """ NAT66 Test Cases """
9160
9161     @classmethod
9162     def setUpClass(cls):
9163         super(TestNAT66, cls).setUpClass()
9164
9165         cls.nat_addr = 'fd01:ff::2'
9166
9167         cls.create_pg_interfaces(range(2))
9168         cls.interfaces = list(cls.pg_interfaces)
9169
9170         for i in cls.interfaces:
9171             i.admin_up()
9172             i.config_ip6()
9173             i.configure_ipv6_neighbors()
9174
9175     @classmethod
9176     def tearDownClass(cls):
9177         super(TestNAT66, cls).tearDownClass()
9178
9179     def test_static(self):
9180         """ 1:1 NAT66 test """
9181         flags = self.config_flags.NAT_IS_INSIDE
9182         self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9183                                           sw_if_index=self.pg0.sw_if_index)
9184         self.vapi.nat66_add_del_interface(is_add=1,
9185                                           sw_if_index=self.pg1.sw_if_index)
9186         self.vapi.nat66_add_del_static_mapping(
9187             local_ip_address=self.pg0.remote_ip6,
9188             external_ip_address=self.nat_addr,
9189             is_add=1)
9190
9191         # in2out
9192         pkts = []
9193         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9194              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9195              TCP())
9196         pkts.append(p)
9197         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9198              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9199              UDP())
9200         pkts.append(p)
9201         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9202              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9203              ICMPv6EchoRequest())
9204         pkts.append(p)
9205         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9206              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9207              GRE() / IP() / TCP())
9208         pkts.append(p)
9209         self.pg0.add_stream(pkts)
9210         self.pg_enable_capture(self.pg_interfaces)
9211         self.pg_start()
9212         capture = self.pg1.get_capture(len(pkts))
9213
9214         for packet in capture:
9215             try:
9216                 self.assertEqual(packet[IPv6].src, self.nat_addr)
9217                 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9218                 self.assert_packet_checksums_valid(packet)
9219             except:
9220                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9221                 raise
9222
9223         # out2in
9224         pkts = []
9225         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9226              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9227              TCP())
9228         pkts.append(p)
9229         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9230              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9231              UDP())
9232         pkts.append(p)
9233         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9234              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9235              ICMPv6EchoReply())
9236         pkts.append(p)
9237         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9238              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9239              GRE() / IP() / TCP())
9240         pkts.append(p)
9241         self.pg1.add_stream(pkts)
9242         self.pg_enable_capture(self.pg_interfaces)
9243         self.pg_start()
9244         capture = self.pg0.get_capture(len(pkts))
9245         for packet in capture:
9246             try:
9247                 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
9248                 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
9249                 self.assert_packet_checksums_valid(packet)
9250             except:
9251                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9252                 raise
9253
9254         sm = self.vapi.nat66_static_mapping_dump()
9255         self.assertEqual(len(sm), 1)
9256         self.assertEqual(sm[0].total_pkts, 8)
9257
9258     def test_check_no_translate(self):
9259         """ NAT66 translate only when egress interface is outside interface """
9260         flags = self.config_flags.NAT_IS_INSIDE
9261         self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9262                                           sw_if_index=self.pg0.sw_if_index)
9263         self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9264                                           sw_if_index=self.pg1.sw_if_index)
9265         self.vapi.nat66_add_del_static_mapping(
9266             local_ip_address=self.pg0.remote_ip6,
9267             external_ip_address=self.nat_addr,
9268             is_add=1)
9269
9270         # in2out
9271         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9272              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9273              UDP())
9274         self.pg0.add_stream([p])
9275         self.pg_enable_capture(self.pg_interfaces)
9276         self.pg_start()
9277         capture = self.pg1.get_capture(1)
9278         packet = capture[0]
9279         try:
9280             self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
9281             self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9282         except:
9283             self.logger.error(ppp("Unexpected or invalid packet:", packet))
9284             raise
9285
9286     def clear_nat66(self):
9287         """
9288         Clear NAT66 configuration.
9289         """
9290         interfaces = self.vapi.nat66_interface_dump()
9291         for intf in interfaces:
9292             self.vapi.nat66_add_del_interface(is_add=0, flags=intf.flags,
9293                                               sw_if_index=intf.sw_if_index)
9294
9295         static_mappings = self.vapi.nat66_static_mapping_dump()
9296         for sm in static_mappings:
9297             self.vapi.nat66_add_del_static_mapping(
9298                 local_ip_address=sm.local_ip_address,
9299                 external_ip_address=sm.external_ip_address, vrf_id=sm.vrf_id,
9300                 is_add=0)
9301
9302     def tearDown(self):
9303         super(TestNAT66, self).tearDown()
9304         self.clear_nat66()
9305
9306     def show_commands_at_teardown(self):
9307         self.logger.info(self.vapi.cli("show nat66 interfaces"))
9308         self.logger.info(self.vapi.cli("show nat66 static mappings"))
9309
9310
9311 if __name__ == '__main__':
9312     unittest.main(testRunner=VppTestRunner)