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