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