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