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