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