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