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