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