acl: API cleanup
[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 TestNAT44EndpointDependent2(MethodHolder):
4191     """ Endpoint-Dependent session test cases """
4192
4193     icmp_timeout = 2
4194
4195     @classmethod
4196     def setUpConstants(cls):
4197         super(TestNAT44EndpointDependent2, cls).setUpConstants()
4198         cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent",
4199                                 "translation", "hash", "buckets", "1",
4200                                 "icmp", "timeout", str(cls.icmp_timeout), "}"])
4201
4202     @classmethod
4203     def setUpClass(cls):
4204         super(TestNAT44EndpointDependent2, cls).setUpClass()
4205         translation_buckets = 1
4206         cls.max_translations = 10 * translation_buckets
4207
4208         cls.create_pg_interfaces(range(2))
4209         cls.interfaces = list(cls.pg_interfaces[0:2])
4210
4211         for i in cls.interfaces:
4212             i.admin_up()
4213             i.config_ip4()
4214             i.resolve_arp()
4215
4216         cls.pg0.generate_remote_hosts(1)
4217         cls.pg0.configure_ipv4_neighbors()
4218
4219         cls.pg1.generate_remote_hosts(1)
4220         cls.pg1.configure_ipv4_neighbors()
4221
4222     @classmethod
4223     def tearDownClass(cls):
4224         super(TestNAT44EndpointDependent2, cls).tearDownClass()
4225
4226     def create_icmp_stream(self, in_if, out_if, count):
4227         """
4228         Create ICMP packet stream for inside network
4229
4230         :param in_if: Inside interface
4231         :param out_if: Outside interface
4232         :param count: Number of packets
4233         """
4234
4235         self.assertTrue(count > 0)
4236         icmp_id = random.randint(0, 65535 - (count - 1))
4237
4238         pkts = list()
4239         for i in range(count):
4240             p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4241                  IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=64) /
4242                  ICMP(id=icmp_id + i, type='echo-request'))
4243             pkts.append(p)
4244         return pkts
4245
4246     def send_pkts(self, pkts, expected=None):
4247         self.pg0.add_stream(pkts)
4248         self.pg_enable_capture(self.pg_interfaces)
4249         self.pg_start()
4250         return self.pg1.get_capture(
4251             len(pkts) if expected is None else expected)
4252
4253     def test_session_cleanup(self):
4254         """ NAT44 session cleanup test """
4255
4256         self.nat44_add_address(self.pg1.local_ip4)
4257         flags = self.config_flags.NAT_IS_INSIDE
4258         self.vapi.nat44_interface_add_del_feature(
4259             sw_if_index=self.pg0.sw_if_index,
4260             flags=flags, is_add=1)
4261         self.vapi.nat44_interface_add_del_feature(
4262             sw_if_index=self.pg1.sw_if_index,
4263             is_add=1)
4264
4265         nat_config = self.vapi.nat_show_config()
4266         self.assertEqual(1, nat_config.endpoint_dependent)
4267
4268         pkts = self.create_icmp_stream(self.pg0, self.pg1,
4269                                        self.max_translations + 2)
4270         sz = len(pkts)
4271
4272         # positive test
4273         self.send_pkts(pkts[0:self.max_translations])
4274
4275         # false positive test
4276         self.send_pkts(pkts[self.max_translations:sz - 1], 0)
4277
4278         sleep(self.icmp_timeout)
4279
4280         # positive test
4281         self.send_pkts(pkts[self.max_translations + 1:sz])
4282
4283
4284 class TestNAT44EndpointDependent(MethodHolder):
4285     """ Endpoint-Dependent mapping and filtering test cases """
4286
4287     @classmethod
4288     def setUpConstants(cls):
4289         super(TestNAT44EndpointDependent, cls).setUpConstants()
4290         cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4291
4292     @classmethod
4293     def setUpClass(cls):
4294         super(TestNAT44EndpointDependent, cls).setUpClass()
4295         cls.vapi.cli("set log class nat level debug")
4296
4297         cls.tcp_port_in = 6303
4298         cls.tcp_port_out = 6303
4299         cls.udp_port_in = 6304
4300         cls.udp_port_out = 6304
4301         cls.icmp_id_in = 6305
4302         cls.icmp_id_out = 6305
4303         cls.nat_addr = '10.0.0.3'
4304         cls.ipfix_src_port = 4739
4305         cls.ipfix_domain_id = 1
4306         cls.tcp_external_port = 80
4307
4308         cls.create_pg_interfaces(range(9))
4309         cls.interfaces = list(cls.pg_interfaces[0:3])
4310
4311         for i in cls.interfaces:
4312             i.admin_up()
4313             i.config_ip4()
4314             i.resolve_arp()
4315
4316         cls.pg0.generate_remote_hosts(3)
4317         cls.pg0.configure_ipv4_neighbors()
4318
4319         cls.pg3.admin_up()
4320
4321         cls.pg4.generate_remote_hosts(2)
4322         cls.pg4.config_ip4()
4323         cls.vapi.sw_interface_add_del_address(
4324             sw_if_index=cls.pg4.sw_if_index,
4325             prefix="10.0.0.1/24")
4326
4327         cls.pg4.admin_up()
4328         cls.pg4.resolve_arp()
4329         cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4330         cls.pg4.resolve_arp()
4331
4332         zero_ip4 = socket.inet_pton(socket.AF_INET, "0.0.0.0")
4333         cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 1})
4334
4335         cls.pg5._local_ip4 = "10.1.1.1"
4336         cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4337         cls.pg5.set_table_ip4(1)
4338         cls.pg5.config_ip4()
4339         cls.pg5.admin_up()
4340         r1 = VppIpRoute(cls, cls.pg5.remote_ip4, 32,
4341                         [VppRoutePath("0.0.0.0",
4342                                       cls.pg5.sw_if_index)],
4343                         table_id=1,
4344                         register=False)
4345         r1.add_vpp_config()
4346
4347         cls.pg6._local_ip4 = "10.1.2.1"
4348         cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4349         cls.pg6.set_table_ip4(1)
4350         cls.pg6.config_ip4()
4351         cls.pg6.admin_up()
4352
4353         r2 = VppIpRoute(cls, cls.pg6.remote_ip4, 32,
4354                         [VppRoutePath("0.0.0.0",
4355                                       cls.pg6.sw_if_index)],
4356                         table_id=1,
4357                         register=False)
4358         r3 = VppIpRoute(cls, cls.pg6.remote_ip4, 16,
4359                         [VppRoutePath("0.0.0.0",
4360                                       0xffffffff,
4361                                       nh_table_id=1)],
4362                         table_id=0,
4363                         register=False)
4364         r4 = VppIpRoute(cls, "0.0.0.0", 0,
4365                         [VppRoutePath("0.0.0.0", 0xffffffff,
4366                                       nh_table_id=0)],
4367                         table_id=1,
4368                         register=False)
4369         r5 = VppIpRoute(cls, "0.0.0.0", 0,
4370                         [VppRoutePath(cls.pg1.local_ip4,
4371                                       cls.pg1.sw_if_index)],
4372                         register=False)
4373         r2.add_vpp_config()
4374         r3.add_vpp_config()
4375         r4.add_vpp_config()
4376         r5.add_vpp_config()
4377
4378         cls.pg5.resolve_arp()
4379         cls.pg6.resolve_arp()
4380
4381         cls.pg7.admin_up()
4382         cls.pg7.config_ip4()
4383         cls.pg7.resolve_arp()
4384         cls.pg7.generate_remote_hosts(3)
4385         cls.pg7.configure_ipv4_neighbors()
4386
4387         cls.pg8.admin_up()
4388         cls.pg8.config_ip4()
4389         cls.pg8.resolve_arp()
4390
4391     def setUp(self):
4392         super(TestNAT44EndpointDependent, self).setUp()
4393         self.vapi.nat_set_timeouts(
4394             udp=300, tcp_established=7440, tcp_transitory=240, icmp=60)
4395
4396     @classmethod
4397     def tearDownClass(cls):
4398         super(TestNAT44EndpointDependent, cls).tearDownClass()
4399
4400     def test_frag_in_order(self):
4401         """ NAT44 translate fragments arriving in order """
4402         self.nat44_add_address(self.nat_addr)
4403         flags = self.config_flags.NAT_IS_INSIDE
4404         self.vapi.nat44_interface_add_del_feature(
4405             sw_if_index=self.pg0.sw_if_index,
4406             flags=flags, is_add=1)
4407         self.vapi.nat44_interface_add_del_feature(
4408             sw_if_index=self.pg1.sw_if_index,
4409             is_add=1)
4410         self.frag_in_order(proto=IP_PROTOS.tcp)
4411         self.frag_in_order(proto=IP_PROTOS.udp)
4412         self.frag_in_order(proto=IP_PROTOS.icmp)
4413
4414     def test_frag_in_order_dont_translate(self):
4415         """ NAT44 don't translate fragments arriving in order """
4416         flags = self.config_flags.NAT_IS_INSIDE
4417         self.vapi.nat44_interface_add_del_feature(
4418             sw_if_index=self.pg0.sw_if_index,
4419             flags=flags, is_add=1)
4420         self.vapi.nat44_interface_add_del_feature(
4421             sw_if_index=self.pg1.sw_if_index,
4422             is_add=1)
4423         self.vapi.nat44_forwarding_enable_disable(enable=True)
4424         self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4425
4426     def test_frag_out_of_order(self):
4427         """ NAT44 translate fragments arriving out of order """
4428         self.nat44_add_address(self.nat_addr)
4429         flags = self.config_flags.NAT_IS_INSIDE
4430         self.vapi.nat44_interface_add_del_feature(
4431             sw_if_index=self.pg0.sw_if_index,
4432             flags=flags, is_add=1)
4433         self.vapi.nat44_interface_add_del_feature(
4434             sw_if_index=self.pg1.sw_if_index,
4435             is_add=1)
4436         self.frag_out_of_order(proto=IP_PROTOS.tcp)
4437         self.frag_out_of_order(proto=IP_PROTOS.udp)
4438         self.frag_out_of_order(proto=IP_PROTOS.icmp)
4439
4440     def test_frag_out_of_order_dont_translate(self):
4441         """ NAT44 don't translate fragments arriving out of order """
4442         flags = self.config_flags.NAT_IS_INSIDE
4443         self.vapi.nat44_interface_add_del_feature(
4444             sw_if_index=self.pg0.sw_if_index,
4445             flags=flags, is_add=1)
4446         self.vapi.nat44_interface_add_del_feature(
4447             sw_if_index=self.pg1.sw_if_index,
4448             is_add=1)
4449         self.vapi.nat44_forwarding_enable_disable(enable=True)
4450         self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4451
4452     def test_frag_in_order_in_plus_out(self):
4453         """ in+out interface fragments in order """
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             is_add=1)
4458         self.vapi.nat44_interface_add_del_feature(
4459             sw_if_index=self.pg0.sw_if_index,
4460             flags=flags, is_add=1)
4461         self.vapi.nat44_interface_add_del_feature(
4462             sw_if_index=self.pg1.sw_if_index,
4463             is_add=1)
4464         self.vapi.nat44_interface_add_del_feature(
4465             sw_if_index=self.pg1.sw_if_index,
4466             flags=flags, is_add=1)
4467
4468         self.server = self.pg1.remote_hosts[0]
4469
4470         self.server_in_addr = self.server.ip4
4471         self.server_out_addr = '11.11.11.11'
4472         self.server_in_port = random.randint(1025, 65535)
4473         self.server_out_port = random.randint(1025, 65535)
4474
4475         self.nat44_add_address(self.server_out_addr)
4476
4477         # add static mappings for server
4478         self.nat44_add_static_mapping(self.server_in_addr,
4479                                       self.server_out_addr,
4480                                       self.server_in_port,
4481                                       self.server_out_port,
4482                                       proto=IP_PROTOS.tcp)
4483         self.nat44_add_static_mapping(self.server_in_addr,
4484                                       self.server_out_addr,
4485                                       self.server_in_port,
4486                                       self.server_out_port,
4487                                       proto=IP_PROTOS.udp)
4488         self.nat44_add_static_mapping(self.server_in_addr,
4489                                       self.server_out_addr,
4490                                       proto=IP_PROTOS.icmp)
4491
4492         self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4493         self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4494         self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4495
4496     def test_frag_out_of_order_in_plus_out(self):
4497         """ in+out interface fragments out of order """
4498         flags = self.config_flags.NAT_IS_INSIDE
4499         self.vapi.nat44_interface_add_del_feature(
4500             sw_if_index=self.pg0.sw_if_index,
4501             is_add=1)
4502         self.vapi.nat44_interface_add_del_feature(
4503             sw_if_index=self.pg0.sw_if_index,
4504             flags=flags, is_add=1)
4505         self.vapi.nat44_interface_add_del_feature(
4506             sw_if_index=self.pg1.sw_if_index,
4507             is_add=1)
4508         self.vapi.nat44_interface_add_del_feature(
4509             sw_if_index=self.pg1.sw_if_index,
4510             flags=flags, is_add=1)
4511
4512         self.server = self.pg1.remote_hosts[0]
4513
4514         self.server_in_addr = self.server.ip4
4515         self.server_out_addr = '11.11.11.11'
4516         self.server_in_port = random.randint(1025, 65535)
4517         self.server_out_port = random.randint(1025, 65535)
4518
4519         self.nat44_add_address(self.server_out_addr)
4520
4521         # add static mappings for server
4522         self.nat44_add_static_mapping(self.server_in_addr,
4523                                       self.server_out_addr,
4524                                       self.server_in_port,
4525                                       self.server_out_port,
4526                                       proto=IP_PROTOS.tcp)
4527         self.nat44_add_static_mapping(self.server_in_addr,
4528                                       self.server_out_addr,
4529                                       self.server_in_port,
4530                                       self.server_out_port,
4531                                       proto=IP_PROTOS.udp)
4532         self.nat44_add_static_mapping(self.server_in_addr,
4533                                       self.server_out_addr,
4534                                       proto=IP_PROTOS.icmp)
4535
4536         self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4537         self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4538         self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4539
4540     def test_reass_hairpinning(self):
4541         """ NAT44 fragments hairpinning """
4542         self.server = self.pg0.remote_hosts[1]
4543         self.host_in_port = random.randint(1025, 65535)
4544         self.server_in_port = random.randint(1025, 65535)
4545         self.server_out_port = random.randint(1025, 65535)
4546
4547         self.nat44_add_address(self.nat_addr)
4548         flags = self.config_flags.NAT_IS_INSIDE
4549         self.vapi.nat44_interface_add_del_feature(
4550             sw_if_index=self.pg0.sw_if_index,
4551             flags=flags, is_add=1)
4552         self.vapi.nat44_interface_add_del_feature(
4553             sw_if_index=self.pg1.sw_if_index,
4554             is_add=1)
4555         # add static mapping for server
4556         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4557                                       self.server_in_port,
4558                                       self.server_out_port,
4559                                       proto=IP_PROTOS.tcp)
4560         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4561                                       self.server_in_port,
4562                                       self.server_out_port,
4563                                       proto=IP_PROTOS.udp)
4564         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
4565
4566         self.reass_hairpinning(proto=IP_PROTOS.tcp)
4567         self.reass_hairpinning(proto=IP_PROTOS.udp)
4568         self.reass_hairpinning(proto=IP_PROTOS.icmp)
4569
4570     def test_dynamic(self):
4571         """ NAT44 dynamic translation test """
4572
4573         self.nat44_add_address(self.nat_addr)
4574         flags = self.config_flags.NAT_IS_INSIDE
4575         self.vapi.nat44_interface_add_del_feature(
4576             sw_if_index=self.pg0.sw_if_index,
4577             flags=flags, is_add=1)
4578         self.vapi.nat44_interface_add_del_feature(
4579             sw_if_index=self.pg1.sw_if_index,
4580             is_add=1)
4581
4582         nat_config = self.vapi.nat_show_config()
4583         self.assertEqual(1, nat_config.endpoint_dependent)
4584
4585         # in2out
4586         tcpn = self.statistics.get_err_counter(
4587             '/err/nat44-ed-in2out-slowpath/TCP packets')
4588         udpn = self.statistics.get_err_counter(
4589             '/err/nat44-ed-in2out-slowpath/UDP packets')
4590         icmpn = self.statistics.get_err_counter(
4591             '/err/nat44-ed-in2out-slowpath/ICMP packets')
4592         totaln = self.statistics.get_err_counter(
4593             '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4594
4595         pkts = self.create_stream_in(self.pg0, self.pg1)
4596         self.pg0.add_stream(pkts)
4597         self.pg_enable_capture(self.pg_interfaces)
4598         self.pg_start()
4599         capture = self.pg1.get_capture(len(pkts))
4600         self.verify_capture_out(capture)
4601
4602         err = self.statistics.get_err_counter(
4603             '/err/nat44-ed-in2out-slowpath/TCP packets')
4604         self.assertEqual(err - tcpn, 2)
4605         err = self.statistics.get_err_counter(
4606             '/err/nat44-ed-in2out-slowpath/UDP packets')
4607         self.assertEqual(err - udpn, 1)
4608         err = self.statistics.get_err_counter(
4609             '/err/nat44-ed-in2out-slowpath/ICMP packets')
4610         self.assertEqual(err - icmpn, 1)
4611         err = self.statistics.get_err_counter(
4612             '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4613         self.assertEqual(err - totaln, 4)
4614
4615         # out2in
4616         tcpn = self.statistics.get_err_counter(
4617             '/err/nat44-ed-out2in/TCP packets')
4618         udpn = self.statistics.get_err_counter(
4619             '/err/nat44-ed-out2in/UDP packets')
4620         icmpn = self.statistics.get_err_counter(
4621             '/err/nat44-ed-out2in-slowpath/ICMP packets')
4622         totaln = self.statistics.get_err_counter(
4623             '/err/nat44-ed-out2in/good out2in packets processed')
4624
4625         pkts = self.create_stream_out(self.pg1)
4626         self.pg1.add_stream(pkts)
4627         self.pg_enable_capture(self.pg_interfaces)
4628         self.pg_start()
4629         capture = self.pg0.get_capture(len(pkts))
4630         self.verify_capture_in(capture, self.pg0)
4631
4632         err = self.statistics.get_err_counter(
4633             '/err/nat44-ed-out2in/TCP packets')
4634         self.assertEqual(err - tcpn, 2)
4635         err = self.statistics.get_err_counter(
4636             '/err/nat44-ed-out2in/UDP packets')
4637         self.assertEqual(err - udpn, 1)
4638         err = self.statistics.get_err_counter(
4639             '/err/nat44-ed-out2in-slowpath/ICMP packets')
4640         self.assertEqual(err - icmpn, 1)
4641         err = self.statistics.get_err_counter(
4642             '/err/nat44-ed-out2in/good out2in packets processed')
4643         self.assertEqual(err - totaln, 3)
4644
4645         users = self.statistics.get_counter('/nat44/total-users')
4646         self.assertEqual(users[0][0], 1)
4647         sessions = self.statistics.get_counter('/nat44/total-sessions')
4648         self.assertEqual(sessions[0][0], 3)
4649
4650     def test_dynamic_output_feature_vrf(self):
4651         """ NAT44 dynamic translation test: output-feature, VRF"""
4652
4653         # other then default (0)
4654         new_vrf_id = 22
4655
4656         self.nat44_add_address(self.nat_addr)
4657         flags = self.config_flags.NAT_IS_INSIDE
4658         self.vapi.nat44_interface_add_del_output_feature(
4659             sw_if_index=self.pg7.sw_if_index,
4660             flags=flags, is_add=1)
4661         self.vapi.nat44_interface_add_del_output_feature(
4662             sw_if_index=self.pg8.sw_if_index,
4663             is_add=1)
4664
4665         try:
4666             self.vapi.ip_table_add_del(is_add=1,
4667                                        table={'table_id': new_vrf_id})
4668
4669             self.pg7.unconfig_ip4()
4670             self.pg7.set_table_ip4(new_vrf_id)
4671             self.pg7.config_ip4()
4672             self.pg7.resolve_arp()
4673
4674             self.pg8.unconfig_ip4()
4675             self.pg8.set_table_ip4(new_vrf_id)
4676             self.pg8.config_ip4()
4677             self.pg8.resolve_arp()
4678
4679             nat_config = self.vapi.nat_show_config()
4680             self.assertEqual(1, nat_config.endpoint_dependent)
4681
4682             # in2out
4683             tcpn = self.statistics.get_err_counter(
4684                 '/err/nat44-ed-in2out-slowpath/TCP packets')
4685             udpn = self.statistics.get_err_counter(
4686                 '/err/nat44-ed-in2out-slowpath/UDP packets')
4687             icmpn = self.statistics.get_err_counter(
4688                 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4689             totaln = self.statistics.get_err_counter(
4690                 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4691
4692             pkts = self.create_stream_in(self.pg7, self.pg8)
4693             self.pg7.add_stream(pkts)
4694             self.pg_enable_capture(self.pg_interfaces)
4695             self.pg_start()
4696             capture = self.pg8.get_capture(len(pkts))
4697             self.verify_capture_out(capture)
4698
4699             err = self.statistics.get_err_counter(
4700                 '/err/nat44-ed-in2out-slowpath/TCP packets')
4701             self.assertEqual(err - tcpn, 2)
4702             err = self.statistics.get_err_counter(
4703                 '/err/nat44-ed-in2out-slowpath/UDP packets')
4704             self.assertEqual(err - udpn, 1)
4705             err = self.statistics.get_err_counter(
4706                 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4707             self.assertEqual(err - icmpn, 1)
4708             err = self.statistics.get_err_counter(
4709                 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4710             self.assertEqual(err - totaln, 4)
4711
4712             # out2in
4713             tcpn = self.statistics.get_err_counter(
4714                 '/err/nat44-ed-out2in/TCP packets')
4715             udpn = self.statistics.get_err_counter(
4716                 '/err/nat44-ed-out2in/UDP packets')
4717             icmpn = self.statistics.get_err_counter(
4718                 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4719             totaln = self.statistics.get_err_counter(
4720                 '/err/nat44-ed-out2in/good out2in packets processed')
4721
4722             pkts = self.create_stream_out(self.pg8)
4723             self.pg8.add_stream(pkts)
4724             self.pg_enable_capture(self.pg_interfaces)
4725             self.pg_start()
4726             capture = self.pg7.get_capture(len(pkts))
4727             self.verify_capture_in(capture, self.pg7)
4728
4729             err = self.statistics.get_err_counter(
4730                 '/err/nat44-ed-out2in/TCP packets')
4731             self.assertEqual(err - tcpn, 2)
4732             err = self.statistics.get_err_counter(
4733                 '/err/nat44-ed-out2in/UDP packets')
4734             self.assertEqual(err - udpn, 1)
4735             err = self.statistics.get_err_counter(
4736                 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4737             self.assertEqual(err - icmpn, 1)
4738             err = self.statistics.get_err_counter(
4739                 '/err/nat44-ed-out2in/good out2in packets processed')
4740             self.assertEqual(err - totaln, 3)
4741
4742             users = self.statistics.get_counter('/nat44/total-users')
4743             self.assertEqual(users[0][0], 1)
4744             sessions = self.statistics.get_counter('/nat44/total-sessions')
4745             self.assertEqual(sessions[0][0], 3)
4746
4747         finally:
4748             self.pg7.unconfig_ip4()
4749             self.pg7.set_table_ip4(1)
4750             self.pg7.config_ip4()
4751             self.pg7.resolve_arp()
4752
4753             self.pg8.unconfig_ip4()
4754             self.pg8.set_table_ip4(1)
4755             self.pg8.config_ip4()
4756             self.pg8.resolve_arp()
4757
4758             self.vapi.ip_table_add_del(is_add=0,
4759                                        table={'table_id': new_vrf_id})
4760
4761     def test_forwarding(self):
4762         """ NAT44 forwarding test """
4763
4764         flags = self.config_flags.NAT_IS_INSIDE
4765         self.vapi.nat44_interface_add_del_feature(
4766             sw_if_index=self.pg0.sw_if_index,
4767             flags=flags, is_add=1)
4768         self.vapi.nat44_interface_add_del_feature(
4769             sw_if_index=self.pg1.sw_if_index,
4770             is_add=1)
4771         self.vapi.nat44_forwarding_enable_disable(enable=1)
4772
4773         real_ip = self.pg0.remote_ip4
4774         alias_ip = self.nat_addr
4775         flags = self.config_flags.NAT_IS_ADDR_ONLY
4776         self.vapi.nat44_add_del_static_mapping(is_add=1,
4777                                                local_ip_address=real_ip,
4778                                                external_ip_address=alias_ip,
4779                                                external_sw_if_index=0xFFFFFFFF,
4780                                                flags=flags)
4781
4782         try:
4783             # in2out - static mapping match
4784
4785             pkts = self.create_stream_out(self.pg1)
4786             self.pg1.add_stream(pkts)
4787             self.pg_enable_capture(self.pg_interfaces)
4788             self.pg_start()
4789             capture = self.pg0.get_capture(len(pkts))
4790             self.verify_capture_in(capture, self.pg0)
4791
4792             pkts = self.create_stream_in(self.pg0, self.pg1)
4793             self.pg0.add_stream(pkts)
4794             self.pg_enable_capture(self.pg_interfaces)
4795             self.pg_start()
4796             capture = self.pg1.get_capture(len(pkts))
4797             self.verify_capture_out(capture, same_port=True)
4798
4799             # in2out - no static mapping match
4800
4801             host0 = self.pg0.remote_hosts[0]
4802             self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4803             try:
4804                 pkts = self.create_stream_out(self.pg1,
4805                                               dst_ip=self.pg0.remote_ip4,
4806                                               use_inside_ports=True)
4807                 self.pg1.add_stream(pkts)
4808                 self.pg_enable_capture(self.pg_interfaces)
4809                 self.pg_start()
4810                 capture = self.pg0.get_capture(len(pkts))
4811                 self.verify_capture_in(capture, self.pg0)
4812
4813                 pkts = self.create_stream_in(self.pg0, self.pg1)
4814                 self.pg0.add_stream(pkts)
4815                 self.pg_enable_capture(self.pg_interfaces)
4816                 self.pg_start()
4817                 capture = self.pg1.get_capture(len(pkts))
4818                 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4819                                         same_port=True)
4820             finally:
4821                 self.pg0.remote_hosts[0] = host0
4822
4823             user = self.pg0.remote_hosts[1]
4824             sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4825             self.assertEqual(len(sessions), 3)
4826             self.assertTrue(sessions[0].flags &
4827                             self.config_flags.NAT_IS_EXT_HOST_VALID)
4828             self.vapi.nat44_del_session(
4829                 address=sessions[0].inside_ip_address,
4830                 port=sessions[0].inside_port,
4831                 protocol=sessions[0].protocol,
4832                 flags=(self.config_flags.NAT_IS_INSIDE |
4833                        self.config_flags.NAT_IS_EXT_HOST_VALID),
4834                 ext_host_address=sessions[0].ext_host_address,
4835                 ext_host_port=sessions[0].ext_host_port)
4836             sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4837             self.assertEqual(len(sessions), 2)
4838
4839         finally:
4840             self.vapi.nat44_forwarding_enable_disable(enable=0)
4841             flags = self.config_flags.NAT_IS_ADDR_ONLY
4842             self.vapi.nat44_add_del_static_mapping(
4843                 is_add=0,
4844                 local_ip_address=real_ip,
4845                 external_ip_address=alias_ip,
4846                 external_sw_if_index=0xFFFFFFFF,
4847                 flags=flags)
4848
4849     def test_static_lb(self):
4850         """ NAT44 local service load balancing """
4851         external_addr_n = self.nat_addr
4852         external_port = 80
4853         local_port = 8080
4854         server1 = self.pg0.remote_hosts[0]
4855         server2 = self.pg0.remote_hosts[1]
4856
4857         locals = [{'addr': server1.ip4,
4858                    'port': local_port,
4859                    'probability': 70,
4860                    'vrf_id': 0},
4861                   {'addr': server2.ip4,
4862                    'port': local_port,
4863                    'probability': 30,
4864                    'vrf_id': 0}]
4865
4866         self.nat44_add_address(self.nat_addr)
4867         self.vapi.nat44_add_del_lb_static_mapping(
4868             is_add=1,
4869             external_addr=external_addr_n,
4870             external_port=external_port,
4871             protocol=IP_PROTOS.tcp,
4872             local_num=len(locals),
4873             locals=locals)
4874         flags = self.config_flags.NAT_IS_INSIDE
4875         self.vapi.nat44_interface_add_del_feature(
4876             sw_if_index=self.pg0.sw_if_index,
4877             flags=flags, is_add=1)
4878         self.vapi.nat44_interface_add_del_feature(
4879             sw_if_index=self.pg1.sw_if_index,
4880             is_add=1)
4881
4882         # from client to service
4883         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4884              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4885              TCP(sport=12345, dport=external_port))
4886         self.pg1.add_stream(p)
4887         self.pg_enable_capture(self.pg_interfaces)
4888         self.pg_start()
4889         capture = self.pg0.get_capture(1)
4890         p = capture[0]
4891         server = None
4892         try:
4893             ip = p[IP]
4894             tcp = p[TCP]
4895             self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4896             if ip.dst == server1.ip4:
4897                 server = server1
4898             else:
4899                 server = server2
4900             self.assertEqual(tcp.dport, local_port)
4901             self.assert_packet_checksums_valid(p)
4902         except:
4903             self.logger.error(ppp("Unexpected or invalid packet:", p))
4904             raise
4905
4906         # from service back to client
4907         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4908              IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4909              TCP(sport=local_port, dport=12345))
4910         self.pg0.add_stream(p)
4911         self.pg_enable_capture(self.pg_interfaces)
4912         self.pg_start()
4913         capture = self.pg1.get_capture(1)
4914         p = capture[0]
4915         try:
4916             ip = p[IP]
4917             tcp = p[TCP]
4918             self.assertEqual(ip.src, self.nat_addr)
4919             self.assertEqual(tcp.sport, external_port)
4920             self.assert_packet_checksums_valid(p)
4921         except:
4922             self.logger.error(ppp("Unexpected or invalid packet:", p))
4923             raise
4924
4925         sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
4926         self.assertEqual(len(sessions), 1)
4927         self.assertTrue(sessions[0].flags &
4928                         self.config_flags.NAT_IS_EXT_HOST_VALID)
4929         self.vapi.nat44_del_session(
4930             address=sessions[0].inside_ip_address,
4931             port=sessions[0].inside_port,
4932             protocol=sessions[0].protocol,
4933             flags=(self.config_flags.NAT_IS_INSIDE |
4934                    self.config_flags.NAT_IS_EXT_HOST_VALID),
4935             ext_host_address=sessions[0].ext_host_address,
4936             ext_host_port=sessions[0].ext_host_port)
4937         sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
4938         self.assertEqual(len(sessions), 0)
4939
4940     @unittest.skipUnless(running_extended_tests, "part of extended tests")
4941     def test_static_lb_multi_clients(self):
4942         """ NAT44 local service load balancing - multiple clients"""
4943
4944         external_addr = self.nat_addr
4945         external_port = 80
4946         local_port = 8080
4947         server1 = self.pg0.remote_hosts[0]
4948         server2 = self.pg0.remote_hosts[1]
4949         server3 = self.pg0.remote_hosts[2]
4950
4951         locals = [{'addr': server1.ip4,
4952                    'port': local_port,
4953                    'probability': 90,
4954                    'vrf_id': 0},
4955                   {'addr': server2.ip4,
4956                    'port': local_port,
4957                    'probability': 10,
4958                    'vrf_id': 0}]
4959
4960         self.nat44_add_address(self.nat_addr)
4961         self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
4962                                                   external_addr=external_addr,
4963                                                   external_port=external_port,
4964                                                   protocol=IP_PROTOS.tcp,
4965                                                   local_num=len(locals),
4966                                                   locals=locals)
4967         flags = self.config_flags.NAT_IS_INSIDE
4968         self.vapi.nat44_interface_add_del_feature(
4969             sw_if_index=self.pg0.sw_if_index,
4970             flags=flags, is_add=1)
4971         self.vapi.nat44_interface_add_del_feature(
4972             sw_if_index=self.pg1.sw_if_index,
4973             is_add=1)
4974
4975         server1_n = 0
4976         server2_n = 0
4977         clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4978         pkts = []
4979         for client in clients:
4980             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4981                  IP(src=client, dst=self.nat_addr) /
4982                  TCP(sport=12345, dport=external_port))
4983             pkts.append(p)
4984         self.pg1.add_stream(pkts)
4985         self.pg_enable_capture(self.pg_interfaces)
4986         self.pg_start()
4987         capture = self.pg0.get_capture(len(pkts))
4988         for p in capture:
4989             if p[IP].dst == server1.ip4:
4990                 server1_n += 1
4991             else:
4992                 server2_n += 1
4993         self.assertGreater(server1_n, server2_n)
4994
4995         local = {
4996             'addr': server3.ip4,
4997             'port': local_port,
4998             'probability': 20,
4999             'vrf_id': 0
5000         }
5001
5002         # add new back-end
5003         self.vapi.nat44_lb_static_mapping_add_del_local(
5004             is_add=1,
5005             external_addr=external_addr,
5006             external_port=external_port,
5007             local=local,
5008             protocol=IP_PROTOS.tcp)
5009         server1_n = 0
5010         server2_n = 0
5011         server3_n = 0
5012         clients = ip4_range(self.pg1.remote_ip4, 60, 110)
5013         pkts = []
5014         for client in clients:
5015             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5016                  IP(src=client, dst=self.nat_addr) /
5017                  TCP(sport=12346, dport=external_port))
5018             pkts.append(p)
5019         self.assertGreater(len(pkts), 0)
5020         self.pg1.add_stream(pkts)
5021         self.pg_enable_capture(self.pg_interfaces)
5022         self.pg_start()
5023         capture = self.pg0.get_capture(len(pkts))
5024         for p in capture:
5025             if p[IP].dst == server1.ip4:
5026                 server1_n += 1
5027             elif p[IP].dst == server2.ip4:
5028                 server2_n += 1
5029             else:
5030                 server3_n += 1
5031         self.assertGreater(server1_n, 0)
5032         self.assertGreater(server2_n, 0)
5033         self.assertGreater(server3_n, 0)
5034
5035         local = {
5036             'addr': server2.ip4,
5037             'port': local_port,
5038             'probability': 10,
5039             'vrf_id': 0
5040         }
5041
5042         # remove one back-end
5043         self.vapi.nat44_lb_static_mapping_add_del_local(
5044             is_add=0,
5045             external_addr=external_addr,
5046             external_port=external_port,
5047             local=local,
5048             protocol=IP_PROTOS.tcp)
5049         server1_n = 0
5050         server2_n = 0
5051         server3_n = 0
5052         self.pg1.add_stream(pkts)
5053         self.pg_enable_capture(self.pg_interfaces)
5054         self.pg_start()
5055         capture = self.pg0.get_capture(len(pkts))
5056         for p in capture:
5057             if p[IP].dst == server1.ip4:
5058                 server1_n += 1
5059             elif p[IP].dst == server2.ip4:
5060                 server2_n += 1
5061             else:
5062                 server3_n += 1
5063         self.assertGreater(server1_n, 0)
5064         self.assertEqual(server2_n, 0)
5065         self.assertGreater(server3_n, 0)
5066
5067     def test_static_lb_2(self):
5068         """ NAT44 local service load balancing (asymmetrical rule) """
5069         external_addr = self.nat_addr
5070         external_port = 80
5071         local_port = 8080
5072         server1 = self.pg0.remote_hosts[0]
5073         server2 = self.pg0.remote_hosts[1]
5074
5075         locals = [{'addr': server1.ip4,
5076                    'port': local_port,
5077                    'probability': 70,
5078                    'vrf_id': 0},
5079                   {'addr': server2.ip4,
5080                    'port': local_port,
5081                    'probability': 30,
5082                    'vrf_id': 0}]
5083
5084         self.vapi.nat44_forwarding_enable_disable(enable=1)
5085         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5086         self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5087                                                   external_addr=external_addr,
5088                                                   external_port=external_port,
5089                                                   protocol=IP_PROTOS.tcp,
5090                                                   local_num=len(locals),
5091                                                   locals=locals)
5092         flags = self.config_flags.NAT_IS_INSIDE
5093         self.vapi.nat44_interface_add_del_feature(
5094             sw_if_index=self.pg0.sw_if_index,
5095             flags=flags, is_add=1)
5096         self.vapi.nat44_interface_add_del_feature(
5097             sw_if_index=self.pg1.sw_if_index,
5098             is_add=1)
5099
5100         # from client to service
5101         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5102              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5103              TCP(sport=12345, dport=external_port))
5104         self.pg1.add_stream(p)
5105         self.pg_enable_capture(self.pg_interfaces)
5106         self.pg_start()
5107         capture = self.pg0.get_capture(1)
5108         p = capture[0]
5109         server = None
5110         try:
5111             ip = p[IP]
5112             tcp = p[TCP]
5113             self.assertIn(ip.dst, [server1.ip4, server2.ip4])
5114             if ip.dst == server1.ip4:
5115                 server = server1
5116             else:
5117                 server = server2
5118             self.assertEqual(tcp.dport, local_port)
5119             self.assert_packet_checksums_valid(p)
5120         except:
5121             self.logger.error(ppp("Unexpected or invalid packet:", p))
5122             raise
5123
5124         # from service back to client
5125         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
5126              IP(src=server.ip4, dst=self.pg1.remote_ip4) /
5127              TCP(sport=local_port, dport=12345))
5128         self.pg0.add_stream(p)
5129         self.pg_enable_capture(self.pg_interfaces)
5130         self.pg_start()
5131         capture = self.pg1.get_capture(1)
5132         p = capture[0]
5133         try:
5134             ip = p[IP]
5135             tcp = p[TCP]
5136             self.assertEqual(ip.src, self.nat_addr)
5137             self.assertEqual(tcp.sport, external_port)
5138             self.assert_packet_checksums_valid(p)
5139         except:
5140             self.logger.error(ppp("Unexpected or invalid packet:", p))
5141             raise
5142
5143         # from client to server (no translation)
5144         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5145              IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
5146              TCP(sport=12346, dport=local_port))
5147         self.pg1.add_stream(p)
5148         self.pg_enable_capture(self.pg_interfaces)
5149         self.pg_start()
5150         capture = self.pg0.get_capture(1)
5151         p = capture[0]
5152         server = None
5153         try:
5154             ip = p[IP]
5155             tcp = p[TCP]
5156             self.assertEqual(ip.dst, server1.ip4)
5157             self.assertEqual(tcp.dport, local_port)
5158             self.assert_packet_checksums_valid(p)
5159         except:
5160             self.logger.error(ppp("Unexpected or invalid packet:", p))
5161             raise
5162
5163         # from service back to client (no translation)
5164         p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
5165              IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
5166              TCP(sport=local_port, dport=12346))
5167         self.pg0.add_stream(p)
5168         self.pg_enable_capture(self.pg_interfaces)
5169         self.pg_start()
5170         capture = self.pg1.get_capture(1)
5171         p = capture[0]
5172         try:
5173             ip = p[IP]
5174             tcp = p[TCP]
5175             self.assertEqual(ip.src, server1.ip4)
5176             self.assertEqual(tcp.sport, local_port)
5177             self.assert_packet_checksums_valid(p)
5178         except:
5179             self.logger.error(ppp("Unexpected or invalid packet:", p))
5180             raise
5181
5182     def test_lb_affinity(self):
5183         """ NAT44 local service load balancing affinity """
5184         external_addr = self.nat_addr
5185         external_port = 80
5186         local_port = 8080
5187         server1 = self.pg0.remote_hosts[0]
5188         server2 = self.pg0.remote_hosts[1]
5189
5190         locals = [{'addr': server1.ip4,
5191                    'port': local_port,
5192                    'probability': 50,
5193                    'vrf_id': 0},
5194                   {'addr': server2.ip4,
5195                    'port': local_port,
5196                    'probability': 50,
5197                    'vrf_id': 0}]
5198
5199         self.nat44_add_address(self.nat_addr)
5200         self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
5201                                                   external_addr=external_addr,
5202                                                   external_port=external_port,
5203                                                   protocol=IP_PROTOS.tcp,
5204                                                   affinity=10800,
5205                                                   local_num=len(locals),
5206                                                   locals=locals)
5207         flags = self.config_flags.NAT_IS_INSIDE
5208         self.vapi.nat44_interface_add_del_feature(
5209             sw_if_index=self.pg0.sw_if_index,
5210             flags=flags, is_add=1)
5211         self.vapi.nat44_interface_add_del_feature(
5212             sw_if_index=self.pg1.sw_if_index,
5213             is_add=1)
5214
5215         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5216              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5217              TCP(sport=1025, dport=external_port))
5218         self.pg1.add_stream(p)
5219         self.pg_enable_capture(self.pg_interfaces)
5220         self.pg_start()
5221         capture = self.pg0.get_capture(1)
5222         backend = capture[0][IP].dst
5223
5224         sessions = self.vapi.nat44_user_session_dump(backend, 0)
5225         self.assertEqual(len(sessions), 1)
5226         self.assertTrue(sessions[0].flags &
5227                         self.config_flags.NAT_IS_EXT_HOST_VALID)
5228         self.vapi.nat44_del_session(
5229             address=sessions[0].inside_ip_address,
5230             port=sessions[0].inside_port,
5231             protocol=sessions[0].protocol,
5232             flags=(self.config_flags.NAT_IS_INSIDE |
5233                    self.config_flags.NAT_IS_EXT_HOST_VALID),
5234             ext_host_address=sessions[0].ext_host_address,
5235             ext_host_port=sessions[0].ext_host_port)
5236
5237         pkts = []
5238         for port in range(1030, 1100):
5239             p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5240                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5241                  TCP(sport=port, dport=external_port))
5242             pkts.append(p)
5243         self.pg1.add_stream(pkts)
5244         self.pg_enable_capture(self.pg_interfaces)
5245         self.pg_start()
5246         capture = self.pg0.get_capture(len(pkts))
5247         for p in capture:
5248             self.assertEqual(p[IP].dst, backend)
5249
5250     def test_unknown_proto(self):
5251         """ NAT44 translate packet with unknown protocol """
5252         self.nat44_add_address(self.nat_addr)
5253         flags = self.config_flags.NAT_IS_INSIDE
5254         self.vapi.nat44_interface_add_del_feature(
5255             sw_if_index=self.pg0.sw_if_index,
5256             flags=flags, is_add=1)
5257         self.vapi.nat44_interface_add_del_feature(
5258             sw_if_index=self.pg1.sw_if_index,
5259             is_add=1)
5260
5261         # in2out
5262         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5263              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5264              TCP(sport=self.tcp_port_in, dport=20))
5265         self.pg0.add_stream(p)
5266         self.pg_enable_capture(self.pg_interfaces)
5267         self.pg_start()
5268         p = self.pg1.get_capture(1)
5269
5270         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5271              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5272              GRE() /
5273              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5274              TCP(sport=1234, dport=1234))
5275         self.pg0.add_stream(p)
5276         self.pg_enable_capture(self.pg_interfaces)
5277         self.pg_start()
5278         p = self.pg1.get_capture(1)
5279         packet = p[0]
5280         try:
5281             self.assertEqual(packet[IP].src, self.nat_addr)
5282             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5283             self.assertEqual(packet.haslayer(GRE), 1)
5284             self.assert_packet_checksums_valid(packet)
5285         except:
5286             self.logger.error(ppp("Unexpected or invalid packet:", packet))
5287             raise
5288
5289         # out2in
5290         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5291              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5292              GRE() /
5293              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5294              TCP(sport=1234, dport=1234))
5295         self.pg1.add_stream(p)
5296         self.pg_enable_capture(self.pg_interfaces)
5297         self.pg_start()
5298         p = self.pg0.get_capture(1)
5299         packet = p[0]
5300         try:
5301             self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
5302             self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
5303             self.assertEqual(packet.haslayer(GRE), 1)
5304             self.assert_packet_checksums_valid(packet)
5305         except:
5306             self.logger.error(ppp("Unexpected or invalid packet:", packet))
5307             raise
5308
5309     def test_hairpinning_unknown_proto(self):
5310         """ NAT44 translate packet with unknown protocol - hairpinning """
5311         host = self.pg0.remote_hosts[0]
5312         server = self.pg0.remote_hosts[1]
5313         host_in_port = 1234
5314         server_out_port = 8765
5315         server_nat_ip = "10.0.0.11"
5316
5317         self.nat44_add_address(self.nat_addr)
5318         flags = self.config_flags.NAT_IS_INSIDE
5319         self.vapi.nat44_interface_add_del_feature(
5320             sw_if_index=self.pg0.sw_if_index,
5321             flags=flags, is_add=1)
5322         self.vapi.nat44_interface_add_del_feature(
5323             sw_if_index=self.pg1.sw_if_index,
5324             is_add=1)
5325
5326         # add static mapping for server
5327         self.nat44_add_static_mapping(server.ip4, server_nat_ip)
5328
5329         # host to server
5330         p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
5331              IP(src=host.ip4, dst=server_nat_ip) /
5332              TCP(sport=host_in_port, dport=server_out_port))
5333         self.pg0.add_stream(p)
5334         self.pg_enable_capture(self.pg_interfaces)
5335         self.pg_start()
5336         self.pg0.get_capture(1)
5337
5338         p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5339              IP(src=host.ip4, dst=server_nat_ip) /
5340              GRE() /
5341              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5342              TCP(sport=1234, dport=1234))
5343         self.pg0.add_stream(p)
5344         self.pg_enable_capture(self.pg_interfaces)
5345         self.pg_start()
5346         p = self.pg0.get_capture(1)
5347         packet = p[0]
5348         try:
5349             self.assertEqual(packet[IP].src, self.nat_addr)
5350             self.assertEqual(packet[IP].dst, server.ip4)
5351             self.assertEqual(packet.haslayer(GRE), 1)
5352             self.assert_packet_checksums_valid(packet)
5353         except:
5354             self.logger.error(ppp("Unexpected or invalid packet:", packet))
5355             raise
5356
5357         # server to host
5358         p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5359              IP(src=server.ip4, dst=self.nat_addr) /
5360              GRE() /
5361              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5362              TCP(sport=1234, dport=1234))
5363         self.pg0.add_stream(p)
5364         self.pg_enable_capture(self.pg_interfaces)
5365         self.pg_start()
5366         p = self.pg0.get_capture(1)
5367         packet = p[0]
5368         try:
5369             self.assertEqual(packet[IP].src, server_nat_ip)
5370             self.assertEqual(packet[IP].dst, host.ip4)
5371             self.assertEqual(packet.haslayer(GRE), 1)
5372             self.assert_packet_checksums_valid(packet)
5373         except:
5374             self.logger.error(ppp("Unexpected or invalid packet:", packet))
5375             raise
5376
5377     def test_output_feature_and_service(self):
5378         """ NAT44 interface output feature and services """
5379         external_addr = '1.2.3.4'
5380         external_port = 80
5381         local_port = 8080
5382
5383         self.vapi.nat44_forwarding_enable_disable(enable=1)
5384         self.nat44_add_address(self.nat_addr)
5385         flags = self.config_flags.NAT_IS_ADDR_ONLY
5386         self.vapi.nat44_add_del_identity_mapping(
5387             ip_address=self.pg1.remote_ip4, sw_if_index=0xFFFFFFFF,
5388             flags=flags, is_add=1)
5389         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5390         self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5391                                       local_port, external_port,
5392                                       proto=IP_PROTOS.tcp, flags=flags)
5393         flags = self.config_flags.NAT_IS_INSIDE
5394         self.vapi.nat44_interface_add_del_feature(
5395             sw_if_index=self.pg0.sw_if_index,
5396             is_add=1)
5397         self.vapi.nat44_interface_add_del_feature(
5398             sw_if_index=self.pg0.sw_if_index,
5399             flags=flags, is_add=1)
5400         self.vapi.nat44_interface_add_del_output_feature(
5401             is_add=1,
5402             sw_if_index=self.pg1.sw_if_index)
5403
5404         # from client to service
5405         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5406              IP(src=self.pg1.remote_ip4, dst=external_addr) /
5407              TCP(sport=12345, dport=external_port))
5408         self.pg1.add_stream(p)
5409         self.pg_enable_capture(self.pg_interfaces)
5410         self.pg_start()
5411         capture = self.pg0.get_capture(1)
5412         p = capture[0]
5413         try:
5414             ip = p[IP]
5415             tcp = p[TCP]
5416             self.assertEqual(ip.dst, self.pg0.remote_ip4)
5417             self.assertEqual(tcp.dport, local_port)
5418             self.assert_packet_checksums_valid(p)
5419         except:
5420             self.logger.error(ppp("Unexpected or invalid packet:", p))
5421             raise
5422
5423         # from service back to client
5424         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5425              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5426              TCP(sport=local_port, dport=12345))
5427         self.pg0.add_stream(p)
5428         self.pg_enable_capture(self.pg_interfaces)
5429         self.pg_start()
5430         capture = self.pg1.get_capture(1)
5431         p = capture[0]
5432         try:
5433             ip = p[IP]
5434             tcp = p[TCP]
5435             self.assertEqual(ip.src, external_addr)
5436             self.assertEqual(tcp.sport, external_port)
5437             self.assert_packet_checksums_valid(p)
5438         except:
5439             self.logger.error(ppp("Unexpected or invalid packet:", p))
5440             raise
5441
5442         # from local network host to external network
5443         pkts = self.create_stream_in(self.pg0, self.pg1)
5444         self.pg0.add_stream(pkts)
5445         self.pg_enable_capture(self.pg_interfaces)
5446         self.pg_start()
5447         capture = self.pg1.get_capture(len(pkts))
5448         self.verify_capture_out(capture)
5449         pkts = self.create_stream_in(self.pg0, self.pg1)
5450         self.pg0.add_stream(pkts)
5451         self.pg_enable_capture(self.pg_interfaces)
5452         self.pg_start()
5453         capture = self.pg1.get_capture(len(pkts))
5454         self.verify_capture_out(capture)
5455
5456         # from external network back to local network host
5457         pkts = self.create_stream_out(self.pg1)
5458         self.pg1.add_stream(pkts)
5459         self.pg_enable_capture(self.pg_interfaces)
5460         self.pg_start()
5461         capture = self.pg0.get_capture(len(pkts))
5462         self.verify_capture_in(capture, self.pg0)
5463
5464     def test_output_feature_and_service2(self):
5465         """ NAT44 interface output feature and service host direct access """
5466         self.vapi.nat44_forwarding_enable_disable(enable=1)
5467         self.nat44_add_address(self.nat_addr)
5468         self.vapi.nat44_interface_add_del_output_feature(
5469             is_add=1,
5470             sw_if_index=self.pg1.sw_if_index)
5471
5472         # session initiated from service host - translate
5473         pkts = self.create_stream_in(self.pg0, self.pg1)
5474         self.pg0.add_stream(pkts)
5475         self.pg_enable_capture(self.pg_interfaces)
5476         self.pg_start()
5477         capture = self.pg1.get_capture(len(pkts))
5478         self.verify_capture_out(capture)
5479
5480         pkts = self.create_stream_out(self.pg1)
5481         self.pg1.add_stream(pkts)
5482         self.pg_enable_capture(self.pg_interfaces)
5483         self.pg_start()
5484         capture = self.pg0.get_capture(len(pkts))
5485         self.verify_capture_in(capture, self.pg0)
5486
5487         # session initiated from remote host - do not translate
5488         self.tcp_port_in = 60303
5489         self.udp_port_in = 60304
5490         self.icmp_id_in = 60305
5491         pkts = self.create_stream_out(self.pg1,
5492                                       self.pg0.remote_ip4,
5493                                       use_inside_ports=True)
5494         self.pg1.add_stream(pkts)
5495         self.pg_enable_capture(self.pg_interfaces)
5496         self.pg_start()
5497         capture = self.pg0.get_capture(len(pkts))
5498         self.verify_capture_in(capture, self.pg0)
5499
5500         pkts = self.create_stream_in(self.pg0, self.pg1)
5501         self.pg0.add_stream(pkts)
5502         self.pg_enable_capture(self.pg_interfaces)
5503         self.pg_start()
5504         capture = self.pg1.get_capture(len(pkts))
5505         self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5506                                 same_port=True)
5507
5508     def test_output_feature_and_service3(self):
5509         """ NAT44 interface output feature and DST NAT """
5510         external_addr = '1.2.3.4'
5511         external_port = 80
5512         local_port = 8080
5513
5514         self.vapi.nat44_forwarding_enable_disable(enable=1)
5515         self.nat44_add_address(self.nat_addr)
5516         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5517         self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5518                                       local_port, external_port,
5519                                       proto=IP_PROTOS.tcp, flags=flags)
5520         flags = self.config_flags.NAT_IS_INSIDE
5521         self.vapi.nat44_interface_add_del_feature(
5522             sw_if_index=self.pg0.sw_if_index,
5523             is_add=1)
5524         self.vapi.nat44_interface_add_del_feature(
5525             sw_if_index=self.pg0.sw_if_index,
5526             flags=flags, is_add=1)
5527         self.vapi.nat44_interface_add_del_output_feature(
5528             is_add=1,
5529             sw_if_index=self.pg1.sw_if_index)
5530
5531         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5532              IP(src=self.pg0.remote_ip4, dst=external_addr) /
5533              TCP(sport=12345, dport=external_port))
5534         self.pg0.add_stream(p)
5535         self.pg_enable_capture(self.pg_interfaces)
5536         self.pg_start()
5537         capture = self.pg1.get_capture(1)
5538         p = capture[0]
5539         try:
5540             ip = p[IP]
5541             tcp = p[TCP]
5542             self.assertEqual(ip.src, self.pg0.remote_ip4)
5543             self.assertEqual(tcp.sport, 12345)
5544             self.assertEqual(ip.dst, self.pg1.remote_ip4)
5545             self.assertEqual(tcp.dport, local_port)
5546             self.assert_packet_checksums_valid(p)
5547         except:
5548             self.logger.error(ppp("Unexpected or invalid packet:", p))
5549             raise
5550
5551         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5552              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5553              TCP(sport=local_port, dport=12345))
5554         self.pg1.add_stream(p)
5555         self.pg_enable_capture(self.pg_interfaces)
5556         self.pg_start()
5557         capture = self.pg0.get_capture(1)
5558         p = capture[0]
5559         try:
5560             ip = p[IP]
5561             tcp = p[TCP]
5562             self.assertEqual(ip.src, external_addr)
5563             self.assertEqual(tcp.sport, external_port)
5564             self.assertEqual(ip.dst, self.pg0.remote_ip4)
5565             self.assertEqual(tcp.dport, 12345)
5566             self.assert_packet_checksums_valid(p)
5567         except:
5568             self.logger.error(ppp("Unexpected or invalid packet:", p))
5569             raise
5570
5571     def test_next_src_nat(self):
5572         """ On way back forward packet to nat44-in2out node. """
5573         twice_nat_addr = '10.0.1.3'
5574         external_port = 80
5575         local_port = 8080
5576         post_twice_nat_port = 0
5577
5578         self.vapi.nat44_forwarding_enable_disable(enable=1)
5579         self.nat44_add_address(twice_nat_addr, twice_nat=1)
5580         flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5581                  self.config_flags.NAT_IS_SELF_TWICE_NAT)
5582         self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5583                                       local_port, external_port,
5584                                       proto=IP_PROTOS.tcp, vrf_id=1,
5585                                       flags=flags)
5586         self.vapi.nat44_interface_add_del_feature(
5587             sw_if_index=self.pg6.sw_if_index,
5588             is_add=1)
5589
5590         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5591              IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5592              TCP(sport=12345, dport=external_port))
5593         self.pg6.add_stream(p)
5594         self.pg_enable_capture(self.pg_interfaces)
5595         self.pg_start()
5596         capture = self.pg6.get_capture(1)
5597         p = capture[0]
5598         try:
5599             ip = p[IP]
5600             tcp = p[TCP]
5601             self.assertEqual(ip.src, twice_nat_addr)
5602             self.assertNotEqual(tcp.sport, 12345)
5603             post_twice_nat_port = tcp.sport
5604             self.assertEqual(ip.dst, self.pg6.remote_ip4)
5605             self.assertEqual(tcp.dport, local_port)
5606             self.assert_packet_checksums_valid(p)
5607         except:
5608             self.logger.error(ppp("Unexpected or invalid packet:", p))
5609             raise
5610
5611         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5612              IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5613              TCP(sport=local_port, dport=post_twice_nat_port))
5614         self.pg6.add_stream(p)
5615         self.pg_enable_capture(self.pg_interfaces)
5616         self.pg_start()
5617         capture = self.pg6.get_capture(1)
5618         p = capture[0]
5619         try:
5620             ip = p[IP]
5621             tcp = p[TCP]
5622             self.assertEqual(ip.src, self.pg1.remote_ip4)
5623             self.assertEqual(tcp.sport, external_port)
5624             self.assertEqual(ip.dst, self.pg6.remote_ip4)
5625             self.assertEqual(tcp.dport, 12345)
5626             self.assert_packet_checksums_valid(p)
5627         except:
5628             self.logger.error(ppp("Unexpected or invalid packet:", p))
5629             raise
5630
5631     def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5632                          client_id=None):
5633         twice_nat_addr = '10.0.1.3'
5634
5635         port_in = 8080
5636         if lb:
5637             if not same_pg:
5638                 port_in1 = port_in
5639                 port_in2 = port_in
5640             else:
5641                 port_in1 = port_in + 1
5642                 port_in2 = port_in + 2
5643
5644         port_out = 80
5645         eh_port_out = 4567
5646
5647         server1 = self.pg0.remote_hosts[0]
5648         server2 = self.pg0.remote_hosts[1]
5649         if lb and same_pg:
5650             server2 = server1
5651         if not lb:
5652             server = server1
5653
5654         pg0 = self.pg0
5655         if same_pg:
5656             pg1 = self.pg0
5657         else:
5658             pg1 = self.pg1
5659
5660         eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5661                         client_id == 1)
5662
5663         self.nat44_add_address(self.nat_addr)
5664         self.nat44_add_address(twice_nat_addr, twice_nat=1)
5665
5666         flags = 0
5667         if self_twice_nat:
5668             flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
5669         else:
5670             flags |= self.config_flags.NAT_IS_TWICE_NAT
5671
5672         if not lb:
5673             self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5674                                           port_in, port_out,
5675                                           proto=IP_PROTOS.tcp,
5676                                           flags=flags)
5677         else:
5678             locals = [{'addr': server1.ip4,
5679                        'port': port_in1,
5680                        'probability': 50,
5681                        'vrf_id': 0},
5682                       {'addr': server2.ip4,
5683                        'port': port_in2,
5684                        'probability': 50,
5685                        'vrf_id': 0}]
5686             out_addr = self.nat_addr
5687
5688             self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5689                                                       external_addr=out_addr,
5690                                                       external_port=port_out,
5691                                                       protocol=IP_PROTOS.tcp,
5692                                                       local_num=len(locals),
5693                                                       locals=locals)
5694         flags = self.config_flags.NAT_IS_INSIDE
5695         self.vapi.nat44_interface_add_del_feature(
5696             sw_if_index=pg0.sw_if_index,
5697             flags=flags, is_add=1)
5698         self.vapi.nat44_interface_add_del_feature(
5699             sw_if_index=pg1.sw_if_index,
5700             is_add=1)
5701
5702         if same_pg:
5703             if not lb:
5704                 client = server
5705             else:
5706                 assert client_id is not None
5707                 if client_id == 1:
5708                     client = self.pg0.remote_hosts[0]
5709                 elif client_id == 2:
5710                     client = self.pg0.remote_hosts[1]
5711         else:
5712             client = pg1.remote_hosts[0]
5713         p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5714              IP(src=client.ip4, dst=self.nat_addr) /
5715              TCP(sport=eh_port_out, dport=port_out))
5716         pg1.add_stream(p)
5717         self.pg_enable_capture(self.pg_interfaces)
5718         self.pg_start()
5719         capture = pg0.get_capture(1)
5720         p = capture[0]
5721         try:
5722             ip = p[IP]
5723             tcp = p[TCP]
5724             if lb:
5725                 if ip.dst == server1.ip4:
5726                     server = server1
5727                     port_in = port_in1
5728                 else:
5729                     server = server2
5730                     port_in = port_in2
5731             self.assertEqual(ip.dst, server.ip4)
5732             if lb and same_pg:
5733                 self.assertIn(tcp.dport, [port_in1, port_in2])
5734             else:
5735                 self.assertEqual(tcp.dport, port_in)
5736             if eh_translate:
5737                 self.assertEqual(ip.src, twice_nat_addr)
5738                 self.assertNotEqual(tcp.sport, eh_port_out)
5739             else:
5740                 self.assertEqual(ip.src, client.ip4)
5741                 self.assertEqual(tcp.sport, eh_port_out)
5742             eh_addr_in = ip.src
5743             eh_port_in = tcp.sport
5744             saved_port_in = tcp.dport
5745             self.assert_packet_checksums_valid(p)
5746         except:
5747             self.logger.error(ppp("Unexpected or invalid packet:", p))
5748             raise
5749
5750         p = (Ether(src=server.mac, dst=pg0.local_mac) /
5751              IP(src=server.ip4, dst=eh_addr_in) /
5752              TCP(sport=saved_port_in, dport=eh_port_in))
5753         pg0.add_stream(p)
5754         self.pg_enable_capture(self.pg_interfaces)
5755         self.pg_start()
5756         capture = pg1.get_capture(1)
5757         p = capture[0]
5758         try:
5759             ip = p[IP]
5760             tcp = p[TCP]
5761             self.assertEqual(ip.dst, client.ip4)
5762             self.assertEqual(ip.src, self.nat_addr)
5763             self.assertEqual(tcp.dport, eh_port_out)
5764             self.assertEqual(tcp.sport, port_out)
5765             self.assert_packet_checksums_valid(p)
5766         except:
5767             self.logger.error(ppp("Unexpected or invalid packet:", p))
5768             raise
5769
5770         if eh_translate:
5771             sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5772             self.assertEqual(len(sessions), 1)
5773             self.assertTrue(sessions[0].flags &
5774                             self.config_flags.NAT_IS_EXT_HOST_VALID)
5775             self.assertTrue(sessions[0].flags &
5776                             self.config_flags.NAT_IS_TWICE_NAT)
5777             self.logger.info(self.vapi.cli("show nat44 sessions detail"))
5778             self.vapi.nat44_del_session(
5779                 address=sessions[0].inside_ip_address,
5780                 port=sessions[0].inside_port,
5781                 protocol=sessions[0].protocol,
5782                 flags=(self.config_flags.NAT_IS_INSIDE |
5783                        self.config_flags.NAT_IS_EXT_HOST_VALID),
5784                 ext_host_address=sessions[0].ext_host_nat_address,
5785                 ext_host_port=sessions[0].ext_host_nat_port)
5786             sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5787             self.assertEqual(len(sessions), 0)
5788
5789     def test_twice_nat(self):
5790         """ Twice NAT44 """
5791         self.twice_nat_common()
5792
5793     def test_self_twice_nat_positive(self):
5794         """ Self Twice NAT44 (positive test) """
5795         self.twice_nat_common(self_twice_nat=True, same_pg=True)
5796
5797     def test_self_twice_nat_negative(self):
5798         """ Self Twice NAT44 (negative test) """
5799         self.twice_nat_common(self_twice_nat=True)
5800
5801     def test_twice_nat_lb(self):
5802         """ Twice NAT44 local service load balancing """
5803         self.twice_nat_common(lb=True)
5804
5805     def test_self_twice_nat_lb_positive(self):
5806         """ Self Twice NAT44 local service load balancing (positive test) """
5807         self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5808                               client_id=1)
5809
5810     def test_self_twice_nat_lb_negative(self):
5811         """ Self Twice NAT44 local service load balancing (negative test) """
5812         self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5813                               client_id=2)
5814
5815     def test_twice_nat_interface_addr(self):
5816         """ Acquire twice NAT44 addresses from interface """
5817         flags = self.config_flags.NAT_IS_TWICE_NAT
5818         self.vapi.nat44_add_del_interface_addr(
5819             is_add=1,
5820             sw_if_index=self.pg3.sw_if_index,
5821             flags=flags)
5822
5823         # no address in NAT pool
5824         adresses = self.vapi.nat44_address_dump()
5825         self.assertEqual(0, len(adresses))
5826
5827         # configure interface address and check NAT address pool
5828         self.pg3.config_ip4()
5829         adresses = self.vapi.nat44_address_dump()
5830         self.assertEqual(1, len(adresses))
5831         self.assertEqual(str(adresses[0].ip_address),
5832                          self.pg3.local_ip4)
5833         self.assertEqual(adresses[0].flags, flags)
5834
5835         # remove interface address and check NAT address pool
5836         self.pg3.unconfig_ip4()
5837         adresses = self.vapi.nat44_address_dump()
5838         self.assertEqual(0, len(adresses))
5839
5840     def test_tcp_close(self):
5841         """ Close TCP session from inside network - output feature """
5842         self.vapi.nat44_forwarding_enable_disable(enable=1)
5843         self.nat44_add_address(self.pg1.local_ip4)
5844         twice_nat_addr = '10.0.1.3'
5845         service_ip = '192.168.16.150'
5846         self.nat44_add_address(twice_nat_addr, twice_nat=1)
5847         flags = self.config_flags.NAT_IS_INSIDE
5848         self.vapi.nat44_interface_add_del_feature(
5849             sw_if_index=self.pg0.sw_if_index,
5850             is_add=1)
5851         self.vapi.nat44_interface_add_del_feature(
5852             sw_if_index=self.pg0.sw_if_index,
5853             flags=flags, is_add=1)
5854         self.vapi.nat44_interface_add_del_output_feature(
5855             is_add=1,
5856             sw_if_index=self.pg1.sw_if_index)
5857         flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5858                  self.config_flags.NAT_IS_TWICE_NAT)
5859         self.nat44_add_static_mapping(self.pg0.remote_ip4,
5860                                       service_ip,
5861                                       80,
5862                                       80,
5863                                       proto=IP_PROTOS.tcp,
5864                                       flags=flags)
5865         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5866         start_sessnum = len(sessions)
5867
5868         # SYN packet out->in
5869         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5870              IP(src=self.pg1.remote_ip4, dst=service_ip) /
5871              TCP(sport=33898, dport=80, flags="S"))
5872         self.pg1.add_stream(p)
5873         self.pg_enable_capture(self.pg_interfaces)
5874         self.pg_start()
5875         capture = self.pg0.get_capture(1)
5876         p = capture[0]
5877         tcp_port = p[TCP].sport
5878
5879         # SYN + ACK packet in->out
5880         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5881              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5882              TCP(sport=80, dport=tcp_port, flags="SA"))
5883         self.pg0.add_stream(p)
5884         self.pg_enable_capture(self.pg_interfaces)
5885         self.pg_start()
5886         self.pg1.get_capture(1)
5887
5888         # ACK packet out->in
5889         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5890              IP(src=self.pg1.remote_ip4, dst=service_ip) /
5891              TCP(sport=33898, dport=80, flags="A"))
5892         self.pg1.add_stream(p)
5893         self.pg_enable_capture(self.pg_interfaces)
5894         self.pg_start()
5895         self.pg0.get_capture(1)
5896
5897         # FIN packet in -> out
5898         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5899              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5900              TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5901         self.pg0.add_stream(p)
5902         self.pg_enable_capture(self.pg_interfaces)
5903         self.pg_start()
5904         self.pg1.get_capture(1)
5905
5906         # FIN+ACK packet out -> in
5907         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5908              IP(src=self.pg1.remote_ip4, dst=service_ip) /
5909              TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5910         self.pg1.add_stream(p)
5911         self.pg_enable_capture(self.pg_interfaces)
5912         self.pg_start()
5913         self.pg0.get_capture(1)
5914
5915         # ACK packet in -> out
5916         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5917              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5918              TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5919         self.pg0.add_stream(p)
5920         self.pg_enable_capture(self.pg_interfaces)
5921         self.pg_start()
5922         self.pg1.get_capture(1)
5923
5924         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4,
5925                                                      0)
5926         self.assertEqual(len(sessions) - start_sessnum, 0)
5927
5928     def test_tcp_session_close_in(self):
5929         """ Close TCP session from inside network """
5930         self.tcp_port_out = 10505
5931         self.nat44_add_address(self.nat_addr)
5932         flags = self.config_flags.NAT_IS_TWICE_NAT
5933         self.nat44_add_static_mapping(self.pg0.remote_ip4,
5934                                       self.nat_addr,
5935                                       self.tcp_port_in,
5936                                       self.tcp_port_out,
5937                                       proto=IP_PROTOS.tcp,
5938                                       flags=flags)
5939         flags = self.config_flags.NAT_IS_INSIDE
5940         self.vapi.nat44_interface_add_del_feature(
5941             sw_if_index=self.pg0.sw_if_index,
5942             flags=flags, is_add=1)
5943         self.vapi.nat44_interface_add_del_feature(
5944             sw_if_index=self.pg1.sw_if_index,
5945             is_add=1)
5946
5947         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5948         start_sessnum = len(sessions)
5949
5950         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
5951                                    tcp_transitory=2, icmp=5)
5952
5953         self.initiate_tcp_session(self.pg0, self.pg1)
5954
5955         # FIN packet in -> out
5956         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5957              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5958              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5959                  flags="FA", seq=100, ack=300))
5960         self.pg0.add_stream(p)
5961         self.pg_enable_capture(self.pg_interfaces)
5962         self.pg_start()
5963         self.pg1.get_capture(1)
5964
5965         pkts = []
5966
5967         # ACK packet out -> in
5968         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5969              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5970              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5971                  flags="A", seq=300, ack=101))
5972         pkts.append(p)
5973
5974         # FIN packet out -> in
5975         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5976              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5977              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5978                  flags="FA", seq=300, ack=101))
5979         pkts.append(p)
5980
5981         self.pg1.add_stream(pkts)
5982         self.pg_enable_capture(self.pg_interfaces)
5983         self.pg_start()
5984         self.pg0.get_capture(2)
5985
5986         # ACK packet in -> out
5987         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5988              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5989              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5990                  flags="A", seq=101, ack=301))
5991         self.pg0.add_stream(p)
5992         self.pg_enable_capture(self.pg_interfaces)
5993         self.pg_start()
5994         self.pg1.get_capture(1)
5995
5996         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5997         self.assertEqual(len(sessions) - start_sessnum, 1)
5998
5999         stats = self.statistics.get_counter(
6000             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6001         out2in_drops = stats[0]
6002         stats = self.statistics.get_counter(
6003             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6004         in2out_drops = stats[0]
6005
6006         # extra FIN packet out -> in - this should be dropped
6007         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6008              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6009              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6010                  flags="FA", seq=300, ack=101))
6011
6012         self.pg1.add_stream(p)
6013         self.pg_enable_capture(self.pg_interfaces)
6014         self.pg_start()
6015         self.pg0.assert_nothing_captured()
6016
6017         # extra ACK packet in -> out - this should be dropped
6018         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6019              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6020              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6021                  flags="A", seq=101, ack=301))
6022         self.pg0.add_stream(p)
6023         self.pg_enable_capture(self.pg_interfaces)
6024         self.pg_start()
6025         self.pg1.assert_nothing_captured()
6026
6027         stats = self.statistics.get_counter(
6028             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6029         self.assertEqual(stats[0] - out2in_drops, 1)
6030         stats = self.statistics.get_counter(
6031             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6032         self.assertEqual(stats[0] - in2out_drops, 1)
6033
6034         self.sleep(3)
6035         # extra ACK packet in -> out - this will cause session to be wiped
6036         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6037              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6038              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6039                  flags="A", seq=101, ack=301))
6040         self.pg0.add_stream(p)
6041         self.pg_enable_capture(self.pg_interfaces)
6042         self.pg_start()
6043         self.pg1.assert_nothing_captured()
6044         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6045         self.assertEqual(len(sessions) - start_sessnum, 0)
6046
6047     def test_tcp_session_close_out(self):
6048         """ Close TCP session from outside network """
6049         self.tcp_port_out = 10505
6050         self.nat44_add_address(self.nat_addr)
6051         flags = self.config_flags.NAT_IS_TWICE_NAT
6052         self.nat44_add_static_mapping(self.pg0.remote_ip4,
6053                                       self.nat_addr,
6054                                       self.tcp_port_in,
6055                                       self.tcp_port_out,
6056                                       proto=IP_PROTOS.tcp,
6057                                       flags=flags)
6058         flags = self.config_flags.NAT_IS_INSIDE
6059         self.vapi.nat44_interface_add_del_feature(
6060             sw_if_index=self.pg0.sw_if_index,
6061             flags=flags, is_add=1)
6062         self.vapi.nat44_interface_add_del_feature(
6063             sw_if_index=self.pg1.sw_if_index,
6064             is_add=1)
6065
6066         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6067         start_sessnum = len(sessions)
6068
6069         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6070                                    tcp_transitory=2, icmp=5)
6071
6072         self.initiate_tcp_session(self.pg0, self.pg1)
6073
6074         # FIN packet out -> in
6075         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6076              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6077              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6078                  flags="FA", seq=100, ack=300))
6079         self.pg1.add_stream(p)
6080         self.pg_enable_capture(self.pg_interfaces)
6081         self.pg_start()
6082         self.pg0.get_capture(1)
6083
6084         # FIN+ACK packet in -> out
6085         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6086              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6087              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6088                  flags="FA", seq=300, ack=101))
6089
6090         self.pg0.add_stream(p)
6091         self.pg_enable_capture(self.pg_interfaces)
6092         self.pg_start()
6093         self.pg1.get_capture(1)
6094
6095         # ACK packet out -> in
6096         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6097              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6098              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6099                  flags="A", seq=101, ack=301))
6100         self.pg1.add_stream(p)
6101         self.pg_enable_capture(self.pg_interfaces)
6102         self.pg_start()
6103         self.pg0.get_capture(1)
6104
6105         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6106         self.assertEqual(len(sessions) - start_sessnum, 1)
6107
6108         stats = self.statistics.get_counter(
6109             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6110         out2in_drops = stats[0]
6111         stats = self.statistics.get_counter(
6112             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6113         in2out_drops = stats[0]
6114
6115         # extra FIN packet out -> in - this should be dropped
6116         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6117              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6118              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6119                  flags="FA", seq=300, ack=101))
6120
6121         self.pg1.add_stream(p)
6122         self.pg_enable_capture(self.pg_interfaces)
6123         self.pg_start()
6124         self.pg0.assert_nothing_captured()
6125
6126         # extra ACK packet in -> out - this should be dropped
6127         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6128              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6129              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6130                  flags="A", seq=101, ack=301))
6131         self.pg0.add_stream(p)
6132         self.pg_enable_capture(self.pg_interfaces)
6133         self.pg_start()
6134         self.pg1.assert_nothing_captured()
6135
6136         stats = self.statistics.get_counter(
6137             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6138         self.assertEqual(stats[0] - out2in_drops, 1)
6139         stats = self.statistics.get_counter(
6140             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6141         self.assertEqual(stats[0] - in2out_drops, 1)
6142
6143         self.sleep(3)
6144         # extra ACK packet in -> out - this will cause session to be wiped
6145         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6146              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6147              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6148                  flags="A", seq=101, ack=301))
6149         self.pg0.add_stream(p)
6150         self.pg_enable_capture(self.pg_interfaces)
6151         self.pg_start()
6152         self.pg1.assert_nothing_captured()
6153         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6154         self.assertEqual(len(sessions) - start_sessnum, 0)
6155
6156     def test_tcp_session_close_simultaneous(self):
6157         """ Close TCP session from inside network """
6158         self.tcp_port_out = 10505
6159         self.nat44_add_address(self.nat_addr)
6160         flags = self.config_flags.NAT_IS_TWICE_NAT
6161         self.nat44_add_static_mapping(self.pg0.remote_ip4,
6162                                       self.nat_addr,
6163                                       self.tcp_port_in,
6164                                       self.tcp_port_out,
6165                                       proto=IP_PROTOS.tcp,
6166                                       flags=flags)
6167         flags = self.config_flags.NAT_IS_INSIDE
6168         self.vapi.nat44_interface_add_del_feature(
6169             sw_if_index=self.pg0.sw_if_index,
6170             flags=flags, is_add=1)
6171         self.vapi.nat44_interface_add_del_feature(
6172             sw_if_index=self.pg1.sw_if_index,
6173             is_add=1)
6174
6175         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6176         start_sessnum = len(sessions)
6177
6178         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6179                                    tcp_transitory=2, icmp=5)
6180
6181         self.initiate_tcp_session(self.pg0, self.pg1)
6182
6183         # FIN packet in -> out
6184         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6185              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6186              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6187                  flags="FA", seq=100, ack=300))
6188         self.pg0.add_stream(p)
6189         self.pg_enable_capture(self.pg_interfaces)
6190         self.pg_start()
6191         self.pg1.get_capture(1)
6192
6193         # FIN packet out -> in
6194         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6195              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6196              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6197                  flags="FA", seq=300, ack=100))
6198         self.pg1.add_stream(p)
6199         self.pg_enable_capture(self.pg_interfaces)
6200         self.pg_start()
6201         self.pg0.get_capture(1)
6202
6203         # ACK packet in -> out
6204         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6205              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6206              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6207                  flags="A", seq=101, ack=301))
6208         self.pg0.add_stream(p)
6209         self.pg_enable_capture(self.pg_interfaces)
6210         self.pg_start()
6211         self.pg1.get_capture(1)
6212
6213         # ACK packet out -> in
6214         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6215              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6216              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6217                  flags="A", seq=301, ack=101))
6218         self.pg1.add_stream(p)
6219         self.pg_enable_capture(self.pg_interfaces)
6220         self.pg_start()
6221         self.pg0.get_capture(1)
6222
6223         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6224         self.assertEqual(len(sessions) - start_sessnum, 1)
6225
6226         stats = self.statistics.get_counter(
6227             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6228         out2in_drops = stats[0]
6229         stats = self.statistics.get_counter(
6230             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6231         in2out_drops = stats[0]
6232
6233         # extra FIN packet out -> in - this should be dropped
6234         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6235              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6236              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6237                  flags="FA", seq=300, ack=101))
6238
6239         self.pg1.add_stream(p)
6240         self.pg_enable_capture(self.pg_interfaces)
6241         self.pg_start()
6242         self.pg0.assert_nothing_captured()
6243
6244         # extra ACK packet in -> out - this should be dropped
6245         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6246              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6247              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6248                  flags="A", seq=101, ack=301))
6249         self.pg0.add_stream(p)
6250         self.pg_enable_capture(self.pg_interfaces)
6251         self.pg_start()
6252         self.pg1.assert_nothing_captured()
6253
6254         stats = self.statistics.get_counter(
6255             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6256         self.assertEqual(stats[0] - out2in_drops, 1)
6257         stats = self.statistics.get_counter(
6258             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6259         self.assertEqual(stats[0] - in2out_drops, 1)
6260
6261         self.sleep(3)
6262         # extra ACK packet in -> out - this will cause session to be wiped
6263         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6264              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6265              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6266                  flags="A", seq=101, ack=301))
6267         self.pg0.add_stream(p)
6268         self.pg_enable_capture(self.pg_interfaces)
6269         self.pg_start()
6270         self.pg1.assert_nothing_captured()
6271         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6272         self.assertEqual(len(sessions) - start_sessnum, 0)
6273
6274     def test_one_armed_nat44_static(self):
6275         """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
6276         remote_host = self.pg4.remote_hosts[0]
6277         local_host = self.pg4.remote_hosts[1]
6278         external_port = 80
6279         local_port = 8080
6280         eh_port_in = 0
6281
6282         self.vapi.nat44_forwarding_enable_disable(enable=1)
6283         self.nat44_add_address(self.nat_addr, twice_nat=1)
6284         flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
6285                  self.config_flags.NAT_IS_TWICE_NAT)
6286         self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
6287                                       local_port, external_port,
6288                                       proto=IP_PROTOS.tcp, flags=flags)
6289         flags = self.config_flags.NAT_IS_INSIDE
6290         self.vapi.nat44_interface_add_del_feature(
6291             sw_if_index=self.pg4.sw_if_index,
6292             is_add=1)
6293         self.vapi.nat44_interface_add_del_feature(
6294             sw_if_index=self.pg4.sw_if_index,
6295             flags=flags, is_add=1)
6296
6297         # from client to service
6298         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6299              IP(src=remote_host.ip4, dst=self.nat_addr) /
6300              TCP(sport=12345, dport=external_port))
6301         self.pg4.add_stream(p)
6302         self.pg_enable_capture(self.pg_interfaces)
6303         self.pg_start()
6304         capture = self.pg4.get_capture(1)
6305         p = capture[0]
6306         try:
6307             ip = p[IP]
6308             tcp = p[TCP]
6309             self.assertEqual(ip.dst, local_host.ip4)
6310             self.assertEqual(ip.src, self.nat_addr)
6311             self.assertEqual(tcp.dport, local_port)
6312             self.assertNotEqual(tcp.sport, 12345)
6313             eh_port_in = tcp.sport
6314             self.assert_packet_checksums_valid(p)
6315         except:
6316             self.logger.error(ppp("Unexpected or invalid packet:", p))
6317             raise
6318
6319         # from service back to client
6320         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6321              IP(src=local_host.ip4, dst=self.nat_addr) /
6322              TCP(sport=local_port, dport=eh_port_in))
6323         self.pg4.add_stream(p)
6324         self.pg_enable_capture(self.pg_interfaces)
6325         self.pg_start()
6326         capture = self.pg4.get_capture(1)
6327         p = capture[0]
6328         try:
6329             ip = p[IP]
6330             tcp = p[TCP]
6331             self.assertEqual(ip.src, self.nat_addr)
6332             self.assertEqual(ip.dst, remote_host.ip4)
6333             self.assertEqual(tcp.sport, external_port)
6334             self.assertEqual(tcp.dport, 12345)
6335             self.assert_packet_checksums_valid(p)
6336         except:
6337             self.logger.error(ppp("Unexpected or invalid packet:", p))
6338             raise
6339
6340     def test_static_with_port_out2(self):
6341         """ 1:1 NAPT asymmetrical rule """
6342
6343         external_port = 80
6344         local_port = 8080
6345
6346         self.vapi.nat44_forwarding_enable_disable(enable=1)
6347         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6348         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
6349                                       local_port, external_port,
6350                                       proto=IP_PROTOS.tcp, flags=flags)
6351         flags = self.config_flags.NAT_IS_INSIDE
6352         self.vapi.nat44_interface_add_del_feature(
6353             sw_if_index=self.pg0.sw_if_index,
6354             flags=flags, is_add=1)
6355         self.vapi.nat44_interface_add_del_feature(
6356             sw_if_index=self.pg1.sw_if_index,
6357             is_add=1)
6358
6359         # from client to service
6360         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6361              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6362              TCP(sport=12345, dport=external_port))
6363         self.pg1.add_stream(p)
6364         self.pg_enable_capture(self.pg_interfaces)
6365         self.pg_start()
6366         capture = self.pg0.get_capture(1)
6367         p = capture[0]
6368         try:
6369             ip = p[IP]
6370             tcp = p[TCP]
6371             self.assertEqual(ip.dst, self.pg0.remote_ip4)
6372             self.assertEqual(tcp.dport, local_port)
6373             self.assert_packet_checksums_valid(p)
6374         except:
6375             self.logger.error(ppp("Unexpected or invalid packet:", p))
6376             raise
6377
6378         # ICMP error
6379         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6380              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6381              ICMP(type=11) / capture[0][IP])
6382         self.pg0.add_stream(p)
6383         self.pg_enable_capture(self.pg_interfaces)
6384         self.pg_start()
6385         capture = self.pg1.get_capture(1)
6386         p = capture[0]
6387         try:
6388             self.assertEqual(p[IP].src, self.nat_addr)
6389             inner = p[IPerror]
6390             self.assertEqual(inner.dst, self.nat_addr)
6391             self.assertEqual(inner[TCPerror].dport, external_port)
6392         except:
6393             self.logger.error(ppp("Unexpected or invalid packet:", p))
6394             raise
6395
6396         # from service back to client
6397         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6398              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6399              TCP(sport=local_port, dport=12345))
6400         self.pg0.add_stream(p)
6401         self.pg_enable_capture(self.pg_interfaces)
6402         self.pg_start()
6403         capture = self.pg1.get_capture(1)
6404         p = capture[0]
6405         try:
6406             ip = p[IP]
6407             tcp = p[TCP]
6408             self.assertEqual(ip.src, self.nat_addr)
6409             self.assertEqual(tcp.sport, external_port)
6410             self.assert_packet_checksums_valid(p)
6411         except:
6412             self.logger.error(ppp("Unexpected or invalid packet:", p))
6413             raise
6414
6415         # ICMP error
6416         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6417              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6418              ICMP(type=11) / capture[0][IP])
6419         self.pg1.add_stream(p)
6420         self.pg_enable_capture(self.pg_interfaces)
6421         self.pg_start()
6422         capture = self.pg0.get_capture(1)
6423         p = capture[0]
6424         try:
6425             self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
6426             inner = p[IPerror]
6427             self.assertEqual(inner.src, self.pg0.remote_ip4)
6428             self.assertEqual(inner[TCPerror].sport, local_port)
6429         except:
6430             self.logger.error(ppp("Unexpected or invalid packet:", p))
6431             raise
6432
6433         # from client to server (no translation)
6434         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6435              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
6436              TCP(sport=12346, dport=local_port))
6437         self.pg1.add_stream(p)
6438         self.pg_enable_capture(self.pg_interfaces)
6439         self.pg_start()
6440         capture = self.pg0.get_capture(1)
6441         p = capture[0]
6442         try:
6443             ip = p[IP]
6444             tcp = p[TCP]
6445             self.assertEqual(ip.dst, self.pg0.remote_ip4)
6446             self.assertEqual(tcp.dport, local_port)
6447             self.assert_packet_checksums_valid(p)
6448         except:
6449             self.logger.error(ppp("Unexpected or invalid packet:", p))
6450             raise
6451
6452         # from service back to client (no translation)
6453         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6454              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6455              TCP(sport=local_port, dport=12346))
6456         self.pg0.add_stream(p)
6457         self.pg_enable_capture(self.pg_interfaces)
6458         self.pg_start()
6459         capture = self.pg1.get_capture(1)
6460         p = capture[0]
6461         try:
6462             ip = p[IP]
6463             tcp = p[TCP]
6464             self.assertEqual(ip.src, self.pg0.remote_ip4)
6465             self.assertEqual(tcp.sport, local_port)
6466             self.assert_packet_checksums_valid(p)
6467         except:
6468             self.logger.error(ppp("Unexpected or invalid packet:", p))
6469             raise
6470
6471     def test_output_feature(self):
6472         """ NAT44 interface output feature (in2out postrouting) """
6473         self.vapi.nat44_forwarding_enable_disable(enable=1)
6474         self.nat44_add_address(self.nat_addr)
6475         self.vapi.nat44_interface_add_del_feature(
6476             sw_if_index=self.pg0.sw_if_index,
6477             is_add=1)
6478         self.vapi.nat44_interface_add_del_output_feature(
6479             is_add=1,
6480             sw_if_index=self.pg1.sw_if_index)
6481
6482         # in2out
6483         pkts = self.create_stream_in(self.pg0, self.pg1)
6484         self.pg0.add_stream(pkts)
6485         self.pg_enable_capture(self.pg_interfaces)
6486         self.pg_start()
6487         capture = self.pg1.get_capture(len(pkts))
6488         self.verify_capture_out(capture)
6489
6490         # out2in
6491         pkts = self.create_stream_out(self.pg1)
6492         self.pg1.add_stream(pkts)
6493         self.pg_enable_capture(self.pg_interfaces)
6494         self.pg_start()
6495         capture = self.pg0.get_capture(len(pkts))
6496         self.verify_capture_in(capture, self.pg0)
6497
6498     def test_output_feature_stateful_acl(self):
6499         """ NAT44 endpoint-dependent output feature works with stateful ACL """
6500         self.nat44_add_address(self.nat_addr)
6501         self.vapi.nat44_interface_add_del_output_feature(
6502             sw_if_index=self.pg0.sw_if_index,
6503             flags=self.config_flags.NAT_IS_INSIDE,
6504             is_add=1)
6505         self.vapi.nat44_interface_add_del_output_feature(
6506             sw_if_index=self.pg1.sw_if_index,
6507             flags=self.config_flags.NAT_IS_OUTSIDE,
6508             is_add=1)
6509
6510         # First ensure that the NAT is working sans ACL
6511
6512         # send packets out2in, no sessions yet so packets should drop
6513         pkts_out2in = self.create_stream_out(self.pg1)
6514         self.send_and_assert_no_replies(self.pg1, pkts_out2in)
6515
6516         # send packets into inside intf, ensure received via outside intf
6517         pkts_in2out = self.create_stream_in(self.pg0, self.pg1)
6518         capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
6519                                        len(pkts_in2out))
6520         self.verify_capture_out(capture)
6521
6522         # send out2in again, with sessions created it should work now
6523         pkts_out2in = self.create_stream_out(self.pg1)
6524         capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
6525                                        len(pkts_out2in))
6526         self.verify_capture_in(capture, self.pg0)
6527
6528         # Create an ACL blocking everything
6529         out2in_deny_rule = AclRule(is_permit=0)
6530         out2in_acl = VppAcl(self, rules=[out2in_deny_rule])
6531         out2in_acl.add_vpp_config()
6532
6533         # create an ACL to permit/reflect everything
6534         in2out_reflect_rule = AclRule(is_permit=2)
6535         in2out_acl = VppAcl(self, rules=[in2out_reflect_rule])
6536         in2out_acl.add_vpp_config()
6537
6538         # apply as input acl on interface and confirm it blocks everything
6539         acl_if = VppAclInterface(self, sw_if_index=self.pg1.sw_if_index,
6540                                  n_input=1, acls=[out2in_acl])
6541         acl_if.add_vpp_config()
6542         self.send_and_assert_no_replies(self.pg1, pkts_out2in)
6543
6544         # apply output acl
6545         acl_if.acls = [out2in_acl, in2out_acl]
6546         acl_if.add_vpp_config()
6547         # send in2out to generate ACL state (NAT state was created earlier)
6548         capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
6549                                        len(pkts_in2out))
6550         self.verify_capture_out(capture)
6551
6552         # send out2in again. ACL state exists so it should work now.
6553         # TCP packets with the syn flag set also need the ack flag
6554         for p in pkts_out2in:
6555             if p.haslayer(TCP) and p[TCP].flags & 0x02:
6556                 p[TCP].flags |= 0x10
6557         capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
6558                                        len(pkts_out2in))
6559         self.verify_capture_in(capture, self.pg0)
6560         self.logger.info(self.vapi.cli("show trace"))
6561
6562     def test_multiple_vrf(self):
6563         """ Multiple VRF setup """
6564         external_addr = '1.2.3.4'
6565         external_port = 80
6566         local_port = 8080
6567         port = 0
6568
6569         self.vapi.nat44_forwarding_enable_disable(enable=1)
6570         self.nat44_add_address(self.nat_addr)
6571         flags = self.config_flags.NAT_IS_INSIDE
6572         self.vapi.nat44_interface_add_del_feature(
6573             sw_if_index=self.pg0.sw_if_index,
6574             is_add=1)
6575         self.vapi.nat44_interface_add_del_feature(
6576             sw_if_index=self.pg0.sw_if_index,
6577             flags=flags, is_add=1)
6578         self.vapi.nat44_interface_add_del_output_feature(
6579             is_add=1,
6580             sw_if_index=self.pg1.sw_if_index)
6581         self.vapi.nat44_interface_add_del_feature(
6582             sw_if_index=self.pg5.sw_if_index,
6583             is_add=1)
6584         self.vapi.nat44_interface_add_del_feature(
6585             sw_if_index=self.pg5.sw_if_index,
6586             flags=flags, is_add=1)
6587         self.vapi.nat44_interface_add_del_feature(
6588             sw_if_index=self.pg6.sw_if_index,
6589             is_add=1)
6590         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6591         self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
6592                                       local_port, external_port, vrf_id=1,
6593                                       proto=IP_PROTOS.tcp, flags=flags)
6594         self.nat44_add_static_mapping(
6595             self.pg0.remote_ip4,
6596             external_sw_if_index=self.pg0.sw_if_index,
6597             local_port=local_port,
6598             vrf_id=0,
6599             external_port=external_port,
6600             proto=IP_PROTOS.tcp,
6601             flags=flags
6602         )
6603
6604         # from client to service (both VRF1)
6605         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6606              IP(src=self.pg6.remote_ip4, dst=external_addr) /
6607              TCP(sport=12345, dport=external_port))
6608         self.pg6.add_stream(p)
6609         self.pg_enable_capture(self.pg_interfaces)
6610         self.pg_start()
6611         capture = self.pg5.get_capture(1)
6612         p = capture[0]
6613         try:
6614             ip = p[IP]
6615             tcp = p[TCP]
6616             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6617             self.assertEqual(tcp.dport, local_port)
6618             self.assert_packet_checksums_valid(p)
6619         except:
6620             self.logger.error(ppp("Unexpected or invalid packet:", p))
6621             raise
6622
6623         # from service back to client (both VRF1)
6624         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6625              IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6626              TCP(sport=local_port, dport=12345))
6627         self.pg5.add_stream(p)
6628         self.pg_enable_capture(self.pg_interfaces)
6629         self.pg_start()
6630         capture = self.pg6.get_capture(1)
6631         p = capture[0]
6632         try:
6633             ip = p[IP]
6634             tcp = p[TCP]
6635             self.assertEqual(ip.src, external_addr)
6636             self.assertEqual(tcp.sport, external_port)
6637             self.assert_packet_checksums_valid(p)
6638         except:
6639             self.logger.error(ppp("Unexpected or invalid packet:", p))
6640             raise
6641
6642         # dynamic NAT from VRF1 to VRF0 (output-feature)
6643         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6644              IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6645              TCP(sport=2345, dport=22))
6646         self.pg5.add_stream(p)
6647         self.pg_enable_capture(self.pg_interfaces)
6648         self.pg_start()
6649         capture = self.pg1.get_capture(1)
6650         p = capture[0]
6651         try:
6652             ip = p[IP]
6653             tcp = p[TCP]
6654             self.assertEqual(ip.src, self.nat_addr)
6655             self.assertNotEqual(tcp.sport, 2345)
6656             self.assert_packet_checksums_valid(p)
6657             port = tcp.sport
6658         except:
6659             self.logger.error(ppp("Unexpected or invalid packet:", p))
6660             raise
6661
6662         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6663              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6664              TCP(sport=22, dport=port))
6665         self.pg1.add_stream(p)
6666         self.pg_enable_capture(self.pg_interfaces)
6667         self.pg_start()
6668         capture = self.pg5.get_capture(1)
6669         p = capture[0]
6670         try:
6671             ip = p[IP]
6672             tcp = p[TCP]
6673             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6674             self.assertEqual(tcp.dport, 2345)
6675             self.assert_packet_checksums_valid(p)
6676         except:
6677             self.logger.error(ppp("Unexpected or invalid packet:", p))
6678             raise
6679
6680         # from client VRF1 to service VRF0
6681         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6682              IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6683              TCP(sport=12346, dport=external_port))
6684         self.pg6.add_stream(p)
6685         self.pg_enable_capture(self.pg_interfaces)
6686         self.pg_start()
6687         capture = self.pg0.get_capture(1)
6688         p = capture[0]
6689         try:
6690             ip = p[IP]
6691             tcp = p[TCP]
6692             self.assertEqual(ip.dst, self.pg0.remote_ip4)
6693             self.assertEqual(tcp.dport, local_port)
6694             self.assert_packet_checksums_valid(p)
6695         except:
6696             self.logger.error(ppp("Unexpected or invalid packet:", p))
6697             raise
6698
6699         # from service VRF0 back to client VRF1
6700         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6701              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6702              TCP(sport=local_port, dport=12346))
6703         self.pg0.add_stream(p)
6704         self.pg_enable_capture(self.pg_interfaces)
6705         self.pg_start()
6706         capture = self.pg6.get_capture(1)
6707         p = capture[0]
6708         try:
6709             ip = p[IP]
6710             tcp = p[TCP]
6711             self.assertEqual(ip.src, self.pg0.local_ip4)
6712             self.assertEqual(tcp.sport, external_port)
6713             self.assert_packet_checksums_valid(p)
6714         except:
6715             self.logger.error(ppp("Unexpected or invalid packet:", p))
6716             raise
6717
6718         # from client VRF0 to service VRF1
6719         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6720              IP(src=self.pg0.remote_ip4, dst=external_addr) /
6721              TCP(sport=12347, dport=external_port))
6722         self.pg0.add_stream(p)
6723         self.pg_enable_capture(self.pg_interfaces)
6724         self.pg_start()
6725         capture = self.pg5.get_capture(1)
6726         p = capture[0]
6727         try:
6728             ip = p[IP]
6729             tcp = p[TCP]
6730             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6731             self.assertEqual(tcp.dport, local_port)
6732             self.assert_packet_checksums_valid(p)
6733         except:
6734             self.logger.error(ppp("Unexpected or invalid packet:", p))
6735             raise
6736
6737         # from service VRF1 back to client VRF0
6738         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6739              IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6740              TCP(sport=local_port, dport=12347))
6741         self.pg5.add_stream(p)
6742         self.pg_enable_capture(self.pg_interfaces)
6743         self.pg_start()
6744         capture = self.pg0.get_capture(1)
6745         p = capture[0]
6746         try:
6747             ip = p[IP]
6748             tcp = p[TCP]
6749             self.assertEqual(ip.src, external_addr)
6750             self.assertEqual(tcp.sport, external_port)
6751             self.assert_packet_checksums_valid(p)
6752         except:
6753             self.logger.error(ppp("Unexpected or invalid packet:", p))
6754             raise
6755
6756         # from client to server (both VRF1, no translation)
6757         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6758              IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6759              TCP(sport=12348, dport=local_port))
6760         self.pg6.add_stream(p)
6761         self.pg_enable_capture(self.pg_interfaces)
6762         self.pg_start()
6763         capture = self.pg5.get_capture(1)
6764         p = capture[0]
6765         try:
6766             ip = p[IP]
6767             tcp = p[TCP]
6768             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6769             self.assertEqual(tcp.dport, local_port)
6770             self.assert_packet_checksums_valid(p)
6771         except:
6772             self.logger.error(ppp("Unexpected or invalid packet:", p))
6773             raise
6774
6775         # from server back to client (both VRF1, no translation)
6776         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6777              IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6778              TCP(sport=local_port, dport=12348))
6779         self.pg5.add_stream(p)
6780         self.pg_enable_capture(self.pg_interfaces)
6781         self.pg_start()
6782         capture = self.pg6.get_capture(1)
6783         p = capture[0]
6784         try:
6785             ip = p[IP]
6786             tcp = p[TCP]
6787             self.assertEqual(ip.src, self.pg5.remote_ip4)
6788             self.assertEqual(tcp.sport, local_port)
6789             self.assert_packet_checksums_valid(p)
6790         except:
6791             self.logger.error(ppp("Unexpected or invalid packet:", p))
6792             raise
6793
6794         # from client VRF1 to server VRF0 (no translation)
6795         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6796              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6797              TCP(sport=local_port, dport=12349))
6798         self.pg0.add_stream(p)
6799         self.pg_enable_capture(self.pg_interfaces)
6800         self.pg_start()
6801         capture = self.pg6.get_capture(1)
6802         p = capture[0]
6803         try:
6804             ip = p[IP]
6805             tcp = p[TCP]
6806             self.assertEqual(ip.src, self.pg0.remote_ip4)
6807             self.assertEqual(tcp.sport, local_port)
6808             self.assert_packet_checksums_valid(p)
6809         except:
6810             self.logger.error(ppp("Unexpected or invalid packet:", p))
6811             raise
6812
6813         # from server VRF0 back to client VRF1 (no translation)
6814         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6815              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6816              TCP(sport=local_port, dport=12349))
6817         self.pg0.add_stream(p)
6818         self.pg_enable_capture(self.pg_interfaces)
6819         self.pg_start()
6820         capture = self.pg6.get_capture(1)
6821         p = capture[0]
6822         try:
6823             ip = p[IP]
6824             tcp = p[TCP]
6825             self.assertEqual(ip.src, self.pg0.remote_ip4)
6826             self.assertEqual(tcp.sport, local_port)
6827             self.assert_packet_checksums_valid(p)
6828         except:
6829             self.logger.error(ppp("Unexpected or invalid packet:", p))
6830             raise
6831
6832         # from client VRF0 to server VRF1 (no translation)
6833         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6834              IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6835              TCP(sport=12344, dport=local_port))
6836         self.pg0.add_stream(p)
6837         self.pg_enable_capture(self.pg_interfaces)
6838         self.pg_start()
6839         capture = self.pg5.get_capture(1)
6840         p = capture[0]
6841         try:
6842             ip = p[IP]
6843             tcp = p[TCP]
6844             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6845             self.assertEqual(tcp.dport, local_port)
6846             self.assert_packet_checksums_valid(p)
6847         except:
6848             self.logger.error(ppp("Unexpected or invalid packet:", p))
6849             raise
6850
6851         # from server VRF1 back to client VRF0 (no translation)
6852         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6853              IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6854              TCP(sport=local_port, dport=12344))
6855         self.pg5.add_stream(p)
6856         self.pg_enable_capture(self.pg_interfaces)
6857         self.pg_start()
6858         capture = self.pg0.get_capture(1)
6859         p = capture[0]
6860         try:
6861             ip = p[IP]
6862             tcp = p[TCP]
6863             self.assertEqual(ip.src, self.pg5.remote_ip4)
6864             self.assertEqual(tcp.sport, local_port)
6865             self.assert_packet_checksums_valid(p)
6866         except:
6867             self.logger.error(ppp("Unexpected or invalid packet:", p))
6868             raise
6869
6870     @unittest.skipUnless(running_extended_tests, "part of extended tests")
6871     def test_session_timeout(self):
6872         """ NAT44 session timeouts """
6873         self.nat44_add_address(self.nat_addr)
6874         flags = self.config_flags.NAT_IS_INSIDE
6875         self.vapi.nat44_interface_add_del_feature(
6876             sw_if_index=self.pg0.sw_if_index,
6877             flags=flags, is_add=1)
6878         self.vapi.nat44_interface_add_del_feature(
6879             sw_if_index=self.pg1.sw_if_index,
6880             is_add=1)
6881         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6882                                    tcp_transitory=240, icmp=5)
6883
6884         max_sessions = 1000
6885         pkts = []
6886         for i in range(0, max_sessions):
6887             src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6888             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6889                  IP(src=src, dst=self.pg1.remote_ip4) /
6890                  ICMP(id=1025, type='echo-request'))
6891             pkts.append(p)
6892         self.pg0.add_stream(pkts)
6893         self.pg_enable_capture(self.pg_interfaces)
6894         self.pg_start()
6895         self.pg1.get_capture(max_sessions)
6896
6897         sleep(10)
6898
6899         pkts = []
6900         for i in range(0, max_sessions):
6901             src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6902             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6903                  IP(src=src, dst=self.pg1.remote_ip4) /
6904                  ICMP(id=1026, type='echo-request'))
6905             pkts.append(p)
6906         self.pg0.add_stream(pkts)
6907         self.pg_enable_capture(self.pg_interfaces)
6908         self.pg_start()
6909         self.pg1.get_capture(max_sessions)
6910
6911         nsessions = 0
6912         users = self.vapi.nat44_user_dump()
6913         for user in users:
6914             nsessions = nsessions + user.nsessions
6915         self.assertLess(nsessions, 2 * max_sessions)
6916
6917     @unittest.skipUnless(running_extended_tests, "part of extended tests")
6918     def test_session_rst_timeout(self):
6919         """ NAT44 session RST timeouts """
6920         self.nat44_add_address(self.nat_addr)
6921         flags = self.config_flags.NAT_IS_INSIDE
6922         self.vapi.nat44_interface_add_del_feature(
6923             sw_if_index=self.pg0.sw_if_index,
6924             flags=flags, is_add=1)
6925         self.vapi.nat44_interface_add_del_feature(
6926             sw_if_index=self.pg1.sw_if_index,
6927             is_add=1)
6928         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6929                                    tcp_transitory=5, icmp=60)
6930
6931         self.initiate_tcp_session(self.pg0, self.pg1)
6932         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6933              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6934              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6935                  flags="R"))
6936         self.pg0.add_stream(p)
6937         self.pg_enable_capture(self.pg_interfaces)
6938         self.pg_start()
6939         self.pg1.get_capture(1)
6940
6941         sleep(6)
6942
6943         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6944              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6945              TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6946                  flags="S"))
6947         self.pg0.add_stream(p)
6948         self.pg_enable_capture(self.pg_interfaces)
6949         self.pg_start()
6950         self.pg1.get_capture(1)
6951
6952         nsessions = 0
6953         users = self.vapi.nat44_user_dump()
6954         self.assertEqual(len(users), 1)
6955         self.assertEqual(str(users[0].ip_address),
6956                          self.pg0.remote_ip4)
6957         self.assertEqual(users[0].nsessions, 1)
6958
6959     def test_syslog_sess(self):
6960         """ Test syslog session creation and deletion """
6961         self.vapi.syslog_set_filter(
6962             self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
6963         self.vapi.syslog_set_sender(self.pg2.local_ip4, self.pg2.remote_ip4)
6964         self.nat44_add_address(self.nat_addr)
6965         flags = self.config_flags.NAT_IS_INSIDE
6966         self.vapi.nat44_interface_add_del_feature(
6967             sw_if_index=self.pg0.sw_if_index,
6968             flags=flags, is_add=1)
6969         self.vapi.nat44_interface_add_del_feature(
6970             sw_if_index=self.pg1.sw_if_index,
6971             is_add=1)
6972
6973         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6974              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6975              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6976         self.pg0.add_stream(p)
6977         self.pg_enable_capture(self.pg_interfaces)
6978         self.pg_start()
6979         capture = self.pg1.get_capture(1)
6980         self.tcp_port_out = capture[0][TCP].sport
6981         capture = self.pg2.get_capture(1)
6982         self.verify_syslog_sess(capture[0][Raw].load)
6983
6984         self.pg_enable_capture(self.pg_interfaces)
6985         self.pg_start()
6986         self.nat44_add_address(self.nat_addr, is_add=0)
6987         capture = self.pg2.get_capture(1)
6988         self.verify_syslog_sess(capture[0][Raw].load, False)
6989
6990     def tearDown(self):
6991         super(TestNAT44EndpointDependent, self).tearDown()
6992         if not self.vpp_dead:
6993             self.clear_nat44()
6994             self.vapi.cli("clear logging")
6995
6996     def show_commands_at_teardown(self):
6997         self.logger.info(self.vapi.cli("show nat44 addresses"))
6998         self.logger.info(self.vapi.cli("show nat44 interfaces"))
6999         self.logger.info(self.vapi.cli("show nat44 static mappings"))
7000         self.logger.info(self.vapi.cli("show nat44 interface address"))
7001         self.logger.info(self.vapi.cli("show nat44 sessions detail"))
7002         self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
7003         self.logger.info(self.vapi.cli("show nat timeouts"))
7004
7005
7006 class TestNAT44Out2InDPO(MethodHolder):
7007     """ NAT44 Test Cases using out2in DPO """
7008
7009     @classmethod
7010     def setUpConstants(cls):
7011         super(TestNAT44Out2InDPO, cls).setUpConstants()
7012         cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
7013
7014     @classmethod
7015     def setUpClass(cls):
7016         super(TestNAT44Out2InDPO, cls).setUpClass()
7017         cls.vapi.cli("set log class nat level debug")
7018
7019         cls.tcp_port_in = 6303
7020         cls.tcp_port_out = 6303
7021         cls.udp_port_in = 6304
7022         cls.udp_port_out = 6304
7023         cls.icmp_id_in = 6305
7024         cls.icmp_id_out = 6305
7025         cls.nat_addr = '10.0.0.3'
7026         cls.dst_ip4 = '192.168.70.1'
7027
7028         cls.create_pg_interfaces(range(2))
7029
7030         cls.pg0.admin_up()
7031         cls.pg0.config_ip4()
7032         cls.pg0.resolve_arp()
7033
7034         cls.pg1.admin_up()
7035         cls.pg1.config_ip6()
7036         cls.pg1.resolve_ndp()
7037
7038         r1 = VppIpRoute(cls, "::", 0,
7039                         [VppRoutePath(cls.pg1.remote_ip6,
7040                                       cls.pg1.sw_if_index)],
7041                         register=False)
7042         r1.add_vpp_config()
7043
7044     @classmethod
7045     def tearDownClass(cls):
7046         super(TestNAT44Out2InDPO, cls).tearDownClass()
7047
7048     def configure_xlat(self):
7049         self.dst_ip6_pfx = '1:2:3::'
7050         self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
7051                                               self.dst_ip6_pfx)
7052         self.dst_ip6_pfx_len = 96
7053         self.src_ip6_pfx = '4:5:6::'
7054         self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
7055                                               self.src_ip6_pfx)
7056         self.src_ip6_pfx_len = 96
7057         self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
7058                                  self.src_ip6_pfx_n, self.src_ip6_pfx_len,
7059                                  '\x00\x00\x00\x00', 0)
7060
7061     @unittest.skip('Temporary disabled')
7062     def test_464xlat_ce(self):
7063         """ Test 464XLAT CE with NAT44 """
7064
7065         nat_config = self.vapi.nat_show_config()
7066         self.assertEqual(1, nat_config.out2in_dpo)
7067
7068         self.configure_xlat()
7069
7070         flags = self.config_flags.NAT_IS_INSIDE
7071         self.vapi.nat44_interface_add_del_feature(
7072             sw_if_index=self.pg0.sw_if_index,
7073             flags=flags, is_add=1)
7074         self.vapi.nat44_add_del_address_range(first_ip_address=self.nat_addr_n,
7075                                               last_ip_address=self.nat_addr_n,
7076                                               vrf_id=0xFFFFFFFF, is_add=1)
7077
7078         out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7079                                        self.dst_ip6_pfx_len)
7080         out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
7081                                        self.src_ip6_pfx_len)
7082
7083         try:
7084             pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7085             self.pg0.add_stream(pkts)
7086             self.pg_enable_capture(self.pg_interfaces)
7087             self.pg_start()
7088             capture = self.pg1.get_capture(len(pkts))
7089             self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
7090                                         dst_ip=out_src_ip6)
7091
7092             pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
7093                                               out_dst_ip6)
7094             self.pg1.add_stream(pkts)
7095             self.pg_enable_capture(self.pg_interfaces)
7096             self.pg_start()
7097             capture = self.pg0.get_capture(len(pkts))
7098             self.verify_capture_in(capture, self.pg0)
7099         finally:
7100             self.vapi.nat44_interface_add_del_feature(
7101                 sw_if_index=self.pg0.sw_if_index,
7102                 flags=flags)
7103             self.vapi.nat44_add_del_address_range(
7104                 first_ip_address=self.nat_addr_n,
7105                 last_ip_address=self.nat_addr_n,
7106                 vrf_id=0xFFFFFFFF)
7107
7108     @unittest.skip('Temporary disabled')
7109     def test_464xlat_ce_no_nat(self):
7110         """ Test 464XLAT CE without NAT44 """
7111
7112         self.configure_xlat()
7113
7114         out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7115                                        self.dst_ip6_pfx_len)
7116         out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
7117                                        self.src_ip6_pfx_len)
7118
7119         pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7120         self.pg0.add_stream(pkts)
7121         self.pg_enable_capture(self.pg_interfaces)
7122         self.pg_start()
7123         capture = self.pg1.get_capture(len(pkts))
7124         self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
7125                                     nat_ip=out_dst_ip6, same_port=True)
7126
7127         pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
7128         self.pg1.add_stream(pkts)
7129         self.pg_enable_capture(self.pg_interfaces)
7130         self.pg_start()
7131         capture = self.pg0.get_capture(len(pkts))
7132         self.verify_capture_in(capture, self.pg0)
7133
7134
7135 class TestDeterministicNAT(MethodHolder):
7136     """ Deterministic NAT Test Cases """
7137
7138     @classmethod
7139     def setUpConstants(cls):
7140         super(TestDeterministicNAT, cls).setUpConstants()
7141         cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
7142
7143     @classmethod
7144     def setUpClass(cls):
7145         super(TestDeterministicNAT, cls).setUpClass()
7146         cls.vapi.cli("set log class nat level debug")
7147
7148         cls.tcp_port_in = 6303
7149         cls.tcp_external_port = 6303
7150         cls.udp_port_in = 6304
7151         cls.udp_external_port = 6304
7152         cls.icmp_id_in = 6305
7153         cls.nat_addr = '10.0.0.3'
7154
7155         cls.create_pg_interfaces(range(3))
7156         cls.interfaces = list(cls.pg_interfaces)
7157
7158         for i in cls.interfaces:
7159             i.admin_up()
7160             i.config_ip4()
7161             i.resolve_arp()
7162
7163         cls.pg0.generate_remote_hosts(2)
7164         cls.pg0.configure_ipv4_neighbors()
7165
7166     @classmethod
7167     def tearDownClass(cls):
7168         super(TestDeterministicNAT, cls).tearDownClass()
7169
7170     def create_stream_in(self, in_if, out_if, ttl=64):
7171         """
7172         Create packet stream for inside network
7173
7174         :param in_if: Inside interface
7175         :param out_if: Outside interface
7176         :param ttl: TTL of generated packets
7177         """
7178         pkts = []
7179         # TCP
7180         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7181              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7182              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
7183         pkts.append(p)
7184
7185         # UDP
7186         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7187              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7188              UDP(sport=self.udp_port_in, dport=self.udp_external_port))
7189         pkts.append(p)
7190
7191         # ICMP
7192         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7193              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7194              ICMP(id=self.icmp_id_in, type='echo-request'))
7195         pkts.append(p)
7196
7197         return pkts
7198
7199     def create_stream_out(self, out_if, dst_ip=None, ttl=64):
7200         """
7201         Create packet stream for outside network
7202
7203         :param out_if: Outside interface
7204         :param dst_ip: Destination IP address (Default use global NAT address)
7205         :param ttl: TTL of generated packets
7206         """
7207         if dst_ip is None:
7208             dst_ip = self.nat_addr
7209         pkts = []
7210         # TCP
7211         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7212              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7213              TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
7214         pkts.append(p)
7215
7216         # UDP
7217         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7218              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7219              UDP(dport=self.udp_port_out, sport=self.udp_external_port))
7220         pkts.append(p)
7221
7222         # ICMP
7223         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7224              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7225              ICMP(id=self.icmp_external_id, type='echo-reply'))
7226         pkts.append(p)
7227
7228         return pkts
7229
7230     def verify_capture_out(self, capture, nat_ip=None):
7231         """
7232         Verify captured packets on outside network
7233
7234         :param capture: Captured packets
7235         :param nat_ip: Translated IP address (Default use global NAT address)
7236         :param same_port: Source port number is not translated (Default False)
7237         """
7238         if nat_ip is None:
7239             nat_ip = self.nat_addr
7240         for packet in capture:
7241             try:
7242                 self.assertEqual(packet[IP].src, nat_ip)
7243                 if packet.haslayer(TCP):
7244                     self.tcp_port_out = packet[TCP].sport
7245                 elif packet.haslayer(UDP):
7246                     self.udp_port_out = packet[UDP].sport
7247                 else:
7248                     self.icmp_external_id = packet[ICMP].id
7249             except:
7250                 self.logger.error(ppp("Unexpected or invalid packet "
7251                                       "(outside network):", packet))
7252                 raise
7253
7254     def test_deterministic_mode(self):
7255         """ NAT plugin run deterministic mode """
7256         in_addr = '172.16.255.0'
7257         out_addr = '172.17.255.50'
7258         in_addr_t = '172.16.255.20'
7259         in_plen = 24
7260         out_plen = 32
7261
7262         nat_config = self.vapi.nat_show_config()
7263         self.assertEqual(1, nat_config.deterministic)
7264
7265         self.vapi.nat_det_add_del_map(is_add=1, in_addr=in_addr,
7266                                       in_plen=in_plen, out_addr=out_addr,
7267                                       out_plen=out_plen)
7268
7269         rep1 = self.vapi.nat_det_forward(in_addr_t)
7270         self.assertEqual(str(rep1.out_addr), out_addr)
7271         rep2 = self.vapi.nat_det_reverse(rep1.out_port_hi, out_addr)
7272
7273         self.assertEqual(str(rep2.in_addr), in_addr_t)
7274
7275         deterministic_mappings = self.vapi.nat_det_map_dump()
7276         self.assertEqual(len(deterministic_mappings), 1)
7277         dsm = deterministic_mappings[0]
7278         self.assertEqual(in_addr, str(dsm.in_addr))
7279         self.assertEqual(in_plen, dsm.in_plen)
7280         self.assertEqual(out_addr, str(dsm.out_addr))
7281         self.assertEqual(out_plen, dsm.out_plen)
7282
7283         self.clear_nat_det()
7284         deterministic_mappings = self.vapi.nat_det_map_dump()
7285         self.assertEqual(len(deterministic_mappings), 0)
7286
7287     def test_set_timeouts(self):
7288         """ Set deterministic NAT timeouts """
7289         timeouts_before = self.vapi.nat_get_timeouts()
7290
7291         self.vapi.nat_set_timeouts(
7292             udp=timeouts_before.udp + 10,
7293             tcp_established=timeouts_before.tcp_established + 10,
7294             tcp_transitory=timeouts_before.tcp_transitory + 10,
7295             icmp=timeouts_before.icmp + 10)
7296
7297         timeouts_after = self.vapi.nat_get_timeouts()
7298
7299         self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
7300         self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
7301         self.assertNotEqual(timeouts_before.tcp_established,
7302                             timeouts_after.tcp_established)
7303         self.assertNotEqual(timeouts_before.tcp_transitory,
7304                             timeouts_after.tcp_transitory)
7305
7306     def test_det_in(self):
7307         """ Deterministic NAT translation test (TCP, UDP, ICMP) """
7308
7309         nat_ip = "10.0.0.10"
7310
7311         self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7312                                       in_plen=32,
7313                                       out_addr=socket.inet_aton(nat_ip),
7314                                       out_plen=32)
7315
7316         flags = self.config_flags.NAT_IS_INSIDE
7317         self.vapi.nat44_interface_add_del_feature(
7318             sw_if_index=self.pg0.sw_if_index,
7319             flags=flags, is_add=1)
7320         self.vapi.nat44_interface_add_del_feature(
7321             sw_if_index=self.pg1.sw_if_index,
7322             is_add=1)
7323
7324         # in2out
7325         pkts = self.create_stream_in(self.pg0, self.pg1)
7326         self.pg0.add_stream(pkts)
7327         self.pg_enable_capture(self.pg_interfaces)
7328         self.pg_start()
7329         capture = self.pg1.get_capture(len(pkts))
7330         self.verify_capture_out(capture, nat_ip)
7331
7332         # out2in
7333         pkts = self.create_stream_out(self.pg1, nat_ip)
7334         self.pg1.add_stream(pkts)
7335         self.pg_enable_capture(self.pg_interfaces)
7336         self.pg_start()
7337         capture = self.pg0.get_capture(len(pkts))
7338         self.verify_capture_in(capture, self.pg0)
7339
7340         # session dump test
7341         sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4)
7342         self.assertEqual(len(sessions), 3)
7343
7344         # TCP session
7345         s = sessions[0]
7346         self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7347         self.assertEqual(s.in_port, self.tcp_port_in)
7348         self.assertEqual(s.out_port, self.tcp_port_out)
7349         self.assertEqual(s.ext_port, self.tcp_external_port)
7350
7351         # UDP session
7352         s = sessions[1]
7353         self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7354         self.assertEqual(s.in_port, self.udp_port_in)
7355         self.assertEqual(s.out_port, self.udp_port_out)
7356         self.assertEqual(s.ext_port, self.udp_external_port)
7357
7358         # ICMP session
7359         s = sessions[2]
7360         self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7361         self.assertEqual(s.in_port, self.icmp_id_in)
7362         self.assertEqual(s.out_port, self.icmp_external_id)
7363
7364     def test_multiple_users(self):
7365         """ Deterministic NAT multiple users """
7366
7367         nat_ip = "10.0.0.10"
7368         port_in = 80
7369         external_port = 6303
7370
7371         host0 = self.pg0.remote_hosts[0]
7372         host1 = self.pg0.remote_hosts[1]
7373
7374         self.vapi.nat_det_add_del_map(is_add=1, in_addr=host0.ip4, in_plen=24,
7375                                       out_addr=socket.inet_aton(nat_ip),
7376                                       out_plen=32)
7377         flags = self.config_flags.NAT_IS_INSIDE
7378         self.vapi.nat44_interface_add_del_feature(
7379             sw_if_index=self.pg0.sw_if_index,
7380             flags=flags, is_add=1)
7381         self.vapi.nat44_interface_add_del_feature(
7382             sw_if_index=self.pg1.sw_if_index,
7383             is_add=1)
7384
7385         # host0 to out
7386         p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
7387              IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
7388              TCP(sport=port_in, dport=external_port))
7389         self.pg0.add_stream(p)
7390         self.pg_enable_capture(self.pg_interfaces)
7391         self.pg_start()
7392         capture = self.pg1.get_capture(1)
7393         p = capture[0]
7394         try:
7395             ip = p[IP]
7396             tcp = p[TCP]
7397             self.assertEqual(ip.src, nat_ip)
7398             self.assertEqual(ip.dst, self.pg1.remote_ip4)
7399             self.assertEqual(tcp.dport, external_port)
7400             port_out0 = tcp.sport
7401         except:
7402             self.logger.error(ppp("Unexpected or invalid packet:", p))
7403             raise
7404
7405         # host1 to out
7406         p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
7407              IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
7408              TCP(sport=port_in, dport=external_port))
7409         self.pg0.add_stream(p)
7410         self.pg_enable_capture(self.pg_interfaces)
7411         self.pg_start()
7412         capture = self.pg1.get_capture(1)
7413         p = capture[0]
7414         try:
7415             ip = p[IP]
7416             tcp = p[TCP]
7417             self.assertEqual(ip.src, nat_ip)
7418             self.assertEqual(ip.dst, self.pg1.remote_ip4)
7419             self.assertEqual(tcp.dport, external_port)
7420             port_out1 = tcp.sport
7421         except:
7422             self.logger.error(ppp("Unexpected or invalid packet:", p))
7423             raise
7424
7425         dms = self.vapi.nat_det_map_dump()
7426         self.assertEqual(1, len(dms))
7427         self.assertEqual(2, dms[0].ses_num)
7428
7429         # out to host0
7430         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7431              IP(src=self.pg1.remote_ip4, dst=nat_ip) /
7432              TCP(sport=external_port, dport=port_out0))
7433         self.pg1.add_stream(p)
7434         self.pg_enable_capture(self.pg_interfaces)
7435         self.pg_start()
7436         capture = self.pg0.get_capture(1)
7437         p = capture[0]
7438         try:
7439             ip = p[IP]
7440             tcp = p[TCP]
7441             self.assertEqual(ip.src, self.pg1.remote_ip4)
7442             self.assertEqual(ip.dst, host0.ip4)
7443             self.assertEqual(tcp.dport, port_in)
7444             self.assertEqual(tcp.sport, external_port)
7445         except:
7446             self.logger.error(ppp("Unexpected or invalid packet:", p))
7447             raise
7448
7449         # out to host1
7450         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7451              IP(src=self.pg1.remote_ip4, dst=nat_ip) /
7452              TCP(sport=external_port, dport=port_out1))
7453         self.pg1.add_stream(p)
7454         self.pg_enable_capture(self.pg_interfaces)
7455         self.pg_start()
7456         capture = self.pg0.get_capture(1)
7457         p = capture[0]
7458         try:
7459             ip = p[IP]
7460             tcp = p[TCP]
7461             self.assertEqual(ip.src, self.pg1.remote_ip4)
7462             self.assertEqual(ip.dst, host1.ip4)
7463             self.assertEqual(tcp.dport, port_in)
7464             self.assertEqual(tcp.sport, external_port)
7465         except:
7466             self.logger.error(ppp("Unexpected or invalid packet", p))
7467             raise
7468
7469         # session close api test
7470         self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
7471                                             port_out1,
7472                                             self.pg1.remote_ip4,
7473                                             external_port)
7474         dms = self.vapi.nat_det_map_dump()
7475         self.assertEqual(dms[0].ses_num, 1)
7476
7477         self.vapi.nat_det_close_session_in(host0.ip4,
7478                                            port_in,
7479                                            self.pg1.remote_ip4,
7480                                            external_port)
7481         dms = self.vapi.nat_det_map_dump()
7482         self.assertEqual(dms[0].ses_num, 0)
7483
7484     def test_tcp_session_close_detection_in(self):
7485         """ Deterministic NAT TCP session close from inside network """
7486         self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7487                                       in_plen=32,
7488                                       out_addr=socket.inet_aton(self.nat_addr),
7489                                       out_plen=32)
7490         flags = self.config_flags.NAT_IS_INSIDE
7491         self.vapi.nat44_interface_add_del_feature(
7492             sw_if_index=self.pg0.sw_if_index,
7493             flags=flags, is_add=1)
7494         self.vapi.nat44_interface_add_del_feature(
7495             sw_if_index=self.pg1.sw_if_index,
7496             is_add=1)
7497
7498         self.initiate_tcp_session(self.pg0, self.pg1)
7499
7500         # close the session from inside
7501         try:
7502             # FIN packet in -> out
7503             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7504                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7505                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7506                      flags="F"))
7507             self.pg0.add_stream(p)
7508             self.pg_enable_capture(self.pg_interfaces)
7509             self.pg_start()
7510             self.pg1.get_capture(1)
7511
7512             pkts = []
7513
7514             # ACK packet out -> in
7515             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7516                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7517                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7518                      flags="A"))
7519             pkts.append(p)
7520
7521             # FIN packet out -> in
7522             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7523                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7524                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7525                      flags="F"))
7526             pkts.append(p)
7527
7528             self.pg1.add_stream(pkts)
7529             self.pg_enable_capture(self.pg_interfaces)
7530             self.pg_start()
7531             self.pg0.get_capture(2)
7532
7533             # ACK packet in -> out
7534             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7535                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7536                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7537                      flags="A"))
7538             self.pg0.add_stream(p)
7539             self.pg_enable_capture(self.pg_interfaces)
7540             self.pg_start()
7541             self.pg1.get_capture(1)
7542
7543             # Check if deterministic NAT44 closed the session
7544             dms = self.vapi.nat_det_map_dump()
7545             self.assertEqual(0, dms[0].ses_num)
7546         except:
7547             self.logger.error("TCP session termination failed")
7548             raise
7549
7550     def test_tcp_session_close_detection_out(self):
7551         """ Deterministic NAT TCP session close from outside network """
7552         self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7553                                       in_plen=32,
7554                                       out_addr=socket.inet_aton(self.nat_addr),
7555                                       out_plen=32)
7556         flags = self.config_flags.NAT_IS_INSIDE
7557         self.vapi.nat44_interface_add_del_feature(
7558             sw_if_index=self.pg0.sw_if_index,
7559             flags=flags, is_add=1)
7560         self.vapi.nat44_interface_add_del_feature(
7561             sw_if_index=self.pg1.sw_if_index,
7562             is_add=1)
7563
7564         self.initiate_tcp_session(self.pg0, self.pg1)
7565
7566         # close the session from outside
7567         try:
7568             # FIN packet out -> in
7569             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7570                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7571                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7572                      flags="F"))
7573             self.pg1.add_stream(p)
7574             self.pg_enable_capture(self.pg_interfaces)
7575             self.pg_start()
7576             self.pg0.get_capture(1)
7577
7578             pkts = []
7579
7580             # ACK packet in -> out
7581             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7582                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7583                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7584                      flags="A"))
7585             pkts.append(p)
7586
7587             # ACK packet in -> out
7588             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7589                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7590                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7591                      flags="F"))
7592             pkts.append(p)
7593
7594             self.pg0.add_stream(pkts)
7595             self.pg_enable_capture(self.pg_interfaces)
7596             self.pg_start()
7597             self.pg1.get_capture(2)
7598
7599             # ACK packet out -> in
7600             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7601                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7602                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7603                      flags="A"))
7604             self.pg1.add_stream(p)
7605             self.pg_enable_capture(self.pg_interfaces)
7606             self.pg_start()
7607             self.pg0.get_capture(1)
7608
7609             # Check if deterministic NAT44 closed the session
7610             dms = self.vapi.nat_det_map_dump()
7611             self.assertEqual(0, dms[0].ses_num)
7612         except:
7613             self.logger.error("TCP session termination failed")
7614             raise
7615
7616     @unittest.skipUnless(running_extended_tests, "part of extended tests")
7617     def test_session_timeout(self):
7618         """ Deterministic NAT session timeouts """
7619         self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7620                                       in_plen=32,
7621                                       out_addr=socket.inet_aton(self.nat_addr),
7622                                       out_plen=32)
7623         flags = self.config_flags.NAT_IS_INSIDE
7624         self.vapi.nat44_interface_add_del_feature(
7625             sw_if_index=self.pg0.sw_if_index,
7626             flags=flags, is_add=1)
7627         self.vapi.nat44_interface_add_del_feature(
7628             sw_if_index=self.pg1.sw_if_index,
7629             is_add=1)
7630
7631         self.initiate_tcp_session(self.pg0, self.pg1)
7632         self.vapi.nat_set_timeouts(udp=5, tcp_established=5, tcp_transitory=5,
7633                                    icmp=5)
7634         pkts = self.create_stream_in(self.pg0, self.pg1)
7635         self.pg0.add_stream(pkts)
7636         self.pg_enable_capture(self.pg_interfaces)
7637         self.pg_start()
7638         capture = self.pg1.get_capture(len(pkts))
7639         sleep(15)
7640
7641         dms = self.vapi.nat_det_map_dump()
7642         self.assertEqual(0, dms[0].ses_num)
7643
7644     @unittest.skipUnless(running_extended_tests, "part of extended tests")
7645     def test_session_limit_per_user(self):
7646         """ Deterministic NAT maximum sessions per user limit """
7647         self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7648                                       in_plen=32,
7649                                       out_addr=socket.inet_aton(self.nat_addr),
7650                                       out_plen=32)
7651         flags = self.config_flags.NAT_IS_INSIDE
7652         self.vapi.nat44_interface_add_del_feature(
7653             sw_if_index=self.pg0.sw_if_index,
7654             flags=flags, is_add=1)
7655         self.vapi.nat44_interface_add_del_feature(
7656             sw_if_index=self.pg1.sw_if_index,
7657             is_add=1)
7658         self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4,
7659                                      src_address=self.pg2.local_ip4,
7660                                      path_mtu=512,
7661                                      template_interval=10)
7662         self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7663                                            enable=1)
7664
7665         pkts = []
7666         for port in range(1025, 2025):
7667             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7668                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7669                  UDP(sport=port, dport=port))
7670             pkts.append(p)
7671
7672         self.pg0.add_stream(pkts)
7673         self.pg_enable_capture(self.pg_interfaces)
7674         self.pg_start()
7675         capture = self.pg1.get_capture(len(pkts))
7676
7677         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7678              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7679              UDP(sport=3001, dport=3002))
7680         self.pg0.add_stream(p)
7681         self.pg_enable_capture(self.pg_interfaces)
7682         self.pg_start()
7683         capture = self.pg1.assert_nothing_captured()
7684
7685         # verify ICMP error packet
7686         capture = self.pg0.get_capture(1)
7687         p = capture[0]
7688         self.assertTrue(p.haslayer(ICMP))
7689         icmp = p[ICMP]
7690         self.assertEqual(icmp.type, 3)
7691         self.assertEqual(icmp.code, 1)
7692         self.assertTrue(icmp.haslayer(IPerror))
7693         inner_ip = icmp[IPerror]
7694         self.assertEqual(inner_ip[UDPerror].sport, 3001)
7695         self.assertEqual(inner_ip[UDPerror].dport, 3002)
7696
7697         dms = self.vapi.nat_det_map_dump()
7698
7699         self.assertEqual(1000, dms[0].ses_num)
7700
7701         # verify IPFIX logging
7702         self.vapi.ipfix_flush()
7703         sleep(1)
7704         capture = self.pg2.get_capture(2)
7705         ipfix = IPFIXDecoder()
7706         # first load template
7707         for p in capture:
7708             self.assertTrue(p.haslayer(IPFIX))
7709             if p.haslayer(Template):
7710                 ipfix.add_template(p.getlayer(Template))
7711         # verify events in data set
7712         for p in capture:
7713             if p.haslayer(Data):
7714                 data = ipfix.decode_data_set(p.getlayer(Set))
7715                 self.verify_ipfix_max_entries_per_user(data,
7716                                                        1000,
7717                                                        self.pg0.remote_ip4)
7718
7719     def clear_nat_det(self):
7720         """
7721         Clear deterministic NAT configuration.
7722         """
7723         self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7724                                            enable=0)
7725         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
7726                                    tcp_transitory=240, icmp=60)
7727         deterministic_mappings = self.vapi.nat_det_map_dump()
7728         for dsm in deterministic_mappings:
7729             self.vapi.nat_det_add_del_map(is_add=0, in_addr=dsm.in_addr,
7730                                           in_plen=dsm.in_plen,
7731                                           out_addr=dsm.out_addr,
7732                                           out_plen=dsm.out_plen)
7733
7734         interfaces = self.vapi.nat44_interface_dump()
7735         for intf in interfaces:
7736             self.vapi.nat44_interface_add_del_feature(
7737                 sw_if_index=intf.sw_if_index,
7738                 flags=intf.flags)
7739
7740     def tearDown(self):
7741         super(TestDeterministicNAT, self).tearDown()
7742         if not self.vpp_dead:
7743             self.clear_nat_det()
7744
7745     def show_commands_at_teardown(self):
7746         self.logger.info(self.vapi.cli("show nat44 interfaces"))
7747         self.logger.info(self.vapi.cli("show nat timeouts"))
7748         self.logger.info(
7749             self.vapi.cli("show nat44 deterministic mappings"))
7750         self.logger.info(
7751             self.vapi.cli("show nat44 deterministic sessions"))
7752
7753
7754 class TestNAT64(MethodHolder):
7755     """ NAT64 Test Cases """
7756
7757     @classmethod
7758     def setUpConstants(cls):
7759         super(TestNAT64, cls).setUpConstants()
7760         cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
7761                                 "nat64 st hash buckets 256", "}"])
7762
7763     @classmethod
7764     def setUpClass(cls):
7765         super(TestNAT64, cls).setUpClass()
7766
7767         cls.tcp_port_in = 6303
7768         cls.tcp_port_out = 6303
7769         cls.udp_port_in = 6304
7770         cls.udp_port_out = 6304
7771         cls.icmp_id_in = 6305
7772         cls.icmp_id_out = 6305
7773         cls.tcp_external_port = 80
7774         cls.nat_addr = '10.0.0.3'
7775         cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
7776         cls.vrf1_id = 10
7777         cls.vrf1_nat_addr = '10.0.10.3'
7778         cls.ipfix_src_port = 4739
7779         cls.ipfix_domain_id = 1
7780
7781         cls.create_pg_interfaces(range(6))
7782         cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
7783         cls.ip6_interfaces.append(cls.pg_interfaces[2])
7784         cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
7785
7786         cls.vapi.ip_table_add_del(is_add=1,
7787                                   table={'table_id': cls.vrf1_id,
7788                                          'is_ip6': 1})
7789
7790         cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
7791
7792         cls.pg0.generate_remote_hosts(2)
7793
7794         for i in cls.ip6_interfaces:
7795             i.admin_up()
7796             i.config_ip6()
7797             i.configure_ipv6_neighbors()
7798
7799         for i in cls.ip4_interfaces:
7800             i.admin_up()
7801             i.config_ip4()
7802             i.resolve_arp()
7803
7804         cls.pg3.admin_up()
7805         cls.pg3.config_ip4()
7806         cls.pg3.resolve_arp()
7807         cls.pg3.config_ip6()
7808         cls.pg3.configure_ipv6_neighbors()
7809
7810         cls.pg5.admin_up()
7811         cls.pg5.config_ip6()
7812
7813     @classmethod
7814     def tearDownClass(cls):
7815         super(TestNAT64, cls).tearDownClass()
7816
7817     def test_nat64_inside_interface_handles_neighbor_advertisement(self):
7818         """ NAT64 inside interface handles Neighbor Advertisement """
7819
7820         flags = self.config_flags.NAT_IS_INSIDE
7821         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7822                                           sw_if_index=self.pg5.sw_if_index)
7823
7824         # Try to send ping
7825         ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7826                 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7827                 ICMPv6EchoRequest())
7828         pkts = [ping]
7829         self.pg5.add_stream(pkts)
7830         self.pg_enable_capture(self.pg_interfaces)
7831         self.pg_start()
7832
7833         # Wait for Neighbor Solicitation
7834         capture = self.pg5.get_capture(len(pkts))
7835         packet = capture[0]
7836         try:
7837             self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7838             self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
7839             tgt = packet[ICMPv6ND_NS].tgt
7840         except:
7841             self.logger.error(ppp("Unexpected or invalid packet:", packet))
7842             raise
7843
7844         # Send Neighbor Advertisement
7845         p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7846              IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7847              ICMPv6ND_NA(tgt=tgt) /
7848              ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
7849         pkts = [p]
7850         self.pg5.add_stream(pkts)
7851         self.pg_enable_capture(self.pg_interfaces)
7852         self.pg_start()
7853
7854         # Try to send ping again
7855         pkts = [ping]
7856         self.pg5.add_stream(pkts)
7857         self.pg_enable_capture(self.pg_interfaces)
7858         self.pg_start()
7859
7860         # Wait for ping reply
7861         capture = self.pg5.get_capture(len(pkts))
7862         packet = capture[0]
7863         try:
7864             self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7865             self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
7866             self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
7867         except:
7868             self.logger.error(ppp("Unexpected or invalid packet:", packet))
7869             raise
7870
7871     def test_pool(self):
7872         """ Add/delete address to NAT64 pool """
7873         nat_addr = '1.2.3.4'
7874
7875         self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7876                                                 end_addr=nat_addr,
7877                                                 vrf_id=0xFFFFFFFF, is_add=1)
7878
7879         addresses = self.vapi.nat64_pool_addr_dump()
7880         self.assertEqual(len(addresses), 1)
7881         self.assertEqual(str(addresses[0].address), nat_addr)
7882
7883         self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7884                                                 end_addr=nat_addr,
7885                                                 vrf_id=0xFFFFFFFF, is_add=0)
7886
7887         addresses = self.vapi.nat64_pool_addr_dump()
7888         self.assertEqual(len(addresses), 0)
7889
7890     def test_interface(self):
7891         """ Enable/disable NAT64 feature on the interface """
7892         flags = self.config_flags.NAT_IS_INSIDE
7893         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7894                                           sw_if_index=self.pg0.sw_if_index)
7895         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7896                                           sw_if_index=self.pg1.sw_if_index)
7897
7898         interfaces = self.vapi.nat64_interface_dump()
7899         self.assertEqual(len(interfaces), 2)
7900         pg0_found = False
7901         pg1_found = False
7902         for intf in interfaces:
7903             if intf.sw_if_index == self.pg0.sw_if_index:
7904                 self.assertEqual(intf.flags, self.config_flags.NAT_IS_INSIDE)
7905                 pg0_found = True
7906             elif intf.sw_if_index == self.pg1.sw_if_index:
7907                 self.assertEqual(intf.flags, self.config_flags.NAT_IS_OUTSIDE)
7908                 pg1_found = True
7909         self.assertTrue(pg0_found)
7910         self.assertTrue(pg1_found)
7911
7912         features = self.vapi.cli("show interface features pg0")
7913         self.assertIn('nat64-in2out', features)
7914         features = self.vapi.cli("show interface features pg1")
7915         self.assertIn('nat64-out2in', features)
7916
7917         self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7918                                           sw_if_index=self.pg0.sw_if_index)
7919         self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7920                                           sw_if_index=self.pg1.sw_if_index)
7921
7922         interfaces = self.vapi.nat64_interface_dump()
7923         self.assertEqual(len(interfaces), 0)
7924
7925     def test_static_bib(self):
7926         """ Add/delete static BIB entry """
7927         in_addr = '2001:db8:85a3::8a2e:370:7334'
7928         out_addr = '10.1.1.3'
7929         in_port = 1234
7930         out_port = 5678
7931         proto = IP_PROTOS.tcp
7932
7933         self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7934                                            i_port=in_port, o_port=out_port,
7935                                            proto=proto, vrf_id=0, is_add=1)
7936         bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
7937         static_bib_num = 0
7938         for bibe in bib:
7939             if bibe.flags & self.config_flags.NAT_IS_STATIC:
7940                 static_bib_num += 1
7941                 self.assertEqual(str(bibe.i_addr), in_addr)
7942                 self.assertEqual(str(bibe.o_addr), out_addr)
7943                 self.assertEqual(bibe.i_port, in_port)
7944                 self.assertEqual(bibe.o_port, out_port)
7945         self.assertEqual(static_bib_num, 1)
7946         bibs = self.statistics.get_counter('/nat64/total-bibs')
7947         self.assertEqual(bibs[0][0], 1)
7948
7949         self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7950                                            i_port=in_port, o_port=out_port,
7951                                            proto=proto, vrf_id=0, is_add=0)
7952         bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
7953         static_bib_num = 0
7954         for bibe in bib:
7955             if bibe.flags & self.config_flags.NAT_IS_STATIC:
7956                 static_bib_num += 1
7957         self.assertEqual(static_bib_num, 0)
7958         bibs = self.statistics.get_counter('/nat64/total-bibs')
7959         self.assertEqual(bibs[0][0], 0)
7960
7961     def test_set_timeouts(self):
7962         """ Set NAT64 timeouts """
7963         # verify default values
7964         timeouts = self.vapi.nat_get_timeouts()
7965         self.assertEqual(timeouts.udp, 300)
7966         self.assertEqual(timeouts.icmp, 60)
7967         self.assertEqual(timeouts.tcp_transitory, 240)
7968         self.assertEqual(timeouts.tcp_established, 7440)
7969
7970         # set and verify custom values
7971         self.vapi.nat_set_timeouts(udp=200, tcp_established=7450,
7972                                    tcp_transitory=250, icmp=30)
7973         timeouts = self.vapi.nat_get_timeouts()
7974         self.assertEqual(timeouts.udp, 200)
7975         self.assertEqual(timeouts.icmp, 30)
7976         self.assertEqual(timeouts.tcp_transitory, 250)
7977         self.assertEqual(timeouts.tcp_established, 7450)
7978
7979     def test_dynamic(self):
7980         """ NAT64 dynamic translation test """
7981         self.tcp_port_in = 6303
7982         self.udp_port_in = 6304
7983         self.icmp_id_in = 6305
7984
7985         ses_num_start = self.nat64_get_ses_num()
7986
7987         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
7988                                                 end_addr=self.nat_addr,
7989                                                 vrf_id=0xFFFFFFFF,
7990                                                 is_add=1)
7991         flags = self.config_flags.NAT_IS_INSIDE
7992         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7993                                           sw_if_index=self.pg0.sw_if_index)
7994         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7995                                           sw_if_index=self.pg1.sw_if_index)
7996
7997         # in2out
7998         tcpn = self.statistics.get_err_counter('/err/nat64-in2out/TCP packets')
7999         udpn = self.statistics.get_err_counter('/err/nat64-in2out/UDP packets')
8000         icmpn = self.statistics.get_err_counter(
8001             '/err/nat64-in2out/ICMP packets')
8002         totaln = self.statistics.get_err_counter(
8003             '/err/nat64-in2out/good in2out packets processed')
8004
8005         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8006         self.pg0.add_stream(pkts)
8007         self.pg_enable_capture(self.pg_interfaces)
8008         self.pg_start()
8009         capture = self.pg1.get_capture(len(pkts))
8010         self.verify_capture_out(capture, nat_ip=self.nat_addr,
8011                                 dst_ip=self.pg1.remote_ip4)
8012
8013         err = self.statistics.get_err_counter('/err/nat64-in2out/TCP packets')
8014         self.assertEqual(err - tcpn, 1)
8015         err = self.statistics.get_err_counter('/err/nat64-in2out/UDP packets')
8016         self.assertEqual(err - udpn, 1)
8017         err = self.statistics.get_err_counter('/err/nat64-in2out/ICMP packets')
8018         self.assertEqual(err - icmpn, 1)
8019         err = self.statistics.get_err_counter(
8020             '/err/nat64-in2out/good in2out packets processed')
8021         self.assertEqual(err - totaln, 3)
8022
8023         # out2in
8024         tcpn = self.statistics.get_err_counter('/err/nat64-out2in/TCP packets')
8025         udpn = self.statistics.get_err_counter('/err/nat64-out2in/UDP packets')
8026         icmpn = self.statistics.get_err_counter(
8027             '/err/nat64-out2in/ICMP packets')
8028         totaln = self.statistics.get_err_counter(
8029             '/err/nat64-out2in/good out2in packets processed')
8030
8031         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8032         self.pg1.add_stream(pkts)
8033         self.pg_enable_capture(self.pg_interfaces)
8034         self.pg_start()
8035         capture = self.pg0.get_capture(len(pkts))
8036         ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8037         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8038
8039         err = self.statistics.get_err_counter('/err/nat64-out2in/TCP packets')
8040         self.assertEqual(err - tcpn, 2)
8041         err = self.statistics.get_err_counter('/err/nat64-out2in/UDP packets')
8042         self.assertEqual(err - udpn, 1)
8043         err = self.statistics.get_err_counter('/err/nat64-out2in/ICMP packets')
8044         self.assertEqual(err - icmpn, 1)
8045         err = self.statistics.get_err_counter(
8046             '/err/nat64-out2in/good out2in packets processed')
8047         self.assertEqual(err - totaln, 4)
8048
8049         bibs = self.statistics.get_counter('/nat64/total-bibs')
8050         self.assertEqual(bibs[0][0], 3)
8051         sessions = self.statistics.get_counter('/nat64/total-sessions')
8052         self.assertEqual(sessions[0][0], 3)
8053
8054         # in2out
8055         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8056         self.pg0.add_stream(pkts)
8057         self.pg_enable_capture(self.pg_interfaces)
8058         self.pg_start()
8059         capture = self.pg1.get_capture(len(pkts))
8060         self.verify_capture_out(capture, nat_ip=self.nat_addr,
8061                                 dst_ip=self.pg1.remote_ip4)
8062
8063         # out2in
8064         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8065         self.pg1.add_stream(pkts)
8066         self.pg_enable_capture(self.pg_interfaces)
8067         self.pg_start()
8068         capture = self.pg0.get_capture(len(pkts))
8069         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8070
8071         ses_num_end = self.nat64_get_ses_num()
8072
8073         self.assertEqual(ses_num_end - ses_num_start, 3)
8074
8075         # tenant with specific VRF
8076         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
8077                                                 end_addr=self.vrf1_nat_addr,
8078                                                 vrf_id=self.vrf1_id, is_add=1)
8079         flags = self.config_flags.NAT_IS_INSIDE
8080         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8081                                           sw_if_index=self.pg2.sw_if_index)
8082
8083         pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
8084         self.pg2.add_stream(pkts)
8085         self.pg_enable_capture(self.pg_interfaces)
8086         self.pg_start()
8087         capture = self.pg1.get_capture(len(pkts))
8088         self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
8089                                 dst_ip=self.pg1.remote_ip4)
8090
8091         pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
8092         self.pg1.add_stream(pkts)
8093         self.pg_enable_capture(self.pg_interfaces)
8094         self.pg_start()
8095         capture = self.pg2.get_capture(len(pkts))
8096         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
8097
8098     def test_static(self):
8099         """ NAT64 static translation test """
8100         self.tcp_port_in = 60303
8101         self.udp_port_in = 60304
8102         self.icmp_id_in = 60305
8103         self.tcp_port_out = 60303
8104         self.udp_port_out = 60304
8105         self.icmp_id_out = 60305
8106
8107         ses_num_start = self.nat64_get_ses_num()
8108
8109         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8110                                                 end_addr=self.nat_addr,
8111                                                 vrf_id=0xFFFFFFFF,
8112                                                 is_add=1)
8113         flags = self.config_flags.NAT_IS_INSIDE
8114         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8115                                           sw_if_index=self.pg0.sw_if_index)
8116         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8117                                           sw_if_index=self.pg1.sw_if_index)
8118
8119         self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8120                                            o_addr=self.nat_addr,
8121                                            i_port=self.tcp_port_in,
8122                                            o_port=self.tcp_port_out,
8123                                            proto=IP_PROTOS.tcp, vrf_id=0,
8124                                            is_add=1)
8125         self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8126                                            o_addr=self.nat_addr,
8127                                            i_port=self.udp_port_in,
8128                                            o_port=self.udp_port_out,
8129                                            proto=IP_PROTOS.udp, vrf_id=0,
8130                                            is_add=1)
8131         self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8132                                            o_addr=self.nat_addr,
8133                                            i_port=self.icmp_id_in,
8134                                            o_port=self.icmp_id_out,
8135                                            proto=IP_PROTOS.icmp, vrf_id=0,
8136                                            is_add=1)
8137
8138         # in2out
8139         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8140         self.pg0.add_stream(pkts)
8141         self.pg_enable_capture(self.pg_interfaces)
8142         self.pg_start()
8143         capture = self.pg1.get_capture(len(pkts))
8144         self.verify_capture_out(capture, nat_ip=self.nat_addr,
8145                                 dst_ip=self.pg1.remote_ip4, same_port=True)
8146
8147         # out2in
8148         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8149         self.pg1.add_stream(pkts)
8150         self.pg_enable_capture(self.pg_interfaces)
8151         self.pg_start()
8152         capture = self.pg0.get_capture(len(pkts))
8153         ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8154         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8155
8156         ses_num_end = self.nat64_get_ses_num()
8157
8158         self.assertEqual(ses_num_end - ses_num_start, 3)
8159
8160     @unittest.skipUnless(running_extended_tests, "part of extended tests")
8161     def test_session_timeout(self):
8162         """ NAT64 session timeout """
8163         self.icmp_id_in = 1234
8164         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8165                                                 end_addr=self.nat_addr,
8166                                                 vrf_id=0xFFFFFFFF,
8167                                                 is_add=1)
8168         flags = self.config_flags.NAT_IS_INSIDE
8169         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8170                                           sw_if_index=self.pg0.sw_if_index)
8171         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8172                                           sw_if_index=self.pg1.sw_if_index)
8173         self.vapi.nat_set_timeouts(udp=300, tcp_established=5,
8174                                    tcp_transitory=5,
8175                                    icmp=5)
8176
8177         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8178         self.pg0.add_stream(pkts)
8179         self.pg_enable_capture(self.pg_interfaces)
8180         self.pg_start()
8181         capture = self.pg1.get_capture(len(pkts))
8182
8183         ses_num_before_timeout = self.nat64_get_ses_num()
8184
8185         sleep(15)
8186
8187         # ICMP and TCP session after timeout
8188         ses_num_after_timeout = self.nat64_get_ses_num()
8189         self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
8190
8191     def test_icmp_error(self):
8192         """ NAT64 ICMP Error message translation """
8193         self.tcp_port_in = 6303
8194         self.udp_port_in = 6304
8195         self.icmp_id_in = 6305
8196
8197         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8198                                                 end_addr=self.nat_addr,
8199                                                 vrf_id=0xFFFFFFFF,
8200                                                 is_add=1)
8201         flags = self.config_flags.NAT_IS_INSIDE
8202         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8203                                           sw_if_index=self.pg0.sw_if_index)
8204         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8205                                           sw_if_index=self.pg1.sw_if_index)
8206
8207         # send some packets to create sessions
8208         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8209         self.pg0.add_stream(pkts)
8210         self.pg_enable_capture(self.pg_interfaces)
8211         self.pg_start()
8212         capture_ip4 = self.pg1.get_capture(len(pkts))
8213         self.verify_capture_out(capture_ip4,
8214                                 nat_ip=self.nat_addr,
8215                                 dst_ip=self.pg1.remote_ip4)
8216
8217         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8218         self.pg1.add_stream(pkts)
8219         self.pg_enable_capture(self.pg_interfaces)
8220         self.pg_start()
8221         capture_ip6 = self.pg0.get_capture(len(pkts))
8222         ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8223         self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
8224                                    self.pg0.remote_ip6)
8225
8226         # in2out
8227         pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8228                 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
8229                 ICMPv6DestUnreach(code=1) /
8230                 packet[IPv6] for packet in capture_ip6]
8231         self.pg0.add_stream(pkts)
8232         self.pg_enable_capture(self.pg_interfaces)
8233         self.pg_start()
8234         capture = self.pg1.get_capture(len(pkts))
8235         for packet in capture:
8236             try:
8237                 self.assertEqual(packet[IP].src, self.nat_addr)
8238                 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
8239                 self.assertEqual(packet[ICMP].type, 3)
8240                 self.assertEqual(packet[ICMP].code, 13)
8241                 inner = packet[IPerror]
8242                 self.assertEqual(inner.src, self.pg1.remote_ip4)
8243                 self.assertEqual(inner.dst, self.nat_addr)
8244                 self.assert_packet_checksums_valid(packet)
8245                 if inner.haslayer(TCPerror):
8246                     self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
8247                 elif inner.haslayer(UDPerror):
8248                     self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
8249                 else:
8250                     self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
8251             except:
8252                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8253                 raise
8254
8255         # out2in
8256         pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8257                 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8258                 ICMP(type=3, code=13) /
8259                 packet[IP] for packet in capture_ip4]
8260         self.pg1.add_stream(pkts)
8261         self.pg_enable_capture(self.pg_interfaces)
8262         self.pg_start()
8263         capture = self.pg0.get_capture(len(pkts))
8264         for packet in capture:
8265             try:
8266                 self.assertEqual(packet[IPv6].src, ip.src)
8267                 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8268                 icmp = packet[ICMPv6DestUnreach]
8269                 self.assertEqual(icmp.code, 1)
8270                 inner = icmp[IPerror6]
8271                 self.assertEqual(inner.src, self.pg0.remote_ip6)
8272                 self.assertEqual(inner.dst, ip.src)
8273                 self.assert_icmpv6_checksum_valid(packet)
8274                 if inner.haslayer(TCPerror):
8275                     self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
8276                 elif inner.haslayer(UDPerror):
8277                     self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
8278                 else:
8279                     self.assertEqual(inner[ICMPv6EchoRequest].id,
8280                                      self.icmp_id_in)
8281             except:
8282                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8283                 raise
8284
8285     def test_hairpinning(self):
8286         """ NAT64 hairpinning """
8287
8288         client = self.pg0.remote_hosts[0]
8289         server = self.pg0.remote_hosts[1]
8290         server_tcp_in_port = 22
8291         server_tcp_out_port = 4022
8292         server_udp_in_port = 23
8293         server_udp_out_port = 4023
8294         client_tcp_in_port = 1234
8295         client_udp_in_port = 1235
8296         client_tcp_out_port = 0
8297         client_udp_out_port = 0
8298         ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8299         nat_addr_ip6 = ip.src
8300
8301         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8302                                                 end_addr=self.nat_addr,
8303                                                 vrf_id=0xFFFFFFFF,
8304                                                 is_add=1)
8305         flags = self.config_flags.NAT_IS_INSIDE
8306         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8307                                           sw_if_index=self.pg0.sw_if_index)
8308         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8309                                           sw_if_index=self.pg1.sw_if_index)
8310
8311         self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8312                                            o_addr=self.nat_addr,
8313                                            i_port=server_tcp_in_port,
8314                                            o_port=server_tcp_out_port,
8315                                            proto=IP_PROTOS.tcp, vrf_id=0,
8316                                            is_add=1)
8317         self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8318                                            o_addr=self.nat_addr,
8319                                            i_port=server_udp_in_port,
8320                                            o_port=server_udp_out_port,
8321                                            proto=IP_PROTOS.udp, vrf_id=0,
8322                                            is_add=1)
8323
8324         # client to server
8325         pkts = []
8326         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8327              IPv6(src=client.ip6, dst=nat_addr_ip6) /
8328              TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8329         pkts.append(p)
8330         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8331              IPv6(src=client.ip6, dst=nat_addr_ip6) /
8332              UDP(sport=client_udp_in_port, dport=server_udp_out_port))
8333         pkts.append(p)
8334         self.pg0.add_stream(pkts)
8335         self.pg_enable_capture(self.pg_interfaces)
8336         self.pg_start()
8337         capture = self.pg0.get_capture(len(pkts))
8338         for packet in capture:
8339             try:
8340                 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8341                 self.assertEqual(packet[IPv6].dst, server.ip6)
8342                 self.assert_packet_checksums_valid(packet)
8343                 if packet.haslayer(TCP):
8344                     self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
8345                     self.assertEqual(packet[TCP].dport, server_tcp_in_port)
8346                     client_tcp_out_port = packet[TCP].sport
8347                 else:
8348                     self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
8349                     self.assertEqual(packet[UDP].dport, server_udp_in_port)
8350                     client_udp_out_port = packet[UDP].sport
8351             except:
8352                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8353                 raise
8354
8355         # server to client
8356         pkts = []
8357         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8358              IPv6(src=server.ip6, dst=nat_addr_ip6) /
8359              TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
8360         pkts.append(p)
8361         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8362              IPv6(src=server.ip6, dst=nat_addr_ip6) /
8363              UDP(sport=server_udp_in_port, dport=client_udp_out_port))
8364         pkts.append(p)
8365         self.pg0.add_stream(pkts)
8366         self.pg_enable_capture(self.pg_interfaces)
8367         self.pg_start()
8368         capture = self.pg0.get_capture(len(pkts))
8369         for packet in capture:
8370             try:
8371                 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8372                 self.assertEqual(packet[IPv6].dst, client.ip6)
8373                 self.assert_packet_checksums_valid(packet)
8374                 if packet.haslayer(TCP):
8375                     self.assertEqual(packet[TCP].sport, server_tcp_out_port)
8376                     self.assertEqual(packet[TCP].dport, client_tcp_in_port)
8377                 else:
8378                     self.assertEqual(packet[UDP].sport, server_udp_out_port)
8379                     self.assertEqual(packet[UDP].dport, client_udp_in_port)
8380             except:
8381                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8382                 raise
8383
8384         # ICMP error
8385         pkts = []
8386         pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8387                 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8388                 ICMPv6DestUnreach(code=1) /
8389                 packet[IPv6] for packet in capture]
8390         self.pg0.add_stream(pkts)
8391         self.pg_enable_capture(self.pg_interfaces)
8392         self.pg_start()
8393         capture = self.pg0.get_capture(len(pkts))
8394         for packet in capture:
8395             try:
8396                 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8397                 self.assertEqual(packet[IPv6].dst, server.ip6)
8398                 icmp = packet[ICMPv6DestUnreach]
8399                 self.assertEqual(icmp.code, 1)
8400                 inner = icmp[IPerror6]
8401                 self.assertEqual(inner.src, server.ip6)
8402                 self.assertEqual(inner.dst, nat_addr_ip6)
8403                 self.assert_packet_checksums_valid(packet)
8404                 if inner.haslayer(TCPerror):
8405                     self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
8406                     self.assertEqual(inner[TCPerror].dport,
8407                                      client_tcp_out_port)
8408                 else:
8409                     self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
8410                     self.assertEqual(inner[UDPerror].dport,
8411                                      client_udp_out_port)
8412             except:
8413                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8414                 raise
8415
8416     def test_prefix(self):
8417         """ NAT64 Network-Specific Prefix """
8418
8419         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8420                                                 end_addr=self.nat_addr,
8421                                                 vrf_id=0xFFFFFFFF,
8422                                                 is_add=1)
8423         flags = self.config_flags.NAT_IS_INSIDE
8424         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8425                                           sw_if_index=self.pg0.sw_if_index)
8426         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8427                                           sw_if_index=self.pg1.sw_if_index)
8428         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
8429                                                 end_addr=self.vrf1_nat_addr,
8430                                                 vrf_id=self.vrf1_id, is_add=1)
8431         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8432                                           sw_if_index=self.pg2.sw_if_index)
8433
8434         # Add global prefix
8435         global_pref64 = "2001:db8::"
8436         global_pref64_len = 32
8437         global_pref64_str = "{}/{}".format(global_pref64, global_pref64_len)
8438         self.vapi.nat64_add_del_prefix(prefix=global_pref64_str, vrf_id=0,
8439                                        is_add=1)
8440
8441         prefix = self.vapi.nat64_prefix_dump()
8442         self.assertEqual(len(prefix), 1)
8443         self.assertEqual(str(prefix[0].prefix), global_pref64_str)
8444         self.assertEqual(prefix[0].vrf_id, 0)
8445
8446         # Add tenant specific prefix
8447         vrf1_pref64 = "2001:db8:122:300::"
8448         vrf1_pref64_len = 56
8449         vrf1_pref64_str = "{}/{}".format(vrf1_pref64, vrf1_pref64_len)
8450         self.vapi.nat64_add_del_prefix(prefix=vrf1_pref64_str,
8451                                        vrf_id=self.vrf1_id, is_add=1)
8452
8453         prefix = self.vapi.nat64_prefix_dump()
8454         self.assertEqual(len(prefix), 2)
8455
8456         # Global prefix
8457         pkts = self.create_stream_in_ip6(self.pg0,
8458                                          self.pg1,
8459                                          pref=global_pref64,
8460                                          plen=global_pref64_len)
8461         self.pg0.add_stream(pkts)
8462         self.pg_enable_capture(self.pg_interfaces)
8463         self.pg_start()
8464         capture = self.pg1.get_capture(len(pkts))
8465         self.verify_capture_out(capture, nat_ip=self.nat_addr,
8466                                 dst_ip=self.pg1.remote_ip4)
8467
8468         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8469         self.pg1.add_stream(pkts)
8470         self.pg_enable_capture(self.pg_interfaces)
8471         self.pg_start()
8472         capture = self.pg0.get_capture(len(pkts))
8473         dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8474                                   global_pref64,
8475                                   global_pref64_len)
8476         self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
8477
8478         # Tenant specific prefix
8479         pkts = self.create_stream_in_ip6(self.pg2,
8480                                          self.pg1,
8481                                          pref=vrf1_pref64,
8482                                          plen=vrf1_pref64_len)
8483         self.pg2.add_stream(pkts)
8484         self.pg_enable_capture(self.pg_interfaces)
8485         self.pg_start()
8486         capture = self.pg1.get_capture(len(pkts))
8487         self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
8488                                 dst_ip=self.pg1.remote_ip4)
8489
8490         pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
8491         self.pg1.add_stream(pkts)
8492         self.pg_enable_capture(self.pg_interfaces)
8493         self.pg_start()
8494         capture = self.pg2.get_capture(len(pkts))
8495         dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8496                                   vrf1_pref64,
8497                                   vrf1_pref64_len)
8498         self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
8499
8500     def test_unknown_proto(self):
8501         """ NAT64 translate packet with unknown protocol """
8502
8503         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8504                                                 end_addr=self.nat_addr,
8505                                                 vrf_id=0xFFFFFFFF,
8506                                                 is_add=1)
8507         flags = self.config_flags.NAT_IS_INSIDE
8508         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8509                                           sw_if_index=self.pg0.sw_if_index)
8510         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8511                                           sw_if_index=self.pg1.sw_if_index)
8512         remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8513
8514         # in2out
8515         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8516              IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
8517              TCP(sport=self.tcp_port_in, dport=20))
8518         self.pg0.add_stream(p)
8519         self.pg_enable_capture(self.pg_interfaces)
8520         self.pg_start()
8521         p = self.pg1.get_capture(1)
8522
8523         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8524              IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
8525              GRE() /
8526              IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8527              TCP(sport=1234, dport=1234))
8528         self.pg0.add_stream(p)
8529         self.pg_enable_capture(self.pg_interfaces)
8530         self.pg_start()
8531         p = self.pg1.get_capture(1)
8532         packet = p[0]
8533         try:
8534             self.assertEqual(packet[IP].src, self.nat_addr)
8535             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
8536             self.assertEqual(packet.haslayer(GRE), 1)
8537             self.assert_packet_checksums_valid(packet)
8538         except:
8539             self.logger.error(ppp("Unexpected or invalid packet:", packet))
8540             raise
8541
8542         # out2in
8543         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8544              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8545              GRE() /
8546              IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8547              TCP(sport=1234, dport=1234))
8548         self.pg1.add_stream(p)
8549         self.pg_enable_capture(self.pg_interfaces)
8550         self.pg_start()
8551         p = self.pg0.get_capture(1)
8552         packet = p[0]
8553         try:
8554             self.assertEqual(packet[IPv6].src, remote_ip6)
8555             self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8556             self.assertEqual(packet[IPv6].nh, 47)
8557         except:
8558             self.logger.error(ppp("Unexpected or invalid packet:", packet))
8559             raise
8560
8561     def test_hairpinning_unknown_proto(self):
8562         """ NAT64 translate packet with unknown protocol - hairpinning """
8563
8564         client = self.pg0.remote_hosts[0]
8565         server = self.pg0.remote_hosts[1]
8566         server_tcp_in_port = 22
8567         server_tcp_out_port = 4022
8568         client_tcp_in_port = 1234
8569         client_tcp_out_port = 1235
8570         server_nat_ip = "10.0.0.100"
8571         client_nat_ip = "10.0.0.110"
8572         server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
8573         client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
8574
8575         self.vapi.nat64_add_del_pool_addr_range(start_addr=server_nat_ip,
8576                                                 end_addr=client_nat_ip,
8577                                                 vrf_id=0xFFFFFFFF,
8578                                                 is_add=1)
8579         flags = self.config_flags.NAT_IS_INSIDE
8580         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8581                                           sw_if_index=self.pg0.sw_if_index)
8582         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8583                                           sw_if_index=self.pg1.sw_if_index)
8584
8585         self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8586                                            o_addr=server_nat_ip,
8587                                            i_port=server_tcp_in_port,
8588                                            o_port=server_tcp_out_port,
8589                                            proto=IP_PROTOS.tcp, vrf_id=0,
8590                                            is_add=1)
8591
8592         self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8593                                            o_addr=server_nat_ip, i_port=0,
8594                                            o_port=0,
8595                                            proto=IP_PROTOS.gre, vrf_id=0,
8596                                            is_add=1)
8597
8598         self.vapi.nat64_add_del_static_bib(i_addr=client.ip6n,
8599                                            o_addr=client_nat_ip,
8600                                            i_port=client_tcp_in_port,
8601                                            o_port=client_tcp_out_port,
8602                                            proto=IP_PROTOS.tcp, vrf_id=0,
8603                                            is_add=1)
8604
8605         # client to server
8606         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8607              IPv6(src=client.ip6, dst=server_nat_ip6) /
8608              TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8609         self.pg0.add_stream(p)
8610         self.pg_enable_capture(self.pg_interfaces)
8611         self.pg_start()
8612         p = self.pg0.get_capture(1)
8613
8614         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8615              IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
8616              GRE() /
8617              IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8618              TCP(sport=1234, dport=1234))
8619         self.pg0.add_stream(p)
8620         self.pg_enable_capture(self.pg_interfaces)
8621         self.pg_start()
8622         p = self.pg0.get_capture(1)
8623         packet = p[0]
8624         try:
8625             self.assertEqual(packet[IPv6].src, client_nat_ip6)
8626             self.assertEqual(packet[IPv6].dst, server.ip6)
8627             self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
8628         except:
8629             self.logger.error(ppp("Unexpected or invalid packet:", packet))
8630             raise
8631
8632         # server to client
8633         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8634              IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
8635              GRE() /
8636              IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8637              TCP(sport=1234, dport=1234))
8638         self.pg0.add_stream(p)
8639         self.pg_enable_capture(self.pg_interfaces)
8640         self.pg_start()
8641         p = self.pg0.get_capture(1)
8642         packet = p[0]
8643         try:
8644             self.assertEqual(packet[IPv6].src, server_nat_ip6)
8645             self.assertEqual(packet[IPv6].dst, client.ip6)
8646             self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
8647         except:
8648             self.logger.error(ppp("Unexpected or invalid packet:", packet))
8649             raise
8650
8651     def test_one_armed_nat64(self):
8652         """ One armed NAT64 """
8653         external_port = 0
8654         remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
8655                                            '64:ff9b::',
8656                                            96)
8657
8658         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8659                                                 end_addr=self.nat_addr,
8660                                                 vrf_id=0xFFFFFFFF,
8661                                                 is_add=1)
8662         flags = self.config_flags.NAT_IS_INSIDE
8663         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8664                                           sw_if_index=self.pg3.sw_if_index)
8665         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8666                                           sw_if_index=self.pg3.sw_if_index)
8667
8668         # in2out
8669         p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8670              IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
8671              TCP(sport=12345, dport=80))
8672         self.pg3.add_stream(p)
8673         self.pg_enable_capture(self.pg_interfaces)
8674         self.pg_start()
8675         capture = self.pg3.get_capture(1)
8676         p = capture[0]
8677         try:
8678             ip = p[IP]
8679             tcp = p[TCP]
8680             self.assertEqual(ip.src, self.nat_addr)
8681             self.assertEqual(ip.dst, self.pg3.remote_ip4)
8682             self.assertNotEqual(tcp.sport, 12345)
8683             external_port = tcp.sport
8684             self.assertEqual(tcp.dport, 80)
8685             self.assert_packet_checksums_valid(p)
8686         except:
8687             self.logger.error(ppp("Unexpected or invalid packet:", p))
8688             raise
8689
8690         # out2in
8691         p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8692              IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
8693              TCP(sport=80, dport=external_port))
8694         self.pg3.add_stream(p)
8695         self.pg_enable_capture(self.pg_interfaces)
8696         self.pg_start()
8697         capture = self.pg3.get_capture(1)
8698         p = capture[0]
8699         try:
8700             ip = p[IPv6]
8701             tcp = p[TCP]
8702             self.assertEqual(ip.src, remote_host_ip6)
8703             self.assertEqual(ip.dst, self.pg3.remote_ip6)
8704             self.assertEqual(tcp.sport, 80)
8705             self.assertEqual(tcp.dport, 12345)
8706             self.assert_packet_checksums_valid(p)
8707         except:
8708             self.logger.error(ppp("Unexpected or invalid packet:", p))
8709             raise
8710
8711     def test_frag_in_order(self):
8712         """ NAT64 translate fragments arriving in order """
8713         self.tcp_port_in = random.randint(1025, 65535)
8714
8715         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8716                                                 end_addr=self.nat_addr,
8717                                                 vrf_id=0xFFFFFFFF,
8718                                                 is_add=1)
8719         flags = self.config_flags.NAT_IS_INSIDE
8720         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8721                                           sw_if_index=self.pg0.sw_if_index)
8722         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8723                                           sw_if_index=self.pg1.sw_if_index)
8724
8725         # in2out
8726         data = b'a' * 200
8727         pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8728                                            self.tcp_port_in, 20, data)
8729         self.pg0.add_stream(pkts)
8730         self.pg_enable_capture(self.pg_interfaces)
8731         self.pg_start()
8732         frags = self.pg1.get_capture(len(pkts))
8733         p = self.reass_frags_and_verify(frags,
8734                                         self.nat_addr,
8735                                         self.pg1.remote_ip4)
8736         self.assertEqual(p[TCP].dport, 20)
8737         self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8738         self.tcp_port_out = p[TCP].sport
8739         self.assertEqual(data, p[Raw].load)
8740
8741         # out2in
8742         data = b"A" * 4 + b"b" * 16 + b"C" * 3
8743         pkts = self.create_stream_frag(self.pg1,
8744                                        self.nat_addr,
8745                                        20,
8746                                        self.tcp_port_out,
8747                                        data)
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         self.logger.debug(ppc("Captured:", frags))
8753         src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8754         p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8755         self.assertEqual(p[TCP].sport, 20)
8756         self.assertEqual(p[TCP].dport, self.tcp_port_in)
8757         self.assertEqual(data, p[Raw].load)
8758
8759     def test_reass_hairpinning(self):
8760         """ NAT64 fragments hairpinning """
8761         data = b'a' * 200
8762         server = self.pg0.remote_hosts[1]
8763         server_in_port = random.randint(1025, 65535)
8764         server_out_port = random.randint(1025, 65535)
8765         client_in_port = random.randint(1025, 65535)
8766         ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8767         nat_addr_ip6 = ip.src
8768
8769         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8770                                                 end_addr=self.nat_addr,
8771                                                 vrf_id=0xFFFFFFFF,
8772                                                 is_add=1)
8773         flags = self.config_flags.NAT_IS_INSIDE
8774         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8775                                           sw_if_index=self.pg0.sw_if_index)
8776         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8777                                           sw_if_index=self.pg1.sw_if_index)
8778
8779         # add static BIB entry for server
8780         self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8781                                            o_addr=self.nat_addr,
8782                                            i_port=server_in_port,
8783                                            o_port=server_out_port,
8784                                            proto=IP_PROTOS.tcp, vrf_id=0,
8785                                            is_add=1)
8786
8787         # send packet from host to server
8788         pkts = self.create_stream_frag_ip6(self.pg0,
8789                                            self.nat_addr,
8790                                            client_in_port,
8791                                            server_out_port,
8792                                            data)
8793         self.pg0.add_stream(pkts)
8794         self.pg_enable_capture(self.pg_interfaces)
8795         self.pg_start()
8796         frags = self.pg0.get_capture(len(pkts))
8797         self.logger.debug(ppc("Captured:", frags))
8798         p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
8799         self.assertNotEqual(p[TCP].sport, client_in_port)
8800         self.assertEqual(p[TCP].dport, server_in_port)
8801         self.assertEqual(data, p[Raw].load)
8802
8803     def test_frag_out_of_order(self):
8804         """ NAT64 translate fragments arriving out of order """
8805         self.tcp_port_in = random.randint(1025, 65535)
8806
8807         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8808                                                 end_addr=self.nat_addr,
8809                                                 vrf_id=0xFFFFFFFF,
8810                                                 is_add=1)
8811         flags = self.config_flags.NAT_IS_INSIDE
8812         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8813                                           sw_if_index=self.pg0.sw_if_index)
8814         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8815                                           sw_if_index=self.pg1.sw_if_index)
8816
8817         # in2out
8818         data = b'a' * 200
8819         pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8820                                            self.tcp_port_in, 20, data)
8821         pkts.reverse()
8822         self.pg0.add_stream(pkts)
8823         self.pg_enable_capture(self.pg_interfaces)
8824         self.pg_start()
8825         frags = self.pg1.get_capture(len(pkts))
8826         p = self.reass_frags_and_verify(frags,
8827                                         self.nat_addr,
8828                                         self.pg1.remote_ip4)
8829         self.assertEqual(p[TCP].dport, 20)
8830         self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8831         self.tcp_port_out = p[TCP].sport
8832         self.assertEqual(data, p[Raw].load)
8833
8834         # out2in
8835         data = b"A" * 4 + b"B" * 16 + b"C" * 3
8836         pkts = self.create_stream_frag(self.pg1,
8837                                        self.nat_addr,
8838                                        20,
8839                                        self.tcp_port_out,
8840                                        data)
8841         pkts.reverse()
8842         self.pg1.add_stream(pkts)
8843         self.pg_enable_capture(self.pg_interfaces)
8844         self.pg_start()
8845         frags = self.pg0.get_capture(len(pkts))
8846         src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8847         p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8848         self.assertEqual(p[TCP].sport, 20)
8849         self.assertEqual(p[TCP].dport, self.tcp_port_in)
8850         self.assertEqual(data, p[Raw].load)
8851
8852     def test_interface_addr(self):
8853         """ Acquire NAT64 pool addresses from interface """
8854         self.vapi.nat64_add_del_interface_addr(
8855             is_add=1,
8856             sw_if_index=self.pg4.sw_if_index)
8857
8858         # no address in NAT64 pool
8859         addresses = self.vapi.nat44_address_dump()
8860         self.assertEqual(0, len(addresses))
8861
8862         # configure interface address and check NAT64 address pool
8863         self.pg4.config_ip4()
8864         addresses = self.vapi.nat64_pool_addr_dump()
8865         self.assertEqual(len(addresses), 1)
8866
8867         self.assertEqual(str(addresses[0].address),
8868                          self.pg4.local_ip4)
8869
8870         # remove interface address and check NAT64 address pool
8871         self.pg4.unconfig_ip4()
8872         addresses = self.vapi.nat64_pool_addr_dump()
8873         self.assertEqual(0, len(addresses))
8874
8875     @unittest.skipUnless(running_extended_tests, "part of extended tests")
8876     def test_ipfix_max_bibs_sessions(self):
8877         """ IPFIX logging maximum session and BIB entries exceeded """
8878         max_bibs = 1280
8879         max_sessions = 2560
8880         remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8881                                            '64:ff9b::',
8882                                            96)
8883
8884         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8885                                                 end_addr=self.nat_addr,
8886                                                 vrf_id=0xFFFFFFFF,
8887                                                 is_add=1)
8888         flags = self.config_flags.NAT_IS_INSIDE
8889         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8890                                           sw_if_index=self.pg0.sw_if_index)
8891         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8892                                           sw_if_index=self.pg1.sw_if_index)
8893
8894         pkts = []
8895         src = ""
8896         for i in range(0, max_bibs):
8897             src = "fd01:aa::%x" % (i)
8898             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8899                  IPv6(src=src, dst=remote_host_ip6) /
8900                  TCP(sport=12345, dport=80))
8901             pkts.append(p)
8902             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8903                  IPv6(src=src, dst=remote_host_ip6) /
8904                  TCP(sport=12345, dport=22))
8905             pkts.append(p)
8906         self.pg0.add_stream(pkts)
8907         self.pg_enable_capture(self.pg_interfaces)
8908         self.pg_start()
8909         self.pg1.get_capture(max_sessions)
8910
8911         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
8912                                      src_address=self.pg3.local_ip4,
8913                                      path_mtu=512,
8914                                      template_interval=10)
8915         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8916                                            src_port=self.ipfix_src_port,
8917                                            enable=1)
8918
8919         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8920              IPv6(src=src, dst=remote_host_ip6) /
8921              TCP(sport=12345, dport=25))
8922         self.pg0.add_stream(p)
8923         self.pg_enable_capture(self.pg_interfaces)
8924         self.pg_start()
8925         self.pg1.assert_nothing_captured()
8926         sleep(1)
8927         self.vapi.ipfix_flush()
8928         capture = self.pg3.get_capture(9)
8929         ipfix = IPFIXDecoder()
8930         # first load template
8931         for p in capture:
8932             self.assertTrue(p.haslayer(IPFIX))
8933             self.assertEqual(p[IP].src, self.pg3.local_ip4)
8934             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8935             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8936             self.assertEqual(p[UDP].dport, 4739)
8937             self.assertEqual(p[IPFIX].observationDomainID,
8938                              self.ipfix_domain_id)
8939             if p.haslayer(Template):
8940                 ipfix.add_template(p.getlayer(Template))
8941         # verify events in data set
8942         for p in capture:
8943             if p.haslayer(Data):
8944                 data = ipfix.decode_data_set(p.getlayer(Set))
8945                 self.verify_ipfix_max_sessions(data, max_sessions)
8946
8947         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8948              IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8949              TCP(sport=12345, dport=80))
8950         self.pg0.add_stream(p)
8951         self.pg_enable_capture(self.pg_interfaces)
8952         self.pg_start()
8953         self.pg1.assert_nothing_captured()
8954         sleep(1)
8955         self.vapi.ipfix_flush()
8956         capture = self.pg3.get_capture(1)
8957         # verify events in data set
8958         for p in capture:
8959             self.assertTrue(p.haslayer(IPFIX))
8960             self.assertEqual(p[IP].src, self.pg3.local_ip4)
8961             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8962             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8963             self.assertEqual(p[UDP].dport, 4739)
8964             self.assertEqual(p[IPFIX].observationDomainID,
8965                              self.ipfix_domain_id)
8966             if p.haslayer(Data):
8967                 data = ipfix.decode_data_set(p.getlayer(Set))
8968                 self.verify_ipfix_max_bibs(data, max_bibs)
8969
8970     def test_ipfix_bib_ses(self):
8971         """ IPFIX logging NAT64 BIB/session create and delete events """
8972         self.tcp_port_in = random.randint(1025, 65535)
8973         remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8974                                            '64:ff9b::',
8975                                            96)
8976
8977         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8978                                                 end_addr=self.nat_addr,
8979                                                 vrf_id=0xFFFFFFFF,
8980                                                 is_add=1)
8981         flags = self.config_flags.NAT_IS_INSIDE
8982         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8983                                           sw_if_index=self.pg0.sw_if_index)
8984         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8985                                           sw_if_index=self.pg1.sw_if_index)
8986         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
8987                                      src_address=self.pg3.local_ip4,
8988                                      path_mtu=512,
8989                                      template_interval=10)
8990         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8991                                            src_port=self.ipfix_src_port,
8992                                            enable=1)
8993
8994         # Create
8995         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8996              IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8997              TCP(sport=self.tcp_port_in, dport=25))
8998         self.pg0.add_stream(p)
8999         self.pg_enable_capture(self.pg_interfaces)
9000         self.pg_start()
9001         p = self.pg1.get_capture(1)
9002         self.tcp_port_out = p[0][TCP].sport
9003         self.vapi.ipfix_flush()
9004         capture = self.pg3.get_capture(10)
9005         ipfix = IPFIXDecoder()
9006         # first load template
9007         for p in capture:
9008             self.assertTrue(p.haslayer(IPFIX))
9009             self.assertEqual(p[IP].src, self.pg3.local_ip4)
9010             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
9011             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
9012             self.assertEqual(p[UDP].dport, 4739)
9013             self.assertEqual(p[IPFIX].observationDomainID,
9014                              self.ipfix_domain_id)
9015             if p.haslayer(Template):
9016                 ipfix.add_template(p.getlayer(Template))
9017         # verify events in data set
9018         for p in capture:
9019             if p.haslayer(Data):
9020                 data = ipfix.decode_data_set(p.getlayer(Set))
9021                 if scapy.compat.orb(data[0][230]) == 10:
9022                     self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
9023                 elif scapy.compat.orb(data[0][230]) == 6:
9024                     self.verify_ipfix_nat64_ses(data,
9025                                                 1,
9026                                                 self.pg0.remote_ip6n,
9027                                                 self.pg1.remote_ip4,
9028                                                 25)
9029                 else:
9030                     self.logger.error(ppp("Unexpected or invalid packet: ", p))
9031
9032         # Delete
9033         self.pg_enable_capture(self.pg_interfaces)
9034         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9035                                                 end_addr=self.nat_addr,
9036                                                 vrf_id=0xFFFFFFFF,
9037                                                 is_add=0)
9038         self.vapi.ipfix_flush()
9039         capture = self.pg3.get_capture(2)
9040         # verify events in data set
9041         for p in capture:
9042             self.assertTrue(p.haslayer(IPFIX))
9043             self.assertEqual(p[IP].src, self.pg3.local_ip4)
9044             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
9045             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
9046             self.assertEqual(p[UDP].dport, 4739)
9047             self.assertEqual(p[IPFIX].observationDomainID,
9048                              self.ipfix_domain_id)
9049             if p.haslayer(Data):
9050                 data = ipfix.decode_data_set(p.getlayer(Set))
9051                 if scapy.compat.orb(data[0][230]) == 11:
9052                     self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
9053                 elif scapy.compat.orb(data[0][230]) == 7:
9054                     self.verify_ipfix_nat64_ses(data,
9055                                                 0,
9056                                                 self.pg0.remote_ip6n,
9057                                                 self.pg1.remote_ip4,
9058                                                 25)
9059                 else:
9060                     self.logger.error(ppp("Unexpected or invalid packet: ", p))
9061
9062     def test_syslog_sess(self):
9063         """ Test syslog session creation and deletion """
9064         self.tcp_port_in = random.randint(1025, 65535)
9065         remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
9066                                            '64:ff9b::',
9067                                            96)
9068
9069         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9070                                                 end_addr=self.nat_addr,
9071                                                 vrf_id=0xFFFFFFFF,
9072                                                 is_add=1)
9073         flags = self.config_flags.NAT_IS_INSIDE
9074         self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
9075                                           sw_if_index=self.pg0.sw_if_index)
9076         self.vapi.nat64_add_del_interface(is_add=1, flags=0,
9077                                           sw_if_index=self.pg1.sw_if_index)
9078         self.vapi.syslog_set_filter(
9079             self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
9080         self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
9081
9082         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
9083              IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
9084              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
9085         self.pg0.add_stream(p)
9086         self.pg_enable_capture(self.pg_interfaces)
9087         self.pg_start()
9088         p = self.pg1.get_capture(1)
9089         self.tcp_port_out = p[0][TCP].sport
9090         capture = self.pg3.get_capture(1)
9091         self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
9092
9093         self.pg_enable_capture(self.pg_interfaces)
9094         self.pg_start()
9095         self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9096                                                 end_addr=self.nat_addr,
9097                                                 vrf_id=0xFFFFFFFF,
9098                                                 is_add=0)
9099         capture = self.pg3.get_capture(1)
9100         self.verify_syslog_sess(capture[0][Raw].load, False, True)
9101
9102     def nat64_get_ses_num(self):
9103         """
9104         Return number of active NAT64 sessions.
9105         """
9106         st = self.vapi.nat64_st_dump(proto=255)
9107         return len(st)
9108
9109     def clear_nat64(self):
9110         """
9111         Clear NAT64 configuration.
9112         """
9113         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
9114                                            src_port=self.ipfix_src_port,
9115                                            enable=0)
9116         self.ipfix_src_port = 4739
9117         self.ipfix_domain_id = 1
9118
9119         self.vapi.syslog_set_filter(
9120             self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_EMERG)
9121
9122         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
9123                                    tcp_transitory=240, icmp=60)
9124
9125         interfaces = self.vapi.nat64_interface_dump()
9126         for intf in interfaces:
9127             self.vapi.nat64_add_del_interface(is_add=0, flags=intf.flags,
9128                                               sw_if_index=intf.sw_if_index)
9129
9130         bib = self.vapi.nat64_bib_dump(proto=255)
9131         for bibe in bib:
9132             if bibe.flags & self.config_flags.NAT_IS_STATIC:
9133                 self.vapi.nat64_add_del_static_bib(i_addr=bibe.i_addr,
9134                                                    o_addr=bibe.o_addr,
9135                                                    i_port=bibe.i_port,
9136                                                    o_port=bibe.o_port,
9137                                                    proto=bibe.proto,
9138                                                    vrf_id=bibe.vrf_id,
9139                                                    is_add=0)
9140
9141         adresses = self.vapi.nat64_pool_addr_dump()
9142         for addr in adresses:
9143             self.vapi.nat64_add_del_pool_addr_range(start_addr=addr.address,
9144                                                     end_addr=addr.address,
9145                                                     vrf_id=addr.vrf_id,
9146                                                     is_add=0)
9147
9148         prefixes = self.vapi.nat64_prefix_dump()
9149         for prefix in prefixes:
9150             self.vapi.nat64_add_del_prefix(prefix=str(prefix.prefix),
9151                                            vrf_id=prefix.vrf_id, is_add=0)
9152
9153         bibs = self.statistics.get_counter('/nat64/total-bibs')
9154         self.assertEqual(bibs[0][0], 0)
9155         sessions = self.statistics.get_counter('/nat64/total-sessions')
9156         self.assertEqual(sessions[0][0], 0)
9157
9158     def tearDown(self):
9159         super(TestNAT64, self).tearDown()
9160         if not self.vpp_dead:
9161             self.clear_nat64()
9162
9163     def show_commands_at_teardown(self):
9164         self.logger.info(self.vapi.cli("show nat64 pool"))
9165         self.logger.info(self.vapi.cli("show nat64 interfaces"))
9166         self.logger.info(self.vapi.cli("show nat64 prefix"))
9167         self.logger.info(self.vapi.cli("show nat64 bib all"))
9168         self.logger.info(self.vapi.cli("show nat64 session table all"))
9169
9170
9171 class TestNAT66(MethodHolder):
9172     """ NAT66 Test Cases """
9173
9174     @classmethod
9175     def setUpClass(cls):
9176         super(TestNAT66, cls).setUpClass()
9177
9178         cls.nat_addr = 'fd01:ff::2'
9179
9180         cls.create_pg_interfaces(range(2))
9181         cls.interfaces = list(cls.pg_interfaces)
9182
9183         for i in cls.interfaces:
9184             i.admin_up()
9185             i.config_ip6()
9186             i.configure_ipv6_neighbors()
9187
9188     @classmethod
9189     def tearDownClass(cls):
9190         super(TestNAT66, cls).tearDownClass()
9191
9192     def test_static(self):
9193         """ 1:1 NAT66 test """
9194         flags = self.config_flags.NAT_IS_INSIDE
9195         self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9196                                           sw_if_index=self.pg0.sw_if_index)
9197         self.vapi.nat66_add_del_interface(is_add=1,
9198                                           sw_if_index=self.pg1.sw_if_index)
9199         self.vapi.nat66_add_del_static_mapping(
9200             local_ip_address=self.pg0.remote_ip6n,
9201             external_ip_address=self.nat_addr,
9202             is_add=1)
9203
9204         # in2out
9205         pkts = []
9206         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9207              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9208              TCP())
9209         pkts.append(p)
9210         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9211              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9212              UDP())
9213         pkts.append(p)
9214         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9215              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9216              ICMPv6EchoRequest())
9217         pkts.append(p)
9218         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9219              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9220              GRE() / IP() / TCP())
9221         pkts.append(p)
9222         self.pg0.add_stream(pkts)
9223         self.pg_enable_capture(self.pg_interfaces)
9224         self.pg_start()
9225         capture = self.pg1.get_capture(len(pkts))
9226
9227         for packet in capture:
9228             try:
9229                 self.assertEqual(packet[IPv6].src, self.nat_addr)
9230                 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9231                 self.assert_packet_checksums_valid(packet)
9232             except:
9233                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9234                 raise
9235
9236         # out2in
9237         pkts = []
9238         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9239              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9240              TCP())
9241         pkts.append(p)
9242         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9243              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9244              UDP())
9245         pkts.append(p)
9246         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9247              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9248              ICMPv6EchoReply())
9249         pkts.append(p)
9250         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9251              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9252              GRE() / IP() / TCP())
9253         pkts.append(p)
9254         self.pg1.add_stream(pkts)
9255         self.pg_enable_capture(self.pg_interfaces)
9256         self.pg_start()
9257         capture = self.pg0.get_capture(len(pkts))
9258         for packet in capture:
9259             try:
9260                 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
9261                 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
9262                 self.assert_packet_checksums_valid(packet)
9263             except:
9264                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9265                 raise
9266
9267         sm = self.vapi.nat66_static_mapping_dump()
9268         self.assertEqual(len(sm), 1)
9269         self.assertEqual(sm[0].total_pkts, 8)
9270
9271     def test_check_no_translate(self):
9272         """ NAT66 translate only when egress interface is outside interface """
9273         flags = self.config_flags.NAT_IS_INSIDE
9274         self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9275                                           sw_if_index=self.pg0.sw_if_index)
9276         self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9277                                           sw_if_index=self.pg1.sw_if_index)
9278         self.vapi.nat66_add_del_static_mapping(
9279             local_ip_address=self.pg0.remote_ip6n,
9280             external_ip_address=self.nat_addr,
9281             is_add=1)
9282
9283         # in2out
9284         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9285              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9286              UDP())
9287         self.pg0.add_stream([p])
9288         self.pg_enable_capture(self.pg_interfaces)
9289         self.pg_start()
9290         capture = self.pg1.get_capture(1)
9291         packet = capture[0]
9292         try:
9293             self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
9294             self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9295         except:
9296             self.logger.error(ppp("Unexpected or invalid packet:", packet))
9297             raise
9298
9299     def clear_nat66(self):
9300         """
9301         Clear NAT66 configuration.
9302         """
9303         interfaces = self.vapi.nat66_interface_dump()
9304         for intf in interfaces:
9305             self.vapi.nat66_add_del_interface(is_add=0, flags=intf.flags,
9306                                               sw_if_index=intf.sw_if_index)
9307
9308         static_mappings = self.vapi.nat66_static_mapping_dump()
9309         for sm in static_mappings:
9310             self.vapi.nat66_add_del_static_mapping(
9311                 local_ip_address=sm.local_ip_address,
9312                 external_ip_address=sm.external_ip_address, vrf_id=sm.vrf_id,
9313                 is_add=0)
9314
9315     def tearDown(self):
9316         super(TestNAT66, self).tearDown()
9317         self.clear_nat66()
9318
9319     def show_commands_at_teardown(self):
9320         self.logger.info(self.vapi.cli("show nat66 interfaces"))
9321         self.logger.info(self.vapi.cli("show nat66 static mappings"))
9322
9323
9324 if __name__ == '__main__':
9325     unittest.main(testRunner=VppTestRunner)