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