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