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