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