nat: move nat64 to a subfeature
[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_out(self, out_if, dst_ip=None, ttl=64,
344                           use_inside_ports=False):
345         """
346         Create packet stream for outside network
347
348         :param out_if: Outside interface
349         :param dst_ip: Destination IP address (Default use global NAT address)
350         :param ttl: TTL of generated packets
351         :param use_inside_ports: Use inside NAT ports as destination ports
352                instead of outside ports
353         """
354         if dst_ip is None:
355             dst_ip = self.nat_addr
356         if not use_inside_ports:
357             tcp_port = self.tcp_port_out
358             udp_port = self.udp_port_out
359             icmp_id = self.icmp_id_out
360         else:
361             tcp_port = self.tcp_port_in
362             udp_port = self.udp_port_in
363             icmp_id = self.icmp_id_in
364         pkts = []
365         # TCP
366         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
367              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
368              TCP(dport=tcp_port, sport=20))
369         pkts.extend([p, p])
370
371         # UDP
372         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
373              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
374              UDP(dport=udp_port, sport=20))
375         pkts.append(p)
376
377         # ICMP
378         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
379              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
380              ICMP(id=icmp_id, type='echo-reply'))
381         pkts.append(p)
382
383         return pkts
384
385     def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
386         """
387         Create packet stream for outside network
388
389         :param out_if: Outside interface
390         :param dst_ip: Destination IP address (Default use global NAT address)
391         :param hl: HL of generated packets
392         """
393         pkts = []
394         # TCP
395         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
396              IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
397              TCP(dport=self.tcp_port_out, sport=20))
398         pkts.append(p)
399
400         # UDP
401         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
402              IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
403              UDP(dport=self.udp_port_out, sport=20))
404         pkts.append(p)
405
406         # ICMP
407         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
408              IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
409              ICMPv6EchoReply(id=self.icmp_id_out))
410         pkts.append(p)
411
412         return pkts
413
414     def verify_capture_out(self, capture, nat_ip=None, same_port=False,
415                            dst_ip=None, is_ip6=False, ignore_port=False):
416         """
417         Verify captured packets on outside network
418
419         :param capture: Captured packets
420         :param nat_ip: Translated IP address (Default use global NAT address)
421         :param same_port: Source port number is not translated (Default False)
422         :param dst_ip: Destination IP address (Default do not verify)
423         :param is_ip6: If L3 protocol is IPv6 (Default False)
424         """
425         if is_ip6:
426             IP46 = IPv6
427             ICMP46 = ICMPv6EchoRequest
428         else:
429             IP46 = IP
430             ICMP46 = ICMP
431         if nat_ip is None:
432             nat_ip = self.nat_addr
433         for packet in capture:
434             try:
435                 if not is_ip6:
436                     self.assert_packet_checksums_valid(packet)
437                 self.assertEqual(packet[IP46].src, nat_ip)
438                 if dst_ip is not None:
439                     self.assertEqual(packet[IP46].dst, dst_ip)
440                 if packet.haslayer(TCP):
441                     if not ignore_port:
442                         if same_port:
443                             self.assertEqual(
444                                 packet[TCP].sport, self.tcp_port_in)
445                         else:
446                             self.assertNotEqual(
447                                 packet[TCP].sport, self.tcp_port_in)
448                     self.tcp_port_out = packet[TCP].sport
449                     self.assert_packet_checksums_valid(packet)
450                 elif packet.haslayer(UDP):
451                     if not ignore_port:
452                         if same_port:
453                             self.assertEqual(
454                                 packet[UDP].sport, self.udp_port_in)
455                         else:
456                             self.assertNotEqual(
457                                 packet[UDP].sport, self.udp_port_in)
458                     self.udp_port_out = packet[UDP].sport
459                 else:
460                     if not ignore_port:
461                         if same_port:
462                             self.assertEqual(
463                                 packet[ICMP46].id, self.icmp_id_in)
464                         else:
465                             self.assertNotEqual(
466                                 packet[ICMP46].id, self.icmp_id_in)
467                     self.icmp_id_out = packet[ICMP46].id
468                     self.assert_packet_checksums_valid(packet)
469             except:
470                 self.logger.error(ppp("Unexpected or invalid packet "
471                                       "(outside network):", packet))
472                 raise
473
474     def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
475                                dst_ip=None):
476         """
477         Verify captured packets on outside network
478
479         :param capture: Captured packets
480         :param nat_ip: Translated IP address
481         :param same_port: Source port number is not translated (Default False)
482         :param dst_ip: Destination IP address (Default do not verify)
483         """
484         return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
485                                        True)
486
487     def verify_capture_in(self, capture, in_if):
488         """
489         Verify captured packets on inside network
490
491         :param capture: Captured packets
492         :param in_if: Inside interface
493         """
494         for packet in capture:
495             try:
496                 self.assert_packet_checksums_valid(packet)
497                 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
498                 if packet.haslayer(TCP):
499                     self.assertEqual(packet[TCP].dport, self.tcp_port_in)
500                 elif packet.haslayer(UDP):
501                     self.assertEqual(packet[UDP].dport, self.udp_port_in)
502                 else:
503                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
504             except:
505                 self.logger.error(ppp("Unexpected or invalid packet "
506                                       "(inside network):", packet))
507                 raise
508
509     def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
510         """
511         Verify captured IPv6 packets on inside network
512
513         :param capture: Captured packets
514         :param src_ip: Source IP
515         :param dst_ip: Destination IP address
516         """
517         for packet in capture:
518             try:
519                 self.assertEqual(packet[IPv6].src, src_ip)
520                 self.assertEqual(packet[IPv6].dst, dst_ip)
521                 self.assert_packet_checksums_valid(packet)
522                 if packet.haslayer(TCP):
523                     self.assertEqual(packet[TCP].dport, self.tcp_port_in)
524                 elif packet.haslayer(UDP):
525                     self.assertEqual(packet[UDP].dport, self.udp_port_in)
526                 else:
527                     self.assertEqual(packet[ICMPv6EchoReply].id,
528                                      self.icmp_id_in)
529             except:
530                 self.logger.error(ppp("Unexpected or invalid packet "
531                                       "(inside network):", packet))
532                 raise
533
534     def verify_capture_no_translation(self, capture, ingress_if, egress_if):
535         """
536         Verify captured packet that don't have to be translated
537
538         :param capture: Captured packets
539         :param ingress_if: Ingress interface
540         :param egress_if: Egress interface
541         """
542         for packet in capture:
543             try:
544                 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
545                 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
546                 if packet.haslayer(TCP):
547                     self.assertEqual(packet[TCP].sport, self.tcp_port_in)
548                 elif packet.haslayer(UDP):
549                     self.assertEqual(packet[UDP].sport, self.udp_port_in)
550                 else:
551                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
552             except:
553                 self.logger.error(ppp("Unexpected or invalid packet "
554                                       "(inside network):", packet))
555                 raise
556
557     def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
558                                             icmp_type=11):
559         """
560         Verify captured packets with ICMP errors on outside network
561
562         :param capture: Captured packets
563         :param src_ip: Translated IP address or IP address of VPP
564                        (Default use global NAT address)
565         :param icmp_type: Type of error ICMP packet
566                           we are expecting (Default 11)
567         """
568         if src_ip is None:
569             src_ip = self.nat_addr
570         for packet in capture:
571             try:
572                 self.assertEqual(packet[IP].src, src_ip)
573                 self.assertEqual(packet.haslayer(ICMP), 1)
574                 icmp = packet[ICMP]
575                 self.assertEqual(icmp.type, icmp_type)
576                 self.assertTrue(icmp.haslayer(IPerror))
577                 inner_ip = icmp[IPerror]
578                 if inner_ip.haslayer(TCPerror):
579                     self.assertEqual(inner_ip[TCPerror].dport,
580                                      self.tcp_port_out)
581                 elif inner_ip.haslayer(UDPerror):
582                     self.assertEqual(inner_ip[UDPerror].dport,
583                                      self.udp_port_out)
584                 else:
585                     self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
586             except:
587                 self.logger.error(ppp("Unexpected or invalid packet "
588                                       "(outside network):", packet))
589                 raise
590
591     def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
592         """
593         Verify captured packets with ICMP errors on inside network
594
595         :param capture: Captured packets
596         :param in_if: Inside interface
597         :param icmp_type: Type of error ICMP packet
598                           we are expecting (Default 11)
599         """
600         for packet in capture:
601             try:
602                 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
603                 self.assertEqual(packet.haslayer(ICMP), 1)
604                 icmp = packet[ICMP]
605                 self.assertEqual(icmp.type, icmp_type)
606                 self.assertTrue(icmp.haslayer(IPerror))
607                 inner_ip = icmp[IPerror]
608                 if inner_ip.haslayer(TCPerror):
609                     self.assertEqual(inner_ip[TCPerror].sport,
610                                      self.tcp_port_in)
611                 elif inner_ip.haslayer(UDPerror):
612                     self.assertEqual(inner_ip[UDPerror].sport,
613                                      self.udp_port_in)
614                 else:
615                     self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
616             except:
617                 self.logger.error(ppp("Unexpected or invalid packet "
618                                       "(inside network):", packet))
619                 raise
620
621     def create_stream_frag(self, src_if, dst, sport, dport, data,
622                            proto=IP_PROTOS.tcp, echo_reply=False):
623         """
624         Create fragmented packet stream
625
626         :param src_if: Source interface
627         :param dst: Destination IPv4 address
628         :param sport: Source port
629         :param dport: Destination port
630         :param data: Payload data
631         :param proto: protocol (TCP, UDP, ICMP)
632         :param echo_reply: use echo_reply if protocol is ICMP
633         :returns: Fragments
634         """
635         if proto == IP_PROTOS.tcp:
636             p = (IP(src=src_if.remote_ip4, dst=dst) /
637                  TCP(sport=sport, dport=dport) /
638                  Raw(data))
639             p = p.__class__(scapy.compat.raw(p))
640             chksum = p[TCP].chksum
641             proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
642         elif proto == IP_PROTOS.udp:
643             proto_header = UDP(sport=sport, dport=dport)
644         elif proto == IP_PROTOS.icmp:
645             if not echo_reply:
646                 proto_header = ICMP(id=sport, type='echo-request')
647             else:
648                 proto_header = ICMP(id=sport, type='echo-reply')
649         else:
650             raise Exception("Unsupported protocol")
651         id = random.randint(0, 65535)
652         pkts = []
653         if proto == IP_PROTOS.tcp:
654             raw = Raw(data[0:4])
655         else:
656             raw = Raw(data[0:16])
657         p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
658              IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
659              proto_header /
660              raw)
661         pkts.append(p)
662         if proto == IP_PROTOS.tcp:
663             raw = Raw(data[4:20])
664         else:
665             raw = Raw(data[16:32])
666         p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
667              IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
668                 proto=proto) /
669              raw)
670         pkts.append(p)
671         if proto == IP_PROTOS.tcp:
672             raw = Raw(data[20:])
673         else:
674             raw = Raw(data[32:])
675         p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
676              IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
677                 id=id) /
678              raw)
679         pkts.append(p)
680         return pkts
681
682     def reass_frags_and_verify(self, frags, src, dst):
683         """
684         Reassemble and verify fragmented packet
685
686         :param frags: Captured fragments
687         :param src: Source IPv4 address to verify
688         :param dst: Destination IPv4 address to verify
689
690         :returns: Reassembled IPv4 packet
691         """
692         buffer = BytesIO()
693         for p in frags:
694             self.assertEqual(p[IP].src, src)
695             self.assertEqual(p[IP].dst, dst)
696             self.assert_ip_checksum_valid(p)
697             buffer.seek(p[IP].frag * 8)
698             buffer.write(bytes(p[IP].payload))
699         ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
700                 proto=frags[0][IP].proto)
701         if ip.proto == IP_PROTOS.tcp:
702             p = (ip / TCP(buffer.getvalue()))
703             self.logger.debug(ppp("Reassembled:", p))
704             self.assert_tcp_checksum_valid(p)
705         elif ip.proto == IP_PROTOS.udp:
706             p = (ip / UDP(buffer.getvalue()[:8]) /
707                  Raw(buffer.getvalue()[8:]))
708         elif ip.proto == IP_PROTOS.icmp:
709             p = (ip / ICMP(buffer.getvalue()))
710         return p
711
712     def reass_frags_and_verify_ip6(self, frags, src, dst):
713         """
714         Reassemble and verify fragmented packet
715
716         :param frags: Captured fragments
717         :param src: Source IPv6 address to verify
718         :param dst: Destination IPv6 address to verify
719
720         :returns: Reassembled IPv6 packet
721         """
722         buffer = BytesIO()
723         for p in frags:
724             self.assertEqual(p[IPv6].src, src)
725             self.assertEqual(p[IPv6].dst, dst)
726             buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
727             buffer.write(bytes(p[IPv6ExtHdrFragment].payload))
728         ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
729                   nh=frags[0][IPv6ExtHdrFragment].nh)
730         if ip.nh == IP_PROTOS.tcp:
731             p = (ip / TCP(buffer.getvalue()))
732         elif ip.nh == IP_PROTOS.udp:
733             p = (ip / UDP(buffer.getvalue()))
734         self.logger.debug(ppp("Reassembled:", p))
735         self.assert_packet_checksums_valid(p)
736         return p
737
738     def initiate_tcp_session(self, in_if, out_if):
739         """
740         Initiates TCP session
741
742         :param in_if: Inside interface
743         :param out_if: Outside interface
744         """
745         try:
746             # SYN packet in->out
747             p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
748                  IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
749                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
750                      flags="S"))
751             in_if.add_stream(p)
752             self.pg_enable_capture(self.pg_interfaces)
753             self.pg_start()
754             capture = out_if.get_capture(1)
755             p = capture[0]
756             self.tcp_port_out = p[TCP].sport
757
758             # SYN + ACK packet out->in
759             p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
760                  IP(src=out_if.remote_ip4, dst=self.nat_addr) /
761                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
762                      flags="SA"))
763             out_if.add_stream(p)
764             self.pg_enable_capture(self.pg_interfaces)
765             self.pg_start()
766             in_if.get_capture(1)
767
768             # ACK packet in->out
769             p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
770                  IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
771                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
772                      flags="A"))
773             in_if.add_stream(p)
774             self.pg_enable_capture(self.pg_interfaces)
775             self.pg_start()
776             out_if.get_capture(1)
777
778         except:
779             self.logger.error("TCP 3 way handshake failed")
780             raise
781
782     def verify_ipfix_nat44_ses(self, data):
783         """
784         Verify IPFIX NAT44 session create/delete event
785
786         :param data: Decoded IPFIX data records
787         """
788         nat44_ses_create_num = 0
789         nat44_ses_delete_num = 0
790         self.assertEqual(6, len(data))
791         for record in data:
792             # natEvent
793             self.assertIn(scapy.compat.orb(record[230]), [4, 5])
794             if scapy.compat.orb(record[230]) == 4:
795                 nat44_ses_create_num += 1
796             else:
797                 nat44_ses_delete_num += 1
798             # sourceIPv4Address
799             self.assertEqual(self.pg0.remote_ip4,
800                              str(ipaddress.IPv4Address(record[8])))
801             # postNATSourceIPv4Address
802             self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
803                              record[225])
804             # ingressVRFID
805             self.assertEqual(struct.pack("!I", 0), record[234])
806             # protocolIdentifier/sourceTransportPort
807             # /postNAPTSourceTransportPort
808             if IP_PROTOS.icmp == scapy.compat.orb(record[4]):
809                 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
810                 self.assertEqual(struct.pack("!H", self.icmp_id_out),
811                                  record[227])
812             elif IP_PROTOS.tcp == scapy.compat.orb(record[4]):
813                 self.assertEqual(struct.pack("!H", self.tcp_port_in),
814                                  record[7])
815                 self.assertEqual(struct.pack("!H", self.tcp_port_out),
816                                  record[227])
817             elif IP_PROTOS.udp == scapy.compat.orb(record[4]):
818                 self.assertEqual(struct.pack("!H", self.udp_port_in),
819                                  record[7])
820                 self.assertEqual(struct.pack("!H", self.udp_port_out),
821                                  record[227])
822             else:
823                 self.fail("Invalid protocol")
824         self.assertEqual(3, nat44_ses_create_num)
825         self.assertEqual(3, nat44_ses_delete_num)
826
827     def verify_ipfix_addr_exhausted(self, data):
828         """
829         Verify IPFIX NAT addresses event
830
831         :param data: Decoded IPFIX data records
832         """
833         self.assertEqual(1, len(data))
834         record = data[0]
835         # natEvent
836         self.assertEqual(scapy.compat.orb(record[230]), 3)
837         # natPoolID
838         self.assertEqual(struct.pack("!I", 0), record[283])
839
840     def verify_ipfix_max_sessions(self, data, limit):
841         """
842         Verify IPFIX maximum session entries exceeded event
843
844         :param data: Decoded IPFIX data records
845         :param limit: Number of maximum session entries that can be created.
846         """
847         self.assertEqual(1, len(data))
848         record = data[0]
849         # natEvent
850         self.assertEqual(scapy.compat.orb(record[230]), 13)
851         # natQuotaExceededEvent
852         self.assertEqual(struct.pack("I", 1), record[466])
853         # maxSessionEntries
854         self.assertEqual(struct.pack("I", limit), record[471])
855
856     def verify_ipfix_max_bibs(self, data, limit):
857         """
858         Verify IPFIX maximum BIB entries exceeded event
859
860         :param data: Decoded IPFIX data records
861         :param limit: Number of maximum BIB entries that can be created.
862         """
863         self.assertEqual(1, len(data))
864         record = data[0]
865         # natEvent
866         self.assertEqual(scapy.compat.orb(record[230]), 13)
867         # natQuotaExceededEvent
868         self.assertEqual(struct.pack("I", 2), record[466])
869         # maxBIBEntries
870         self.assertEqual(struct.pack("I", limit), record[472])
871
872     def verify_no_nat44_user(self):
873         """ Verify that there is no NAT44 user """
874         users = self.vapi.nat44_user_dump()
875         self.assertEqual(len(users), 0)
876         users = self.statistics.get_counter('/nat44/total-users')
877         self.assertEqual(users[0][0], 0)
878         sessions = self.statistics.get_counter('/nat44/total-sessions')
879         self.assertEqual(sessions[0][0], 0)
880
881     def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
882         """
883         Verify IPFIX maximum entries per user exceeded event
884
885         :param data: Decoded IPFIX data records
886         :param limit: Number of maximum entries per user
887         :param src_addr: IPv4 source address
888         """
889         self.assertEqual(1, len(data))
890         record = data[0]
891         # natEvent
892         self.assertEqual(scapy.compat.orb(record[230]), 13)
893         # natQuotaExceededEvent
894         self.assertEqual(struct.pack("I", 3), record[466])
895         # maxEntriesPerUser
896         self.assertEqual(struct.pack("I", limit), record[473])
897         # sourceIPv4Address
898         self.assertEqual(socket.inet_pton(socket.AF_INET, src_addr), record[8])
899
900     def verify_syslog_apmap(self, data, is_add=True):
901         message = data.decode('utf-8')
902         try:
903             message = SyslogMessage.parse(message)
904         except ParseError as e:
905             self.logger.error(e)
906             raise
907         else:
908             self.assertEqual(message.severity, SyslogSeverity.info)
909             self.assertEqual(message.appname, 'NAT')
910             self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
911             sd_params = message.sd.get('napmap')
912             self.assertTrue(sd_params is not None)
913             self.assertEqual(sd_params.get('IATYP'), 'IPv4')
914             self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
915             self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
916             self.assertEqual(sd_params.get('XATYP'), 'IPv4')
917             self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
918             self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
919             self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
920             self.assertTrue(sd_params.get('SSUBIX') is not None)
921             self.assertEqual(sd_params.get('SVLAN'), '0')
922
923     def verify_syslog_sess(self, data, is_add=True, is_ip6=False):
924         message = data.decode('utf-8')
925         try:
926             message = SyslogMessage.parse(message)
927         except ParseError as e:
928             self.logger.error(e)
929             raise
930         else:
931             self.assertEqual(message.severity, SyslogSeverity.info)
932             self.assertEqual(message.appname, 'NAT')
933             self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL')
934             sd_params = message.sd.get('nsess')
935             self.assertTrue(sd_params is not None)
936             if is_ip6:
937                 self.assertEqual(sd_params.get('IATYP'), 'IPv6')
938                 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
939             else:
940                 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
941                 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
942                 self.assertTrue(sd_params.get('SSUBIX') is not None)
943             self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
944             self.assertEqual(sd_params.get('XATYP'), 'IPv4')
945             self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
946             self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
947             self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
948             self.assertEqual(sd_params.get('SVLAN'), '0')
949             self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
950             self.assertEqual(sd_params.get('XDPORT'),
951                              "%d" % self.tcp_external_port)
952
953     def verify_mss_value(self, pkt, mss):
954         """
955         Verify TCP MSS value
956
957         :param pkt:
958         :param mss:
959         """
960         if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
961             raise TypeError("Not a TCP/IP packet")
962
963         for option in pkt[TCP].options:
964             if option[0] == 'MSS':
965                 self.assertEqual(option[1], mss)
966                 self.assert_tcp_checksum_valid(pkt)
967
968     @staticmethod
969     def proto2layer(proto):
970         if proto == IP_PROTOS.tcp:
971             return TCP
972         elif proto == IP_PROTOS.udp:
973             return UDP
974         elif proto == IP_PROTOS.icmp:
975             return ICMP
976         else:
977             raise Exception("Unsupported protocol")
978
979     def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False,
980                       ignore_port=False):
981         layer = self.proto2layer(proto)
982
983         if proto == IP_PROTOS.tcp:
984             data = b"A" * 4 + b"B" * 16 + b"C" * 3
985         else:
986             data = b"A" * 16 + b"B" * 16 + b"C" * 3
987         self.port_in = random.randint(1025, 65535)
988
989         # in2out
990         pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
991                                        self.port_in, 20, data, proto)
992         self.pg0.add_stream(pkts)
993         self.pg_enable_capture(self.pg_interfaces)
994         self.pg_start()
995         frags = self.pg1.get_capture(len(pkts))
996         if not dont_translate:
997             p = self.reass_frags_and_verify(frags,
998                                             self.nat_addr,
999                                             self.pg1.remote_ip4)
1000         else:
1001             p = self.reass_frags_and_verify(frags,
1002                                             self.pg0.remote_ip4,
1003                                             self.pg1.remote_ip4)
1004         if proto != IP_PROTOS.icmp:
1005             if not dont_translate:
1006                 self.assertEqual(p[layer].dport, 20)
1007                 if not ignore_port:
1008                     self.assertNotEqual(p[layer].sport, self.port_in)
1009             else:
1010                 self.assertEqual(p[layer].sport, self.port_in)
1011         else:
1012             if not ignore_port:
1013                 if not dont_translate:
1014                     self.assertNotEqual(p[layer].id, self.port_in)
1015                 else:
1016                     self.assertEqual(p[layer].id, self.port_in)
1017         self.assertEqual(data, p[Raw].load)
1018
1019         # out2in
1020         if not dont_translate:
1021             dst_addr = self.nat_addr
1022         else:
1023             dst_addr = self.pg0.remote_ip4
1024         if proto != IP_PROTOS.icmp:
1025             sport = 20
1026             dport = p[layer].sport
1027         else:
1028             sport = p[layer].id
1029             dport = 0
1030         pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport, data,
1031                                        proto, echo_reply=True)
1032         self.pg1.add_stream(pkts)
1033         self.pg_enable_capture(self.pg_interfaces)
1034         self.pg_start()
1035         frags = self.pg0.get_capture(len(pkts))
1036         p = self.reass_frags_and_verify(frags,
1037                                         self.pg1.remote_ip4,
1038                                         self.pg0.remote_ip4)
1039         if proto != IP_PROTOS.icmp:
1040             self.assertEqual(p[layer].sport, 20)
1041             self.assertEqual(p[layer].dport, self.port_in)
1042         else:
1043             self.assertEqual(p[layer].id, self.port_in)
1044         self.assertEqual(data, p[Raw].load)
1045
1046     def frag_in_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1047         layer = self.proto2layer(proto)
1048
1049         if proto == IP_PROTOS.tcp:
1050             data = b"A" * 4 + b"B" * 16 + b"C" * 3
1051         else:
1052             data = b"A" * 16 + b"B" * 16 + b"C" * 3
1053         self.port_in = random.randint(1025, 65535)
1054
1055         for i in range(2):
1056             # out2in
1057             pkts = self.create_stream_frag(self.pg0, self.server_out_addr,
1058                                            self.port_in, self.server_out_port,
1059                                            data, proto)
1060             self.pg0.add_stream(pkts)
1061             self.pg_enable_capture(self.pg_interfaces)
1062             self.pg_start()
1063             frags = self.pg1.get_capture(len(pkts))
1064             p = self.reass_frags_and_verify(frags,
1065                                             self.pg0.remote_ip4,
1066                                             self.server_in_addr)
1067             if proto != IP_PROTOS.icmp:
1068                 self.assertEqual(p[layer].sport, self.port_in)
1069                 self.assertEqual(p[layer].dport, self.server_in_port)
1070             else:
1071                 self.assertEqual(p[layer].id, self.port_in)
1072             self.assertEqual(data, p[Raw].load)
1073
1074             # in2out
1075             if proto != IP_PROTOS.icmp:
1076                 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1077                                                self.server_in_port,
1078                                                p[layer].sport, data, proto)
1079             else:
1080                 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1081                                                p[layer].id, 0, data, proto,
1082                                                echo_reply=True)
1083             self.pg1.add_stream(pkts)
1084             self.pg_enable_capture(self.pg_interfaces)
1085             self.pg_start()
1086             frags = self.pg0.get_capture(len(pkts))
1087             p = self.reass_frags_and_verify(frags,
1088                                             self.server_out_addr,
1089                                             self.pg0.remote_ip4)
1090             if proto != IP_PROTOS.icmp:
1091                 self.assertEqual(p[layer].sport, self.server_out_port)
1092                 self.assertEqual(p[layer].dport, self.port_in)
1093             else:
1094                 self.assertEqual(p[layer].id, self.port_in)
1095             self.assertEqual(data, p[Raw].load)
1096
1097     def reass_hairpinning(self, proto=IP_PROTOS.tcp, ignore_port=False):
1098         layer = self.proto2layer(proto)
1099
1100         if proto == IP_PROTOS.tcp:
1101             data = b"A" * 4 + b"B" * 16 + b"C" * 3
1102         else:
1103             data = b"A" * 16 + b"B" * 16 + b"C" * 3
1104
1105         # send packet from host to server
1106         pkts = self.create_stream_frag(self.pg0,
1107                                        self.nat_addr,
1108                                        self.host_in_port,
1109                                        self.server_out_port,
1110                                        data,
1111                                        proto)
1112         self.pg0.add_stream(pkts)
1113         self.pg_enable_capture(self.pg_interfaces)
1114         self.pg_start()
1115         frags = self.pg0.get_capture(len(pkts))
1116         p = self.reass_frags_and_verify(frags,
1117                                         self.nat_addr,
1118                                         self.server.ip4)
1119         if proto != IP_PROTOS.icmp:
1120             if not ignore_port:
1121                 self.assertNotEqual(p[layer].sport, self.host_in_port)
1122             self.assertEqual(p[layer].dport, self.server_in_port)
1123         else:
1124             if not ignore_port:
1125                 self.assertNotEqual(p[layer].id, self.host_in_port)
1126         self.assertEqual(data, p[Raw].load)
1127
1128     def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False,
1129                           ignore_port=False):
1130         layer = self.proto2layer(proto)
1131
1132         if proto == IP_PROTOS.tcp:
1133             data = b"A" * 4 + b"B" * 16 + b"C" * 3
1134         else:
1135             data = b"A" * 16 + b"B" * 16 + b"C" * 3
1136         self.port_in = random.randint(1025, 65535)
1137
1138         for i in range(2):
1139             # in2out
1140             pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
1141                                            self.port_in, 20, data, proto)
1142             pkts.reverse()
1143             self.pg0.add_stream(pkts)
1144             self.pg_enable_capture(self.pg_interfaces)
1145             self.pg_start()
1146             frags = self.pg1.get_capture(len(pkts))
1147             if not dont_translate:
1148                 p = self.reass_frags_and_verify(frags,
1149                                                 self.nat_addr,
1150                                                 self.pg1.remote_ip4)
1151             else:
1152                 p = self.reass_frags_and_verify(frags,
1153                                                 self.pg0.remote_ip4,
1154                                                 self.pg1.remote_ip4)
1155             if proto != IP_PROTOS.icmp:
1156                 if not dont_translate:
1157                     self.assertEqual(p[layer].dport, 20)
1158                     if not ignore_port:
1159                         self.assertNotEqual(p[layer].sport, self.port_in)
1160                 else:
1161                     self.assertEqual(p[layer].sport, self.port_in)
1162             else:
1163                 if not ignore_port:
1164                     if not dont_translate:
1165                         self.assertNotEqual(p[layer].id, self.port_in)
1166                     else:
1167                         self.assertEqual(p[layer].id, self.port_in)
1168             self.assertEqual(data, p[Raw].load)
1169
1170             # out2in
1171             if not dont_translate:
1172                 dst_addr = self.nat_addr
1173             else:
1174                 dst_addr = self.pg0.remote_ip4
1175             if proto != IP_PROTOS.icmp:
1176                 sport = 20
1177                 dport = p[layer].sport
1178             else:
1179                 sport = p[layer].id
1180                 dport = 0
1181             pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport,
1182                                            data, proto, echo_reply=True)
1183             pkts.reverse()
1184             self.pg1.add_stream(pkts)
1185             self.pg_enable_capture(self.pg_interfaces)
1186             self.pg_start()
1187             frags = self.pg0.get_capture(len(pkts))
1188             p = self.reass_frags_and_verify(frags,
1189                                             self.pg1.remote_ip4,
1190                                             self.pg0.remote_ip4)
1191             if proto != IP_PROTOS.icmp:
1192                 self.assertEqual(p[layer].sport, 20)
1193                 self.assertEqual(p[layer].dport, self.port_in)
1194             else:
1195                 self.assertEqual(p[layer].id, self.port_in)
1196             self.assertEqual(data, p[Raw].load)
1197
1198     def frag_out_of_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1199         layer = self.proto2layer(proto)
1200
1201         if proto == IP_PROTOS.tcp:
1202             data = b"A" * 4 + b"B" * 16 + b"C" * 3
1203         else:
1204             data = b"A" * 16 + b"B" * 16 + b"C" * 3
1205         self.port_in = random.randint(1025, 65535)
1206
1207         for i in range(2):
1208             # out2in
1209             pkts = self.create_stream_frag(self.pg0, self.server_out_addr,
1210                                            self.port_in, self.server_out_port,
1211                                            data, proto)
1212             pkts.reverse()
1213             self.pg0.add_stream(pkts)
1214             self.pg_enable_capture(self.pg_interfaces)
1215             self.pg_start()
1216             frags = self.pg1.get_capture(len(pkts))
1217             p = self.reass_frags_and_verify(frags,
1218                                             self.pg0.remote_ip4,
1219                                             self.server_in_addr)
1220             if proto != IP_PROTOS.icmp:
1221                 self.assertEqual(p[layer].dport, self.server_in_port)
1222                 self.assertEqual(p[layer].sport, self.port_in)
1223                 self.assertEqual(p[layer].dport, self.server_in_port)
1224             else:
1225                 self.assertEqual(p[layer].id, self.port_in)
1226             self.assertEqual(data, p[Raw].load)
1227
1228             # in2out
1229             if proto != IP_PROTOS.icmp:
1230                 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1231                                                self.server_in_port,
1232                                                p[layer].sport, data, proto)
1233             else:
1234                 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1235                                                p[layer].id, 0, data, proto,
1236                                                echo_reply=True)
1237             pkts.reverse()
1238             self.pg1.add_stream(pkts)
1239             self.pg_enable_capture(self.pg_interfaces)
1240             self.pg_start()
1241             frags = self.pg0.get_capture(len(pkts))
1242             p = self.reass_frags_and_verify(frags,
1243                                             self.server_out_addr,
1244                                             self.pg0.remote_ip4)
1245             if proto != IP_PROTOS.icmp:
1246                 self.assertEqual(p[layer].sport, self.server_out_port)
1247                 self.assertEqual(p[layer].dport, self.port_in)
1248             else:
1249                 self.assertEqual(p[layer].id, self.port_in)
1250             self.assertEqual(data, p[Raw].load)
1251
1252
1253 class TestNATMisc(MethodHolder):
1254     """ NAT misc Test Cases """
1255
1256     max_translations = 10240
1257     max_users = 10240
1258
1259     @classmethod
1260     def setUpConstants(cls):
1261         super(TestNATMisc, cls).setUpConstants()
1262         cls.vpp_cmdline.extend([
1263             "nat", "{",
1264             "max translations per thread %d" % cls.max_translations,
1265             "max users per thread %d" % cls.max_users,
1266             "}"
1267         ])
1268
1269     @classmethod
1270     def tearDownClass(cls):
1271         super(TestNATMisc, cls).tearDownClass()
1272
1273     def test_show_config(self):
1274         """ NAT config translation memory """
1275
1276         nat_config = self.vapi.nat_show_config()
1277         mem = nat_config.translation_memory_size
1278         self.assertTrue(mem > 0)
1279         self.logger.info("max translation memory: %d" % mem)
1280
1281     def test_show_config_2(self):
1282         """ NAT config2 translation memory """
1283
1284         nat_config = self.vapi.nat_show_config_2()
1285         mem = nat_config.translation_memory_size
1286         self.assertTrue(mem > 0)
1287         self.logger.info("max translation memory: %d" % mem)
1288
1289     def test_show_max_translations(self):
1290         """ API test - max translations per thread """
1291         nat_config = self.vapi.nat_show_config_2()
1292         self.assertEqual(self.max_translations,
1293                          nat_config.max_translations_per_thread)
1294
1295
1296 class TestNAT44(MethodHolder):
1297     """ NAT44 Test Cases """
1298
1299     max_translations = 10240
1300     max_users = 10240
1301
1302     @classmethod
1303     def setUpConstants(cls):
1304         super(TestNAT44, cls).setUpConstants()
1305         cls.vpp_cmdline.extend([
1306             "nat", "{",
1307             "max translations per thread %d" % cls.max_translations,
1308             "max users per thread %d" % cls.max_users,
1309             "}"
1310         ])
1311
1312     @classmethod
1313     def setUpClass(cls):
1314         super(TestNAT44, cls).setUpClass()
1315         cls.vapi.cli("set log class nat level debug")
1316
1317         cls.tcp_port_in = 6303
1318         cls.tcp_port_out = 6303
1319         cls.udp_port_in = 6304
1320         cls.udp_port_out = 6304
1321         cls.icmp_id_in = 6305
1322         cls.icmp_id_out = 6305
1323         cls.nat_addr = '10.0.0.3'
1324         cls.ipfix_src_port = 4739
1325         cls.ipfix_domain_id = 1
1326         cls.tcp_external_port = 80
1327         cls.udp_external_port = 69
1328
1329         cls.create_pg_interfaces(range(10))
1330         cls.interfaces = list(cls.pg_interfaces[0:4])
1331
1332         for i in cls.interfaces:
1333             i.admin_up()
1334             i.config_ip4()
1335             i.resolve_arp()
1336
1337         cls.pg0.generate_remote_hosts(3)
1338         cls.pg0.configure_ipv4_neighbors()
1339
1340         cls.pg1.generate_remote_hosts(1)
1341         cls.pg1.configure_ipv4_neighbors()
1342
1343         cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
1344         cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 10})
1345         cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 20})
1346
1347         cls.pg4._local_ip4 = "172.16.255.1"
1348         cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1349         cls.pg4.set_table_ip4(10)
1350         cls.pg5._local_ip4 = "172.17.255.3"
1351         cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
1352         cls.pg5.set_table_ip4(10)
1353         cls.pg6._local_ip4 = "172.16.255.1"
1354         cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1355         cls.pg6.set_table_ip4(20)
1356         for i in cls.overlapping_interfaces:
1357             i.config_ip4()
1358             i.admin_up()
1359             i.resolve_arp()
1360
1361         cls.pg7.admin_up()
1362         cls.pg8.admin_up()
1363
1364         cls.pg9.generate_remote_hosts(2)
1365         cls.pg9.config_ip4()
1366         cls.vapi.sw_interface_add_del_address(
1367             sw_if_index=cls.pg9.sw_if_index,
1368             prefix="10.0.0.1/24")
1369
1370         cls.pg9.admin_up()
1371         cls.pg9.resolve_arp()
1372         cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1373         cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1374         cls.pg9.resolve_arp()
1375
1376     @classmethod
1377     def tearDownClass(cls):
1378         super(TestNAT44, cls).tearDownClass()
1379
1380     def test_clear_sessions(self):
1381         """ NAT44 session clearing test """
1382
1383         self.nat44_add_address(self.nat_addr)
1384         flags = self.config_flags.NAT_IS_INSIDE
1385         self.vapi.nat44_interface_add_del_feature(
1386             sw_if_index=self.pg0.sw_if_index,
1387             flags=flags, is_add=1)
1388         self.vapi.nat44_interface_add_del_feature(
1389             sw_if_index=self.pg1.sw_if_index,
1390             is_add=1)
1391
1392         nat_config = self.vapi.nat_show_config()
1393         self.assertEqual(0, nat_config.endpoint_dependent)
1394
1395         pkts = self.create_stream_in(self.pg0, self.pg1)
1396         self.pg0.add_stream(pkts)
1397         self.pg_enable_capture(self.pg_interfaces)
1398         self.pg_start()
1399         capture = self.pg1.get_capture(len(pkts))
1400         self.verify_capture_out(capture)
1401
1402         sessions = self.statistics.get_counter('/nat44/total-sessions')
1403         self.assertTrue(sessions[0][0] > 0)
1404         self.logger.info("sessions before clearing: %s" % sessions[0][0])
1405
1406         self.vapi.cli("clear nat44 sessions")
1407
1408         sessions = self.statistics.get_counter('/nat44/total-sessions')
1409         self.assertEqual(sessions[0][0], 0)
1410         self.logger.info("sessions after clearing: %s" % sessions[0][0])
1411
1412     def test_dynamic(self):
1413         """ NAT44 dynamic translation test """
1414         self.nat44_add_address(self.nat_addr)
1415         flags = self.config_flags.NAT_IS_INSIDE
1416         self.vapi.nat44_interface_add_del_feature(
1417             sw_if_index=self.pg0.sw_if_index,
1418             flags=flags, is_add=1)
1419         self.vapi.nat44_interface_add_del_feature(
1420             sw_if_index=self.pg1.sw_if_index,
1421             is_add=1)
1422
1423         # in2out
1424         tcpn = self.statistics.get_counter('/nat44/in2out/slowpath/tcp')[0]
1425         udpn = self.statistics.get_counter('/nat44/in2out/slowpath/udp')[0]
1426         icmpn = self.statistics.get_counter('/nat44/in2out/slowpath/icmp')[0]
1427         drops = self.statistics.get_counter('/nat44/in2out/slowpath/drops')[0]
1428
1429         pkts = self.create_stream_in(self.pg0, self.pg1)
1430         self.pg0.add_stream(pkts)
1431         self.pg_enable_capture(self.pg_interfaces)
1432         self.pg_start()
1433         capture = self.pg1.get_capture(len(pkts))
1434         self.verify_capture_out(capture)
1435
1436         if_idx = self.pg0.sw_if_index
1437         cnt = self.statistics.get_counter('/nat44/in2out/slowpath/tcp')[0]
1438         self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
1439         cnt = self.statistics.get_counter('/nat44/in2out/slowpath/udp')[0]
1440         self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
1441         cnt = self.statistics.get_counter('/nat44/in2out/slowpath/icmp')[0]
1442         self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
1443         cnt = self.statistics.get_counter('/nat44/in2out/slowpath/drops')[0]
1444         self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
1445
1446         # out2in
1447         tcpn = self.statistics.get_counter('/nat44/out2in/slowpath/tcp')[0]
1448         udpn = self.statistics.get_counter('/nat44/out2in/slowpath/udp')[0]
1449         icmpn = self.statistics.get_counter('/nat44/out2in/slowpath/icmp')[0]
1450         drops = self.statistics.get_counter('/nat44/out2in/slowpath/drops')[0]
1451
1452         pkts = self.create_stream_out(self.pg1)
1453         self.pg1.add_stream(pkts)
1454         self.pg_enable_capture(self.pg_interfaces)
1455         self.pg_start()
1456         capture = self.pg0.get_capture(len(pkts))
1457         self.verify_capture_in(capture, self.pg0)
1458
1459         if_idx = self.pg1.sw_if_index
1460         cnt = self.statistics.get_counter('/nat44/out2in/slowpath/tcp')[0]
1461         self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
1462         cnt = self.statistics.get_counter('/nat44/out2in/slowpath/udp')[0]
1463         self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
1464         cnt = self.statistics.get_counter('/nat44/out2in/slowpath/icmp')[0]
1465         self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
1466         cnt = self.statistics.get_counter('/nat44/out2in/slowpath/drops')[0]
1467         self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
1468
1469         users = self.statistics.get_counter('/nat44/total-users')
1470         self.assertEqual(users[0][0], 1)
1471         sessions = self.statistics.get_counter('/nat44/total-sessions')
1472         self.assertEqual(sessions[0][0], 3)
1473
1474     def test_dynamic_icmp_errors_in2out_ttl_1(self):
1475         """ NAT44 handling of client packets with TTL=1 """
1476
1477         self.nat44_add_address(self.nat_addr)
1478         flags = self.config_flags.NAT_IS_INSIDE
1479         self.vapi.nat44_interface_add_del_feature(
1480             sw_if_index=self.pg0.sw_if_index,
1481             flags=flags, is_add=1)
1482         self.vapi.nat44_interface_add_del_feature(
1483             sw_if_index=self.pg1.sw_if_index,
1484             is_add=1)
1485
1486         # Client side - generate traffic
1487         pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1488         self.pg0.add_stream(pkts)
1489         self.pg_enable_capture(self.pg_interfaces)
1490         self.pg_start()
1491
1492         # Client side - verify ICMP type 11 packets
1493         capture = self.pg0.get_capture(len(pkts))
1494         self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1495
1496     def test_dynamic_icmp_errors_out2in_ttl_1(self):
1497         """ NAT44 handling of server packets with TTL=1 """
1498
1499         self.nat44_add_address(self.nat_addr)
1500         flags = self.config_flags.NAT_IS_INSIDE
1501         self.vapi.nat44_interface_add_del_feature(
1502             sw_if_index=self.pg0.sw_if_index,
1503             flags=flags, is_add=1)
1504         self.vapi.nat44_interface_add_del_feature(
1505             sw_if_index=self.pg1.sw_if_index,
1506             is_add=1)
1507
1508         # Client side - create sessions
1509         pkts = self.create_stream_in(self.pg0, self.pg1)
1510         self.pg0.add_stream(pkts)
1511         self.pg_enable_capture(self.pg_interfaces)
1512         self.pg_start()
1513
1514         # Server side - generate traffic
1515         capture = self.pg1.get_capture(len(pkts))
1516         self.verify_capture_out(capture)
1517         pkts = self.create_stream_out(self.pg1, ttl=1)
1518         self.pg1.add_stream(pkts)
1519         self.pg_enable_capture(self.pg_interfaces)
1520         self.pg_start()
1521
1522         # Server side - verify ICMP type 11 packets
1523         capture = self.pg1.get_capture(len(pkts))
1524         self.verify_capture_out_with_icmp_errors(capture,
1525                                                  src_ip=self.pg1.local_ip4)
1526
1527     def test_dynamic_icmp_errors_in2out_ttl_2(self):
1528         """ NAT44 handling of error responses to client packets with TTL=2 """
1529
1530         self.nat44_add_address(self.nat_addr)
1531         flags = self.config_flags.NAT_IS_INSIDE
1532         self.vapi.nat44_interface_add_del_feature(
1533             sw_if_index=self.pg0.sw_if_index,
1534             flags=flags, is_add=1)
1535         self.vapi.nat44_interface_add_del_feature(
1536             sw_if_index=self.pg1.sw_if_index,
1537             is_add=1)
1538
1539         # Client side - generate traffic
1540         pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1541         self.pg0.add_stream(pkts)
1542         self.pg_enable_capture(self.pg_interfaces)
1543         self.pg_start()
1544
1545         # Server side - simulate ICMP type 11 response
1546         capture = self.pg1.get_capture(len(pkts))
1547         pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1548                 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1549                 ICMP(type=11) / packet[IP] for packet in capture]
1550         self.pg1.add_stream(pkts)
1551         self.pg_enable_capture(self.pg_interfaces)
1552         self.pg_start()
1553
1554         # Client side - verify ICMP type 11 packets
1555         capture = self.pg0.get_capture(len(pkts))
1556         self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1557
1558     def test_dynamic_icmp_errors_out2in_ttl_2(self):
1559         """ NAT44 handling of error responses to server packets with TTL=2 """
1560
1561         self.nat44_add_address(self.nat_addr)
1562         flags = self.config_flags.NAT_IS_INSIDE
1563         self.vapi.nat44_interface_add_del_feature(
1564             sw_if_index=self.pg0.sw_if_index,
1565             flags=flags, is_add=1)
1566         self.vapi.nat44_interface_add_del_feature(
1567             sw_if_index=self.pg1.sw_if_index,
1568             is_add=1)
1569
1570         # Client side - create sessions
1571         pkts = self.create_stream_in(self.pg0, self.pg1)
1572         self.pg0.add_stream(pkts)
1573         self.pg_enable_capture(self.pg_interfaces)
1574         self.pg_start()
1575
1576         # Server side - generate traffic
1577         capture = self.pg1.get_capture(len(pkts))
1578         self.verify_capture_out(capture)
1579         pkts = self.create_stream_out(self.pg1, ttl=2)
1580         self.pg1.add_stream(pkts)
1581         self.pg_enable_capture(self.pg_interfaces)
1582         self.pg_start()
1583
1584         # Client side - simulate ICMP type 11 response
1585         capture = self.pg0.get_capture(len(pkts))
1586         pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1587                 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1588                 ICMP(type=11) / packet[IP] for packet in capture]
1589         self.pg0.add_stream(pkts)
1590         self.pg_enable_capture(self.pg_interfaces)
1591         self.pg_start()
1592
1593         # Server side - verify ICMP type 11 packets
1594         capture = self.pg1.get_capture(len(pkts))
1595         self.verify_capture_out_with_icmp_errors(capture)
1596
1597     def test_ping_out_interface_from_outside(self):
1598         """ Ping NAT44 out interface from outside network """
1599
1600         self.nat44_add_address(self.nat_addr)
1601         flags = self.config_flags.NAT_IS_INSIDE
1602         self.vapi.nat44_interface_add_del_feature(
1603             sw_if_index=self.pg0.sw_if_index,
1604             flags=flags, is_add=1)
1605         self.vapi.nat44_interface_add_del_feature(
1606             sw_if_index=self.pg1.sw_if_index,
1607             is_add=1)
1608
1609         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1610              IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1611              ICMP(id=self.icmp_id_out, type='echo-request'))
1612         pkts = [p]
1613         self.pg1.add_stream(pkts)
1614         self.pg_enable_capture(self.pg_interfaces)
1615         self.pg_start()
1616         capture = self.pg1.get_capture(len(pkts))
1617         packet = capture[0]
1618         try:
1619             self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1620             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1621             self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1622             self.assertEqual(packet[ICMP].type, 0)  # echo reply
1623         except:
1624             self.logger.error(ppp("Unexpected or invalid packet "
1625                                   "(outside network):", packet))
1626             raise
1627
1628     def test_ping_internal_host_from_outside(self):
1629         """ Ping internal host from outside network """
1630
1631         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1632         flags = self.config_flags.NAT_IS_INSIDE
1633         self.vapi.nat44_interface_add_del_feature(
1634             sw_if_index=self.pg0.sw_if_index,
1635             flags=flags, is_add=1)
1636         self.vapi.nat44_interface_add_del_feature(
1637             sw_if_index=self.pg1.sw_if_index,
1638             is_add=1)
1639
1640         # out2in
1641         pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1642                IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
1643                ICMP(id=self.icmp_id_out, type='echo-request'))
1644         self.pg1.add_stream(pkt)
1645         self.pg_enable_capture(self.pg_interfaces)
1646         self.pg_start()
1647         capture = self.pg0.get_capture(1)
1648         self.verify_capture_in(capture, self.pg0)
1649         self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1650
1651         # in2out
1652         pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1653                IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1654                ICMP(id=self.icmp_id_in, type='echo-reply'))
1655         self.pg0.add_stream(pkt)
1656         self.pg_enable_capture(self.pg_interfaces)
1657         self.pg_start()
1658         capture = self.pg1.get_capture(1)
1659         self.verify_capture_out(capture, same_port=True)
1660         self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1661
1662     def test_forwarding(self):
1663         """ NAT44 forwarding test """
1664
1665         flags = self.config_flags.NAT_IS_INSIDE
1666         self.vapi.nat44_interface_add_del_feature(
1667             sw_if_index=self.pg0.sw_if_index,
1668             flags=flags, is_add=1)
1669         self.vapi.nat44_interface_add_del_feature(
1670             sw_if_index=self.pg1.sw_if_index,
1671             is_add=1)
1672         self.vapi.nat44_forwarding_enable_disable(enable=1)
1673
1674         real_ip = self.pg0.remote_ip4
1675         alias_ip = self.nat_addr
1676         flags = self.config_flags.NAT_IS_ADDR_ONLY
1677         self.vapi.nat44_add_del_static_mapping(is_add=1,
1678                                                local_ip_address=real_ip,
1679                                                external_ip_address=alias_ip,
1680                                                external_sw_if_index=0xFFFFFFFF,
1681                                                flags=flags)
1682
1683         try:
1684             # static mapping match
1685
1686             pkts = self.create_stream_out(self.pg1)
1687             self.pg1.add_stream(pkts)
1688             self.pg_enable_capture(self.pg_interfaces)
1689             self.pg_start()
1690             capture = self.pg0.get_capture(len(pkts))
1691             self.verify_capture_in(capture, self.pg0)
1692
1693             pkts = self.create_stream_in(self.pg0, self.pg1)
1694             self.pg0.add_stream(pkts)
1695             self.pg_enable_capture(self.pg_interfaces)
1696             self.pg_start()
1697             capture = self.pg1.get_capture(len(pkts))
1698             self.verify_capture_out(capture, same_port=True)
1699
1700             # no static mapping match
1701
1702             host0 = self.pg0.remote_hosts[0]
1703             self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1704             try:
1705                 pkts = self.create_stream_out(self.pg1,
1706                                               dst_ip=self.pg0.remote_ip4,
1707                                               use_inside_ports=True)
1708                 self.pg1.add_stream(pkts)
1709                 self.pg_enable_capture(self.pg_interfaces)
1710                 self.pg_start()
1711                 capture = self.pg0.get_capture(len(pkts))
1712                 self.verify_capture_in(capture, self.pg0)
1713
1714                 pkts = self.create_stream_in(self.pg0, self.pg1)
1715                 self.pg0.add_stream(pkts)
1716                 self.pg_enable_capture(self.pg_interfaces)
1717                 self.pg_start()
1718                 capture = self.pg1.get_capture(len(pkts))
1719                 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1720                                         same_port=True)
1721             finally:
1722                 self.pg0.remote_hosts[0] = host0
1723
1724         finally:
1725             self.vapi.nat44_forwarding_enable_disable(enable=0)
1726             flags = self.config_flags.NAT_IS_ADDR_ONLY
1727             self.vapi.nat44_add_del_static_mapping(
1728                 is_add=0,
1729                 local_ip_address=real_ip,
1730                 external_ip_address=alias_ip,
1731                 external_sw_if_index=0xFFFFFFFF,
1732                 flags=flags)
1733
1734     def test_static_in(self):
1735         """ 1:1 NAT initialized from inside network """
1736
1737         nat_ip = "10.0.0.10"
1738         self.tcp_port_out = 6303
1739         self.udp_port_out = 6304
1740         self.icmp_id_out = 6305
1741
1742         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1743         flags = self.config_flags.NAT_IS_INSIDE
1744         self.vapi.nat44_interface_add_del_feature(
1745             sw_if_index=self.pg0.sw_if_index,
1746             flags=flags, is_add=1)
1747         self.vapi.nat44_interface_add_del_feature(
1748             sw_if_index=self.pg1.sw_if_index,
1749             is_add=1)
1750         sm = self.vapi.nat44_static_mapping_dump()
1751         self.assertEqual(len(sm), 1)
1752         self.assertEqual(sm[0].tag, '')
1753         self.assertEqual(sm[0].protocol, 0)
1754         self.assertEqual(sm[0].local_port, 0)
1755         self.assertEqual(sm[0].external_port, 0)
1756
1757         # in2out
1758         pkts = self.create_stream_in(self.pg0, self.pg1)
1759         self.pg0.add_stream(pkts)
1760         self.pg_enable_capture(self.pg_interfaces)
1761         self.pg_start()
1762         capture = self.pg1.get_capture(len(pkts))
1763         self.verify_capture_out(capture, nat_ip, True)
1764
1765         # out2in
1766         pkts = self.create_stream_out(self.pg1, nat_ip)
1767         self.pg1.add_stream(pkts)
1768         self.pg_enable_capture(self.pg_interfaces)
1769         self.pg_start()
1770         capture = self.pg0.get_capture(len(pkts))
1771         self.verify_capture_in(capture, self.pg0)
1772
1773     def test_static_out(self):
1774         """ 1:1 NAT initialized from outside network """
1775
1776         nat_ip = "10.0.0.20"
1777         self.tcp_port_out = 6303
1778         self.udp_port_out = 6304
1779         self.icmp_id_out = 6305
1780         tag = "testTAG"
1781
1782         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
1783         flags = self.config_flags.NAT_IS_INSIDE
1784         self.vapi.nat44_interface_add_del_feature(
1785             sw_if_index=self.pg0.sw_if_index,
1786             flags=flags, is_add=1)
1787         self.vapi.nat44_interface_add_del_feature(
1788             sw_if_index=self.pg1.sw_if_index,
1789             is_add=1)
1790         sm = self.vapi.nat44_static_mapping_dump()
1791         self.assertEqual(len(sm), 1)
1792         self.assertEqual(sm[0].tag, tag)
1793
1794         # out2in
1795         pkts = self.create_stream_out(self.pg1, nat_ip)
1796         self.pg1.add_stream(pkts)
1797         self.pg_enable_capture(self.pg_interfaces)
1798         self.pg_start()
1799         capture = self.pg0.get_capture(len(pkts))
1800         self.verify_capture_in(capture, self.pg0)
1801
1802         # in2out
1803         pkts = self.create_stream_in(self.pg0, self.pg1)
1804         self.pg0.add_stream(pkts)
1805         self.pg_enable_capture(self.pg_interfaces)
1806         self.pg_start()
1807         capture = self.pg1.get_capture(len(pkts))
1808         self.verify_capture_out(capture, nat_ip, True)
1809
1810     def test_static_with_port_in(self):
1811         """ 1:1 NAPT initialized from inside network """
1812
1813         self.tcp_port_out = 3606
1814         self.udp_port_out = 3607
1815         self.icmp_id_out = 3608
1816
1817         self.nat44_add_address(self.nat_addr)
1818         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1819                                       self.tcp_port_in, self.tcp_port_out,
1820                                       proto=IP_PROTOS.tcp)
1821         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1822                                       self.udp_port_in, self.udp_port_out,
1823                                       proto=IP_PROTOS.udp)
1824         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1825                                       self.icmp_id_in, self.icmp_id_out,
1826                                       proto=IP_PROTOS.icmp)
1827         flags = self.config_flags.NAT_IS_INSIDE
1828         self.vapi.nat44_interface_add_del_feature(
1829             sw_if_index=self.pg0.sw_if_index,
1830             flags=flags, is_add=1)
1831         self.vapi.nat44_interface_add_del_feature(
1832             sw_if_index=self.pg1.sw_if_index,
1833             is_add=1)
1834
1835         # in2out
1836         pkts = self.create_stream_in(self.pg0, self.pg1)
1837         self.pg0.add_stream(pkts)
1838         self.pg_enable_capture(self.pg_interfaces)
1839         self.pg_start()
1840         capture = self.pg1.get_capture(len(pkts))
1841         self.verify_capture_out(capture)
1842
1843         # out2in
1844         pkts = self.create_stream_out(self.pg1)
1845         self.pg1.add_stream(pkts)
1846         self.pg_enable_capture(self.pg_interfaces)
1847         self.pg_start()
1848         capture = self.pg0.get_capture(len(pkts))
1849         self.verify_capture_in(capture, self.pg0)
1850
1851     def test_static_with_port_out(self):
1852         """ 1:1 NAPT initialized from outside network """
1853
1854         self.tcp_port_out = 30606
1855         self.udp_port_out = 30607
1856         self.icmp_id_out = 30608
1857
1858         self.nat44_add_address(self.nat_addr)
1859         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1860                                       self.tcp_port_in, self.tcp_port_out,
1861                                       proto=IP_PROTOS.tcp)
1862         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1863                                       self.udp_port_in, self.udp_port_out,
1864                                       proto=IP_PROTOS.udp)
1865         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1866                                       self.icmp_id_in, self.icmp_id_out,
1867                                       proto=IP_PROTOS.icmp)
1868         flags = self.config_flags.NAT_IS_INSIDE
1869         self.vapi.nat44_interface_add_del_feature(
1870             sw_if_index=self.pg0.sw_if_index,
1871             flags=flags, is_add=1)
1872         self.vapi.nat44_interface_add_del_feature(
1873             sw_if_index=self.pg1.sw_if_index,
1874             is_add=1)
1875
1876         # out2in
1877         pkts = self.create_stream_out(self.pg1)
1878         self.pg1.add_stream(pkts)
1879         self.pg_enable_capture(self.pg_interfaces)
1880         self.pg_start()
1881         capture = self.pg0.get_capture(len(pkts))
1882         self.verify_capture_in(capture, self.pg0)
1883
1884         # in2out
1885         pkts = self.create_stream_in(self.pg0, self.pg1)
1886         self.pg0.add_stream(pkts)
1887         self.pg_enable_capture(self.pg_interfaces)
1888         self.pg_start()
1889         capture = self.pg1.get_capture(len(pkts))
1890         self.verify_capture_out(capture)
1891
1892     def test_static_vrf_aware(self):
1893         """ 1:1 NAT VRF awareness """
1894
1895         nat_ip1 = "10.0.0.30"
1896         nat_ip2 = "10.0.0.40"
1897         self.tcp_port_out = 6303
1898         self.udp_port_out = 6304
1899         self.icmp_id_out = 6305
1900
1901         self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1902                                       vrf_id=10)
1903         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1904                                       vrf_id=10)
1905         flags = self.config_flags.NAT_IS_INSIDE
1906         self.vapi.nat44_interface_add_del_feature(
1907             sw_if_index=self.pg3.sw_if_index,
1908             is_add=1)
1909         self.vapi.nat44_interface_add_del_feature(
1910             sw_if_index=self.pg0.sw_if_index,
1911             flags=flags, is_add=1)
1912         self.vapi.nat44_interface_add_del_feature(
1913             sw_if_index=self.pg4.sw_if_index,
1914             flags=flags, is_add=1)
1915
1916         # inside interface VRF match NAT44 static mapping VRF
1917         pkts = self.create_stream_in(self.pg4, self.pg3)
1918         self.pg4.add_stream(pkts)
1919         self.pg_enable_capture(self.pg_interfaces)
1920         self.pg_start()
1921         capture = self.pg3.get_capture(len(pkts))
1922         self.verify_capture_out(capture, nat_ip1, True)
1923
1924         # inside interface VRF don't match NAT44 static mapping VRF (packets
1925         # are dropped)
1926         pkts = self.create_stream_in(self.pg0, self.pg3)
1927         self.pg0.add_stream(pkts)
1928         self.pg_enable_capture(self.pg_interfaces)
1929         self.pg_start()
1930         self.pg3.assert_nothing_captured()
1931
1932     def test_dynamic_to_static(self):
1933         """ Switch from dynamic translation to 1:1NAT """
1934         nat_ip = "10.0.0.10"
1935         self.tcp_port_out = 6303
1936         self.udp_port_out = 6304
1937         self.icmp_id_out = 6305
1938
1939         self.nat44_add_address(self.nat_addr)
1940         flags = self.config_flags.NAT_IS_INSIDE
1941         self.vapi.nat44_interface_add_del_feature(
1942             sw_if_index=self.pg0.sw_if_index,
1943             flags=flags, is_add=1)
1944         self.vapi.nat44_interface_add_del_feature(
1945             sw_if_index=self.pg1.sw_if_index,
1946             is_add=1)
1947
1948         # dynamic
1949         pkts = self.create_stream_in(self.pg0, self.pg1)
1950         self.pg0.add_stream(pkts)
1951         self.pg_enable_capture(self.pg_interfaces)
1952         self.pg_start()
1953         capture = self.pg1.get_capture(len(pkts))
1954         self.verify_capture_out(capture)
1955
1956         # 1:1NAT
1957         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1958         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
1959         self.assertEqual(len(sessions), 0)
1960         pkts = self.create_stream_in(self.pg0, self.pg1)
1961         self.pg0.add_stream(pkts)
1962         self.pg_enable_capture(self.pg_interfaces)
1963         self.pg_start()
1964         capture = self.pg1.get_capture(len(pkts))
1965         self.verify_capture_out(capture, nat_ip, True)
1966
1967     def test_identity_nat(self):
1968         """ Identity NAT """
1969         flags = self.config_flags.NAT_IS_ADDR_ONLY
1970         self.vapi.nat44_add_del_identity_mapping(
1971             ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
1972             flags=flags, is_add=1)
1973         flags = self.config_flags.NAT_IS_INSIDE
1974         self.vapi.nat44_interface_add_del_feature(
1975             sw_if_index=self.pg0.sw_if_index,
1976             flags=flags, is_add=1)
1977         self.vapi.nat44_interface_add_del_feature(
1978             sw_if_index=self.pg1.sw_if_index,
1979             is_add=1)
1980
1981         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1982              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1983              TCP(sport=12345, dport=56789))
1984         self.pg1.add_stream(p)
1985         self.pg_enable_capture(self.pg_interfaces)
1986         self.pg_start()
1987         capture = self.pg0.get_capture(1)
1988         p = capture[0]
1989         try:
1990             ip = p[IP]
1991             tcp = p[TCP]
1992             self.assertEqual(ip.dst, self.pg0.remote_ip4)
1993             self.assertEqual(ip.src, self.pg1.remote_ip4)
1994             self.assertEqual(tcp.dport, 56789)
1995             self.assertEqual(tcp.sport, 12345)
1996             self.assert_packet_checksums_valid(p)
1997         except:
1998             self.logger.error(ppp("Unexpected or invalid packet:", p))
1999             raise
2000
2001         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
2002         self.assertEqual(len(sessions), 0)
2003         flags = self.config_flags.NAT_IS_ADDR_ONLY
2004         self.vapi.nat44_add_del_identity_mapping(
2005             ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
2006             flags=flags, vrf_id=1, is_add=1)
2007         identity_mappings = self.vapi.nat44_identity_mapping_dump()
2008         self.assertEqual(len(identity_mappings), 2)
2009
2010     def test_multiple_inside_interfaces(self):
2011         """ NAT44 multiple non-overlapping address space inside interfaces """
2012
2013         self.nat44_add_address(self.nat_addr)
2014         flags = self.config_flags.NAT_IS_INSIDE
2015         self.vapi.nat44_interface_add_del_feature(
2016             sw_if_index=self.pg0.sw_if_index,
2017             flags=flags, is_add=1)
2018         self.vapi.nat44_interface_add_del_feature(
2019             sw_if_index=self.pg1.sw_if_index,
2020             flags=flags, is_add=1)
2021         self.vapi.nat44_interface_add_del_feature(
2022             sw_if_index=self.pg3.sw_if_index,
2023             is_add=1)
2024
2025         # between two NAT44 inside interfaces (no translation)
2026         pkts = self.create_stream_in(self.pg0, self.pg1)
2027         self.pg0.add_stream(pkts)
2028         self.pg_enable_capture(self.pg_interfaces)
2029         self.pg_start()
2030         capture = self.pg1.get_capture(len(pkts))
2031         self.verify_capture_no_translation(capture, self.pg0, self.pg1)
2032
2033         # from NAT44 inside to interface without NAT44 feature (no translation)
2034         pkts = self.create_stream_in(self.pg0, self.pg2)
2035         self.pg0.add_stream(pkts)
2036         self.pg_enable_capture(self.pg_interfaces)
2037         self.pg_start()
2038         capture = self.pg2.get_capture(len(pkts))
2039         self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2040
2041         # in2out 1st interface
2042         pkts = self.create_stream_in(self.pg0, self.pg3)
2043         self.pg0.add_stream(pkts)
2044         self.pg_enable_capture(self.pg_interfaces)
2045         self.pg_start()
2046         capture = self.pg3.get_capture(len(pkts))
2047         self.verify_capture_out(capture)
2048
2049         # out2in 1st interface
2050         pkts = self.create_stream_out(self.pg3)
2051         self.pg3.add_stream(pkts)
2052         self.pg_enable_capture(self.pg_interfaces)
2053         self.pg_start()
2054         capture = self.pg0.get_capture(len(pkts))
2055         self.verify_capture_in(capture, self.pg0)
2056
2057         # in2out 2nd interface
2058         pkts = self.create_stream_in(self.pg1, self.pg3)
2059         self.pg1.add_stream(pkts)
2060         self.pg_enable_capture(self.pg_interfaces)
2061         self.pg_start()
2062         capture = self.pg3.get_capture(len(pkts))
2063         self.verify_capture_out(capture)
2064
2065         # out2in 2nd interface
2066         pkts = self.create_stream_out(self.pg3)
2067         self.pg3.add_stream(pkts)
2068         self.pg_enable_capture(self.pg_interfaces)
2069         self.pg_start()
2070         capture = self.pg1.get_capture(len(pkts))
2071         self.verify_capture_in(capture, self.pg1)
2072
2073     def test_inside_overlapping_interfaces(self):
2074         """ NAT44 multiple inside interfaces with overlapping address space """
2075
2076         static_nat_ip = "10.0.0.10"
2077         self.nat44_add_address(self.nat_addr)
2078         flags = self.config_flags.NAT_IS_INSIDE
2079         self.vapi.nat44_interface_add_del_feature(
2080             sw_if_index=self.pg3.sw_if_index,
2081             is_add=1)
2082         self.vapi.nat44_interface_add_del_feature(
2083             sw_if_index=self.pg4.sw_if_index,
2084             flags=flags, is_add=1)
2085         self.vapi.nat44_interface_add_del_feature(
2086             sw_if_index=self.pg5.sw_if_index,
2087             flags=flags, is_add=1)
2088         self.vapi.nat44_interface_add_del_feature(
2089             sw_if_index=self.pg6.sw_if_index,
2090             flags=flags, is_add=1)
2091         self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2092                                       vrf_id=20)
2093
2094         # between NAT44 inside interfaces with same VRF (no translation)
2095         pkts = self.create_stream_in(self.pg4, self.pg5)
2096         self.pg4.add_stream(pkts)
2097         self.pg_enable_capture(self.pg_interfaces)
2098         self.pg_start()
2099         capture = self.pg5.get_capture(len(pkts))
2100         self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2101
2102         # between NAT44 inside interfaces with different VRF (hairpinning)
2103         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2104              IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2105              TCP(sport=1234, dport=5678))
2106         self.pg4.add_stream(p)
2107         self.pg_enable_capture(self.pg_interfaces)
2108         self.pg_start()
2109         capture = self.pg6.get_capture(1)
2110         p = capture[0]
2111         try:
2112             ip = p[IP]
2113             tcp = p[TCP]
2114             self.assertEqual(ip.src, self.nat_addr)
2115             self.assertEqual(ip.dst, self.pg6.remote_ip4)
2116             self.assertNotEqual(tcp.sport, 1234)
2117             self.assertEqual(tcp.dport, 5678)
2118         except:
2119             self.logger.error(ppp("Unexpected or invalid packet:", p))
2120             raise
2121
2122         # in2out 1st interface
2123         pkts = self.create_stream_in(self.pg4, self.pg3)
2124         self.pg4.add_stream(pkts)
2125         self.pg_enable_capture(self.pg_interfaces)
2126         self.pg_start()
2127         capture = self.pg3.get_capture(len(pkts))
2128         self.verify_capture_out(capture)
2129
2130         # out2in 1st interface
2131         pkts = self.create_stream_out(self.pg3)
2132         self.pg3.add_stream(pkts)
2133         self.pg_enable_capture(self.pg_interfaces)
2134         self.pg_start()
2135         capture = self.pg4.get_capture(len(pkts))
2136         self.verify_capture_in(capture, self.pg4)
2137
2138         # in2out 2nd interface
2139         pkts = self.create_stream_in(self.pg5, self.pg3)
2140         self.pg5.add_stream(pkts)
2141         self.pg_enable_capture(self.pg_interfaces)
2142         self.pg_start()
2143         capture = self.pg3.get_capture(len(pkts))
2144         self.verify_capture_out(capture)
2145
2146         # out2in 2nd interface
2147         pkts = self.create_stream_out(self.pg3)
2148         self.pg3.add_stream(pkts)
2149         self.pg_enable_capture(self.pg_interfaces)
2150         self.pg_start()
2151         capture = self.pg5.get_capture(len(pkts))
2152         self.verify_capture_in(capture, self.pg5)
2153
2154         # pg5 session dump
2155         addresses = self.vapi.nat44_address_dump()
2156         self.assertEqual(len(addresses), 1)
2157         sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4, 10)
2158         self.assertEqual(len(sessions), 3)
2159         for session in sessions:
2160             self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2161             self.assertEqual(str(session.inside_ip_address),
2162                              self.pg5.remote_ip4)
2163             self.assertEqual(session.outside_ip_address,
2164                              addresses[0].ip_address)
2165         self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2166         self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2167         self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2168         self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2169         self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2170         self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2171         self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2172         self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2173         self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2174
2175         # in2out 3rd interface
2176         pkts = self.create_stream_in(self.pg6, self.pg3)
2177         self.pg6.add_stream(pkts)
2178         self.pg_enable_capture(self.pg_interfaces)
2179         self.pg_start()
2180         capture = self.pg3.get_capture(len(pkts))
2181         self.verify_capture_out(capture, static_nat_ip, True)
2182
2183         # out2in 3rd interface
2184         pkts = self.create_stream_out(self.pg3, static_nat_ip)
2185         self.pg3.add_stream(pkts)
2186         self.pg_enable_capture(self.pg_interfaces)
2187         self.pg_start()
2188         capture = self.pg6.get_capture(len(pkts))
2189         self.verify_capture_in(capture, self.pg6)
2190
2191         # general user and session dump verifications
2192         users = self.vapi.nat44_user_dump()
2193         self.assertGreaterEqual(len(users), 3)
2194         addresses = self.vapi.nat44_address_dump()
2195         self.assertEqual(len(addresses), 1)
2196         for user in users:
2197             sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2198                                                          user.vrf_id)
2199             for session in sessions:
2200                 self.assertEqual(user.ip_address, session.inside_ip_address)
2201                 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2202                 self.assertTrue(session.protocol in
2203                                 [IP_PROTOS.tcp, IP_PROTOS.udp,
2204                                  IP_PROTOS.icmp])
2205                 self.assertFalse(session.flags &
2206                                  self.config_flags.NAT_IS_EXT_HOST_VALID)
2207
2208         # pg4 session dump
2209         sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4, 10)
2210         self.assertGreaterEqual(len(sessions), 4)
2211         for session in sessions:
2212             self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2213             self.assertEqual(str(session.inside_ip_address),
2214                              self.pg4.remote_ip4)
2215             self.assertEqual(session.outside_ip_address,
2216                              addresses[0].ip_address)
2217
2218         # pg6 session dump
2219         sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4, 20)
2220         self.assertGreaterEqual(len(sessions), 3)
2221         for session in sessions:
2222             self.assertTrue(session.flags & self.config_flags.NAT_IS_STATIC)
2223             self.assertEqual(str(session.inside_ip_address),
2224                              self.pg6.remote_ip4)
2225             self.assertEqual(str(session.outside_ip_address),
2226                              static_nat_ip)
2227             self.assertTrue(session.inside_port in
2228                             [self.tcp_port_in, self.udp_port_in,
2229                              self.icmp_id_in])
2230
2231     def test_hairpinning(self):
2232         """ NAT44 hairpinning - 1:1 NAPT """
2233
2234         host = self.pg0.remote_hosts[0]
2235         server = self.pg0.remote_hosts[1]
2236         host_in_port = 1234
2237         host_out_port = 0
2238         server_in_port = 5678
2239         server_out_port = 8765
2240
2241         self.nat44_add_address(self.nat_addr)
2242         flags = self.config_flags.NAT_IS_INSIDE
2243         self.vapi.nat44_interface_add_del_feature(
2244             sw_if_index=self.pg0.sw_if_index,
2245             flags=flags, is_add=1)
2246         self.vapi.nat44_interface_add_del_feature(
2247             sw_if_index=self.pg1.sw_if_index,
2248             is_add=1)
2249
2250         # add static mapping for server
2251         self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2252                                       server_in_port, server_out_port,
2253                                       proto=IP_PROTOS.tcp)
2254
2255         cnt = self.statistics.get_counter('/nat44/hairpinning')[0]
2256         # send packet from host to server
2257         p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2258              IP(src=host.ip4, dst=self.nat_addr) /
2259              TCP(sport=host_in_port, dport=server_out_port))
2260         self.pg0.add_stream(p)
2261         self.pg_enable_capture(self.pg_interfaces)
2262         self.pg_start()
2263         capture = self.pg0.get_capture(1)
2264         p = capture[0]
2265         try:
2266             ip = p[IP]
2267             tcp = p[TCP]
2268             self.assertEqual(ip.src, self.nat_addr)
2269             self.assertEqual(ip.dst, server.ip4)
2270             self.assertNotEqual(tcp.sport, host_in_port)
2271             self.assertEqual(tcp.dport, server_in_port)
2272             self.assert_packet_checksums_valid(p)
2273             host_out_port = tcp.sport
2274         except:
2275             self.logger.error(ppp("Unexpected or invalid packet:", p))
2276             raise
2277
2278         after = self.statistics.get_counter('/nat44/hairpinning')[0]
2279         if_idx = self.pg0.sw_if_index
2280         self.assertEqual(after[if_idx] - cnt[if_idx], 1)
2281
2282         # send reply from server to host
2283         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2284              IP(src=server.ip4, dst=self.nat_addr) /
2285              TCP(sport=server_in_port, dport=host_out_port))
2286         self.pg0.add_stream(p)
2287         self.pg_enable_capture(self.pg_interfaces)
2288         self.pg_start()
2289         capture = self.pg0.get_capture(1)
2290         p = capture[0]
2291         try:
2292             ip = p[IP]
2293             tcp = p[TCP]
2294             self.assertEqual(ip.src, self.nat_addr)
2295             self.assertEqual(ip.dst, host.ip4)
2296             self.assertEqual(tcp.sport, server_out_port)
2297             self.assertEqual(tcp.dport, host_in_port)
2298             self.assert_packet_checksums_valid(p)
2299         except:
2300             self.logger.error(ppp("Unexpected or invalid packet:", p))
2301             raise
2302
2303         after = self.statistics.get_counter('/nat44/hairpinning')[0]
2304         if_idx = self.pg0.sw_if_index
2305         self.assertEqual(after[if_idx] - cnt[if_idx], 2)
2306
2307     def test_hairpinning2(self):
2308         """ NAT44 hairpinning - 1:1 NAT"""
2309
2310         server1_nat_ip = "10.0.0.10"
2311         server2_nat_ip = "10.0.0.11"
2312         host = self.pg0.remote_hosts[0]
2313         server1 = self.pg0.remote_hosts[1]
2314         server2 = self.pg0.remote_hosts[2]
2315         server_tcp_port = 22
2316         server_udp_port = 20
2317
2318         self.nat44_add_address(self.nat_addr)
2319         flags = self.config_flags.NAT_IS_INSIDE
2320         self.vapi.nat44_interface_add_del_feature(
2321             sw_if_index=self.pg0.sw_if_index,
2322             flags=flags, is_add=1)
2323         self.vapi.nat44_interface_add_del_feature(
2324             sw_if_index=self.pg1.sw_if_index,
2325             is_add=1)
2326
2327         # add static mapping for servers
2328         self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2329         self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
2330
2331         # host to server1
2332         pkts = []
2333         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2334              IP(src=host.ip4, dst=server1_nat_ip) /
2335              TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2336         pkts.append(p)
2337         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2338              IP(src=host.ip4, dst=server1_nat_ip) /
2339              UDP(sport=self.udp_port_in, dport=server_udp_port))
2340         pkts.append(p)
2341         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2342              IP(src=host.ip4, dst=server1_nat_ip) /
2343              ICMP(id=self.icmp_id_in, type='echo-request'))
2344         pkts.append(p)
2345         self.pg0.add_stream(pkts)
2346         self.pg_enable_capture(self.pg_interfaces)
2347         self.pg_start()
2348         capture = self.pg0.get_capture(len(pkts))
2349         for packet in capture:
2350             try:
2351                 self.assertEqual(packet[IP].src, self.nat_addr)
2352                 self.assertEqual(packet[IP].dst, server1.ip4)
2353                 if packet.haslayer(TCP):
2354                     self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2355                     self.assertEqual(packet[TCP].dport, server_tcp_port)
2356                     self.tcp_port_out = packet[TCP].sport
2357                     self.assert_packet_checksums_valid(packet)
2358                 elif packet.haslayer(UDP):
2359                     self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2360                     self.assertEqual(packet[UDP].dport, server_udp_port)
2361                     self.udp_port_out = packet[UDP].sport
2362                 else:
2363                     self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2364                     self.icmp_id_out = packet[ICMP].id
2365             except:
2366                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2367                 raise
2368
2369         # server1 to host
2370         pkts = []
2371         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2372              IP(src=server1.ip4, dst=self.nat_addr) /
2373              TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2374         pkts.append(p)
2375         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2376              IP(src=server1.ip4, dst=self.nat_addr) /
2377              UDP(sport=server_udp_port, dport=self.udp_port_out))
2378         pkts.append(p)
2379         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2380              IP(src=server1.ip4, dst=self.nat_addr) /
2381              ICMP(id=self.icmp_id_out, type='echo-reply'))
2382         pkts.append(p)
2383         self.pg0.add_stream(pkts)
2384         self.pg_enable_capture(self.pg_interfaces)
2385         self.pg_start()
2386         capture = self.pg0.get_capture(len(pkts))
2387         for packet in capture:
2388             try:
2389                 self.assertEqual(packet[IP].src, server1_nat_ip)
2390                 self.assertEqual(packet[IP].dst, host.ip4)
2391                 if packet.haslayer(TCP):
2392                     self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2393                     self.assertEqual(packet[TCP].sport, server_tcp_port)
2394                     self.assert_packet_checksums_valid(packet)
2395                 elif packet.haslayer(UDP):
2396                     self.assertEqual(packet[UDP].dport, self.udp_port_in)
2397                     self.assertEqual(packet[UDP].sport, server_udp_port)
2398                 else:
2399                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2400             except:
2401                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2402                 raise
2403
2404         # server2 to server1
2405         pkts = []
2406         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2407              IP(src=server2.ip4, dst=server1_nat_ip) /
2408              TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2409         pkts.append(p)
2410         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2411              IP(src=server2.ip4, dst=server1_nat_ip) /
2412              UDP(sport=self.udp_port_in, dport=server_udp_port))
2413         pkts.append(p)
2414         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2415              IP(src=server2.ip4, dst=server1_nat_ip) /
2416              ICMP(id=self.icmp_id_in, type='echo-request'))
2417         pkts.append(p)
2418         self.pg0.add_stream(pkts)
2419         self.pg_enable_capture(self.pg_interfaces)
2420         self.pg_start()
2421         capture = self.pg0.get_capture(len(pkts))
2422         for packet in capture:
2423             try:
2424                 self.assertEqual(packet[IP].src, server2_nat_ip)
2425                 self.assertEqual(packet[IP].dst, server1.ip4)
2426                 if packet.haslayer(TCP):
2427                     self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2428                     self.assertEqual(packet[TCP].dport, server_tcp_port)
2429                     self.tcp_port_out = packet[TCP].sport
2430                     self.assert_packet_checksums_valid(packet)
2431                 elif packet.haslayer(UDP):
2432                     self.assertEqual(packet[UDP].sport, self.udp_port_in)
2433                     self.assertEqual(packet[UDP].dport, server_udp_port)
2434                     self.udp_port_out = packet[UDP].sport
2435                 else:
2436                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2437                     self.icmp_id_out = packet[ICMP].id
2438             except:
2439                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2440                 raise
2441
2442         # server1 to server2
2443         pkts = []
2444         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2445              IP(src=server1.ip4, dst=server2_nat_ip) /
2446              TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2447         pkts.append(p)
2448         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2449              IP(src=server1.ip4, dst=server2_nat_ip) /
2450              UDP(sport=server_udp_port, dport=self.udp_port_out))
2451         pkts.append(p)
2452         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2453              IP(src=server1.ip4, dst=server2_nat_ip) /
2454              ICMP(id=self.icmp_id_out, type='echo-reply'))
2455         pkts.append(p)
2456         self.pg0.add_stream(pkts)
2457         self.pg_enable_capture(self.pg_interfaces)
2458         self.pg_start()
2459         capture = self.pg0.get_capture(len(pkts))
2460         for packet in capture:
2461             try:
2462                 self.assertEqual(packet[IP].src, server1_nat_ip)
2463                 self.assertEqual(packet[IP].dst, server2.ip4)
2464                 if packet.haslayer(TCP):
2465                     self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2466                     self.assertEqual(packet[TCP].sport, server_tcp_port)
2467                     self.assert_packet_checksums_valid(packet)
2468                 elif packet.haslayer(UDP):
2469                     self.assertEqual(packet[UDP].dport, self.udp_port_in)
2470                     self.assertEqual(packet[UDP].sport, server_udp_port)
2471                 else:
2472                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2473             except:
2474                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2475                 raise
2476
2477     def test_interface_addr(self):
2478         """ Acquire NAT44 addresses from interface """
2479         self.vapi.nat44_add_del_interface_addr(
2480             is_add=1,
2481             sw_if_index=self.pg7.sw_if_index)
2482
2483         # no address in NAT pool
2484         addresses = self.vapi.nat44_address_dump()
2485         self.assertEqual(0, len(addresses))
2486
2487         # configure interface address and check NAT address pool
2488         self.pg7.config_ip4()
2489         addresses = self.vapi.nat44_address_dump()
2490         self.assertEqual(1, len(addresses))
2491         self.assertEqual(str(addresses[0].ip_address), self.pg7.local_ip4)
2492
2493         # remove interface address and check NAT address pool
2494         self.pg7.unconfig_ip4()
2495         addresses = self.vapi.nat44_address_dump()
2496         self.assertEqual(0, len(addresses))
2497
2498     def test_interface_addr_static_mapping(self):
2499         """ Static mapping with addresses from interface """
2500         tag = "testTAG"
2501
2502         self.vapi.nat44_add_del_interface_addr(
2503             is_add=1,
2504             sw_if_index=self.pg7.sw_if_index)
2505         self.nat44_add_static_mapping(
2506             '1.2.3.4',
2507             external_sw_if_index=self.pg7.sw_if_index,
2508             tag=tag)
2509
2510         # static mappings with external interface
2511         static_mappings = self.vapi.nat44_static_mapping_dump()
2512         self.assertEqual(1, len(static_mappings))
2513         self.assertEqual(self.pg7.sw_if_index,
2514                          static_mappings[0].external_sw_if_index)
2515         self.assertEqual(static_mappings[0].tag, tag)
2516
2517         # configure interface address and check static mappings
2518         self.pg7.config_ip4()
2519         static_mappings = self.vapi.nat44_static_mapping_dump()
2520         self.assertEqual(2, len(static_mappings))
2521         resolved = False
2522         for sm in static_mappings:
2523             if sm.external_sw_if_index == 0xFFFFFFFF:
2524                 self.assertEqual(str(sm.external_ip_address),
2525                                  self.pg7.local_ip4)
2526                 self.assertEqual(sm.tag, tag)
2527                 resolved = True
2528         self.assertTrue(resolved)
2529
2530         # remove interface address and check static mappings
2531         self.pg7.unconfig_ip4()
2532         static_mappings = self.vapi.nat44_static_mapping_dump()
2533         self.assertEqual(1, len(static_mappings))
2534         self.assertEqual(self.pg7.sw_if_index,
2535                          static_mappings[0].external_sw_if_index)
2536         self.assertEqual(static_mappings[0].tag, tag)
2537
2538         # configure interface address again and check static mappings
2539         self.pg7.config_ip4()
2540         static_mappings = self.vapi.nat44_static_mapping_dump()
2541         self.assertEqual(2, len(static_mappings))
2542         resolved = False
2543         for sm in static_mappings:
2544             if sm.external_sw_if_index == 0xFFFFFFFF:
2545                 self.assertEqual(str(sm.external_ip_address),
2546                                  self.pg7.local_ip4)
2547                 self.assertEqual(sm.tag, tag)
2548                 resolved = True
2549         self.assertTrue(resolved)
2550
2551         # remove static mapping
2552         self.nat44_add_static_mapping(
2553             '1.2.3.4',
2554             external_sw_if_index=self.pg7.sw_if_index,
2555             tag=tag,
2556             is_add=0)
2557         static_mappings = self.vapi.nat44_static_mapping_dump()
2558         self.assertEqual(0, len(static_mappings))
2559
2560     def test_interface_addr_identity_nat(self):
2561         """ Identity NAT with addresses from interface """
2562
2563         port = 53053
2564         self.vapi.nat44_add_del_interface_addr(
2565             is_add=1,
2566             sw_if_index=self.pg7.sw_if_index)
2567         self.vapi.nat44_add_del_identity_mapping(
2568             ip_address=b'0',
2569             sw_if_index=self.pg7.sw_if_index,
2570             port=port,
2571             protocol=IP_PROTOS.tcp,
2572             is_add=1)
2573
2574         # identity mappings with external interface
2575         identity_mappings = self.vapi.nat44_identity_mapping_dump()
2576         self.assertEqual(1, len(identity_mappings))
2577         self.assertEqual(self.pg7.sw_if_index,
2578                          identity_mappings[0].sw_if_index)
2579
2580         # configure interface address and check identity mappings
2581         self.pg7.config_ip4()
2582         identity_mappings = self.vapi.nat44_identity_mapping_dump()
2583         resolved = False
2584         self.assertEqual(2, len(identity_mappings))
2585         for sm in identity_mappings:
2586             if sm.sw_if_index == 0xFFFFFFFF:
2587                 self.assertEqual(str(identity_mappings[0].ip_address),
2588                                  self.pg7.local_ip4)
2589                 self.assertEqual(port, identity_mappings[0].port)
2590                 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2591                 resolved = True
2592         self.assertTrue(resolved)
2593
2594         # remove interface address and check identity mappings
2595         self.pg7.unconfig_ip4()
2596         identity_mappings = self.vapi.nat44_identity_mapping_dump()
2597         self.assertEqual(1, len(identity_mappings))
2598         self.assertEqual(self.pg7.sw_if_index,
2599                          identity_mappings[0].sw_if_index)
2600
2601     def test_ipfix_nat44_sess(self):
2602         """ IPFIX logging NAT44 session created/deleted """
2603         self.ipfix_domain_id = 10
2604         self.ipfix_src_port = 20202
2605         collector_port = 30303
2606         bind_layers(UDP, IPFIX, dport=30303)
2607         self.nat44_add_address(self.nat_addr)
2608         flags = self.config_flags.NAT_IS_INSIDE
2609         self.vapi.nat44_interface_add_del_feature(
2610             sw_if_index=self.pg0.sw_if_index,
2611             flags=flags, is_add=1)
2612         self.vapi.nat44_interface_add_del_feature(
2613             sw_if_index=self.pg1.sw_if_index,
2614             is_add=1)
2615         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2616                                      src_address=self.pg3.local_ip4,
2617                                      path_mtu=512,
2618                                      template_interval=10,
2619                                      collector_port=collector_port)
2620         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2621                                            src_port=self.ipfix_src_port,
2622                                            enable=1)
2623
2624         pkts = self.create_stream_in(self.pg0, self.pg1)
2625         self.pg0.add_stream(pkts)
2626         self.pg_enable_capture(self.pg_interfaces)
2627         self.pg_start()
2628         capture = self.pg1.get_capture(len(pkts))
2629         self.verify_capture_out(capture)
2630         self.nat44_add_address(self.nat_addr, is_add=0)
2631         self.vapi.ipfix_flush()
2632         capture = self.pg3.get_capture(7)
2633         ipfix = IPFIXDecoder()
2634         # first load template
2635         for p in capture:
2636             self.assertTrue(p.haslayer(IPFIX))
2637             self.assertEqual(p[IP].src, self.pg3.local_ip4)
2638             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2639             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2640             self.assertEqual(p[UDP].dport, collector_port)
2641             self.assertEqual(p[IPFIX].observationDomainID,
2642                              self.ipfix_domain_id)
2643             if p.haslayer(Template):
2644                 ipfix.add_template(p.getlayer(Template))
2645         # verify events in data set
2646         for p in capture:
2647             if p.haslayer(Data):
2648                 data = ipfix.decode_data_set(p.getlayer(Set))
2649                 self.verify_ipfix_nat44_ses(data)
2650
2651     def test_ipfix_addr_exhausted(self):
2652         """ IPFIX logging NAT addresses exhausted """
2653         flags = self.config_flags.NAT_IS_INSIDE
2654         self.vapi.nat44_interface_add_del_feature(
2655             sw_if_index=self.pg0.sw_if_index,
2656             flags=flags, is_add=1)
2657         self.vapi.nat44_interface_add_del_feature(
2658             sw_if_index=self.pg1.sw_if_index,
2659             is_add=1)
2660         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2661                                      src_address=self.pg3.local_ip4,
2662                                      path_mtu=512,
2663                                      template_interval=10)
2664         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2665                                            src_port=self.ipfix_src_port,
2666                                            enable=1)
2667
2668         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2669              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2670              TCP(sport=3025))
2671         self.pg0.add_stream(p)
2672         self.pg_enable_capture(self.pg_interfaces)
2673         self.pg_start()
2674         self.pg1.assert_nothing_captured()
2675         sleep(1)
2676         self.vapi.ipfix_flush()
2677         capture = self.pg3.get_capture(7)
2678         ipfix = IPFIXDecoder()
2679         # first load template
2680         for p in capture:
2681             self.assertTrue(p.haslayer(IPFIX))
2682             self.assertEqual(p[IP].src, self.pg3.local_ip4)
2683             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2684             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2685             self.assertEqual(p[UDP].dport, 4739)
2686             self.assertEqual(p[IPFIX].observationDomainID,
2687                              self.ipfix_domain_id)
2688             if p.haslayer(Template):
2689                 ipfix.add_template(p.getlayer(Template))
2690         # verify events in data set
2691         for p in capture:
2692             if p.haslayer(Data):
2693                 data = ipfix.decode_data_set(p.getlayer(Set))
2694                 self.verify_ipfix_addr_exhausted(data)
2695
2696     @unittest.skipUnless(running_extended_tests, "part of extended tests")
2697     def test_ipfix_max_sessions(self):
2698         """ IPFIX logging maximum session entries exceeded """
2699         self.nat44_add_address(self.nat_addr)
2700         flags = self.config_flags.NAT_IS_INSIDE
2701         self.vapi.nat44_interface_add_del_feature(
2702             sw_if_index=self.pg0.sw_if_index,
2703             flags=flags, is_add=1)
2704         self.vapi.nat44_interface_add_del_feature(
2705             sw_if_index=self.pg1.sw_if_index,
2706             is_add=1)
2707
2708         max_sessions = self.max_translations
2709
2710         pkts = []
2711         for i in range(0, max_sessions):
2712             src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2713             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2714                  IP(src=src, dst=self.pg1.remote_ip4) /
2715                  TCP(sport=1025))
2716             pkts.append(p)
2717         self.pg0.add_stream(pkts)
2718         self.pg_enable_capture(self.pg_interfaces)
2719         self.pg_start()
2720
2721         self.pg1.get_capture(max_sessions)
2722         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2723                                      src_address=self.pg3.local_ip4,
2724                                      path_mtu=512,
2725                                      template_interval=10)
2726         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2727                                            src_port=self.ipfix_src_port,
2728                                            enable=1)
2729
2730         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2731              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2732              TCP(sport=1025))
2733         self.pg0.add_stream(p)
2734         self.pg_enable_capture(self.pg_interfaces)
2735         self.pg_start()
2736         self.pg1.assert_nothing_captured()
2737         sleep(1)
2738         self.vapi.ipfix_flush()
2739         capture = self.pg3.get_capture(7)
2740         ipfix = IPFIXDecoder()
2741         # first load template
2742         for p in capture:
2743             self.assertTrue(p.haslayer(IPFIX))
2744             self.assertEqual(p[IP].src, self.pg3.local_ip4)
2745             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2746             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2747             self.assertEqual(p[UDP].dport, 4739)
2748             self.assertEqual(p[IPFIX].observationDomainID,
2749                              self.ipfix_domain_id)
2750             if p.haslayer(Template):
2751                 ipfix.add_template(p.getlayer(Template))
2752         # verify events in data set
2753         for p in capture:
2754             if p.haslayer(Data):
2755                 data = ipfix.decode_data_set(p.getlayer(Set))
2756                 self.verify_ipfix_max_sessions(data, max_sessions)
2757
2758     def test_syslog_apmap(self):
2759         """ Test syslog address and port mapping creation and deletion """
2760         self.vapi.syslog_set_filter(
2761             self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
2762         self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
2763         self.nat44_add_address(self.nat_addr)
2764         flags = self.config_flags.NAT_IS_INSIDE
2765         self.vapi.nat44_interface_add_del_feature(
2766             sw_if_index=self.pg0.sw_if_index,
2767             flags=flags, is_add=1)
2768         self.vapi.nat44_interface_add_del_feature(
2769             sw_if_index=self.pg1.sw_if_index,
2770             is_add=1)
2771
2772         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2773              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2774              TCP(sport=self.tcp_port_in, dport=20))
2775         self.pg0.add_stream(p)
2776         self.pg_enable_capture(self.pg_interfaces)
2777         self.pg_start()
2778         capture = self.pg1.get_capture(1)
2779         self.tcp_port_out = capture[0][TCP].sport
2780         capture = self.pg3.get_capture(1)
2781         self.verify_syslog_apmap(capture[0][Raw].load)
2782
2783         self.pg_enable_capture(self.pg_interfaces)
2784         self.pg_start()
2785         self.nat44_add_address(self.nat_addr, is_add=0)
2786         capture = self.pg3.get_capture(1)
2787         self.verify_syslog_apmap(capture[0][Raw].load, False)
2788
2789     def test_pool_addr_fib(self):
2790         """ NAT44 add pool addresses to FIB """
2791         static_addr = '10.0.0.10'
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         self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
2801
2802         # NAT44 address
2803         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2804              ARP(op=ARP.who_has, pdst=self.nat_addr,
2805                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2806         self.pg1.add_stream(p)
2807         self.pg_enable_capture(self.pg_interfaces)
2808         self.pg_start()
2809         capture = self.pg1.get_capture(1)
2810         self.assertTrue(capture[0].haslayer(ARP))
2811         self.assertTrue(capture[0][ARP].op, ARP.is_at)
2812
2813         # 1:1 NAT address
2814         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2815              ARP(op=ARP.who_has, pdst=static_addr,
2816                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2817         self.pg1.add_stream(p)
2818         self.pg_enable_capture(self.pg_interfaces)
2819         self.pg_start()
2820         capture = self.pg1.get_capture(1)
2821         self.assertTrue(capture[0].haslayer(ARP))
2822         self.assertTrue(capture[0][ARP].op, ARP.is_at)
2823
2824         # send ARP to non-NAT44 interface
2825         p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2826              ARP(op=ARP.who_has, pdst=self.nat_addr,
2827                  psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2828         self.pg2.add_stream(p)
2829         self.pg_enable_capture(self.pg_interfaces)
2830         self.pg_start()
2831         self.pg1.assert_nothing_captured()
2832
2833         # remove addresses and verify
2834         self.nat44_add_address(self.nat_addr, is_add=0)
2835         self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2836                                       is_add=0)
2837
2838         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2839              ARP(op=ARP.who_has, pdst=self.nat_addr,
2840                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2841         self.pg1.add_stream(p)
2842         self.pg_enable_capture(self.pg_interfaces)
2843         self.pg_start()
2844         self.pg1.assert_nothing_captured()
2845
2846         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2847              ARP(op=ARP.who_has, pdst=static_addr,
2848                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2849         self.pg1.add_stream(p)
2850         self.pg_enable_capture(self.pg_interfaces)
2851         self.pg_start()
2852         self.pg1.assert_nothing_captured()
2853
2854     def test_vrf_mode(self):
2855         """ NAT44 tenant VRF aware address pool mode """
2856
2857         vrf_id1 = 1
2858         vrf_id2 = 2
2859         nat_ip1 = "10.0.0.10"
2860         nat_ip2 = "10.0.0.11"
2861
2862         self.pg0.unconfig_ip4()
2863         self.pg1.unconfig_ip4()
2864         self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
2865         self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
2866         self.pg0.set_table_ip4(vrf_id1)
2867         self.pg1.set_table_ip4(vrf_id2)
2868         self.pg0.config_ip4()
2869         self.pg1.config_ip4()
2870         self.pg0.resolve_arp()
2871         self.pg1.resolve_arp()
2872
2873         self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2874         self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2875         flags = self.config_flags.NAT_IS_INSIDE
2876         self.vapi.nat44_interface_add_del_feature(
2877             sw_if_index=self.pg0.sw_if_index,
2878             flags=flags, is_add=1)
2879         self.vapi.nat44_interface_add_del_feature(
2880             sw_if_index=self.pg1.sw_if_index,
2881             flags=flags, is_add=1)
2882         self.vapi.nat44_interface_add_del_feature(
2883             sw_if_index=self.pg2.sw_if_index,
2884             is_add=1)
2885
2886         try:
2887             # first VRF
2888             pkts = self.create_stream_in(self.pg0, self.pg2)
2889             self.pg0.add_stream(pkts)
2890             self.pg_enable_capture(self.pg_interfaces)
2891             self.pg_start()
2892             capture = self.pg2.get_capture(len(pkts))
2893             self.verify_capture_out(capture, nat_ip1)
2894
2895             # second VRF
2896             pkts = self.create_stream_in(self.pg1, self.pg2)
2897             self.pg1.add_stream(pkts)
2898             self.pg_enable_capture(self.pg_interfaces)
2899             self.pg_start()
2900             capture = self.pg2.get_capture(len(pkts))
2901             self.verify_capture_out(capture, nat_ip2)
2902
2903         finally:
2904             self.pg0.unconfig_ip4()
2905             self.pg1.unconfig_ip4()
2906             self.pg0.set_table_ip4(0)
2907             self.pg1.set_table_ip4(0)
2908             self.pg0.config_ip4()
2909             self.pg1.config_ip4()
2910             self.pg0.resolve_arp()
2911             self.pg1.resolve_arp()
2912             self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id1})
2913             self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id2})
2914
2915     def test_vrf_feature_independent(self):
2916         """ NAT44 tenant VRF independent address pool mode """
2917
2918         nat_ip1 = "10.0.0.10"
2919         nat_ip2 = "10.0.0.11"
2920
2921         self.nat44_add_address(nat_ip1)
2922         self.nat44_add_address(nat_ip2, vrf_id=99)
2923         flags = self.config_flags.NAT_IS_INSIDE
2924         self.vapi.nat44_interface_add_del_feature(
2925             sw_if_index=self.pg0.sw_if_index,
2926             flags=flags, is_add=1)
2927         self.vapi.nat44_interface_add_del_feature(
2928             sw_if_index=self.pg1.sw_if_index,
2929             flags=flags, is_add=1)
2930         self.vapi.nat44_interface_add_del_feature(
2931             sw_if_index=self.pg2.sw_if_index,
2932             is_add=1)
2933
2934         # first VRF
2935         pkts = self.create_stream_in(self.pg0, self.pg2)
2936         self.pg0.add_stream(pkts)
2937         self.pg_enable_capture(self.pg_interfaces)
2938         self.pg_start()
2939         capture = self.pg2.get_capture(len(pkts))
2940         self.verify_capture_out(capture, nat_ip1)
2941
2942         # second VRF
2943         pkts = self.create_stream_in(self.pg1, self.pg2)
2944         self.pg1.add_stream(pkts)
2945         self.pg_enable_capture(self.pg_interfaces)
2946         self.pg_start()
2947         capture = self.pg2.get_capture(len(pkts))
2948         self.verify_capture_out(capture, nat_ip1)
2949
2950     def create_routes_and_neigbors(self):
2951         r1 = VppIpRoute(self, self.pg7.remote_ip4, 32,
2952                         [VppRoutePath(self.pg7.remote_ip4,
2953                                       self.pg7.sw_if_index)])
2954         r2 = VppIpRoute(self, self.pg8.remote_ip4, 32,
2955                         [VppRoutePath(self.pg8.remote_ip4,
2956                                       self.pg8.sw_if_index)])
2957         r1.add_vpp_config()
2958         r2.add_vpp_config()
2959
2960         n1 = VppNeighbor(self,
2961                          self.pg7.sw_if_index,
2962                          self.pg7.remote_mac,
2963                          self.pg7.remote_ip4,
2964                          is_static=1)
2965         n2 = VppNeighbor(self,
2966                          self.pg8.sw_if_index,
2967                          self.pg8.remote_mac,
2968                          self.pg8.remote_ip4,
2969                          is_static=1)
2970         n1.add_vpp_config()
2971         n2.add_vpp_config()
2972
2973     def test_dynamic_ipless_interfaces(self):
2974         """ NAT44 interfaces without configured IP address """
2975         self.create_routes_and_neigbors()
2976         self.nat44_add_address(self.nat_addr)
2977         flags = self.config_flags.NAT_IS_INSIDE
2978         self.vapi.nat44_interface_add_del_feature(
2979             sw_if_index=self.pg7.sw_if_index,
2980             flags=flags, is_add=1)
2981         self.vapi.nat44_interface_add_del_feature(
2982             sw_if_index=self.pg8.sw_if_index,
2983             is_add=1)
2984
2985         # in2out
2986         pkts = self.create_stream_in(self.pg7, self.pg8)
2987         self.pg7.add_stream(pkts)
2988         self.pg_enable_capture(self.pg_interfaces)
2989         self.pg_start()
2990         capture = self.pg8.get_capture(len(pkts))
2991         self.verify_capture_out(capture)
2992
2993         # out2in
2994         pkts = self.create_stream_out(self.pg8, self.nat_addr)
2995         self.pg8.add_stream(pkts)
2996         self.pg_enable_capture(self.pg_interfaces)
2997         self.pg_start()
2998         capture = self.pg7.get_capture(len(pkts))
2999         self.verify_capture_in(capture, self.pg7)
3000
3001     def test_static_ipless_interfaces(self):
3002         """ NAT44 interfaces without configured IP address - 1:1 NAT """
3003
3004         self.create_routes_and_neigbors()
3005         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
3006         flags = self.config_flags.NAT_IS_INSIDE
3007         self.vapi.nat44_interface_add_del_feature(
3008             sw_if_index=self.pg7.sw_if_index,
3009             flags=flags, is_add=1)
3010         self.vapi.nat44_interface_add_del_feature(
3011             sw_if_index=self.pg8.sw_if_index,
3012             is_add=1)
3013
3014         # out2in
3015         pkts = self.create_stream_out(self.pg8)
3016         self.pg8.add_stream(pkts)
3017         self.pg_enable_capture(self.pg_interfaces)
3018         self.pg_start()
3019         capture = self.pg7.get_capture(len(pkts))
3020         self.verify_capture_in(capture, self.pg7)
3021
3022         # in2out
3023         pkts = self.create_stream_in(self.pg7, self.pg8)
3024         self.pg7.add_stream(pkts)
3025         self.pg_enable_capture(self.pg_interfaces)
3026         self.pg_start()
3027         capture = self.pg8.get_capture(len(pkts))
3028         self.verify_capture_out(capture, self.nat_addr, True)
3029
3030     def test_static_with_port_ipless_interfaces(self):
3031         """ NAT44 interfaces without configured IP address - 1:1 NAPT """
3032
3033         self.tcp_port_out = 30606
3034         self.udp_port_out = 30607
3035         self.icmp_id_out = 30608
3036
3037         self.create_routes_and_neigbors()
3038         self.nat44_add_address(self.nat_addr)
3039         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3040                                       self.tcp_port_in, self.tcp_port_out,
3041                                       proto=IP_PROTOS.tcp)
3042         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3043                                       self.udp_port_in, self.udp_port_out,
3044                                       proto=IP_PROTOS.udp)
3045         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3046                                       self.icmp_id_in, self.icmp_id_out,
3047                                       proto=IP_PROTOS.icmp)
3048         flags = self.config_flags.NAT_IS_INSIDE
3049         self.vapi.nat44_interface_add_del_feature(
3050             sw_if_index=self.pg7.sw_if_index,
3051             flags=flags, is_add=1)
3052         self.vapi.nat44_interface_add_del_feature(
3053             sw_if_index=self.pg8.sw_if_index,
3054             is_add=1)
3055
3056         # out2in
3057         pkts = self.create_stream_out(self.pg8)
3058         self.pg8.add_stream(pkts)
3059         self.pg_enable_capture(self.pg_interfaces)
3060         self.pg_start()
3061         capture = self.pg7.get_capture(len(pkts))
3062         self.verify_capture_in(capture, self.pg7)
3063
3064         # in2out
3065         pkts = self.create_stream_in(self.pg7, self.pg8)
3066         self.pg7.add_stream(pkts)
3067         self.pg_enable_capture(self.pg_interfaces)
3068         self.pg_start()
3069         capture = self.pg8.get_capture(len(pkts))
3070         self.verify_capture_out(capture)
3071
3072     def test_static_unknown_proto(self):
3073         """ 1:1 NAT translate packet with unknown protocol """
3074         nat_ip = "10.0.0.10"
3075         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
3076         flags = self.config_flags.NAT_IS_INSIDE
3077         self.vapi.nat44_interface_add_del_feature(
3078             sw_if_index=self.pg0.sw_if_index,
3079             flags=flags, is_add=1)
3080         self.vapi.nat44_interface_add_del_feature(
3081             sw_if_index=self.pg1.sw_if_index,
3082             is_add=1)
3083
3084         # in2out
3085         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3086              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3087              GRE() /
3088              IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3089              TCP(sport=1234, dport=1234))
3090         self.pg0.add_stream(p)
3091         self.pg_enable_capture(self.pg_interfaces)
3092         self.pg_start()
3093         p = self.pg1.get_capture(1)
3094         packet = p[0]
3095         try:
3096             self.assertEqual(packet[IP].src, nat_ip)
3097             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3098             self.assertEqual(packet.haslayer(GRE), 1)
3099             self.assert_packet_checksums_valid(packet)
3100         except:
3101             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3102             raise
3103
3104         # out2in
3105         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3106              IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3107              GRE() /
3108              IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3109              TCP(sport=1234, dport=1234))
3110         self.pg1.add_stream(p)
3111         self.pg_enable_capture(self.pg_interfaces)
3112         self.pg_start()
3113         p = self.pg0.get_capture(1)
3114         packet = p[0]
3115         try:
3116             self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3117             self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3118             self.assertEqual(packet.haslayer(GRE), 1)
3119             self.assert_packet_checksums_valid(packet)
3120         except:
3121             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3122             raise
3123
3124     def test_hairpinning_static_unknown_proto(self):
3125         """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3126
3127         host = self.pg0.remote_hosts[0]
3128         server = self.pg0.remote_hosts[1]
3129
3130         host_nat_ip = "10.0.0.10"
3131         server_nat_ip = "10.0.0.11"
3132
3133         self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3134         self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3135         flags = self.config_flags.NAT_IS_INSIDE
3136         self.vapi.nat44_interface_add_del_feature(
3137             sw_if_index=self.pg0.sw_if_index,
3138             flags=flags, is_add=1)
3139         self.vapi.nat44_interface_add_del_feature(
3140             sw_if_index=self.pg1.sw_if_index,
3141             is_add=1)
3142
3143         # host to server
3144         p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3145              IP(src=host.ip4, dst=server_nat_ip) /
3146              GRE() /
3147              IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3148              TCP(sport=1234, dport=1234))
3149         self.pg0.add_stream(p)
3150         self.pg_enable_capture(self.pg_interfaces)
3151         self.pg_start()
3152         p = self.pg0.get_capture(1)
3153         packet = p[0]
3154         try:
3155             self.assertEqual(packet[IP].src, host_nat_ip)
3156             self.assertEqual(packet[IP].dst, server.ip4)
3157             self.assertEqual(packet.haslayer(GRE), 1)
3158             self.assert_packet_checksums_valid(packet)
3159         except:
3160             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3161             raise
3162
3163         # server to host
3164         p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3165              IP(src=server.ip4, dst=host_nat_ip) /
3166              GRE() /
3167              IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3168              TCP(sport=1234, dport=1234))
3169         self.pg0.add_stream(p)
3170         self.pg_enable_capture(self.pg_interfaces)
3171         self.pg_start()
3172         p = self.pg0.get_capture(1)
3173         packet = p[0]
3174         try:
3175             self.assertEqual(packet[IP].src, server_nat_ip)
3176             self.assertEqual(packet[IP].dst, host.ip4)
3177             self.assertEqual(packet.haslayer(GRE), 1)
3178             self.assert_packet_checksums_valid(packet)
3179         except:
3180             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3181             raise
3182
3183     def test_output_feature(self):
3184         """ NAT44 interface output feature (in2out postrouting) """
3185         self.nat44_add_address(self.nat_addr)
3186         flags = self.config_flags.NAT_IS_INSIDE
3187         self.vapi.nat44_interface_add_del_output_feature(
3188             is_add=1, flags=flags,
3189             sw_if_index=self.pg0.sw_if_index)
3190         self.vapi.nat44_interface_add_del_output_feature(
3191             is_add=1, flags=flags,
3192             sw_if_index=self.pg1.sw_if_index)
3193         self.vapi.nat44_interface_add_del_output_feature(
3194             is_add=1,
3195             sw_if_index=self.pg3.sw_if_index)
3196
3197         # in2out
3198         pkts = self.create_stream_in(self.pg0, self.pg3)
3199         self.pg0.add_stream(pkts)
3200         self.pg_enable_capture(self.pg_interfaces)
3201         self.pg_start()
3202         capture = self.pg3.get_capture(len(pkts))
3203         self.verify_capture_out(capture)
3204
3205         # out2in
3206         pkts = self.create_stream_out(self.pg3)
3207         self.pg3.add_stream(pkts)
3208         self.pg_enable_capture(self.pg_interfaces)
3209         self.pg_start()
3210         capture = self.pg0.get_capture(len(pkts))
3211         self.verify_capture_in(capture, self.pg0)
3212
3213         # from non-NAT interface to NAT inside interface
3214         pkts = self.create_stream_in(self.pg2, self.pg0)
3215         self.pg2.add_stream(pkts)
3216         self.pg_enable_capture(self.pg_interfaces)
3217         self.pg_start()
3218         capture = self.pg0.get_capture(len(pkts))
3219         self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3220
3221     def test_output_feature_vrf_aware(self):
3222         """ NAT44 interface output feature VRF aware (in2out postrouting) """
3223         nat_ip_vrf10 = "10.0.0.10"
3224         nat_ip_vrf20 = "10.0.0.20"
3225
3226         r1 = VppIpRoute(self, self.pg3.remote_ip4, 32,
3227                         [VppRoutePath(self.pg3.remote_ip4,
3228                                       self.pg3.sw_if_index)],
3229                         table_id=10)
3230         r2 = VppIpRoute(self, self.pg3.remote_ip4, 32,
3231                         [VppRoutePath(self.pg3.remote_ip4,
3232                                       self.pg3.sw_if_index)],
3233                         table_id=20)
3234         r1.add_vpp_config()
3235         r2.add_vpp_config()
3236
3237         self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3238         self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3239         flags = self.config_flags.NAT_IS_INSIDE
3240         self.vapi.nat44_interface_add_del_output_feature(
3241             is_add=1, flags=flags,
3242             sw_if_index=self.pg4.sw_if_index)
3243         self.vapi.nat44_interface_add_del_output_feature(
3244             is_add=1, flags=flags,
3245             sw_if_index=self.pg6.sw_if_index)
3246         self.vapi.nat44_interface_add_del_output_feature(
3247             is_add=1,
3248             sw_if_index=self.pg3.sw_if_index)
3249
3250         # in2out VRF 10
3251         pkts = self.create_stream_in(self.pg4, self.pg3)
3252         self.pg4.add_stream(pkts)
3253         self.pg_enable_capture(self.pg_interfaces)
3254         self.pg_start()
3255         capture = self.pg3.get_capture(len(pkts))
3256         self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3257
3258         # out2in VRF 10
3259         pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3260         self.pg3.add_stream(pkts)
3261         self.pg_enable_capture(self.pg_interfaces)
3262         self.pg_start()
3263         capture = self.pg4.get_capture(len(pkts))
3264         self.verify_capture_in(capture, self.pg4)
3265
3266         # in2out VRF 20
3267         pkts = self.create_stream_in(self.pg6, self.pg3)
3268         self.pg6.add_stream(pkts)
3269         self.pg_enable_capture(self.pg_interfaces)
3270         self.pg_start()
3271         capture = self.pg3.get_capture(len(pkts))
3272         self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3273
3274         # out2in VRF 20
3275         pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3276         self.pg3.add_stream(pkts)
3277         self.pg_enable_capture(self.pg_interfaces)
3278         self.pg_start()
3279         capture = self.pg6.get_capture(len(pkts))
3280         self.verify_capture_in(capture, self.pg6)
3281
3282     def test_output_feature_hairpinning(self):
3283         """ NAT44 interface output feature hairpinning (in2out postrouting) """
3284         host = self.pg0.remote_hosts[0]
3285         server = self.pg0.remote_hosts[1]
3286         host_in_port = 1234
3287         host_out_port = 0
3288         server_in_port = 5678
3289         server_out_port = 8765
3290
3291         self.nat44_add_address(self.nat_addr)
3292         flags = self.config_flags.NAT_IS_INSIDE
3293         self.vapi.nat44_interface_add_del_output_feature(
3294             is_add=1, flags=flags,
3295             sw_if_index=self.pg0.sw_if_index)
3296         self.vapi.nat44_interface_add_del_output_feature(
3297             is_add=1,
3298             sw_if_index=self.pg1.sw_if_index)
3299
3300         # add static mapping for server
3301         self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3302                                       server_in_port, server_out_port,
3303                                       proto=IP_PROTOS.tcp)
3304
3305         # send packet from host to server
3306         p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3307              IP(src=host.ip4, dst=self.nat_addr) /
3308              TCP(sport=host_in_port, dport=server_out_port))
3309         self.pg0.add_stream(p)
3310         self.pg_enable_capture(self.pg_interfaces)
3311         self.pg_start()
3312         capture = self.pg0.get_capture(1)
3313         p = capture[0]
3314         try:
3315             ip = p[IP]
3316             tcp = p[TCP]
3317             self.assertEqual(ip.src, self.nat_addr)
3318             self.assertEqual(ip.dst, server.ip4)
3319             self.assertNotEqual(tcp.sport, host_in_port)
3320             self.assertEqual(tcp.dport, server_in_port)
3321             self.assert_packet_checksums_valid(p)
3322             host_out_port = tcp.sport
3323         except:
3324             self.logger.error(ppp("Unexpected or invalid packet:", p))
3325             raise
3326
3327         # send reply from server to host
3328         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3329              IP(src=server.ip4, dst=self.nat_addr) /
3330              TCP(sport=server_in_port, dport=host_out_port))
3331         self.pg0.add_stream(p)
3332         self.pg_enable_capture(self.pg_interfaces)
3333         self.pg_start()
3334         capture = self.pg0.get_capture(1)
3335         p = capture[0]
3336         try:
3337             ip = p[IP]
3338             tcp = p[TCP]
3339             self.assertEqual(ip.src, self.nat_addr)
3340             self.assertEqual(ip.dst, host.ip4)
3341             self.assertEqual(tcp.sport, server_out_port)
3342             self.assertEqual(tcp.dport, host_in_port)
3343             self.assert_packet_checksums_valid(p)
3344         except:
3345             self.logger.error(ppp("Unexpected or invalid packet:", p))
3346             raise
3347
3348     def test_one_armed_nat44(self):
3349         """ One armed NAT44 """
3350         remote_host = self.pg9.remote_hosts[0]
3351         local_host = self.pg9.remote_hosts[1]
3352         external_port = 0
3353
3354         self.nat44_add_address(self.nat_addr)
3355         flags = self.config_flags.NAT_IS_INSIDE
3356         self.vapi.nat44_interface_add_del_feature(
3357             sw_if_index=self.pg9.sw_if_index,
3358             is_add=1)
3359         self.vapi.nat44_interface_add_del_feature(
3360             sw_if_index=self.pg9.sw_if_index,
3361             flags=flags, is_add=1)
3362
3363         # in2out
3364         p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3365              IP(src=local_host.ip4, dst=remote_host.ip4) /
3366              TCP(sport=12345, dport=80))
3367         self.pg9.add_stream(p)
3368         self.pg_enable_capture(self.pg_interfaces)
3369         self.pg_start()
3370         capture = self.pg9.get_capture(1)
3371         p = capture[0]
3372         try:
3373             ip = p[IP]
3374             tcp = p[TCP]
3375             self.assertEqual(ip.src, self.nat_addr)
3376             self.assertEqual(ip.dst, remote_host.ip4)
3377             self.assertNotEqual(tcp.sport, 12345)
3378             external_port = tcp.sport
3379             self.assertEqual(tcp.dport, 80)
3380             self.assert_packet_checksums_valid(p)
3381         except:
3382             self.logger.error(ppp("Unexpected or invalid packet:", p))
3383             raise
3384
3385         # out2in
3386         p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3387              IP(src=remote_host.ip4, dst=self.nat_addr) /
3388              TCP(sport=80, dport=external_port))
3389         self.pg9.add_stream(p)
3390         self.pg_enable_capture(self.pg_interfaces)
3391         self.pg_start()
3392         capture = self.pg9.get_capture(1)
3393         p = capture[0]
3394         try:
3395             ip = p[IP]
3396             tcp = p[TCP]
3397             self.assertEqual(ip.src, remote_host.ip4)
3398             self.assertEqual(ip.dst, local_host.ip4)
3399             self.assertEqual(tcp.sport, 80)
3400             self.assertEqual(tcp.dport, 12345)
3401             self.assert_packet_checksums_valid(p)
3402         except:
3403             self.logger.error(ppp("Unexpected or invalid packet:", p))
3404             raise
3405
3406         err = self.statistics.get_err_counter(
3407             '/err/nat44-classify/next in2out')
3408         self.assertEqual(err, 1)
3409         err = self.statistics.get_err_counter(
3410             '/err/nat44-classify/next out2in')
3411         self.assertEqual(err, 1)
3412
3413     def test_del_session(self):
3414         """ Delete NAT44 session """
3415         self.nat44_add_address(self.nat_addr)
3416         flags = self.config_flags.NAT_IS_INSIDE
3417         self.vapi.nat44_interface_add_del_feature(
3418             sw_if_index=self.pg0.sw_if_index,
3419             flags=flags, is_add=1)
3420         self.vapi.nat44_interface_add_del_feature(
3421             sw_if_index=self.pg1.sw_if_index,
3422             is_add=1)
3423
3424         pkts = self.create_stream_in(self.pg0, self.pg1)
3425         self.pg0.add_stream(pkts)
3426         self.pg_enable_capture(self.pg_interfaces)
3427         self.pg_start()
3428         self.pg1.get_capture(len(pkts))
3429
3430         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3431         nsessions = len(sessions)
3432
3433         self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3434                                     port=sessions[0].inside_port,
3435                                     protocol=sessions[0].protocol,
3436                                     flags=self.config_flags.NAT_IS_INSIDE)
3437         self.vapi.nat44_del_session(address=sessions[1].outside_ip_address,
3438                                     port=sessions[1].outside_port,
3439                                     protocol=sessions[1].protocol)
3440
3441         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3442         self.assertEqual(nsessions - len(sessions), 2)
3443
3444         self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3445                                     port=sessions[0].inside_port,
3446                                     protocol=sessions[0].protocol,
3447                                     flags=self.config_flags.NAT_IS_INSIDE)
3448
3449         self.verify_no_nat44_user()
3450
3451     def test_frag_in_order(self):
3452         """ NAT44 translate fragments arriving in order """
3453
3454         self.nat44_add_address(self.nat_addr)
3455         flags = self.config_flags.NAT_IS_INSIDE
3456         self.vapi.nat44_interface_add_del_feature(
3457             sw_if_index=self.pg0.sw_if_index,
3458             flags=flags, is_add=1)
3459         self.vapi.nat44_interface_add_del_feature(
3460             sw_if_index=self.pg1.sw_if_index,
3461             is_add=1)
3462
3463         self.frag_in_order(proto=IP_PROTOS.tcp)
3464         self.frag_in_order(proto=IP_PROTOS.udp)
3465         self.frag_in_order(proto=IP_PROTOS.icmp)
3466
3467     def test_frag_forwarding(self):
3468         """ NAT44 forwarding fragment test """
3469         self.vapi.nat44_add_del_interface_addr(
3470             is_add=1,
3471             sw_if_index=self.pg1.sw_if_index)
3472         flags = self.config_flags.NAT_IS_INSIDE
3473         self.vapi.nat44_interface_add_del_feature(
3474             sw_if_index=self.pg0.sw_if_index,
3475             flags=flags, is_add=1)
3476         self.vapi.nat44_interface_add_del_feature(
3477             sw_if_index=self.pg1.sw_if_index,
3478             is_add=1)
3479         self.vapi.nat44_forwarding_enable_disable(enable=1)
3480
3481         data = b"A" * 16 + b"B" * 16 + b"C" * 3
3482         pkts = self.create_stream_frag(self.pg1,
3483                                        self.pg0.remote_ip4,
3484                                        4789,
3485                                        4789,
3486                                        data,
3487                                        proto=IP_PROTOS.udp)
3488         self.pg1.add_stream(pkts)
3489         self.pg_enable_capture(self.pg_interfaces)
3490         self.pg_start()
3491         frags = self.pg0.get_capture(len(pkts))
3492         p = self.reass_frags_and_verify(frags,
3493                                         self.pg1.remote_ip4,
3494                                         self.pg0.remote_ip4)
3495         self.assertEqual(p[UDP].sport, 4789)
3496         self.assertEqual(p[UDP].dport, 4789)
3497         self.assertEqual(data, p[Raw].load)
3498
3499     def test_reass_hairpinning(self):
3500         """ NAT44 fragments hairpinning """
3501
3502         self.server = self.pg0.remote_hosts[1]
3503         self.host_in_port = random.randint(1025, 65535)
3504         self.server_in_port = random.randint(1025, 65535)
3505         self.server_out_port = random.randint(1025, 65535)
3506
3507         self.nat44_add_address(self.nat_addr)
3508         flags = self.config_flags.NAT_IS_INSIDE
3509         self.vapi.nat44_interface_add_del_feature(
3510             sw_if_index=self.pg0.sw_if_index,
3511             flags=flags, is_add=1)
3512         self.vapi.nat44_interface_add_del_feature(
3513             sw_if_index=self.pg1.sw_if_index,
3514             is_add=1)
3515         # add static mapping for server
3516         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3517                                       self.server_in_port,
3518                                       self.server_out_port,
3519                                       proto=IP_PROTOS.tcp)
3520         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3521                                       self.server_in_port,
3522                                       self.server_out_port,
3523                                       proto=IP_PROTOS.udp)
3524         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
3525
3526         self.reass_hairpinning(proto=IP_PROTOS.tcp)
3527         self.reass_hairpinning(proto=IP_PROTOS.udp)
3528         self.reass_hairpinning(proto=IP_PROTOS.icmp)
3529
3530     def test_frag_out_of_order(self):
3531         """ NAT44 translate fragments arriving out of order """
3532
3533         self.nat44_add_address(self.nat_addr)
3534         flags = self.config_flags.NAT_IS_INSIDE
3535         self.vapi.nat44_interface_add_del_feature(
3536             sw_if_index=self.pg0.sw_if_index,
3537             flags=flags, is_add=1)
3538         self.vapi.nat44_interface_add_del_feature(
3539             sw_if_index=self.pg1.sw_if_index,
3540             is_add=1)
3541
3542         self.frag_out_of_order(proto=IP_PROTOS.tcp)
3543         self.frag_out_of_order(proto=IP_PROTOS.udp)
3544         self.frag_out_of_order(proto=IP_PROTOS.icmp)
3545
3546     def test_port_restricted(self):
3547         """ Port restricted NAT44 (MAP-E CE) """
3548         self.nat44_add_address(self.nat_addr)
3549         flags = self.config_flags.NAT_IS_INSIDE
3550         self.vapi.nat44_interface_add_del_feature(
3551             sw_if_index=self.pg0.sw_if_index,
3552             flags=flags, is_add=1)
3553         self.vapi.nat44_interface_add_del_feature(
3554             sw_if_index=self.pg1.sw_if_index,
3555             is_add=1)
3556         self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3557                                                   psid_offset=6,
3558                                                   psid_length=6,
3559                                                   psid=10)
3560
3561         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3562              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3563              TCP(sport=4567, dport=22))
3564         self.pg0.add_stream(p)
3565         self.pg_enable_capture(self.pg_interfaces)
3566         self.pg_start()
3567         capture = self.pg1.get_capture(1)
3568         p = capture[0]
3569         try:
3570             ip = p[IP]
3571             tcp = p[TCP]
3572             self.assertEqual(ip.dst, self.pg1.remote_ip4)
3573             self.assertEqual(ip.src, self.nat_addr)
3574             self.assertEqual(tcp.dport, 22)
3575             self.assertNotEqual(tcp.sport, 4567)
3576             self.assertEqual((tcp.sport >> 6) & 63, 10)
3577             self.assert_packet_checksums_valid(p)
3578         except:
3579             self.logger.error(ppp("Unexpected or invalid packet:", p))
3580             raise
3581
3582     def test_port_range(self):
3583         """ External address port range """
3584         self.nat44_add_address(self.nat_addr)
3585         flags = self.config_flags.NAT_IS_INSIDE
3586         self.vapi.nat44_interface_add_del_feature(
3587             sw_if_index=self.pg0.sw_if_index,
3588             flags=flags, is_add=1)
3589         self.vapi.nat44_interface_add_del_feature(
3590             sw_if_index=self.pg1.sw_if_index,
3591             is_add=1)
3592         self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3593                                                   start_port=1025,
3594                                                   end_port=1027)
3595
3596         pkts = []
3597         for port in range(0, 5):
3598             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3599                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3600                  TCP(sport=1125 + port))
3601             pkts.append(p)
3602         self.pg0.add_stream(pkts)
3603         self.pg_enable_capture(self.pg_interfaces)
3604         self.pg_start()
3605         capture = self.pg1.get_capture(3)
3606         for p in capture:
3607             tcp = p[TCP]
3608             self.assertGreaterEqual(tcp.sport, 1025)
3609             self.assertLessEqual(tcp.sport, 1027)
3610
3611     def test_multiple_outside_vrf(self):
3612         """ Multiple outside VRF """
3613         vrf_id1 = 1
3614         vrf_id2 = 2
3615
3616         self.pg1.unconfig_ip4()
3617         self.pg2.unconfig_ip4()
3618         self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
3619         self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
3620         self.pg1.set_table_ip4(vrf_id1)
3621         self.pg2.set_table_ip4(vrf_id2)
3622         self.pg1.config_ip4()
3623         self.pg2.config_ip4()
3624         self.pg1.resolve_arp()
3625         self.pg2.resolve_arp()
3626
3627         self.nat44_add_address(self.nat_addr)
3628         flags = self.config_flags.NAT_IS_INSIDE
3629         self.vapi.nat44_interface_add_del_feature(
3630             sw_if_index=self.pg0.sw_if_index,
3631             flags=flags, is_add=1)
3632         self.vapi.nat44_interface_add_del_feature(
3633             sw_if_index=self.pg1.sw_if_index,
3634             is_add=1)
3635         self.vapi.nat44_interface_add_del_feature(
3636             sw_if_index=self.pg2.sw_if_index,
3637             is_add=1)
3638
3639         try:
3640             # first VRF
3641             pkts = self.create_stream_in(self.pg0, self.pg1)
3642             self.pg0.add_stream(pkts)
3643             self.pg_enable_capture(self.pg_interfaces)
3644             self.pg_start()
3645             capture = self.pg1.get_capture(len(pkts))
3646             self.verify_capture_out(capture, self.nat_addr)
3647
3648             pkts = self.create_stream_out(self.pg1, self.nat_addr)
3649             self.pg1.add_stream(pkts)
3650             self.pg_enable_capture(self.pg_interfaces)
3651             self.pg_start()
3652             capture = self.pg0.get_capture(len(pkts))
3653             self.verify_capture_in(capture, self.pg0)
3654
3655             self.tcp_port_in = 60303
3656             self.udp_port_in = 60304
3657             self.icmp_id_in = 60305
3658
3659             # second VRF
3660             pkts = self.create_stream_in(self.pg0, self.pg2)
3661             self.pg0.add_stream(pkts)
3662             self.pg_enable_capture(self.pg_interfaces)
3663             self.pg_start()
3664             capture = self.pg2.get_capture(len(pkts))
3665             self.verify_capture_out(capture, self.nat_addr)
3666
3667             pkts = self.create_stream_out(self.pg2, self.nat_addr)
3668             self.pg2.add_stream(pkts)
3669             self.pg_enable_capture(self.pg_interfaces)
3670             self.pg_start()
3671             capture = self.pg0.get_capture(len(pkts))
3672             self.verify_capture_in(capture, self.pg0)
3673
3674         finally:
3675             self.nat44_add_address(self.nat_addr, is_add=0)
3676             self.pg1.unconfig_ip4()
3677             self.pg2.unconfig_ip4()
3678             self.pg1.set_table_ip4(0)
3679             self.pg2.set_table_ip4(0)
3680             self.pg1.config_ip4()
3681             self.pg2.config_ip4()
3682             self.pg1.resolve_arp()
3683             self.pg2.resolve_arp()
3684
3685     @unittest.skipUnless(running_extended_tests, "part of extended tests")
3686     def test_session_timeout(self):
3687         """ NAT44 session timeouts """
3688         self.nat44_add_address(self.nat_addr)
3689         flags = self.config_flags.NAT_IS_INSIDE
3690         self.vapi.nat44_interface_add_del_feature(
3691             sw_if_index=self.pg0.sw_if_index,
3692             flags=flags, is_add=1)
3693         self.vapi.nat44_interface_add_del_feature(
3694             sw_if_index=self.pg1.sw_if_index,
3695             is_add=1)
3696         self.vapi.nat_set_timeouts(udp=5, tcp_established=7440,
3697                                    tcp_transitory=240, icmp=60)
3698
3699         max_sessions = 1000
3700         pkts = []
3701         for i in range(0, max_sessions):
3702             src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3703             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3704                  IP(src=src, dst=self.pg1.remote_ip4) /
3705                  UDP(sport=1025, dport=53))
3706             pkts.append(p)
3707         self.pg0.add_stream(pkts)
3708         self.pg_enable_capture(self.pg_interfaces)
3709         self.pg_start()
3710         self.pg1.get_capture(max_sessions)
3711
3712         sleep(6)
3713
3714         pkts = []
3715         for i in range(0, max_sessions):
3716             src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3717             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3718                  IP(src=src, dst=self.pg1.remote_ip4) /
3719                  UDP(sport=1026, dport=53))
3720             pkts.append(p)
3721         self.pg0.add_stream(pkts)
3722         self.pg_enable_capture(self.pg_interfaces)
3723         self.pg_start()
3724         self.pg1.get_capture(max_sessions)
3725
3726         nsessions = 0
3727         users = self.vapi.nat44_user_dump()
3728         for user in users:
3729             nsessions = nsessions + user.nsessions
3730         self.assertLess(nsessions, 2 * max_sessions)
3731
3732     def test_mss_clamping(self):
3733         """ TCP MSS clamping """
3734         self.nat44_add_address(self.nat_addr)
3735         flags = self.config_flags.NAT_IS_INSIDE
3736         self.vapi.nat44_interface_add_del_feature(
3737             sw_if_index=self.pg0.sw_if_index,
3738             flags=flags, is_add=1)
3739         self.vapi.nat44_interface_add_del_feature(
3740             sw_if_index=self.pg1.sw_if_index,
3741             is_add=1)
3742
3743         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3744              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3745              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3746                  flags="S", options=[('MSS', 1400)]))
3747
3748         self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3749         self.pg0.add_stream(p)
3750         self.pg_enable_capture(self.pg_interfaces)
3751         self.pg_start()
3752         capture = self.pg1.get_capture(1)
3753         # Negotiated MSS value greater than configured - changed
3754         self.verify_mss_value(capture[0], 1000)
3755
3756         self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
3757         self.pg0.add_stream(p)
3758         self.pg_enable_capture(self.pg_interfaces)
3759         self.pg_start()
3760         capture = self.pg1.get_capture(1)
3761         # MSS clamping disabled - negotiated MSS unchanged
3762         self.verify_mss_value(capture[0], 1400)
3763
3764         self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3765         self.pg0.add_stream(p)
3766         self.pg_enable_capture(self.pg_interfaces)
3767         self.pg_start()
3768         capture = self.pg1.get_capture(1)
3769         # Negotiated MSS value smaller than configured - unchanged
3770         self.verify_mss_value(capture[0], 1400)
3771
3772     @unittest.skipUnless(running_extended_tests, "part of extended tests")
3773     def test_ha_send(self):
3774         """ Send HA session synchronization events (active) """
3775         self.nat44_add_address(self.nat_addr)
3776         flags = self.config_flags.NAT_IS_INSIDE
3777         self.vapi.nat44_interface_add_del_feature(
3778             sw_if_index=self.pg0.sw_if_index,
3779             flags=flags, is_add=1)
3780         self.vapi.nat44_interface_add_del_feature(
3781             sw_if_index=self.pg1.sw_if_index,
3782             is_add=1)
3783         self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
3784                                       port=12345,
3785                                       path_mtu=512)
3786         self.vapi.nat_ha_set_failover(ip_address=self.pg3.remote_ip4,
3787                                       port=12346, session_refresh_interval=10)
3788         bind_layers(UDP, HANATStateSync, sport=12345)
3789
3790         # create sessions
3791         pkts = self.create_stream_in(self.pg0, self.pg1)
3792         self.pg0.add_stream(pkts)
3793         self.pg_enable_capture(self.pg_interfaces)
3794         self.pg_start()
3795         capture = self.pg1.get_capture(len(pkts))
3796         self.verify_capture_out(capture)
3797         # active send HA events
3798         self.vapi.nat_ha_flush()
3799         stats = self.statistics.get_counter('/nat44/ha/add-event-send')
3800         self.assertEqual(stats[0][0], 3)
3801         capture = self.pg3.get_capture(1)
3802         p = capture[0]
3803         self.assert_packet_checksums_valid(p)
3804         try:
3805             ip = p[IP]
3806             udp = p[UDP]
3807             hanat = p[HANATStateSync]
3808         except IndexError:
3809             self.logger.error(ppp("Invalid packet:", p))
3810             raise
3811         else:
3812             self.assertEqual(ip.src, self.pg3.local_ip4)
3813             self.assertEqual(ip.dst, self.pg3.remote_ip4)
3814             self.assertEqual(udp.sport, 12345)
3815             self.assertEqual(udp.dport, 12346)
3816             self.assertEqual(hanat.version, 1)
3817             self.assertEqual(hanat.thread_index, 0)
3818             self.assertEqual(hanat.count, 3)
3819             seq = hanat.sequence_number
3820             for event in hanat.events:
3821                 self.assertEqual(event.event_type, 1)
3822                 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
3823                 self.assertEqual(event.out_addr, self.nat_addr)
3824                 self.assertEqual(event.fib_index, 0)
3825
3826         # ACK received events
3827         ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3828                IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3829                UDP(sport=12346, dport=12345) /
3830                HANATStateSync(sequence_number=seq, flags='ACK'))
3831         self.pg3.add_stream(ack)
3832         self.pg_start()
3833         stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3834         self.assertEqual(stats[0][0], 1)
3835
3836         # delete one session
3837         self.pg_enable_capture(self.pg_interfaces)
3838         self.vapi.nat44_del_session(address=self.pg0.remote_ip4,
3839                                     port=self.tcp_port_in,
3840                                     protocol=IP_PROTOS.tcp,
3841                                     flags=self.config_flags.NAT_IS_INSIDE)
3842         self.vapi.nat_ha_flush()
3843         stats = self.statistics.get_counter('/nat44/ha/del-event-send')
3844         self.assertEqual(stats[0][0], 1)
3845         capture = self.pg3.get_capture(1)
3846         p = capture[0]
3847         try:
3848             hanat = p[HANATStateSync]
3849         except IndexError:
3850             self.logger.error(ppp("Invalid packet:", p))
3851             raise
3852         else:
3853             self.assertGreater(hanat.sequence_number, seq)
3854
3855         # do not send ACK, active retry send HA event again
3856         self.pg_enable_capture(self.pg_interfaces)
3857         sleep(12)
3858         stats = self.statistics.get_counter('/nat44/ha/retry-count')
3859         self.assertEqual(stats[0][0], 3)
3860         stats = self.statistics.get_counter('/nat44/ha/missed-count')
3861         self.assertEqual(stats[0][0], 1)
3862         capture = self.pg3.get_capture(3)
3863         for packet in capture:
3864             self.assertEqual(packet, p)
3865
3866         # session counters refresh
3867         pkts = self.create_stream_out(self.pg1)
3868         self.pg1.add_stream(pkts)
3869         self.pg_enable_capture(self.pg_interfaces)
3870         self.pg_start()
3871         self.pg0.get_capture(2)
3872         self.vapi.nat_ha_flush()
3873         stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
3874         self.assertEqual(stats[0][0], 2)
3875         capture = self.pg3.get_capture(1)
3876         p = capture[0]
3877         self.assert_packet_checksums_valid(p)
3878         try:
3879             ip = p[IP]
3880             udp = p[UDP]
3881             hanat = p[HANATStateSync]
3882         except IndexError:
3883             self.logger.error(ppp("Invalid packet:", p))
3884             raise
3885         else:
3886             self.assertEqual(ip.src, self.pg3.local_ip4)
3887             self.assertEqual(ip.dst, self.pg3.remote_ip4)
3888             self.assertEqual(udp.sport, 12345)
3889             self.assertEqual(udp.dport, 12346)
3890             self.assertEqual(hanat.version, 1)
3891             self.assertEqual(hanat.count, 2)
3892             seq = hanat.sequence_number
3893             for event in hanat.events:
3894                 self.assertEqual(event.event_type, 3)
3895                 self.assertEqual(event.out_addr, self.nat_addr)
3896                 self.assertEqual(event.fib_index, 0)
3897                 self.assertEqual(event.total_pkts, 2)
3898                 self.assertGreater(event.total_bytes, 0)
3899
3900         ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3901                IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3902                UDP(sport=12346, dport=12345) /
3903                HANATStateSync(sequence_number=seq, flags='ACK'))
3904         self.pg3.add_stream(ack)
3905         self.pg_start()
3906         stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3907         self.assertEqual(stats[0][0], 2)
3908
3909     def test_ha_recv(self):
3910         """ Receive HA session synchronization events (passive) """
3911         self.nat44_add_address(self.nat_addr)
3912         flags = self.config_flags.NAT_IS_INSIDE
3913         self.vapi.nat44_interface_add_del_feature(
3914             sw_if_index=self.pg0.sw_if_index,
3915             flags=flags, is_add=1)
3916         self.vapi.nat44_interface_add_del_feature(
3917             sw_if_index=self.pg1.sw_if_index,
3918             is_add=1)
3919         self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
3920                                       port=12345,
3921                                       path_mtu=512)
3922         bind_layers(UDP, HANATStateSync, sport=12345)
3923
3924         self.tcp_port_out = random.randint(1025, 65535)
3925         self.udp_port_out = random.randint(1025, 65535)
3926
3927         # send HA session add events to failover/passive
3928         p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3929              IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3930              UDP(sport=12346, dport=12345) /
3931              HANATStateSync(sequence_number=1, events=[
3932                  Event(event_type='add', protocol='tcp',
3933                        in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3934                        in_port=self.tcp_port_in, out_port=self.tcp_port_out,
3935                        eh_addr=self.pg1.remote_ip4,
3936                        ehn_addr=self.pg1.remote_ip4,
3937                        eh_port=self.tcp_external_port,
3938                        ehn_port=self.tcp_external_port, fib_index=0),
3939                  Event(event_type='add', protocol='udp',
3940                        in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3941                        in_port=self.udp_port_in, out_port=self.udp_port_out,
3942                        eh_addr=self.pg1.remote_ip4,
3943                        ehn_addr=self.pg1.remote_ip4,
3944                        eh_port=self.udp_external_port,
3945                        ehn_port=self.udp_external_port, fib_index=0)]))
3946
3947         self.pg3.add_stream(p)
3948         self.pg_enable_capture(self.pg_interfaces)
3949         self.pg_start()
3950         # receive ACK
3951         capture = self.pg3.get_capture(1)
3952         p = capture[0]
3953         try:
3954             hanat = p[HANATStateSync]
3955         except IndexError:
3956             self.logger.error(ppp("Invalid packet:", p))
3957             raise
3958         else:
3959             self.assertEqual(hanat.sequence_number, 1)
3960             self.assertEqual(hanat.flags, 'ACK')
3961             self.assertEqual(hanat.version, 1)
3962             self.assertEqual(hanat.thread_index, 0)
3963         stats = self.statistics.get_counter('/nat44/ha/ack-send')
3964         self.assertEqual(stats[0][0], 1)
3965         stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
3966         self.assertEqual(stats[0][0], 2)
3967         users = self.statistics.get_counter('/nat44/total-users')
3968         self.assertEqual(users[0][0], 1)
3969         sessions = self.statistics.get_counter('/nat44/total-sessions')
3970         self.assertEqual(sessions[0][0], 2)
3971         users = self.vapi.nat44_user_dump()
3972         self.assertEqual(len(users), 1)
3973         self.assertEqual(str(users[0].ip_address),
3974                          self.pg0.remote_ip4)
3975         # there should be 2 sessions created by HA
3976         sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
3977                                                      users[0].vrf_id)
3978         self.assertEqual(len(sessions), 2)
3979         for session in sessions:
3980             self.assertEqual(str(session.inside_ip_address),
3981                              self.pg0.remote_ip4)
3982             self.assertEqual(str(session.outside_ip_address),
3983                              self.nat_addr)
3984             self.assertIn(session.inside_port,
3985                           [self.tcp_port_in, self.udp_port_in])
3986             self.assertIn(session.outside_port,
3987                           [self.tcp_port_out, self.udp_port_out])
3988             self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
3989
3990         # send HA session delete event to failover/passive
3991         p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3992              IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3993              UDP(sport=12346, dport=12345) /
3994              HANATStateSync(sequence_number=2, events=[
3995                  Event(event_type='del', protocol='udp',
3996                        in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3997                        in_port=self.udp_port_in, out_port=self.udp_port_out,
3998                        eh_addr=self.pg1.remote_ip4,
3999                        ehn_addr=self.pg1.remote_ip4,
4000                        eh_port=self.udp_external_port,
4001                        ehn_port=self.udp_external_port, fib_index=0)]))
4002
4003         self.pg3.add_stream(p)
4004         self.pg_enable_capture(self.pg_interfaces)
4005         self.pg_start()
4006         # receive ACK
4007         capture = self.pg3.get_capture(1)
4008         p = capture[0]
4009         try:
4010             hanat = p[HANATStateSync]
4011         except IndexError:
4012             self.logger.error(ppp("Invalid packet:", p))
4013             raise
4014         else:
4015             self.assertEqual(hanat.sequence_number, 2)
4016             self.assertEqual(hanat.flags, 'ACK')
4017             self.assertEqual(hanat.version, 1)
4018         users = self.vapi.nat44_user_dump()
4019         self.assertEqual(len(users), 1)
4020         self.assertEqual(str(users[0].ip_address),
4021                          self.pg0.remote_ip4)
4022         # now we should have only 1 session, 1 deleted by HA
4023         sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4024                                                      users[0].vrf_id)
4025         self.assertEqual(len(sessions), 1)
4026         stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
4027         self.assertEqual(stats[0][0], 1)
4028
4029         stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
4030         self.assertEqual(stats, 2)
4031
4032         # send HA session refresh event to failover/passive
4033         p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4034              IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4035              UDP(sport=12346, dport=12345) /
4036              HANATStateSync(sequence_number=3, events=[
4037                  Event(event_type='refresh', protocol='tcp',
4038                        in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4039                        in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4040                        eh_addr=self.pg1.remote_ip4,
4041                        ehn_addr=self.pg1.remote_ip4,
4042                        eh_port=self.tcp_external_port,
4043                        ehn_port=self.tcp_external_port, fib_index=0,
4044                        total_bytes=1024, total_pkts=2)]))
4045         self.pg3.add_stream(p)
4046         self.pg_enable_capture(self.pg_interfaces)
4047         self.pg_start()
4048         # receive ACK
4049         capture = self.pg3.get_capture(1)
4050         p = capture[0]
4051         try:
4052             hanat = p[HANATStateSync]
4053         except IndexError:
4054             self.logger.error(ppp("Invalid packet:", p))
4055             raise
4056         else:
4057             self.assertEqual(hanat.sequence_number, 3)
4058             self.assertEqual(hanat.flags, 'ACK')
4059             self.assertEqual(hanat.version, 1)
4060         users = self.vapi.nat44_user_dump()
4061         self.assertEqual(len(users), 1)
4062         self.assertEqual(str(users[0].ip_address),
4063                          self.pg0.remote_ip4)
4064         sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4065                                                      users[0].vrf_id)
4066         self.assertEqual(len(sessions), 1)
4067         session = sessions[0]
4068         self.assertEqual(session.total_bytes, 1024)
4069         self.assertEqual(session.total_pkts, 2)
4070         stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
4071         self.assertEqual(stats[0][0], 1)
4072
4073         stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
4074         self.assertEqual(stats, 3)
4075
4076         # send packet to test session created by HA
4077         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4078              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4079              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
4080         self.pg1.add_stream(p)
4081         self.pg_enable_capture(self.pg_interfaces)
4082         self.pg_start()
4083         capture = self.pg0.get_capture(1)
4084         p = capture[0]
4085         try:
4086             ip = p[IP]
4087             tcp = p[TCP]
4088         except IndexError:
4089             self.logger.error(ppp("Invalid packet:", p))
4090             raise
4091         else:
4092             self.assertEqual(ip.src, self.pg1.remote_ip4)
4093             self.assertEqual(ip.dst, self.pg0.remote_ip4)
4094             self.assertEqual(tcp.sport, self.tcp_external_port)
4095             self.assertEqual(tcp.dport, self.tcp_port_in)
4096
4097     def tearDown(self):
4098         super(TestNAT44, self).tearDown()
4099         self.clear_nat44()
4100         self.vapi.cli("clear logging")
4101
4102     def show_commands_at_teardown(self):
4103         self.logger.info(self.vapi.cli("show nat44 addresses"))
4104         self.logger.info(self.vapi.cli("show nat44 interfaces"))
4105         self.logger.info(self.vapi.cli("show nat44 static mappings"))
4106         self.logger.info(self.vapi.cli("show nat44 interface address"))
4107         self.logger.info(self.vapi.cli("show nat44 sessions detail"))
4108         self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
4109         self.logger.info(self.vapi.cli("show nat timeouts"))
4110         self.logger.info(
4111             self.vapi.cli("show nat addr-port-assignment-alg"))
4112         self.logger.info(self.vapi.cli("show nat ha"))
4113
4114
4115 class TestNAT44EndpointDependent2(MethodHolder):
4116     """ Endpoint-Dependent mapping and filtering test cases """
4117
4118     @classmethod
4119     def setUpConstants(cls):
4120         super(TestNAT44EndpointDependent2, cls).setUpConstants()
4121         cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4122
4123     @classmethod
4124     def tearDownClass(cls):
4125         super(TestNAT44EndpointDependent2, cls).tearDownClass()
4126
4127     def tearDown(self):
4128         super(TestNAT44EndpointDependent2, self).tearDown()
4129
4130     @classmethod
4131     def create_and_add_ip4_table(cls, i, table_id):
4132         cls.vapi.ip_table_add_del(is_add=1, table={'table_id': table_id})
4133         i.set_table_ip4(table_id)
4134
4135     @classmethod
4136     def setUpClass(cls):
4137         super(TestNAT44EndpointDependent2, cls).setUpClass()
4138
4139         cls.create_pg_interfaces(range(3))
4140         cls.interfaces = list(cls.pg_interfaces)
4141
4142         cls.create_and_add_ip4_table(cls.pg1, 10)
4143
4144         for i in cls.interfaces:
4145             i.admin_up()
4146             i.config_ip4()
4147             i.resolve_arp()
4148
4149             i.generate_remote_hosts(1)
4150             i.configure_ipv4_neighbors()
4151
4152     def setUp(self):
4153         super(TestNAT44EndpointDependent2, self).setUp()
4154
4155         nat_config = self.vapi.nat_show_config()
4156         self.assertEqual(1, nat_config.endpoint_dependent)
4157
4158     def nat_add_inside_interface(self, i):
4159         self.vapi.nat44_interface_add_del_feature(
4160             flags=self.config_flags.NAT_IS_INSIDE,
4161             sw_if_index=i.sw_if_index, is_add=1)
4162
4163     def nat_add_outside_interface(self, i):
4164         self.vapi.nat44_interface_add_del_feature(
4165             flags=self.config_flags.NAT_IS_OUTSIDE,
4166             sw_if_index=i.sw_if_index, is_add=1)
4167
4168     def nat_add_interface_address(self, i):
4169         self.nat_addr = i.local_ip4
4170         self.vapi.nat44_add_del_interface_addr(
4171             sw_if_index=i.sw_if_index, is_add=1)
4172
4173     def nat_add_address(self, address, vrf_id=0xFFFFFFFF):
4174         self.nat_addr = address
4175         self.nat44_add_address(address, vrf_id=vrf_id)
4176
4177     def cli(self, command):
4178         result = self.vapi.cli(command)
4179         self.logger.info(result)
4180         # print(result)
4181
4182     def show_configuration(self):
4183         self.cli("show interface")
4184         self.cli("show interface address")
4185         self.cli("show nat44 addresses")
4186         self.cli("show nat44 interfaces")
4187
4188     def create_tcp_stream(self, in_if, out_if, count):
4189         """
4190         Create tcp packet stream
4191
4192         :param in_if: Inside interface
4193         :param out_if: Outside interface
4194         :param count: count of packets to generate
4195         """
4196         pkts = []
4197         port = 6303
4198
4199         for i in range(count):
4200             p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4201                  IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=64) /
4202                  TCP(sport=port + i, dport=20))
4203             pkts.append(p)
4204
4205         return pkts
4206
4207     def test_session_limit_per_vrf(self):
4208
4209         inside = self.pg0
4210         inside_vrf10 = self.pg1
4211         outside = self.pg2
4212
4213         limit = 5
4214
4215         # 2 interfaces pg0, pg1 (vrf10, limit 1 tcp session)
4216         # non existing vrf_id makes process core dump
4217         self.vapi.nat44_set_session_limit(session_limit=limit, vrf_id=10)
4218
4219         self.nat_add_inside_interface(inside)
4220         self.nat_add_inside_interface(inside_vrf10)
4221         self.nat_add_outside_interface(outside)
4222
4223         # vrf independent
4224         self.nat_add_interface_address(outside)
4225
4226         # BUG: causing core dump - when bad vrf_id is specified
4227         # self.nat44_add_address(outside.local_ip4, vrf_id=20)
4228
4229         self.show_configuration()
4230
4231         stream = self.create_tcp_stream(inside_vrf10, outside, limit * 2)
4232         inside_vrf10.add_stream(stream)
4233
4234         self.pg_enable_capture(self.pg_interfaces)
4235         self.pg_start()
4236
4237         capture = outside.get_capture(limit)
4238
4239         stream = self.create_tcp_stream(inside, outside, limit * 2)
4240         inside.add_stream(stream)
4241
4242         self.pg_enable_capture(self.pg_interfaces)
4243         self.pg_start()
4244
4245         capture = outside.get_capture(len(stream))
4246
4247
4248 class TestNAT44EndpointDependent(MethodHolder):
4249     """ Endpoint-Dependent mapping and filtering test cases """
4250
4251     @classmethod
4252     def setUpConstants(cls):
4253         super(TestNAT44EndpointDependent, cls).setUpConstants()
4254         cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4255
4256     @classmethod
4257     def setUpClass(cls):
4258         super(TestNAT44EndpointDependent, cls).setUpClass()
4259         cls.vapi.cli("set log class nat level debug")
4260
4261         cls.tcp_port_in = 6303
4262         cls.tcp_port_out = 6303
4263         cls.udp_port_in = 6304
4264         cls.udp_port_out = 6304
4265         cls.icmp_id_in = 6305
4266         cls.icmp_id_out = 6305
4267         cls.nat_addr = '10.0.0.3'
4268         cls.ipfix_src_port = 4739
4269         cls.ipfix_domain_id = 1
4270         cls.tcp_external_port = 80
4271
4272         cls.create_pg_interfaces(range(9))
4273         cls.interfaces = list(cls.pg_interfaces[0:3])
4274
4275         for i in cls.interfaces:
4276             i.admin_up()
4277             i.config_ip4()
4278             i.resolve_arp()
4279
4280         cls.pg0.generate_remote_hosts(3)
4281         cls.pg0.configure_ipv4_neighbors()
4282
4283         cls.pg3.admin_up()
4284
4285         cls.pg4.generate_remote_hosts(2)
4286         cls.pg4.config_ip4()
4287         cls.vapi.sw_interface_add_del_address(
4288             sw_if_index=cls.pg4.sw_if_index,
4289             prefix="10.0.0.1/24")
4290
4291         cls.pg4.admin_up()
4292         cls.pg4.resolve_arp()
4293         cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4294         cls.pg4.resolve_arp()
4295
4296         zero_ip4 = socket.inet_pton(socket.AF_INET, "0.0.0.0")
4297         cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 1})
4298
4299         cls.pg5._local_ip4 = "10.1.1.1"
4300         cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4301         cls.pg5.set_table_ip4(1)
4302         cls.pg5.config_ip4()
4303         cls.pg5.admin_up()
4304         r1 = VppIpRoute(cls, cls.pg5.remote_ip4, 32,
4305                         [VppRoutePath("0.0.0.0",
4306                                       cls.pg5.sw_if_index)],
4307                         table_id=1,
4308                         register=False)
4309         r1.add_vpp_config()
4310
4311         cls.pg6._local_ip4 = "10.1.2.1"
4312         cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4313         cls.pg6.set_table_ip4(1)
4314         cls.pg6.config_ip4()
4315         cls.pg6.admin_up()
4316
4317         r2 = VppIpRoute(cls, cls.pg6.remote_ip4, 32,
4318                         [VppRoutePath("0.0.0.0",
4319                                       cls.pg6.sw_if_index)],
4320                         table_id=1,
4321                         register=False)
4322         r3 = VppIpRoute(cls, cls.pg6.remote_ip4, 16,
4323                         [VppRoutePath("0.0.0.0",
4324                                       0xffffffff,
4325                                       nh_table_id=1)],
4326                         table_id=0,
4327                         register=False)
4328         r4 = VppIpRoute(cls, "0.0.0.0", 0,
4329                         [VppRoutePath("0.0.0.0", 0xffffffff,
4330                                       nh_table_id=0)],
4331                         table_id=1,
4332                         register=False)
4333         r5 = VppIpRoute(cls, "0.0.0.0", 0,
4334                         [VppRoutePath(cls.pg1.local_ip4,
4335                                       cls.pg1.sw_if_index)],
4336                         register=False)
4337         r2.add_vpp_config()
4338         r3.add_vpp_config()
4339         r4.add_vpp_config()
4340         r5.add_vpp_config()
4341
4342         cls.pg5.resolve_arp()
4343         cls.pg6.resolve_arp()
4344
4345         cls.pg7.admin_up()
4346         cls.pg7.config_ip4()
4347         cls.pg7.resolve_arp()
4348         cls.pg7.generate_remote_hosts(3)
4349         cls.pg7.configure_ipv4_neighbors()
4350
4351         cls.pg8.admin_up()
4352         cls.pg8.config_ip4()
4353         cls.pg8.resolve_arp()
4354
4355     def setUp(self):
4356         super(TestNAT44EndpointDependent, self).setUp()
4357         self.vapi.nat_set_timeouts(
4358             udp=300, tcp_established=7440, tcp_transitory=240, icmp=60)
4359
4360     @classmethod
4361     def tearDownClass(cls):
4362         super(TestNAT44EndpointDependent, cls).tearDownClass()
4363
4364     def test_frag_in_order(self):
4365         """ NAT44 translate fragments arriving in order """
4366         self.nat44_add_address(self.nat_addr)
4367         flags = self.config_flags.NAT_IS_INSIDE
4368         self.vapi.nat44_interface_add_del_feature(
4369             sw_if_index=self.pg0.sw_if_index,
4370             flags=flags, is_add=1)
4371         self.vapi.nat44_interface_add_del_feature(
4372             sw_if_index=self.pg1.sw_if_index,
4373             is_add=1)
4374         self.frag_in_order(proto=IP_PROTOS.tcp, ignore_port=True)
4375         self.frag_in_order(proto=IP_PROTOS.udp, ignore_port=True)
4376         self.frag_in_order(proto=IP_PROTOS.icmp, ignore_port=True)
4377
4378     def test_frag_in_order_dont_translate(self):
4379         """ NAT44 don't translate fragments arriving in order """
4380         flags = self.config_flags.NAT_IS_INSIDE
4381         self.vapi.nat44_interface_add_del_feature(
4382             sw_if_index=self.pg0.sw_if_index,
4383             flags=flags, is_add=1)
4384         self.vapi.nat44_interface_add_del_feature(
4385             sw_if_index=self.pg1.sw_if_index,
4386             is_add=1)
4387         self.vapi.nat44_forwarding_enable_disable(enable=True)
4388         self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4389
4390     def test_frag_out_of_order(self):
4391         """ NAT44 translate fragments arriving out of order """
4392         self.nat44_add_address(self.nat_addr)
4393         flags = self.config_flags.NAT_IS_INSIDE
4394         self.vapi.nat44_interface_add_del_feature(
4395             sw_if_index=self.pg0.sw_if_index,
4396             flags=flags, is_add=1)
4397         self.vapi.nat44_interface_add_del_feature(
4398             sw_if_index=self.pg1.sw_if_index,
4399             is_add=1)
4400         self.frag_out_of_order(proto=IP_PROTOS.tcp, ignore_port=True)
4401         self.frag_out_of_order(proto=IP_PROTOS.udp, ignore_port=True)
4402         self.frag_out_of_order(proto=IP_PROTOS.icmp, ignore_port=True)
4403
4404     def test_frag_out_of_order_dont_translate(self):
4405         """ NAT44 don't translate fragments arriving out of order """
4406         flags = self.config_flags.NAT_IS_INSIDE
4407         self.vapi.nat44_interface_add_del_feature(
4408             sw_if_index=self.pg0.sw_if_index,
4409             flags=flags, is_add=1)
4410         self.vapi.nat44_interface_add_del_feature(
4411             sw_if_index=self.pg1.sw_if_index,
4412             is_add=1)
4413         self.vapi.nat44_forwarding_enable_disable(enable=True)
4414         self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4415
4416     def test_frag_in_order_in_plus_out(self):
4417         """ in+out interface fragments in order """
4418         flags = self.config_flags.NAT_IS_INSIDE
4419         self.vapi.nat44_interface_add_del_feature(
4420             sw_if_index=self.pg0.sw_if_index,
4421             is_add=1)
4422         self.vapi.nat44_interface_add_del_feature(
4423             sw_if_index=self.pg0.sw_if_index,
4424             flags=flags, is_add=1)
4425         self.vapi.nat44_interface_add_del_feature(
4426             sw_if_index=self.pg1.sw_if_index,
4427             is_add=1)
4428         self.vapi.nat44_interface_add_del_feature(
4429             sw_if_index=self.pg1.sw_if_index,
4430             flags=flags, is_add=1)
4431
4432         self.server = self.pg1.remote_hosts[0]
4433
4434         self.server_in_addr = self.server.ip4
4435         self.server_out_addr = '11.11.11.11'
4436         self.server_in_port = random.randint(1025, 65535)
4437         self.server_out_port = random.randint(1025, 65535)
4438
4439         self.nat44_add_address(self.server_out_addr)
4440
4441         # add static mappings for server
4442         self.nat44_add_static_mapping(self.server_in_addr,
4443                                       self.server_out_addr,
4444                                       self.server_in_port,
4445                                       self.server_out_port,
4446                                       proto=IP_PROTOS.tcp)
4447         self.nat44_add_static_mapping(self.server_in_addr,
4448                                       self.server_out_addr,
4449                                       self.server_in_port,
4450                                       self.server_out_port,
4451                                       proto=IP_PROTOS.udp)
4452         self.nat44_add_static_mapping(self.server_in_addr,
4453                                       self.server_out_addr,
4454                                       proto=IP_PROTOS.icmp)
4455
4456         self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4457         self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4458         self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4459
4460     def test_frag_out_of_order_in_plus_out(self):
4461         """ in+out interface fragments out of order """
4462         flags = self.config_flags.NAT_IS_INSIDE
4463         self.vapi.nat44_interface_add_del_feature(
4464             sw_if_index=self.pg0.sw_if_index,
4465             is_add=1)
4466         self.vapi.nat44_interface_add_del_feature(
4467             sw_if_index=self.pg0.sw_if_index,
4468             flags=flags, is_add=1)
4469         self.vapi.nat44_interface_add_del_feature(
4470             sw_if_index=self.pg1.sw_if_index,
4471             is_add=1)
4472         self.vapi.nat44_interface_add_del_feature(
4473             sw_if_index=self.pg1.sw_if_index,
4474             flags=flags, is_add=1)
4475
4476         self.server = self.pg1.remote_hosts[0]
4477
4478         self.server_in_addr = self.server.ip4
4479         self.server_out_addr = '11.11.11.11'
4480         self.server_in_port = random.randint(1025, 65535)
4481         self.server_out_port = random.randint(1025, 65535)
4482
4483         self.nat44_add_address(self.server_out_addr)
4484
4485         # add static mappings for server
4486         self.nat44_add_static_mapping(self.server_in_addr,
4487                                       self.server_out_addr,
4488                                       self.server_in_port,
4489                                       self.server_out_port,
4490                                       proto=IP_PROTOS.tcp)
4491         self.nat44_add_static_mapping(self.server_in_addr,
4492                                       self.server_out_addr,
4493                                       self.server_in_port,
4494                                       self.server_out_port,
4495                                       proto=IP_PROTOS.udp)
4496         self.nat44_add_static_mapping(self.server_in_addr,
4497                                       self.server_out_addr,
4498                                       proto=IP_PROTOS.icmp)
4499
4500         self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4501         self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4502         self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4503
4504     def test_reass_hairpinning(self):
4505         """ NAT44 fragments hairpinning """
4506         self.server = self.pg0.remote_hosts[1]
4507         self.host_in_port = random.randint(1025, 65535)
4508         self.server_in_port = random.randint(1025, 65535)
4509         self.server_out_port = random.randint(1025, 65535)
4510
4511         self.nat44_add_address(self.nat_addr)
4512         flags = self.config_flags.NAT_IS_INSIDE
4513         self.vapi.nat44_interface_add_del_feature(
4514             sw_if_index=self.pg0.sw_if_index,
4515             flags=flags, is_add=1)
4516         self.vapi.nat44_interface_add_del_feature(
4517             sw_if_index=self.pg1.sw_if_index,
4518             is_add=1)
4519         # add static mapping for server
4520         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4521                                       self.server_in_port,
4522                                       self.server_out_port,
4523                                       proto=IP_PROTOS.tcp)
4524         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4525                                       self.server_in_port,
4526                                       self.server_out_port,
4527                                       proto=IP_PROTOS.udp)
4528         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
4529
4530         self.reass_hairpinning(proto=IP_PROTOS.tcp, ignore_port=True)
4531         self.reass_hairpinning(proto=IP_PROTOS.udp, ignore_port=True)
4532         self.reass_hairpinning(proto=IP_PROTOS.icmp, ignore_port=True)
4533
4534     def test_clear_sessions(self):
4535         """ NAT44 ED session clearing test """
4536
4537         self.nat44_add_address(self.nat_addr)
4538         flags = self.config_flags.NAT_IS_INSIDE
4539         self.vapi.nat44_interface_add_del_feature(
4540             sw_if_index=self.pg0.sw_if_index,
4541             flags=flags, is_add=1)
4542         self.vapi.nat44_interface_add_del_feature(
4543             sw_if_index=self.pg1.sw_if_index,
4544             is_add=1)
4545
4546         nat_config = self.vapi.nat_show_config()
4547         self.assertEqual(1, nat_config.endpoint_dependent)
4548
4549         pkts = self.create_stream_in(self.pg0, self.pg1)
4550         self.pg0.add_stream(pkts)
4551         self.pg_enable_capture(self.pg_interfaces)
4552         self.pg_start()
4553         capture = self.pg1.get_capture(len(pkts))
4554         self.verify_capture_out(capture, ignore_port=True)
4555
4556         sessions = self.statistics.get_counter('/nat44/total-sessions')
4557         self.assertTrue(sessions[0][0] > 0)
4558         self.logger.info("sessions before clearing: %s" % sessions[0][0])
4559
4560         # just for testing purposes
4561         self.logger.info(self.vapi.cli("show nat44 summary"))
4562
4563         self.vapi.cli("clear nat44 sessions")
4564
4565         self.logger.info(self.vapi.cli("show nat44 summary"))
4566
4567         sessions = self.statistics.get_counter('/nat44/total-sessions')
4568         self.assertEqual(sessions[0][0], 0)
4569         self.logger.info("sessions after clearing: %s" % sessions[0][0])
4570
4571     def test_dynamic(self):
4572         """ NAT44 dynamic translation test """
4573
4574         self.nat44_add_address(self.nat_addr)
4575         flags = self.config_flags.NAT_IS_INSIDE
4576         self.vapi.nat44_interface_add_del_feature(
4577             sw_if_index=self.pg0.sw_if_index,
4578             flags=flags, is_add=1)
4579         self.vapi.nat44_interface_add_del_feature(
4580             sw_if_index=self.pg1.sw_if_index,
4581             is_add=1)
4582
4583         nat_config = self.vapi.nat_show_config()
4584         self.assertEqual(1, nat_config.endpoint_dependent)
4585
4586         # in2out
4587         tcpn = self.statistics.get_counter('/nat44/ed/in2out/slowpath/tcp')[0]
4588         udpn = self.statistics.get_counter('/nat44/ed/in2out/slowpath/udp')[0]
4589         icmpn = self.statistics.get_counter(
4590             '/nat44/ed/in2out/slowpath/icmp')[0]
4591         drops = self.statistics.get_counter(
4592             '/nat44/ed/in2out/slowpath/drops')[0]
4593
4594         pkts = self.create_stream_in(self.pg0, self.pg1)
4595         self.pg0.add_stream(pkts)
4596         self.pg_enable_capture(self.pg_interfaces)
4597         self.pg_start()
4598         capture = self.pg1.get_capture(len(pkts))
4599         self.verify_capture_out(capture, ignore_port=True)
4600
4601         if_idx = self.pg0.sw_if_index
4602         cnt = self.statistics.get_counter('/nat44/ed/in2out/slowpath/tcp')[0]
4603         self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
4604         cnt = self.statistics.get_counter('/nat44/ed/in2out/slowpath/udp')[0]
4605         self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
4606         cnt = self.statistics.get_counter('/nat44/ed/in2out/slowpath/icmp')[0]
4607         self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
4608         cnt = self.statistics.get_counter('/nat44/ed/in2out/slowpath/drops')[0]
4609         self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
4610
4611         # out2in
4612         tcpn = self.statistics.get_counter('/nat44/ed/out2in/fastpath/tcp')[0]
4613         udpn = self.statistics.get_counter('/nat44/ed/out2in/fastpath/udp')[0]
4614         icmpn = self.statistics.get_counter(
4615             '/nat44/ed/out2in/slowpath/icmp')[0]
4616         drops = self.statistics.get_counter(
4617             '/nat44/ed/out2in/fastpath/drops')[0]
4618
4619         pkts = self.create_stream_out(self.pg1)
4620         self.pg1.add_stream(pkts)
4621         self.pg_enable_capture(self.pg_interfaces)
4622         self.pg_start()
4623         capture = self.pg0.get_capture(len(pkts))
4624         self.verify_capture_in(capture, self.pg0)
4625
4626         if_idx = self.pg1.sw_if_index
4627         cnt = self.statistics.get_counter('/nat44/ed/out2in/fastpath/tcp')[0]
4628         self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
4629         cnt = self.statistics.get_counter('/nat44/ed/out2in/fastpath/udp')[0]
4630         self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
4631         cnt = self.statistics.get_counter('/nat44/ed/out2in/slowpath/icmp')[0]
4632         self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
4633         cnt = self.statistics.get_counter('/nat44/ed/out2in/fastpath/drops')[0]
4634         self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
4635
4636         sessions = self.statistics.get_counter('/nat44/total-sessions')
4637         self.assertEqual(sessions[0][0], 3)
4638
4639     def test_dynamic_out_of_ports(self):
4640         """ NAT44 dynamic translation test: out of ports """
4641
4642         flags = self.config_flags.NAT_IS_INSIDE
4643         self.vapi.nat44_interface_add_del_feature(
4644             sw_if_index=self.pg0.sw_if_index,
4645             flags=flags, is_add=1)
4646         self.vapi.nat44_interface_add_del_feature(
4647             sw_if_index=self.pg1.sw_if_index,
4648             is_add=1)
4649
4650         nat_config = self.vapi.nat_show_config()
4651         self.assertEqual(1, nat_config.endpoint_dependent)
4652
4653         # in2out and no NAT addresses added
4654         err_old = self.statistics.get_err_counter(
4655             '/err/nat44-ed-in2out-slowpath/out of ports')
4656
4657         pkts = self.create_stream_in(self.pg0, self.pg1)
4658         self.pg0.add_stream(pkts)
4659         self.pg_enable_capture(self.pg_interfaces)
4660         self.pg_start()
4661         self.pg1.get_capture(0, timeout=1)
4662
4663         err_new = self.statistics.get_err_counter(
4664             '/err/nat44-ed-in2out-slowpath/out of ports')
4665
4666         self.assertEqual(err_new - err_old, len(pkts))
4667
4668         # in2out after NAT addresses added
4669         self.nat44_add_address(self.nat_addr)
4670
4671         err_old = self.statistics.get_err_counter(
4672             '/err/nat44-ed-in2out-slowpath/out of ports')
4673
4674         pkts = self.create_stream_in(self.pg0, self.pg1)
4675         self.pg0.add_stream(pkts)
4676         self.pg_enable_capture(self.pg_interfaces)
4677         self.pg_start()
4678         capture = self.pg1.get_capture(len(pkts))
4679         self.verify_capture_out(capture, ignore_port=True)
4680
4681         err_new = self.statistics.get_err_counter(
4682             '/err/nat44-ed-in2out-slowpath/out of ports')
4683
4684         self.assertEqual(err_new, err_old)
4685
4686     def test_dynamic_output_feature_vrf(self):
4687         """ NAT44 dynamic translation test: output-feature, VRF"""
4688
4689         # other then default (0)
4690         new_vrf_id = 22
4691
4692         self.nat44_add_address(self.nat_addr)
4693         flags = self.config_flags.NAT_IS_INSIDE
4694         self.vapi.nat44_interface_add_del_output_feature(
4695             sw_if_index=self.pg7.sw_if_index,
4696             flags=flags, is_add=1)
4697         self.vapi.nat44_interface_add_del_output_feature(
4698             sw_if_index=self.pg8.sw_if_index,
4699             is_add=1)
4700
4701         try:
4702             self.vapi.ip_table_add_del(is_add=1,
4703                                        table={'table_id': new_vrf_id})
4704
4705             self.pg7.unconfig_ip4()
4706             self.pg7.set_table_ip4(new_vrf_id)
4707             self.pg7.config_ip4()
4708             self.pg7.resolve_arp()
4709
4710             self.pg8.unconfig_ip4()
4711             self.pg8.set_table_ip4(new_vrf_id)
4712             self.pg8.config_ip4()
4713             self.pg8.resolve_arp()
4714
4715             nat_config = self.vapi.nat_show_config()
4716             self.assertEqual(1, nat_config.endpoint_dependent)
4717
4718             # in2out
4719             tcpn = self.statistics.get_counter(
4720                 '/nat44/ed/in2out/slowpath/tcp')[0]
4721             udpn = self.statistics.get_counter(
4722                 '/nat44/ed/in2out/slowpath/udp')[0]
4723             icmpn = self.statistics.get_counter(
4724                 '/nat44/ed/in2out/slowpath/icmp')[0]
4725             drops = self.statistics.get_counter(
4726                 '/nat44/ed/in2out/slowpath/drops')[0]
4727
4728             pkts = self.create_stream_in(self.pg7, self.pg8)
4729             self.pg7.add_stream(pkts)
4730             self.pg_enable_capture(self.pg_interfaces)
4731             self.pg_start()
4732             capture = self.pg8.get_capture(len(pkts))
4733             self.verify_capture_out(capture, ignore_port=True)
4734
4735             if_idx = self.pg7.sw_if_index
4736             cnt = self.statistics.get_counter(
4737                 '/nat44/ed/in2out/slowpath/tcp')[0]
4738             self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
4739             cnt = self.statistics.get_counter(
4740                 '/nat44/ed/in2out/slowpath/udp')[0]
4741             self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
4742             cnt = self.statistics.get_counter(
4743                 '/nat44/ed/in2out/slowpath/icmp')[0]
4744             self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
4745             cnt = self.statistics.get_counter(
4746                 '/nat44/ed/in2out/slowpath/drops')[0]
4747             self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
4748
4749             # out2in
4750             tcpn = self.statistics.get_counter(
4751                 '/nat44/ed/out2in/fastpath/tcp')[0]
4752             udpn = self.statistics.get_counter(
4753                 '/nat44/ed/out2in/fastpath/udp')[0]
4754             icmpn = self.statistics.get_counter(
4755                 '/nat44/ed/out2in/slowpath/icmp')[0]
4756             drops = self.statistics.get_counter(
4757                 '/nat44/ed/out2in/fastpath/drops')[0]
4758
4759             pkts = self.create_stream_out(self.pg8)
4760             self.pg8.add_stream(pkts)
4761             self.pg_enable_capture(self.pg_interfaces)
4762             self.pg_start()
4763             capture = self.pg7.get_capture(len(pkts))
4764             self.verify_capture_in(capture, self.pg7)
4765
4766             if_idx = self.pg8.sw_if_index
4767             cnt = self.statistics.get_counter(
4768                 '/nat44/ed/out2in/fastpath/tcp')[0]
4769             self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
4770             cnt = self.statistics.get_counter(
4771                 '/nat44/ed/out2in/fastpath/udp')[0]
4772             self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
4773             cnt = self.statistics.get_counter(
4774                 '/nat44/ed/out2in/slowpath/icmp')[0]
4775             self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
4776             cnt = self.statistics.get_counter(
4777                 '/nat44/ed/out2in/fastpath/drops')[0]
4778             self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
4779
4780             sessions = self.statistics.get_counter('/nat44/total-sessions')
4781             self.assertEqual(sessions[0][0], 3)
4782
4783         finally:
4784             self.pg7.unconfig_ip4()
4785             self.pg7.set_table_ip4(1)
4786             self.pg7.config_ip4()
4787             self.pg7.resolve_arp()
4788
4789             self.pg8.unconfig_ip4()
4790             self.pg8.set_table_ip4(1)
4791             self.pg8.config_ip4()
4792             self.pg8.resolve_arp()
4793
4794             self.vapi.ip_table_add_del(is_add=0,
4795                                        table={'table_id': new_vrf_id})
4796
4797     def test_forwarding(self):
4798         """ NAT44 forwarding test """
4799
4800         flags = self.config_flags.NAT_IS_INSIDE
4801         self.vapi.nat44_interface_add_del_feature(
4802             sw_if_index=self.pg0.sw_if_index,
4803             flags=flags, is_add=1)
4804         self.vapi.nat44_interface_add_del_feature(
4805             sw_if_index=self.pg1.sw_if_index,
4806             is_add=1)
4807         self.vapi.nat44_forwarding_enable_disable(enable=1)
4808
4809         real_ip = self.pg0.remote_ip4
4810         alias_ip = self.nat_addr
4811         flags = self.config_flags.NAT_IS_ADDR_ONLY
4812         self.vapi.nat44_add_del_static_mapping(is_add=1,
4813                                                local_ip_address=real_ip,
4814                                                external_ip_address=alias_ip,
4815                                                external_sw_if_index=0xFFFFFFFF,
4816                                                flags=flags)
4817
4818         try:
4819             # in2out - static mapping match
4820
4821             pkts = self.create_stream_out(self.pg1)
4822             self.pg1.add_stream(pkts)
4823             self.pg_enable_capture(self.pg_interfaces)
4824             self.pg_start()
4825             capture = self.pg0.get_capture(len(pkts))
4826             self.verify_capture_in(capture, self.pg0)
4827
4828             pkts = self.create_stream_in(self.pg0, self.pg1)
4829             self.pg0.add_stream(pkts)
4830             self.pg_enable_capture(self.pg_interfaces)
4831             self.pg_start()
4832             capture = self.pg1.get_capture(len(pkts))
4833             self.verify_capture_out(capture, same_port=True)
4834
4835             # in2out - no static mapping match
4836
4837             host0 = self.pg0.remote_hosts[0]
4838             self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4839             try:
4840                 pkts = self.create_stream_out(self.pg1,
4841                                               dst_ip=self.pg0.remote_ip4,
4842                                               use_inside_ports=True)
4843                 self.pg1.add_stream(pkts)
4844                 self.pg_enable_capture(self.pg_interfaces)
4845                 self.pg_start()
4846                 capture = self.pg0.get_capture(len(pkts))
4847                 self.verify_capture_in(capture, self.pg0)
4848
4849                 pkts = self.create_stream_in(self.pg0, self.pg1)
4850                 self.pg0.add_stream(pkts)
4851                 self.pg_enable_capture(self.pg_interfaces)
4852                 self.pg_start()
4853                 capture = self.pg1.get_capture(len(pkts))
4854                 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4855                                         same_port=True)
4856             finally:
4857                 self.pg0.remote_hosts[0] = host0
4858
4859             user = self.pg0.remote_hosts[1]
4860             sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4861             self.assertEqual(len(sessions), 3)
4862             self.assertTrue(sessions[0].flags &
4863                             self.config_flags.NAT_IS_EXT_HOST_VALID)
4864             self.vapi.nat44_del_session(
4865                 address=sessions[0].inside_ip_address,
4866                 port=sessions[0].inside_port,
4867                 protocol=sessions[0].protocol,
4868                 flags=(self.config_flags.NAT_IS_INSIDE |
4869                        self.config_flags.NAT_IS_EXT_HOST_VALID),
4870                 ext_host_address=sessions[0].ext_host_address,
4871                 ext_host_port=sessions[0].ext_host_port)
4872             sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4873             self.assertEqual(len(sessions), 2)
4874
4875         finally:
4876             self.vapi.nat44_forwarding_enable_disable(enable=0)
4877             flags = self.config_flags.NAT_IS_ADDR_ONLY
4878             self.vapi.nat44_add_del_static_mapping(
4879                 is_add=0,
4880                 local_ip_address=real_ip,
4881                 external_ip_address=alias_ip,
4882                 external_sw_if_index=0xFFFFFFFF,
4883                 flags=flags)
4884
4885     def test_static_lb(self):
4886         """ NAT44 local service load balancing """
4887         external_addr_n = self.nat_addr
4888         external_port = 80
4889         local_port = 8080
4890         server1 = self.pg0.remote_hosts[0]
4891         server2 = self.pg0.remote_hosts[1]
4892
4893         locals = [{'addr': server1.ip4,
4894                    'port': local_port,
4895                    'probability': 70,
4896                    'vrf_id': 0},
4897                   {'addr': server2.ip4,
4898                    'port': local_port,
4899                    'probability': 30,
4900                    'vrf_id': 0}]
4901
4902         self.nat44_add_address(self.nat_addr)
4903         self.vapi.nat44_add_del_lb_static_mapping(
4904             is_add=1,
4905             external_addr=external_addr_n,
4906             external_port=external_port,
4907             protocol=IP_PROTOS.tcp,
4908             local_num=len(locals),
4909             locals=locals)
4910         flags = self.config_flags.NAT_IS_INSIDE
4911         self.vapi.nat44_interface_add_del_feature(
4912             sw_if_index=self.pg0.sw_if_index,
4913             flags=flags, is_add=1)
4914         self.vapi.nat44_interface_add_del_feature(
4915             sw_if_index=self.pg1.sw_if_index,
4916             is_add=1)
4917
4918         # from client to service
4919         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4920              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4921              TCP(sport=12345, dport=external_port))
4922         self.pg1.add_stream(p)
4923         self.pg_enable_capture(self.pg_interfaces)
4924         self.pg_start()
4925         capture = self.pg0.get_capture(1)
4926         p = capture[0]
4927         server = None
4928         try:
4929             ip = p[IP]
4930             tcp = p[TCP]
4931             self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4932             if ip.dst == server1.ip4:
4933                 server = server1
4934             else:
4935                 server = server2
4936             self.assertEqual(tcp.dport, local_port)
4937             self.assert_packet_checksums_valid(p)
4938         except:
4939             self.logger.error(ppp("Unexpected or invalid packet:", p))
4940             raise
4941
4942         # from service back to client
4943         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4944              IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4945              TCP(sport=local_port, dport=12345))
4946         self.pg0.add_stream(p)
4947         self.pg_enable_capture(self.pg_interfaces)
4948         self.pg_start()
4949         capture = self.pg1.get_capture(1)
4950         p = capture[0]
4951         try:
4952             ip = p[IP]
4953             tcp = p[TCP]
4954             self.assertEqual(ip.src, self.nat_addr)
4955             self.assertEqual(tcp.sport, external_port)
4956             self.assert_packet_checksums_valid(p)
4957         except:
4958             self.logger.error(ppp("Unexpected or invalid packet:", p))
4959             raise
4960
4961         sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
4962         self.assertEqual(len(sessions), 1)
4963         self.assertTrue(sessions[0].flags &
4964                         self.config_flags.NAT_IS_EXT_HOST_VALID)
4965         self.vapi.nat44_del_session(
4966             address=sessions[0].inside_ip_address,
4967             port=sessions[0].inside_port,
4968             protocol=sessions[0].protocol,
4969             flags=(self.config_flags.NAT_IS_INSIDE |
4970                    self.config_flags.NAT_IS_EXT_HOST_VALID),
4971             ext_host_address=sessions[0].ext_host_address,
4972             ext_host_port=sessions[0].ext_host_port)
4973         sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
4974         self.assertEqual(len(sessions), 0)
4975
4976     @unittest.skipUnless(running_extended_tests, "part of extended tests")
4977     def test_static_lb_multi_clients(self):
4978         """ NAT44 local service load balancing - multiple clients"""
4979
4980         external_addr = 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         server3 = self.pg0.remote_hosts[2]
4986
4987         locals = [{'addr': server1.ip4,
4988                    'port': local_port,
4989                    'probability': 90,
4990                    'vrf_id': 0},
4991                   {'addr': server2.ip4,
4992                    'port': local_port,
4993                    'probability': 10,
4994                    'vrf_id': 0}]
4995
4996         self.nat44_add_address(self.nat_addr)
4997         self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
4998                                                   external_addr=external_addr,
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         server1_n = 0
5012         server2_n = 0
5013         clients = ip4_range(self.pg1.remote_ip4, 10, 50)
5014         pkts = []
5015         for client in clients:
5016             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5017                  IP(src=client, dst=self.nat_addr) /
5018                  TCP(sport=12345, dport=external_port))
5019             pkts.append(p)
5020         self.pg1.add_stream(pkts)
5021         self.pg_enable_capture(self.pg_interfaces)
5022         self.pg_start()
5023         capture = self.pg0.get_capture(len(pkts))
5024         for p in capture:
5025             if p[IP].dst == server1.ip4:
5026                 server1_n += 1
5027             else:
5028                 server2_n += 1
5029         self.assertGreater(server1_n, server2_n)
5030
5031         local = {
5032             'addr': server3.ip4,
5033             'port': local_port,
5034             'probability': 20,
5035             'vrf_id': 0
5036         }
5037
5038         # add new back-end
5039         self.vapi.nat44_lb_static_mapping_add_del_local(
5040             is_add=1,
5041             external_addr=external_addr,
5042             external_port=external_port,
5043             local=local,
5044             protocol=IP_PROTOS.tcp)
5045         server1_n = 0
5046         server2_n = 0
5047         server3_n = 0
5048         clients = ip4_range(self.pg1.remote_ip4, 60, 110)
5049         pkts = []
5050         for client in clients:
5051             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5052                  IP(src=client, dst=self.nat_addr) /
5053                  TCP(sport=12346, dport=external_port))
5054             pkts.append(p)
5055         self.assertGreater(len(pkts), 0)
5056         self.pg1.add_stream(pkts)
5057         self.pg_enable_capture(self.pg_interfaces)
5058         self.pg_start()
5059         capture = self.pg0.get_capture(len(pkts))
5060         for p in capture:
5061             if p[IP].dst == server1.ip4:
5062                 server1_n += 1
5063             elif p[IP].dst == server2.ip4:
5064                 server2_n += 1
5065             else:
5066                 server3_n += 1
5067         self.assertGreater(server1_n, 0)
5068         self.assertGreater(server2_n, 0)
5069         self.assertGreater(server3_n, 0)
5070
5071         local = {
5072             'addr': server2.ip4,
5073             'port': local_port,
5074             'probability': 10,
5075             'vrf_id': 0
5076         }
5077
5078         # remove one back-end
5079         self.vapi.nat44_lb_static_mapping_add_del_local(
5080             is_add=0,
5081             external_addr=external_addr,
5082             external_port=external_port,
5083             local=local,
5084             protocol=IP_PROTOS.tcp)
5085         server1_n = 0
5086         server2_n = 0
5087         server3_n = 0
5088         self.pg1.add_stream(pkts)
5089         self.pg_enable_capture(self.pg_interfaces)
5090         self.pg_start()
5091         capture = self.pg0.get_capture(len(pkts))
5092         for p in capture:
5093             if p[IP].dst == server1.ip4:
5094                 server1_n += 1
5095             elif p[IP].dst == server2.ip4:
5096                 server2_n += 1
5097             else:
5098                 server3_n += 1
5099         self.assertGreater(server1_n, 0)
5100         self.assertEqual(server2_n, 0)
5101         self.assertGreater(server3_n, 0)
5102
5103     def test_static_lb_2(self):
5104         """ NAT44 local service load balancing (asymmetrical rule) """
5105         external_addr = self.nat_addr
5106         external_port = 80
5107         local_port = 8080
5108         server1 = self.pg0.remote_hosts[0]
5109         server2 = self.pg0.remote_hosts[1]
5110
5111         locals = [{'addr': server1.ip4,
5112                    'port': local_port,
5113                    'probability': 70,
5114                    'vrf_id': 0},
5115                   {'addr': server2.ip4,
5116                    'port': local_port,
5117                    'probability': 30,
5118                    'vrf_id': 0}]
5119
5120         self.vapi.nat44_forwarding_enable_disable(enable=1)
5121         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5122         self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5123                                                   external_addr=external_addr,
5124                                                   external_port=external_port,
5125                                                   protocol=IP_PROTOS.tcp,
5126                                                   local_num=len(locals),
5127                                                   locals=locals)
5128         flags = self.config_flags.NAT_IS_INSIDE
5129         self.vapi.nat44_interface_add_del_feature(
5130             sw_if_index=self.pg0.sw_if_index,
5131             flags=flags, is_add=1)
5132         self.vapi.nat44_interface_add_del_feature(
5133             sw_if_index=self.pg1.sw_if_index,
5134             is_add=1)
5135
5136         # from client to service
5137         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5138              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5139              TCP(sport=12345, dport=external_port))
5140         self.pg1.add_stream(p)
5141         self.pg_enable_capture(self.pg_interfaces)
5142         self.pg_start()
5143         capture = self.pg0.get_capture(1)
5144         p = capture[0]
5145         server = None
5146         try:
5147             ip = p[IP]
5148             tcp = p[TCP]
5149             self.assertIn(ip.dst, [server1.ip4, server2.ip4])
5150             if ip.dst == server1.ip4:
5151                 server = server1
5152             else:
5153                 server = server2
5154             self.assertEqual(tcp.dport, local_port)
5155             self.assert_packet_checksums_valid(p)
5156         except:
5157             self.logger.error(ppp("Unexpected or invalid packet:", p))
5158             raise
5159
5160         # from service back to client
5161         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
5162              IP(src=server.ip4, dst=self.pg1.remote_ip4) /
5163              TCP(sport=local_port, dport=12345))
5164         self.pg0.add_stream(p)
5165         self.pg_enable_capture(self.pg_interfaces)
5166         self.pg_start()
5167         capture = self.pg1.get_capture(1)
5168         p = capture[0]
5169         try:
5170             ip = p[IP]
5171             tcp = p[TCP]
5172             self.assertEqual(ip.src, self.nat_addr)
5173             self.assertEqual(tcp.sport, external_port)
5174             self.assert_packet_checksums_valid(p)
5175         except:
5176             self.logger.error(ppp("Unexpected or invalid packet:", p))
5177             raise
5178
5179         # from client to server (no translation)
5180         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5181              IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
5182              TCP(sport=12346, dport=local_port))
5183         self.pg1.add_stream(p)
5184         self.pg_enable_capture(self.pg_interfaces)
5185         self.pg_start()
5186         capture = self.pg0.get_capture(1)
5187         p = capture[0]
5188         server = None
5189         try:
5190             ip = p[IP]
5191             tcp = p[TCP]
5192             self.assertEqual(ip.dst, server1.ip4)
5193             self.assertEqual(tcp.dport, local_port)
5194             self.assert_packet_checksums_valid(p)
5195         except:
5196             self.logger.error(ppp("Unexpected or invalid packet:", p))
5197             raise
5198
5199         # from service back to client (no translation)
5200         p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
5201              IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
5202              TCP(sport=local_port, dport=12346))
5203         self.pg0.add_stream(p)
5204         self.pg_enable_capture(self.pg_interfaces)
5205         self.pg_start()
5206         capture = self.pg1.get_capture(1)
5207         p = capture[0]
5208         try:
5209             ip = p[IP]
5210             tcp = p[TCP]
5211             self.assertEqual(ip.src, server1.ip4)
5212             self.assertEqual(tcp.sport, local_port)
5213             self.assert_packet_checksums_valid(p)
5214         except:
5215             self.logger.error(ppp("Unexpected or invalid packet:", p))
5216             raise
5217
5218     def test_lb_affinity(self):
5219         """ NAT44 local service load balancing affinity """
5220         external_addr = self.nat_addr
5221         external_port = 80
5222         local_port = 8080
5223         server1 = self.pg0.remote_hosts[0]
5224         server2 = self.pg0.remote_hosts[1]
5225
5226         locals = [{'addr': server1.ip4,
5227                    'port': local_port,
5228                    'probability': 50,
5229                    'vrf_id': 0},
5230                   {'addr': server2.ip4,
5231                    'port': local_port,
5232                    'probability': 50,
5233                    'vrf_id': 0}]
5234
5235         self.nat44_add_address(self.nat_addr)
5236         self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
5237                                                   external_addr=external_addr,
5238                                                   external_port=external_port,
5239                                                   protocol=IP_PROTOS.tcp,
5240                                                   affinity=10800,
5241                                                   local_num=len(locals),
5242                                                   locals=locals)
5243         flags = self.config_flags.NAT_IS_INSIDE
5244         self.vapi.nat44_interface_add_del_feature(
5245             sw_if_index=self.pg0.sw_if_index,
5246             flags=flags, is_add=1)
5247         self.vapi.nat44_interface_add_del_feature(
5248             sw_if_index=self.pg1.sw_if_index,
5249             is_add=1)
5250
5251         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5252              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5253              TCP(sport=1025, dport=external_port))
5254         self.pg1.add_stream(p)
5255         self.pg_enable_capture(self.pg_interfaces)
5256         self.pg_start()
5257         capture = self.pg0.get_capture(1)
5258         backend = capture[0][IP].dst
5259
5260         sessions = self.vapi.nat44_user_session_dump(backend, 0)
5261         self.assertEqual(len(sessions), 1)
5262         self.assertTrue(sessions[0].flags &
5263                         self.config_flags.NAT_IS_EXT_HOST_VALID)
5264         self.vapi.nat44_del_session(
5265             address=sessions[0].inside_ip_address,
5266             port=sessions[0].inside_port,
5267             protocol=sessions[0].protocol,
5268             flags=(self.config_flags.NAT_IS_INSIDE |
5269                    self.config_flags.NAT_IS_EXT_HOST_VALID),
5270             ext_host_address=sessions[0].ext_host_address,
5271             ext_host_port=sessions[0].ext_host_port)
5272
5273         pkts = []
5274         for port in range(1030, 1100):
5275             p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5276                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5277                  TCP(sport=port, dport=external_port))
5278             pkts.append(p)
5279         self.pg1.add_stream(pkts)
5280         self.pg_enable_capture(self.pg_interfaces)
5281         self.pg_start()
5282         capture = self.pg0.get_capture(len(pkts))
5283         for p in capture:
5284             self.assertEqual(p[IP].dst, backend)
5285
5286     def test_unknown_proto(self):
5287         """ NAT44 translate packet with unknown protocol """
5288         self.nat44_add_address(self.nat_addr)
5289         flags = self.config_flags.NAT_IS_INSIDE
5290         self.vapi.nat44_interface_add_del_feature(
5291             sw_if_index=self.pg0.sw_if_index,
5292             flags=flags, is_add=1)
5293         self.vapi.nat44_interface_add_del_feature(
5294             sw_if_index=self.pg1.sw_if_index,
5295             is_add=1)
5296
5297         # in2out
5298         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5299              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5300              TCP(sport=self.tcp_port_in, dport=20))
5301         self.pg0.add_stream(p)
5302         self.pg_enable_capture(self.pg_interfaces)
5303         self.pg_start()
5304         p = self.pg1.get_capture(1)
5305
5306         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5307              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5308              GRE() /
5309              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5310              TCP(sport=1234, dport=1234))
5311         self.pg0.add_stream(p)
5312         self.pg_enable_capture(self.pg_interfaces)
5313         self.pg_start()
5314         p = self.pg1.get_capture(1)
5315         packet = p[0]
5316         try:
5317             self.assertEqual(packet[IP].src, self.nat_addr)
5318             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5319             self.assertEqual(packet.haslayer(GRE), 1)
5320             self.assert_packet_checksums_valid(packet)
5321         except:
5322             self.logger.error(ppp("Unexpected or invalid packet:", packet))
5323             raise
5324
5325         # out2in
5326         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5327              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5328              GRE() /
5329              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5330              TCP(sport=1234, dport=1234))
5331         self.pg1.add_stream(p)
5332         self.pg_enable_capture(self.pg_interfaces)
5333         self.pg_start()
5334         p = self.pg0.get_capture(1)
5335         packet = p[0]
5336         try:
5337             self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
5338             self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
5339             self.assertEqual(packet.haslayer(GRE), 1)
5340             self.assert_packet_checksums_valid(packet)
5341         except:
5342             self.logger.error(ppp("Unexpected or invalid packet:", packet))
5343             raise
5344
5345     def test_hairpinning_unknown_proto(self):
5346         """ NAT44 translate packet with unknown protocol - hairpinning """
5347         host = self.pg0.remote_hosts[0]
5348         server = self.pg0.remote_hosts[1]
5349         host_in_port = 1234
5350         server_out_port = 8765
5351         server_nat_ip = "10.0.0.11"
5352
5353         self.nat44_add_address(self.nat_addr)
5354         flags = self.config_flags.NAT_IS_INSIDE
5355         self.vapi.nat44_interface_add_del_feature(
5356             sw_if_index=self.pg0.sw_if_index,
5357             flags=flags, is_add=1)
5358         self.vapi.nat44_interface_add_del_feature(
5359             sw_if_index=self.pg1.sw_if_index,
5360             is_add=1)
5361
5362         # add static mapping for server
5363         self.nat44_add_static_mapping(server.ip4, server_nat_ip)
5364
5365         # host to server
5366         p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
5367              IP(src=host.ip4, dst=server_nat_ip) /
5368              TCP(sport=host_in_port, dport=server_out_port))
5369         self.pg0.add_stream(p)
5370         self.pg_enable_capture(self.pg_interfaces)
5371         self.pg_start()
5372         self.pg0.get_capture(1)
5373
5374         p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5375              IP(src=host.ip4, dst=server_nat_ip) /
5376              GRE() /
5377              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5378              TCP(sport=1234, dport=1234))
5379         self.pg0.add_stream(p)
5380         self.pg_enable_capture(self.pg_interfaces)
5381         self.pg_start()
5382         p = self.pg0.get_capture(1)
5383         packet = p[0]
5384         try:
5385             self.assertEqual(packet[IP].src, self.nat_addr)
5386             self.assertEqual(packet[IP].dst, server.ip4)
5387             self.assertEqual(packet.haslayer(GRE), 1)
5388             self.assert_packet_checksums_valid(packet)
5389         except:
5390             self.logger.error(ppp("Unexpected or invalid packet:", packet))
5391             raise
5392
5393         # server to host
5394         p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5395              IP(src=server.ip4, dst=self.nat_addr) /
5396              GRE() /
5397              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5398              TCP(sport=1234, dport=1234))
5399         self.pg0.add_stream(p)
5400         self.pg_enable_capture(self.pg_interfaces)
5401         self.pg_start()
5402         p = self.pg0.get_capture(1)
5403         packet = p[0]
5404         try:
5405             self.assertEqual(packet[IP].src, server_nat_ip)
5406             self.assertEqual(packet[IP].dst, host.ip4)
5407             self.assertEqual(packet.haslayer(GRE), 1)
5408             self.assert_packet_checksums_valid(packet)
5409         except:
5410             self.logger.error(ppp("Unexpected or invalid packet:", packet))
5411             raise
5412
5413     def test_output_feature_and_service(self):
5414         """ NAT44 interface output feature and services """
5415         external_addr = '1.2.3.4'
5416         external_port = 80
5417         local_port = 8080
5418
5419         self.vapi.nat44_forwarding_enable_disable(enable=1)
5420         self.nat44_add_address(self.nat_addr)
5421         flags = self.config_flags.NAT_IS_ADDR_ONLY
5422         self.vapi.nat44_add_del_identity_mapping(
5423             ip_address=self.pg1.remote_ip4, sw_if_index=0xFFFFFFFF,
5424             flags=flags, is_add=1)
5425         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5426         self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5427                                       local_port, external_port,
5428                                       proto=IP_PROTOS.tcp, flags=flags)
5429         flags = self.config_flags.NAT_IS_INSIDE
5430         self.vapi.nat44_interface_add_del_feature(
5431             sw_if_index=self.pg0.sw_if_index,
5432             is_add=1)
5433         self.vapi.nat44_interface_add_del_feature(
5434             sw_if_index=self.pg0.sw_if_index,
5435             flags=flags, is_add=1)
5436         self.vapi.nat44_interface_add_del_output_feature(
5437             is_add=1,
5438             sw_if_index=self.pg1.sw_if_index)
5439
5440         # from client to service
5441         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5442              IP(src=self.pg1.remote_ip4, dst=external_addr) /
5443              TCP(sport=12345, dport=external_port))
5444         self.pg1.add_stream(p)
5445         self.pg_enable_capture(self.pg_interfaces)
5446         self.pg_start()
5447         capture = self.pg0.get_capture(1)
5448         p = capture[0]
5449         try:
5450             ip = p[IP]
5451             tcp = p[TCP]
5452             self.assertEqual(ip.dst, self.pg0.remote_ip4)
5453             self.assertEqual(tcp.dport, local_port)
5454             self.assert_packet_checksums_valid(p)
5455         except:
5456             self.logger.error(ppp("Unexpected or invalid packet:", p))
5457             raise
5458
5459         # from service back to client
5460         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5461              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5462              TCP(sport=local_port, dport=12345))
5463         self.pg0.add_stream(p)
5464         self.pg_enable_capture(self.pg_interfaces)
5465         self.pg_start()
5466         capture = self.pg1.get_capture(1)
5467         p = capture[0]
5468         try:
5469             ip = p[IP]
5470             tcp = p[TCP]
5471             self.assertEqual(ip.src, external_addr)
5472             self.assertEqual(tcp.sport, external_port)
5473             self.assert_packet_checksums_valid(p)
5474         except:
5475             self.logger.error(ppp("Unexpected or invalid packet:", p))
5476             raise
5477
5478         # from local network host to external network
5479         pkts = self.create_stream_in(self.pg0, self.pg1)
5480         self.pg0.add_stream(pkts)
5481         self.pg_enable_capture(self.pg_interfaces)
5482         self.pg_start()
5483         capture = self.pg1.get_capture(len(pkts))
5484         self.verify_capture_out(capture, ignore_port=True)
5485         pkts = self.create_stream_in(self.pg0, self.pg1)
5486         self.pg0.add_stream(pkts)
5487         self.pg_enable_capture(self.pg_interfaces)
5488         self.pg_start()
5489         capture = self.pg1.get_capture(len(pkts))
5490         self.verify_capture_out(capture, ignore_port=True)
5491
5492         # from external network back to local network host
5493         pkts = self.create_stream_out(self.pg1)
5494         self.pg1.add_stream(pkts)
5495         self.pg_enable_capture(self.pg_interfaces)
5496         self.pg_start()
5497         capture = self.pg0.get_capture(len(pkts))
5498         self.verify_capture_in(capture, self.pg0)
5499
5500     def test_output_feature_and_service2(self):
5501         """ NAT44 interface output feature and service host direct access """
5502         self.vapi.nat44_forwarding_enable_disable(enable=1)
5503         self.nat44_add_address(self.nat_addr)
5504         self.vapi.nat44_interface_add_del_output_feature(
5505             is_add=1,
5506             sw_if_index=self.pg1.sw_if_index)
5507
5508         # session initiated from service host - translate
5509         pkts = self.create_stream_in(self.pg0, self.pg1)
5510         self.pg0.add_stream(pkts)
5511         self.pg_enable_capture(self.pg_interfaces)
5512         self.pg_start()
5513         capture = self.pg1.get_capture(len(pkts))
5514         self.verify_capture_out(capture, ignore_port=True)
5515
5516         pkts = self.create_stream_out(self.pg1)
5517         self.pg1.add_stream(pkts)
5518         self.pg_enable_capture(self.pg_interfaces)
5519         self.pg_start()
5520         capture = self.pg0.get_capture(len(pkts))
5521         self.verify_capture_in(capture, self.pg0)
5522
5523         # session initiated from remote host - do not translate
5524         self.tcp_port_in = 60303
5525         self.udp_port_in = 60304
5526         self.icmp_id_in = 60305
5527         pkts = self.create_stream_out(self.pg1,
5528                                       self.pg0.remote_ip4,
5529                                       use_inside_ports=True)
5530         self.pg1.add_stream(pkts)
5531         self.pg_enable_capture(self.pg_interfaces)
5532         self.pg_start()
5533         capture = self.pg0.get_capture(len(pkts))
5534         self.verify_capture_in(capture, self.pg0)
5535
5536         pkts = self.create_stream_in(self.pg0, self.pg1)
5537         self.pg0.add_stream(pkts)
5538         self.pg_enable_capture(self.pg_interfaces)
5539         self.pg_start()
5540         capture = self.pg1.get_capture(len(pkts))
5541         self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5542                                 same_port=True)
5543
5544     def test_output_feature_and_service3(self):
5545         """ NAT44 interface output feature and DST NAT """
5546         external_addr = '1.2.3.4'
5547         external_port = 80
5548         local_port = 8080
5549
5550         self.vapi.nat44_forwarding_enable_disable(enable=1)
5551         self.nat44_add_address(self.nat_addr)
5552         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5553         self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5554                                       local_port, external_port,
5555                                       proto=IP_PROTOS.tcp, flags=flags)
5556         flags = self.config_flags.NAT_IS_INSIDE
5557         self.vapi.nat44_interface_add_del_feature(
5558             sw_if_index=self.pg0.sw_if_index,
5559             is_add=1)
5560         self.vapi.nat44_interface_add_del_feature(
5561             sw_if_index=self.pg0.sw_if_index,
5562             flags=flags, is_add=1)
5563         self.vapi.nat44_interface_add_del_output_feature(
5564             is_add=1,
5565             sw_if_index=self.pg1.sw_if_index)
5566
5567         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5568              IP(src=self.pg0.remote_ip4, dst=external_addr) /
5569              TCP(sport=12345, dport=external_port))
5570         self.pg0.add_stream(p)
5571         self.pg_enable_capture(self.pg_interfaces)
5572         self.pg_start()
5573         capture = self.pg1.get_capture(1)
5574         p = capture[0]
5575         try:
5576             ip = p[IP]
5577             tcp = p[TCP]
5578             self.assertEqual(ip.src, self.pg0.remote_ip4)
5579             self.assertEqual(tcp.sport, 12345)
5580             self.assertEqual(ip.dst, self.pg1.remote_ip4)
5581             self.assertEqual(tcp.dport, local_port)
5582             self.assert_packet_checksums_valid(p)
5583         except:
5584             self.logger.error(ppp("Unexpected or invalid packet:", p))
5585             raise
5586
5587         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5588              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5589              TCP(sport=local_port, dport=12345))
5590         self.pg1.add_stream(p)
5591         self.pg_enable_capture(self.pg_interfaces)
5592         self.pg_start()
5593         capture = self.pg0.get_capture(1)
5594         p = capture[0]
5595         try:
5596             ip = p[IP]
5597             tcp = p[TCP]
5598             self.assertEqual(ip.src, external_addr)
5599             self.assertEqual(tcp.sport, external_port)
5600             self.assertEqual(ip.dst, self.pg0.remote_ip4)
5601             self.assertEqual(tcp.dport, 12345)
5602             self.assert_packet_checksums_valid(p)
5603         except:
5604             self.logger.error(ppp("Unexpected or invalid packet:", p))
5605             raise
5606
5607     def test_next_src_nat(self):
5608         """ On way back forward packet to nat44-in2out node. """
5609         twice_nat_addr = '10.0.1.3'
5610         external_port = 80
5611         local_port = 8080
5612         post_twice_nat_port = 0
5613
5614         self.vapi.nat44_forwarding_enable_disable(enable=1)
5615         self.nat44_add_address(twice_nat_addr, twice_nat=1)
5616         flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5617                  self.config_flags.NAT_IS_SELF_TWICE_NAT)
5618         self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5619                                       local_port, external_port,
5620                                       proto=IP_PROTOS.tcp, vrf_id=1,
5621                                       flags=flags)
5622         self.vapi.nat44_interface_add_del_feature(
5623             sw_if_index=self.pg6.sw_if_index,
5624             is_add=1)
5625
5626         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5627              IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5628              TCP(sport=12345, dport=external_port))
5629         self.pg6.add_stream(p)
5630         self.pg_enable_capture(self.pg_interfaces)
5631         self.pg_start()
5632         capture = self.pg6.get_capture(1)
5633         p = capture[0]
5634         try:
5635             ip = p[IP]
5636             tcp = p[TCP]
5637             self.assertEqual(ip.src, twice_nat_addr)
5638             self.assertNotEqual(tcp.sport, 12345)
5639             post_twice_nat_port = tcp.sport
5640             self.assertEqual(ip.dst, self.pg6.remote_ip4)
5641             self.assertEqual(tcp.dport, local_port)
5642             self.assert_packet_checksums_valid(p)
5643         except:
5644             self.logger.error(ppp("Unexpected or invalid packet:", p))
5645             raise
5646
5647         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5648              IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5649              TCP(sport=local_port, dport=post_twice_nat_port))
5650         self.pg6.add_stream(p)
5651         self.pg_enable_capture(self.pg_interfaces)
5652         self.pg_start()
5653         capture = self.pg6.get_capture(1)
5654         p = capture[0]
5655         try:
5656             ip = p[IP]
5657             tcp = p[TCP]
5658             self.assertEqual(ip.src, self.pg1.remote_ip4)
5659             self.assertEqual(tcp.sport, external_port)
5660             self.assertEqual(ip.dst, self.pg6.remote_ip4)
5661             self.assertEqual(tcp.dport, 12345)
5662             self.assert_packet_checksums_valid(p)
5663         except:
5664             self.logger.error(ppp("Unexpected or invalid packet:", p))
5665             raise
5666
5667     def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5668                          client_id=None):
5669         twice_nat_addr = '10.0.1.3'
5670
5671         port_in = 8080
5672         if lb:
5673             if not same_pg:
5674                 port_in1 = port_in
5675                 port_in2 = port_in
5676             else:
5677                 port_in1 = port_in + 1
5678                 port_in2 = port_in + 2
5679
5680         port_out = 80
5681         eh_port_out = 4567
5682
5683         server1 = self.pg0.remote_hosts[0]
5684         server2 = self.pg0.remote_hosts[1]
5685         if lb and same_pg:
5686             server2 = server1
5687         if not lb:
5688             server = server1
5689
5690         pg0 = self.pg0
5691         if same_pg:
5692             pg1 = self.pg0
5693         else:
5694             pg1 = self.pg1
5695
5696         eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5697                         client_id == 1)
5698
5699         self.nat44_add_address(self.nat_addr)
5700         self.nat44_add_address(twice_nat_addr, twice_nat=1)
5701
5702         flags = 0
5703         if self_twice_nat:
5704             flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
5705         else:
5706             flags |= self.config_flags.NAT_IS_TWICE_NAT
5707
5708         if not lb:
5709             self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5710                                           port_in, port_out,
5711                                           proto=IP_PROTOS.tcp,
5712                                           flags=flags)
5713         else:
5714             locals = [{'addr': server1.ip4,
5715                        'port': port_in1,
5716                        'probability': 50,
5717                        'vrf_id': 0},
5718                       {'addr': server2.ip4,
5719                        'port': port_in2,
5720                        'probability': 50,
5721                        'vrf_id': 0}]
5722             out_addr = self.nat_addr
5723
5724             self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5725                                                       external_addr=out_addr,
5726                                                       external_port=port_out,
5727                                                       protocol=IP_PROTOS.tcp,
5728                                                       local_num=len(locals),
5729                                                       locals=locals)
5730         flags = self.config_flags.NAT_IS_INSIDE
5731         self.vapi.nat44_interface_add_del_feature(
5732             sw_if_index=pg0.sw_if_index,
5733             flags=flags, is_add=1)
5734         self.vapi.nat44_interface_add_del_feature(
5735             sw_if_index=pg1.sw_if_index,
5736             is_add=1)
5737
5738         if same_pg:
5739             if not lb:
5740                 client = server
5741             else:
5742                 assert client_id is not None
5743                 if client_id == 1:
5744                     client = self.pg0.remote_hosts[0]
5745                 elif client_id == 2:
5746                     client = self.pg0.remote_hosts[1]
5747         else:
5748             client = pg1.remote_hosts[0]
5749         p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5750              IP(src=client.ip4, dst=self.nat_addr) /
5751              TCP(sport=eh_port_out, dport=port_out))
5752         pg1.add_stream(p)
5753         self.pg_enable_capture(self.pg_interfaces)
5754         self.pg_start()
5755         capture = pg0.get_capture(1)
5756         p = capture[0]
5757         try:
5758             ip = p[IP]
5759             tcp = p[TCP]
5760             if lb:
5761                 if ip.dst == server1.ip4:
5762                     server = server1
5763                     port_in = port_in1
5764                 else:
5765                     server = server2
5766                     port_in = port_in2
5767             self.assertEqual(ip.dst, server.ip4)
5768             if lb and same_pg:
5769                 self.assertIn(tcp.dport, [port_in1, port_in2])
5770             else:
5771                 self.assertEqual(tcp.dport, port_in)
5772             if eh_translate:
5773                 self.assertEqual(ip.src, twice_nat_addr)
5774                 self.assertNotEqual(tcp.sport, eh_port_out)
5775             else:
5776                 self.assertEqual(ip.src, client.ip4)
5777                 self.assertEqual(tcp.sport, eh_port_out)
5778             eh_addr_in = ip.src
5779             eh_port_in = tcp.sport
5780             saved_port_in = tcp.dport
5781             self.assert_packet_checksums_valid(p)
5782         except:
5783             self.logger.error(ppp("Unexpected or invalid packet:", p))
5784             raise
5785
5786         p = (Ether(src=server.mac, dst=pg0.local_mac) /
5787              IP(src=server.ip4, dst=eh_addr_in) /
5788              TCP(sport=saved_port_in, dport=eh_port_in))
5789         pg0.add_stream(p)
5790         self.pg_enable_capture(self.pg_interfaces)
5791         self.pg_start()
5792         capture = pg1.get_capture(1)
5793         p = capture[0]
5794         try:
5795             ip = p[IP]
5796             tcp = p[TCP]
5797             self.assertEqual(ip.dst, client.ip4)
5798             self.assertEqual(ip.src, self.nat_addr)
5799             self.assertEqual(tcp.dport, eh_port_out)
5800             self.assertEqual(tcp.sport, port_out)
5801             self.assert_packet_checksums_valid(p)
5802         except:
5803             self.logger.error(ppp("Unexpected or invalid packet:", p))
5804             raise
5805
5806         if eh_translate:
5807             sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5808             self.assertEqual(len(sessions), 1)
5809             self.assertTrue(sessions[0].flags &
5810                             self.config_flags.NAT_IS_EXT_HOST_VALID)
5811             self.assertTrue(sessions[0].flags &
5812                             self.config_flags.NAT_IS_TWICE_NAT)
5813             self.logger.info(self.vapi.cli("show nat44 sessions detail"))
5814             self.vapi.nat44_del_session(
5815                 address=sessions[0].inside_ip_address,
5816                 port=sessions[0].inside_port,
5817                 protocol=sessions[0].protocol,
5818                 flags=(self.config_flags.NAT_IS_INSIDE |
5819                        self.config_flags.NAT_IS_EXT_HOST_VALID),
5820                 ext_host_address=sessions[0].ext_host_nat_address,
5821                 ext_host_port=sessions[0].ext_host_nat_port)
5822             sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5823             self.assertEqual(len(sessions), 0)
5824
5825     def test_twice_nat(self):
5826         """ Twice NAT44 """
5827         self.twice_nat_common()
5828
5829     def test_self_twice_nat_positive(self):
5830         """ Self Twice NAT44 (positive test) """
5831         self.twice_nat_common(self_twice_nat=True, same_pg=True)
5832
5833     def test_self_twice_nat_negative(self):
5834         """ Self Twice NAT44 (negative test) """
5835         self.twice_nat_common(self_twice_nat=True)
5836
5837     def test_twice_nat_lb(self):
5838         """ Twice NAT44 local service load balancing """
5839         self.twice_nat_common(lb=True)
5840
5841     def test_self_twice_nat_lb_positive(self):
5842         """ Self Twice NAT44 local service load balancing (positive test) """
5843         self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5844                               client_id=1)
5845
5846     def test_self_twice_nat_lb_negative(self):
5847         """ Self Twice NAT44 local service load balancing (negative test) """
5848         self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5849                               client_id=2)
5850
5851     def test_twice_nat_interface_addr(self):
5852         """ Acquire twice NAT44 addresses from interface """
5853         flags = self.config_flags.NAT_IS_TWICE_NAT
5854         self.vapi.nat44_add_del_interface_addr(
5855             is_add=1,
5856             sw_if_index=self.pg3.sw_if_index,
5857             flags=flags)
5858
5859         # no address in NAT pool
5860         adresses = self.vapi.nat44_address_dump()
5861         self.assertEqual(0, len(adresses))
5862
5863         # configure interface address and check NAT address pool
5864         self.pg3.config_ip4()
5865         adresses = self.vapi.nat44_address_dump()
5866         self.assertEqual(1, len(adresses))
5867         self.assertEqual(str(adresses[0].ip_address),
5868                          self.pg3.local_ip4)
5869         self.assertEqual(adresses[0].flags, flags)
5870
5871         # remove interface address and check NAT address pool
5872         self.pg3.unconfig_ip4()
5873         adresses = self.vapi.nat44_address_dump()
5874         self.assertEqual(0, len(adresses))
5875
5876     def test_tcp_close(self):
5877         """ Close TCP session from inside network - output feature """
5878         self.vapi.nat44_forwarding_enable_disable(enable=1)
5879         self.nat44_add_address(self.pg1.local_ip4)
5880         twice_nat_addr = '10.0.1.3'
5881         service_ip = '192.168.16.150'
5882         self.nat44_add_address(twice_nat_addr, twice_nat=1)
5883         flags = self.config_flags.NAT_IS_INSIDE
5884         self.vapi.nat44_interface_add_del_feature(
5885             sw_if_index=self.pg0.sw_if_index,
5886             is_add=1)
5887         self.vapi.nat44_interface_add_del_feature(
5888             sw_if_index=self.pg0.sw_if_index,
5889             flags=flags, is_add=1)
5890         self.vapi.nat44_interface_add_del_output_feature(
5891             is_add=1,
5892             sw_if_index=self.pg1.sw_if_index)
5893         flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5894                  self.config_flags.NAT_IS_TWICE_NAT)
5895         self.nat44_add_static_mapping(self.pg0.remote_ip4,
5896                                       service_ip,
5897                                       80,
5898                                       80,
5899                                       proto=IP_PROTOS.tcp,
5900                                       flags=flags)
5901         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5902         start_sessnum = len(sessions)
5903
5904         # SYN packet out->in
5905         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5906              IP(src=self.pg1.remote_ip4, dst=service_ip) /
5907              TCP(sport=33898, dport=80, flags="S"))
5908         self.pg1.add_stream(p)
5909         self.pg_enable_capture(self.pg_interfaces)
5910         self.pg_start()
5911         capture = self.pg0.get_capture(1)
5912         p = capture[0]
5913         tcp_port = p[TCP].sport
5914
5915         # SYN + ACK packet in->out
5916         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5917              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5918              TCP(sport=80, dport=tcp_port, flags="SA"))
5919         self.pg0.add_stream(p)
5920         self.pg_enable_capture(self.pg_interfaces)
5921         self.pg_start()
5922         self.pg1.get_capture(1)
5923
5924         # ACK packet out->in
5925         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5926              IP(src=self.pg1.remote_ip4, dst=service_ip) /
5927              TCP(sport=33898, dport=80, flags="A"))
5928         self.pg1.add_stream(p)
5929         self.pg_enable_capture(self.pg_interfaces)
5930         self.pg_start()
5931         self.pg0.get_capture(1)
5932
5933         # FIN packet in -> out
5934         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5935              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5936              TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5937         self.pg0.add_stream(p)
5938         self.pg_enable_capture(self.pg_interfaces)
5939         self.pg_start()
5940         self.pg1.get_capture(1)
5941
5942         # FIN+ACK packet out -> in
5943         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5944              IP(src=self.pg1.remote_ip4, dst=service_ip) /
5945              TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5946         self.pg1.add_stream(p)
5947         self.pg_enable_capture(self.pg_interfaces)
5948         self.pg_start()
5949         self.pg0.get_capture(1)
5950
5951         # ACK packet in -> out
5952         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5953              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5954              TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5955         self.pg0.add_stream(p)
5956         self.pg_enable_capture(self.pg_interfaces)
5957         self.pg_start()
5958         self.pg1.get_capture(1)
5959
5960         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4,
5961                                                      0)
5962         self.assertEqual(len(sessions) - start_sessnum, 0)
5963
5964     def test_tcp_session_close_in(self):
5965         """ Close TCP session from inside network """
5966         self.tcp_port_out = 10505
5967         self.nat44_add_address(self.nat_addr)
5968         flags = self.config_flags.NAT_IS_TWICE_NAT
5969         self.nat44_add_static_mapping(self.pg0.remote_ip4,
5970                                       self.nat_addr,
5971                                       self.tcp_port_in,
5972                                       self.tcp_port_out,
5973                                       proto=IP_PROTOS.tcp,
5974                                       flags=flags)
5975         flags = self.config_flags.NAT_IS_INSIDE
5976         self.vapi.nat44_interface_add_del_feature(
5977             sw_if_index=self.pg0.sw_if_index,
5978             flags=flags, is_add=1)
5979         self.vapi.nat44_interface_add_del_feature(
5980             sw_if_index=self.pg1.sw_if_index,
5981             is_add=1)
5982
5983         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5984         start_sessnum = len(sessions)
5985
5986         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
5987                                    tcp_transitory=2, icmp=5)
5988
5989         self.initiate_tcp_session(self.pg0, self.pg1)
5990
5991         # FIN packet in -> out
5992         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5993              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5994              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5995                  flags="FA", seq=100, ack=300))
5996         self.pg0.add_stream(p)
5997         self.pg_enable_capture(self.pg_interfaces)
5998         self.pg_start()
5999         self.pg1.get_capture(1)
6000
6001         pkts = []
6002
6003         # ACK packet out -> in
6004         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6005              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6006              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6007                  flags="A", seq=300, ack=101))
6008         pkts.append(p)
6009
6010         # FIN packet out -> in
6011         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6012              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6013              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6014                  flags="FA", seq=300, ack=101))
6015         pkts.append(p)
6016
6017         self.pg1.add_stream(pkts)
6018         self.pg_enable_capture(self.pg_interfaces)
6019         self.pg_start()
6020         self.pg0.get_capture(2)
6021
6022         # ACK packet in -> out
6023         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6024              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6025              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6026                  flags="A", seq=101, ack=301))
6027         self.pg0.add_stream(p)
6028         self.pg_enable_capture(self.pg_interfaces)
6029         self.pg_start()
6030         self.pg1.get_capture(1)
6031
6032         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6033         self.assertEqual(len(sessions) - start_sessnum, 1)
6034
6035         stats = self.statistics.get_counter(
6036             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6037         out2in_drops = stats[0]
6038         stats = self.statistics.get_counter(
6039             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6040         in2out_drops = stats[0]
6041
6042         # extra FIN packet out -> in - this should be dropped
6043         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6044              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6045              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6046                  flags="FA", seq=300, ack=101))
6047
6048         self.pg1.add_stream(p)
6049         self.pg_enable_capture(self.pg_interfaces)
6050         self.pg_start()
6051         self.pg0.assert_nothing_captured()
6052
6053         # extra ACK packet in -> out - this should be dropped
6054         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6055              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6056              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6057                  flags="A", seq=101, ack=301))
6058         self.pg0.add_stream(p)
6059         self.pg_enable_capture(self.pg_interfaces)
6060         self.pg_start()
6061         self.pg1.assert_nothing_captured()
6062
6063         stats = self.statistics.get_counter(
6064             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6065         self.assertEqual(stats[0] - out2in_drops, 1)
6066         stats = self.statistics.get_counter(
6067             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6068         self.assertEqual(stats[0] - in2out_drops, 1)
6069
6070         self.sleep(3)
6071         # extra ACK packet in -> out - this will cause session to be wiped
6072         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6073              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6074              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6075                  flags="A", seq=101, ack=301))
6076         self.pg0.add_stream(p)
6077         self.pg_enable_capture(self.pg_interfaces)
6078         self.pg_start()
6079         self.pg1.assert_nothing_captured()
6080         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6081         self.assertEqual(len(sessions) - start_sessnum, 0)
6082
6083     def test_tcp_session_close_out(self):
6084         """ Close TCP session from outside network """
6085         self.tcp_port_out = 10505
6086         self.nat44_add_address(self.nat_addr)
6087         flags = self.config_flags.NAT_IS_TWICE_NAT
6088         self.nat44_add_static_mapping(self.pg0.remote_ip4,
6089                                       self.nat_addr,
6090                                       self.tcp_port_in,
6091                                       self.tcp_port_out,
6092                                       proto=IP_PROTOS.tcp,
6093                                       flags=flags)
6094         flags = self.config_flags.NAT_IS_INSIDE
6095         self.vapi.nat44_interface_add_del_feature(
6096             sw_if_index=self.pg0.sw_if_index,
6097             flags=flags, is_add=1)
6098         self.vapi.nat44_interface_add_del_feature(
6099             sw_if_index=self.pg1.sw_if_index,
6100             is_add=1)
6101
6102         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6103         start_sessnum = len(sessions)
6104
6105         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6106                                    tcp_transitory=2, icmp=5)
6107
6108         self.initiate_tcp_session(self.pg0, self.pg1)
6109
6110         # FIN packet out -> in
6111         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6112              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6113              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6114                  flags="FA", seq=100, ack=300))
6115         self.pg1.add_stream(p)
6116         self.pg_enable_capture(self.pg_interfaces)
6117         self.pg_start()
6118         self.pg0.get_capture(1)
6119
6120         # FIN+ACK packet in -> out
6121         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6122              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6123              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6124                  flags="FA", seq=300, ack=101))
6125
6126         self.pg0.add_stream(p)
6127         self.pg_enable_capture(self.pg_interfaces)
6128         self.pg_start()
6129         self.pg1.get_capture(1)
6130
6131         # ACK packet out -> in
6132         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6133              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6134              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6135                  flags="A", seq=101, ack=301))
6136         self.pg1.add_stream(p)
6137         self.pg_enable_capture(self.pg_interfaces)
6138         self.pg_start()
6139         self.pg0.get_capture(1)
6140
6141         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6142         self.assertEqual(len(sessions) - start_sessnum, 1)
6143
6144         stats = self.statistics.get_counter(
6145             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6146         out2in_drops = stats[0]
6147         stats = self.statistics.get_counter(
6148             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6149         in2out_drops = stats[0]
6150
6151         # extra FIN packet out -> in - this should be dropped
6152         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6153              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6154              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6155                  flags="FA", seq=300, ack=101))
6156
6157         self.pg1.add_stream(p)
6158         self.pg_enable_capture(self.pg_interfaces)
6159         self.pg_start()
6160         self.pg0.assert_nothing_captured()
6161
6162         # extra ACK packet in -> out - this should be dropped
6163         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6164              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6165              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6166                  flags="A", seq=101, ack=301))
6167         self.pg0.add_stream(p)
6168         self.pg_enable_capture(self.pg_interfaces)
6169         self.pg_start()
6170         self.pg1.assert_nothing_captured()
6171
6172         stats = self.statistics.get_counter(
6173             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6174         self.assertEqual(stats[0] - out2in_drops, 1)
6175         stats = self.statistics.get_counter(
6176             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6177         self.assertEqual(stats[0] - in2out_drops, 1)
6178
6179         self.sleep(3)
6180         # extra ACK packet in -> out - this will cause session to be wiped
6181         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6182              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6183              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6184                  flags="A", seq=101, ack=301))
6185         self.pg0.add_stream(p)
6186         self.pg_enable_capture(self.pg_interfaces)
6187         self.pg_start()
6188         self.pg1.assert_nothing_captured()
6189         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6190         self.assertEqual(len(sessions) - start_sessnum, 0)
6191
6192     def test_tcp_session_close_simultaneous(self):
6193         """ Close TCP session from inside network """
6194         self.tcp_port_out = 10505
6195         self.nat44_add_address(self.nat_addr)
6196         flags = self.config_flags.NAT_IS_TWICE_NAT
6197         self.nat44_add_static_mapping(self.pg0.remote_ip4,
6198                                       self.nat_addr,
6199                                       self.tcp_port_in,
6200                                       self.tcp_port_out,
6201                                       proto=IP_PROTOS.tcp,
6202                                       flags=flags)
6203         flags = self.config_flags.NAT_IS_INSIDE
6204         self.vapi.nat44_interface_add_del_feature(
6205             sw_if_index=self.pg0.sw_if_index,
6206             flags=flags, is_add=1)
6207         self.vapi.nat44_interface_add_del_feature(
6208             sw_if_index=self.pg1.sw_if_index,
6209             is_add=1)
6210
6211         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6212         start_sessnum = len(sessions)
6213
6214         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6215                                    tcp_transitory=2, icmp=5)
6216
6217         self.initiate_tcp_session(self.pg0, self.pg1)
6218
6219         # FIN packet in -> out
6220         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6221              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6222              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6223                  flags="FA", seq=100, ack=300))
6224         self.pg0.add_stream(p)
6225         self.pg_enable_capture(self.pg_interfaces)
6226         self.pg_start()
6227         self.pg1.get_capture(1)
6228
6229         # FIN packet out -> in
6230         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6231              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6232              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6233                  flags="FA", seq=300, ack=100))
6234         self.pg1.add_stream(p)
6235         self.pg_enable_capture(self.pg_interfaces)
6236         self.pg_start()
6237         self.pg0.get_capture(1)
6238
6239         # ACK packet in -> out
6240         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6241              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6242              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6243                  flags="A", seq=101, ack=301))
6244         self.pg0.add_stream(p)
6245         self.pg_enable_capture(self.pg_interfaces)
6246         self.pg_start()
6247         self.pg1.get_capture(1)
6248
6249         # ACK packet out -> in
6250         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6251              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6252              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6253                  flags="A", seq=301, ack=101))
6254         self.pg1.add_stream(p)
6255         self.pg_enable_capture(self.pg_interfaces)
6256         self.pg_start()
6257         self.pg0.get_capture(1)
6258
6259         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6260         self.assertEqual(len(sessions) - start_sessnum, 1)
6261
6262         stats = self.statistics.get_counter(
6263             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6264         out2in_drops = stats[0]
6265         stats = self.statistics.get_counter(
6266             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6267         in2out_drops = stats[0]
6268
6269         # extra FIN packet out -> in - this should be dropped
6270         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6271              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6272              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6273                  flags="FA", seq=300, ack=101))
6274
6275         self.pg1.add_stream(p)
6276         self.pg_enable_capture(self.pg_interfaces)
6277         self.pg_start()
6278         self.pg0.assert_nothing_captured()
6279
6280         # extra ACK packet in -> out - this should be dropped
6281         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6282              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6283              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6284                  flags="A", seq=101, ack=301))
6285         self.pg0.add_stream(p)
6286         self.pg_enable_capture(self.pg_interfaces)
6287         self.pg_start()
6288         self.pg1.assert_nothing_captured()
6289
6290         stats = self.statistics.get_counter(
6291             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6292         self.assertEqual(stats[0] - out2in_drops, 1)
6293         stats = self.statistics.get_counter(
6294             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6295         self.assertEqual(stats[0] - in2out_drops, 1)
6296
6297         self.sleep(3)
6298         # extra ACK packet in -> out - this will cause session to be wiped
6299         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6300              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6301              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6302                  flags="A", seq=101, ack=301))
6303         self.pg0.add_stream(p)
6304         self.pg_enable_capture(self.pg_interfaces)
6305         self.pg_start()
6306         self.pg1.assert_nothing_captured()
6307         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6308         self.assertEqual(len(sessions) - start_sessnum, 0)
6309
6310     def test_one_armed_nat44_static(self):
6311         """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
6312         remote_host = self.pg4.remote_hosts[0]
6313         local_host = self.pg4.remote_hosts[1]
6314         external_port = 80
6315         local_port = 8080
6316         eh_port_in = 0
6317
6318         self.vapi.nat44_forwarding_enable_disable(enable=1)
6319         self.nat44_add_address(self.nat_addr, twice_nat=1)
6320         flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
6321                  self.config_flags.NAT_IS_TWICE_NAT)
6322         self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
6323                                       local_port, external_port,
6324                                       proto=IP_PROTOS.tcp, flags=flags)
6325         flags = self.config_flags.NAT_IS_INSIDE
6326         self.vapi.nat44_interface_add_del_feature(
6327             sw_if_index=self.pg4.sw_if_index,
6328             is_add=1)
6329         self.vapi.nat44_interface_add_del_feature(
6330             sw_if_index=self.pg4.sw_if_index,
6331             flags=flags, is_add=1)
6332
6333         # from client to service
6334         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6335              IP(src=remote_host.ip4, dst=self.nat_addr) /
6336              TCP(sport=12345, dport=external_port))
6337         self.pg4.add_stream(p)
6338         self.pg_enable_capture(self.pg_interfaces)
6339         self.pg_start()
6340         capture = self.pg4.get_capture(1)
6341         p = capture[0]
6342         try:
6343             ip = p[IP]
6344             tcp = p[TCP]
6345             self.assertEqual(ip.dst, local_host.ip4)
6346             self.assertEqual(ip.src, self.nat_addr)
6347             self.assertEqual(tcp.dport, local_port)
6348             self.assertNotEqual(tcp.sport, 12345)
6349             eh_port_in = tcp.sport
6350             self.assert_packet_checksums_valid(p)
6351         except:
6352             self.logger.error(ppp("Unexpected or invalid packet:", p))
6353             raise
6354
6355         # from service back to client
6356         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6357              IP(src=local_host.ip4, dst=self.nat_addr) /
6358              TCP(sport=local_port, dport=eh_port_in))
6359         self.pg4.add_stream(p)
6360         self.pg_enable_capture(self.pg_interfaces)
6361         self.pg_start()
6362         capture = self.pg4.get_capture(1)
6363         p = capture[0]
6364         try:
6365             ip = p[IP]
6366             tcp = p[TCP]
6367             self.assertEqual(ip.src, self.nat_addr)
6368             self.assertEqual(ip.dst, remote_host.ip4)
6369             self.assertEqual(tcp.sport, external_port)
6370             self.assertEqual(tcp.dport, 12345)
6371             self.assert_packet_checksums_valid(p)
6372         except:
6373             self.logger.error(ppp("Unexpected or invalid packet:", p))
6374             raise
6375
6376     def test_static_with_port_out2(self):
6377         """ 1:1 NAPT asymmetrical rule """
6378
6379         external_port = 80
6380         local_port = 8080
6381
6382         self.vapi.nat44_forwarding_enable_disable(enable=1)
6383         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6384         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
6385                                       local_port, external_port,
6386                                       proto=IP_PROTOS.tcp, flags=flags)
6387         flags = self.config_flags.NAT_IS_INSIDE
6388         self.vapi.nat44_interface_add_del_feature(
6389             sw_if_index=self.pg0.sw_if_index,
6390             flags=flags, is_add=1)
6391         self.vapi.nat44_interface_add_del_feature(
6392             sw_if_index=self.pg1.sw_if_index,
6393             is_add=1)
6394
6395         # from client to service
6396         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6397              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6398              TCP(sport=12345, dport=external_port))
6399         self.pg1.add_stream(p)
6400         self.pg_enable_capture(self.pg_interfaces)
6401         self.pg_start()
6402         capture = self.pg0.get_capture(1)
6403         p = capture[0]
6404         try:
6405             ip = p[IP]
6406             tcp = p[TCP]
6407             self.assertEqual(ip.dst, self.pg0.remote_ip4)
6408             self.assertEqual(tcp.dport, local_port)
6409             self.assert_packet_checksums_valid(p)
6410         except:
6411             self.logger.error(ppp("Unexpected or invalid packet:", p))
6412             raise
6413
6414         # ICMP error
6415         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6416              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6417              ICMP(type=11) / capture[0][IP])
6418         self.pg0.add_stream(p)
6419         self.pg_enable_capture(self.pg_interfaces)
6420         self.pg_start()
6421         capture = self.pg1.get_capture(1)
6422         p = capture[0]
6423         try:
6424             self.assertEqual(p[IP].src, self.nat_addr)
6425             inner = p[IPerror]
6426             self.assertEqual(inner.dst, self.nat_addr)
6427             self.assertEqual(inner[TCPerror].dport, external_port)
6428         except:
6429             self.logger.error(ppp("Unexpected or invalid packet:", p))
6430             raise
6431
6432         # from service back to client
6433         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6434              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6435              TCP(sport=local_port, dport=12345))
6436         self.pg0.add_stream(p)
6437         self.pg_enable_capture(self.pg_interfaces)
6438         self.pg_start()
6439         capture = self.pg1.get_capture(1)
6440         p = capture[0]
6441         try:
6442             ip = p[IP]
6443             tcp = p[TCP]
6444             self.assertEqual(ip.src, self.nat_addr)
6445             self.assertEqual(tcp.sport, external_port)
6446             self.assert_packet_checksums_valid(p)
6447         except:
6448             self.logger.error(ppp("Unexpected or invalid packet:", p))
6449             raise
6450
6451         # ICMP error
6452         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6453              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6454              ICMP(type=11) / capture[0][IP])
6455         self.pg1.add_stream(p)
6456         self.pg_enable_capture(self.pg_interfaces)
6457         self.pg_start()
6458         capture = self.pg0.get_capture(1)
6459         p = capture[0]
6460         try:
6461             self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
6462             inner = p[IPerror]
6463             self.assertEqual(inner.src, self.pg0.remote_ip4)
6464             self.assertEqual(inner[TCPerror].sport, local_port)
6465         except:
6466             self.logger.error(ppp("Unexpected or invalid packet:", p))
6467             raise
6468
6469         # from client to server (no translation)
6470         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6471              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
6472              TCP(sport=12346, dport=local_port))
6473         self.pg1.add_stream(p)
6474         self.pg_enable_capture(self.pg_interfaces)
6475         self.pg_start()
6476         capture = self.pg0.get_capture(1)
6477         p = capture[0]
6478         try:
6479             ip = p[IP]
6480             tcp = p[TCP]
6481             self.assertEqual(ip.dst, self.pg0.remote_ip4)
6482             self.assertEqual(tcp.dport, local_port)
6483             self.assert_packet_checksums_valid(p)
6484         except:
6485             self.logger.error(ppp("Unexpected or invalid packet:", p))
6486             raise
6487
6488         # from service back to client (no translation)
6489         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6490              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6491              TCP(sport=local_port, dport=12346))
6492         self.pg0.add_stream(p)
6493         self.pg_enable_capture(self.pg_interfaces)
6494         self.pg_start()
6495         capture = self.pg1.get_capture(1)
6496         p = capture[0]
6497         try:
6498             ip = p[IP]
6499             tcp = p[TCP]
6500             self.assertEqual(ip.src, self.pg0.remote_ip4)
6501             self.assertEqual(tcp.sport, 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     def test_output_feature(self):
6508         """ NAT44 interface output feature (in2out postrouting) """
6509         self.vapi.nat44_forwarding_enable_disable(enable=1)
6510         self.nat44_add_address(self.nat_addr)
6511         self.vapi.nat44_interface_add_del_feature(
6512             sw_if_index=self.pg0.sw_if_index,
6513             is_add=1)
6514         self.vapi.nat44_interface_add_del_output_feature(
6515             is_add=1,
6516             sw_if_index=self.pg1.sw_if_index)
6517
6518         # in2out
6519         pkts = self.create_stream_in(self.pg0, self.pg1)
6520         self.pg0.add_stream(pkts)
6521         self.pg_enable_capture(self.pg_interfaces)
6522         self.pg_start()
6523         capture = self.pg1.get_capture(len(pkts))
6524         self.verify_capture_out(capture, ignore_port=True)
6525
6526         # out2in
6527         pkts = self.create_stream_out(self.pg1)
6528         self.pg1.add_stream(pkts)
6529         self.pg_enable_capture(self.pg_interfaces)
6530         self.pg_start()
6531         capture = self.pg0.get_capture(len(pkts))
6532         self.verify_capture_in(capture, self.pg0)
6533
6534     def test_output_feature_stateful_acl(self):
6535         """ NAT44 endpoint-dependent output feature works with stateful ACL """
6536         self.nat44_add_address(self.nat_addr)
6537         self.vapi.nat44_interface_add_del_output_feature(
6538             sw_if_index=self.pg0.sw_if_index,
6539             flags=self.config_flags.NAT_IS_INSIDE,
6540             is_add=1)
6541         self.vapi.nat44_interface_add_del_output_feature(
6542             sw_if_index=self.pg1.sw_if_index,
6543             flags=self.config_flags.NAT_IS_OUTSIDE,
6544             is_add=1)
6545
6546         # First ensure that the NAT is working sans ACL
6547
6548         # send packets out2in, no sessions yet so packets should drop
6549         pkts_out2in = self.create_stream_out(self.pg1)
6550         self.send_and_assert_no_replies(self.pg1, pkts_out2in)
6551
6552         # send packets into inside intf, ensure received via outside intf
6553         pkts_in2out = self.create_stream_in(self.pg0, self.pg1)
6554         capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
6555                                        len(pkts_in2out))
6556         self.verify_capture_out(capture, ignore_port=True)
6557
6558         # send out2in again, with sessions created it should work now
6559         pkts_out2in = self.create_stream_out(self.pg1)
6560         capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
6561                                        len(pkts_out2in))
6562         self.verify_capture_in(capture, self.pg0)
6563
6564         # Create an ACL blocking everything
6565         out2in_deny_rule = AclRule(is_permit=0)
6566         out2in_acl = VppAcl(self, rules=[out2in_deny_rule])
6567         out2in_acl.add_vpp_config()
6568
6569         # create an ACL to permit/reflect everything
6570         in2out_reflect_rule = AclRule(is_permit=2)
6571         in2out_acl = VppAcl(self, rules=[in2out_reflect_rule])
6572         in2out_acl.add_vpp_config()
6573
6574         # apply as input acl on interface and confirm it blocks everything
6575         acl_if = VppAclInterface(self, sw_if_index=self.pg1.sw_if_index,
6576                                  n_input=1, acls=[out2in_acl])
6577         acl_if.add_vpp_config()
6578         self.send_and_assert_no_replies(self.pg1, pkts_out2in)
6579
6580         # apply output acl
6581         acl_if.acls = [out2in_acl, in2out_acl]
6582         acl_if.add_vpp_config()
6583         # send in2out to generate ACL state (NAT state was created earlier)
6584         capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
6585                                        len(pkts_in2out))
6586         self.verify_capture_out(capture, ignore_port=True)
6587
6588         # send out2in again. ACL state exists so it should work now.
6589         # TCP packets with the syn flag set also need the ack flag
6590         for p in pkts_out2in:
6591             if p.haslayer(TCP) and p[TCP].flags & 0x02:
6592                 p[TCP].flags |= 0x10
6593         capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
6594                                        len(pkts_out2in))
6595         self.verify_capture_in(capture, self.pg0)
6596         self.logger.info(self.vapi.cli("show trace"))
6597
6598     def test_multiple_vrf(self):
6599         """ Multiple VRF setup """
6600         external_addr = '1.2.3.4'
6601         external_port = 80
6602         local_port = 8080
6603         port = 0
6604
6605         self.vapi.nat44_forwarding_enable_disable(enable=1)
6606         self.nat44_add_address(self.nat_addr)
6607         flags = self.config_flags.NAT_IS_INSIDE
6608         self.vapi.nat44_interface_add_del_feature(
6609             sw_if_index=self.pg0.sw_if_index,
6610             is_add=1)
6611         self.vapi.nat44_interface_add_del_feature(
6612             sw_if_index=self.pg0.sw_if_index,
6613             is_add=1, flags=flags)
6614         self.vapi.nat44_interface_add_del_output_feature(
6615             sw_if_index=self.pg1.sw_if_index,
6616             is_add=1)
6617         self.vapi.nat44_interface_add_del_feature(
6618             sw_if_index=self.pg5.sw_if_index,
6619             is_add=1)
6620         self.vapi.nat44_interface_add_del_feature(
6621             sw_if_index=self.pg5.sw_if_index,
6622             is_add=1, flags=flags)
6623         self.vapi.nat44_interface_add_del_feature(
6624             sw_if_index=self.pg6.sw_if_index,
6625             is_add=1)
6626         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6627         self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
6628                                       local_port, external_port, vrf_id=1,
6629                                       proto=IP_PROTOS.tcp, flags=flags)
6630         self.nat44_add_static_mapping(
6631             self.pg0.remote_ip4,
6632             external_sw_if_index=self.pg0.sw_if_index,
6633             local_port=local_port,
6634             vrf_id=0,
6635             external_port=external_port,
6636             proto=IP_PROTOS.tcp,
6637             flags=flags
6638         )
6639
6640         # from client to service (both VRF1)
6641         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6642              IP(src=self.pg6.remote_ip4, dst=external_addr) /
6643              TCP(sport=12345, dport=external_port))
6644         self.pg6.add_stream(p)
6645         self.pg_enable_capture(self.pg_interfaces)
6646         self.pg_start()
6647         capture = self.pg5.get_capture(1)
6648         p = capture[0]
6649         try:
6650             ip = p[IP]
6651             tcp = p[TCP]
6652             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6653             self.assertEqual(tcp.dport, local_port)
6654             self.assert_packet_checksums_valid(p)
6655         except:
6656             self.logger.error(ppp("Unexpected or invalid packet:", p))
6657             raise
6658
6659         # from service back to client (both VRF1)
6660         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6661              IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6662              TCP(sport=local_port, dport=12345))
6663         self.pg5.add_stream(p)
6664         self.pg_enable_capture(self.pg_interfaces)
6665         self.pg_start()
6666         capture = self.pg6.get_capture(1)
6667         p = capture[0]
6668         try:
6669             ip = p[IP]
6670             tcp = p[TCP]
6671             self.assertEqual(ip.src, external_addr)
6672             self.assertEqual(tcp.sport, external_port)
6673             self.assert_packet_checksums_valid(p)
6674         except:
6675             self.logger.error(ppp("Unexpected or invalid packet:", p))
6676             raise
6677
6678         # dynamic NAT from VRF1 to VRF0 (output-feature)
6679         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6680              IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6681              TCP(sport=2345, dport=22))
6682         self.pg5.add_stream(p)
6683         self.pg_enable_capture(self.pg_interfaces)
6684         self.pg_start()
6685         capture = self.pg1.get_capture(1)
6686         p = capture[0]
6687         try:
6688             ip = p[IP]
6689             tcp = p[TCP]
6690             self.assertEqual(ip.src, self.nat_addr)
6691             self.assert_packet_checksums_valid(p)
6692             port = tcp.sport
6693         except:
6694             self.logger.error(ppp("Unexpected or invalid packet:", p))
6695             raise
6696
6697         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6698              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6699              TCP(sport=22, dport=port))
6700         self.pg1.add_stream(p)
6701         self.pg_enable_capture(self.pg_interfaces)
6702         self.pg_start()
6703         capture = self.pg5.get_capture(1)
6704         p = capture[0]
6705         try:
6706             ip = p[IP]
6707             tcp = p[TCP]
6708             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6709             self.assertEqual(tcp.dport, 2345)
6710             self.assert_packet_checksums_valid(p)
6711         except:
6712             self.logger.error(ppp("Unexpected or invalid packet:", p))
6713             raise
6714
6715         # from client VRF1 to service VRF0
6716         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6717              IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6718              TCP(sport=12346, dport=external_port))
6719         self.pg6.add_stream(p)
6720         self.pg_enable_capture(self.pg_interfaces)
6721         self.pg_start()
6722         capture = self.pg0.get_capture(1)
6723         p = capture[0]
6724         try:
6725             ip = p[IP]
6726             tcp = p[TCP]
6727             self.assertEqual(ip.dst, self.pg0.remote_ip4)
6728             self.assertEqual(tcp.dport, local_port)
6729             self.assert_packet_checksums_valid(p)
6730         except:
6731             self.logger.error(ppp("Unexpected or invalid packet:", p))
6732             raise
6733
6734         # from service VRF0 back to client VRF1
6735         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6736              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6737              TCP(sport=local_port, dport=12346))
6738         self.pg0.add_stream(p)
6739         self.pg_enable_capture(self.pg_interfaces)
6740         self.pg_start()
6741         capture = self.pg6.get_capture(1)
6742         p = capture[0]
6743         try:
6744             ip = p[IP]
6745             tcp = p[TCP]
6746             self.assertEqual(ip.src, self.pg0.local_ip4)
6747             self.assertEqual(tcp.sport, external_port)
6748             self.assert_packet_checksums_valid(p)
6749         except:
6750             self.logger.error(ppp("Unexpected or invalid packet:", p))
6751             raise
6752
6753         # from client VRF0 to service VRF1
6754         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6755              IP(src=self.pg0.remote_ip4, dst=external_addr) /
6756              TCP(sport=12347, dport=external_port))
6757         self.pg0.add_stream(p)
6758         self.pg_enable_capture(self.pg_interfaces)
6759         self.pg_start()
6760         capture = self.pg5.get_capture(1)
6761         p = capture[0]
6762         try:
6763             ip = p[IP]
6764             tcp = p[TCP]
6765             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6766             self.assertEqual(tcp.dport, local_port)
6767             self.assert_packet_checksums_valid(p)
6768         except:
6769             self.logger.error(ppp("Unexpected or invalid packet:", p))
6770             raise
6771
6772         # from service VRF1 back to client VRF0
6773         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6774              IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6775              TCP(sport=local_port, dport=12347))
6776         self.pg5.add_stream(p)
6777         self.pg_enable_capture(self.pg_interfaces)
6778         self.pg_start()
6779         capture = self.pg0.get_capture(1)
6780         p = capture[0]
6781         try:
6782             ip = p[IP]
6783             tcp = p[TCP]
6784             self.assertEqual(ip.src, external_addr)
6785             self.assertEqual(tcp.sport, external_port)
6786             self.assert_packet_checksums_valid(p)
6787         except:
6788             self.logger.error(ppp("Unexpected or invalid packet:", p))
6789             raise
6790
6791         # from client to server (both VRF1, no translation)
6792         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6793              IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6794              TCP(sport=12348, dport=local_port))
6795         self.pg6.add_stream(p)
6796         self.pg_enable_capture(self.pg_interfaces)
6797         self.pg_start()
6798         capture = self.pg5.get_capture(1)
6799         p = capture[0]
6800         try:
6801             ip = p[IP]
6802             tcp = p[TCP]
6803             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6804             self.assertEqual(tcp.dport, local_port)
6805             self.assert_packet_checksums_valid(p)
6806         except:
6807             self.logger.error(ppp("Unexpected or invalid packet:", p))
6808             raise
6809
6810         # from server back to client (both VRF1, no translation)
6811         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6812              IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6813              TCP(sport=local_port, dport=12348))
6814         self.pg5.add_stream(p)
6815         self.pg_enable_capture(self.pg_interfaces)
6816         self.pg_start()
6817         capture = self.pg6.get_capture(1)
6818         p = capture[0]
6819         try:
6820             ip = p[IP]
6821             tcp = p[TCP]
6822             self.assertEqual(ip.src, self.pg5.remote_ip4)
6823             self.assertEqual(tcp.sport, local_port)
6824             self.assert_packet_checksums_valid(p)
6825         except:
6826             self.logger.error(ppp("Unexpected or invalid packet:", p))
6827             raise
6828
6829         # from client VRF1 to server VRF0 (no translation)
6830         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6831              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6832              TCP(sport=local_port, dport=12349))
6833         self.pg0.add_stream(p)
6834         self.pg_enable_capture(self.pg_interfaces)
6835         self.pg_start()
6836         capture = self.pg6.get_capture(1)
6837         p = capture[0]
6838         try:
6839             ip = p[IP]
6840             tcp = p[TCP]
6841             self.assertEqual(ip.src, self.pg0.remote_ip4)
6842             self.assertEqual(tcp.sport, local_port)
6843             self.assert_packet_checksums_valid(p)
6844         except:
6845             self.logger.error(ppp("Unexpected or invalid packet:", p))
6846             raise
6847
6848         # from server VRF0 back to client VRF1 (no translation)
6849         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6850              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6851              TCP(sport=local_port, dport=12349))
6852         self.pg0.add_stream(p)
6853         self.pg_enable_capture(self.pg_interfaces)
6854         self.pg_start()
6855         capture = self.pg6.get_capture(1)
6856         p = capture[0]
6857         try:
6858             ip = p[IP]
6859             tcp = p[TCP]
6860             self.assertEqual(ip.src, self.pg0.remote_ip4)
6861             self.assertEqual(tcp.sport, local_port)
6862             self.assert_packet_checksums_valid(p)
6863         except:
6864             self.logger.error(ppp("Unexpected or invalid packet:", p))
6865             raise
6866
6867         # from client VRF0 to server VRF1 (no translation)
6868         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6869              IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6870              TCP(sport=12344, dport=local_port))
6871         self.pg0.add_stream(p)
6872         self.pg_enable_capture(self.pg_interfaces)
6873         self.pg_start()
6874         capture = self.pg5.get_capture(1)
6875         p = capture[0]
6876         try:
6877             ip = p[IP]
6878             tcp = p[TCP]
6879             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6880             self.assertEqual(tcp.dport, local_port)
6881             self.assert_packet_checksums_valid(p)
6882         except:
6883             self.logger.error(ppp("Unexpected or invalid packet:", p))
6884             raise
6885
6886         # from server VRF1 back to client VRF0 (no translation)
6887         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6888              IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6889              TCP(sport=local_port, dport=12344))
6890         self.pg5.add_stream(p)
6891         self.pg_enable_capture(self.pg_interfaces)
6892         self.pg_start()
6893         capture = self.pg0.get_capture(1)
6894         p = capture[0]
6895         try:
6896             ip = p[IP]
6897             tcp = p[TCP]
6898             self.assertEqual(ip.src, self.pg5.remote_ip4)
6899             self.assertEqual(tcp.sport, local_port)
6900             self.assert_packet_checksums_valid(p)
6901         except:
6902             self.logger.error(ppp("Unexpected or invalid packet:", p))
6903             raise
6904
6905     @unittest.skipUnless(running_extended_tests, "part of extended tests")
6906     def test_session_timeout(self):
6907         """ NAT44 session timeouts """
6908         self.nat44_add_address(self.nat_addr)
6909         flags = self.config_flags.NAT_IS_INSIDE
6910         self.vapi.nat44_interface_add_del_feature(
6911             sw_if_index=self.pg0.sw_if_index,
6912             flags=flags, is_add=1)
6913         self.vapi.nat44_interface_add_del_feature(
6914             sw_if_index=self.pg1.sw_if_index,
6915             is_add=1)
6916         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6917                                    tcp_transitory=240, icmp=5)
6918
6919         max_sessions = 1000
6920         pkts = []
6921         for i in range(0, max_sessions):
6922             src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6923             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6924                  IP(src=src, dst=self.pg1.remote_ip4) /
6925                  ICMP(id=1025, type='echo-request'))
6926             pkts.append(p)
6927         self.pg0.add_stream(pkts)
6928         self.pg_enable_capture(self.pg_interfaces)
6929         self.pg_start()
6930         self.pg1.get_capture(max_sessions)
6931
6932         sleep(10)
6933
6934         pkts = []
6935         for i in range(0, max_sessions):
6936             src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6937             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6938                  IP(src=src, dst=self.pg1.remote_ip4) /
6939                  ICMP(id=1026, type='echo-request'))
6940             pkts.append(p)
6941         self.pg0.add_stream(pkts)
6942         self.pg_enable_capture(self.pg_interfaces)
6943         self.pg_start()
6944         self.pg1.get_capture(max_sessions)
6945
6946         nsessions = 0
6947         users = self.vapi.nat44_user_dump()
6948         for user in users:
6949             nsessions = nsessions + user.nsessions
6950         self.assertLess(nsessions, 2 * max_sessions)
6951
6952     @unittest.skipUnless(running_extended_tests, "part of extended tests")
6953     def test_session_rst_timeout(self):
6954         """ NAT44 session RST timeouts """
6955         self.nat44_add_address(self.nat_addr)
6956         flags = self.config_flags.NAT_IS_INSIDE
6957         self.vapi.nat44_interface_add_del_feature(
6958             sw_if_index=self.pg0.sw_if_index,
6959             flags=flags, is_add=1)
6960         self.vapi.nat44_interface_add_del_feature(
6961             sw_if_index=self.pg1.sw_if_index,
6962             is_add=1)
6963         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6964                                    tcp_transitory=5, icmp=60)
6965
6966         self.initiate_tcp_session(self.pg0, self.pg1)
6967         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6968              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6969              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6970                  flags="R"))
6971         self.pg0.add_stream(p)
6972         self.pg_enable_capture(self.pg_interfaces)
6973         self.pg_start()
6974         self.pg1.get_capture(1)
6975
6976         sleep(6)
6977
6978         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6979              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6980              TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6981                  flags="S"))
6982         self.pg0.add_stream(p)
6983         self.pg_enable_capture(self.pg_interfaces)
6984         self.pg_start()
6985         self.pg1.get_capture(1)
6986
6987     def test_syslog_sess(self):
6988         """ Test syslog session creation and deletion """
6989         self.vapi.syslog_set_filter(
6990             self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
6991         self.vapi.syslog_set_sender(self.pg2.local_ip4, self.pg2.remote_ip4)
6992         self.nat44_add_address(self.nat_addr)
6993         flags = self.config_flags.NAT_IS_INSIDE
6994         self.vapi.nat44_interface_add_del_feature(
6995             sw_if_index=self.pg0.sw_if_index,
6996             flags=flags, is_add=1)
6997         self.vapi.nat44_interface_add_del_feature(
6998             sw_if_index=self.pg1.sw_if_index,
6999             is_add=1)
7000
7001         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7002              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7003              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
7004         self.pg0.add_stream(p)
7005         self.pg_enable_capture(self.pg_interfaces)
7006         self.pg_start()
7007         capture = self.pg1.get_capture(1)
7008         self.tcp_port_out = capture[0][TCP].sport
7009         capture = self.pg2.get_capture(1)
7010         self.verify_syslog_sess(capture[0][Raw].load)
7011
7012         self.pg_enable_capture(self.pg_interfaces)
7013         self.pg_start()
7014         self.nat44_add_address(self.nat_addr, is_add=0)
7015         capture = self.pg2.get_capture(1)
7016         self.verify_syslog_sess(capture[0][Raw].load, False)
7017
7018     def test_ed_users_dump(self):
7019         """ API test - nat44_user_dump """
7020         flags = self.config_flags.NAT_IS_INSIDE
7021         self.vapi.nat44_interface_add_del_feature(
7022             sw_if_index=self.pg0.sw_if_index,
7023             flags=flags, is_add=1)
7024         self.vapi.nat44_interface_add_del_feature(
7025             sw_if_index=self.pg1.sw_if_index,
7026             is_add=1)
7027         self.vapi.nat44_forwarding_enable_disable(enable=1)
7028
7029         real_ip = self.pg0.remote_ip4
7030         alias_ip = self.nat_addr
7031         flags = self.config_flags.NAT_IS_ADDR_ONLY
7032         self.vapi.nat44_add_del_static_mapping(is_add=1,
7033                                                local_ip_address=real_ip,
7034                                                external_ip_address=alias_ip,
7035                                                external_sw_if_index=0xFFFFFFFF,
7036                                                flags=flags)
7037
7038         users = self.vapi.nat44_user_dump()
7039         self.assertEqual(len(users), 0)
7040         try:
7041             # in2out - static mapping match
7042
7043             pkts = self.create_stream_out(self.pg1)
7044             self.pg1.add_stream(pkts)
7045             self.pg_enable_capture(self.pg_interfaces)
7046             self.pg_start()
7047             capture = self.pg0.get_capture(len(pkts))
7048             self.verify_capture_in(capture, self.pg0)
7049
7050             pkts = self.create_stream_in(self.pg0, self.pg1)
7051             self.pg0.add_stream(pkts)
7052             self.pg_enable_capture(self.pg_interfaces)
7053             self.pg_start()
7054             capture = self.pg1.get_capture(len(pkts))
7055             self.verify_capture_out(capture, same_port=True)
7056
7057             users = self.vapi.nat44_user_dump()
7058             self.assertEqual(len(users), 1)
7059             static_user = users[0]
7060             self.assertEqual(static_user.nstaticsessions, 3)
7061             self.assertEqual(static_user.nsessions, 0)
7062
7063             # in2out - no static mapping match
7064
7065             host0 = self.pg0.remote_hosts[0]
7066             self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
7067             try:
7068                 pkts = self.create_stream_out(self.pg1,
7069                                               dst_ip=self.pg0.remote_ip4,
7070                                               use_inside_ports=True)
7071                 self.pg1.add_stream(pkts)
7072                 self.pg_enable_capture(self.pg_interfaces)
7073                 self.pg_start()
7074                 capture = self.pg0.get_capture(len(pkts))
7075                 self.verify_capture_in(capture, self.pg0)
7076
7077                 pkts = self.create_stream_in(self.pg0, self.pg1)
7078                 self.pg0.add_stream(pkts)
7079                 self.pg_enable_capture(self.pg_interfaces)
7080                 self.pg_start()
7081                 capture = self.pg1.get_capture(len(pkts))
7082                 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
7083                                         same_port=True)
7084             finally:
7085                 self.pg0.remote_hosts[0] = host0
7086
7087             users = self.vapi.nat44_user_dump()
7088             self.assertEqual(len(users), 2)
7089             if str(users[0].ip_address) == self.pg0.remote_hosts[0].ip4:
7090                 non_static_user = users[1]
7091                 static_user = users[0]
7092             else:
7093                 non_static_user = users[0]
7094                 static_user = users[1]
7095             self.assertEqual(static_user.nstaticsessions, 3)
7096             self.assertEqual(static_user.nsessions, 0)
7097             self.assertEqual(non_static_user.nstaticsessions, 0)
7098             self.assertEqual(non_static_user.nsessions, 3)
7099
7100             users = self.vapi.nat44_user_dump()
7101             self.assertEqual(len(users), 2)
7102             if str(users[0].ip_address) == self.pg0.remote_hosts[0].ip4:
7103                 non_static_user = users[1]
7104                 static_user = users[0]
7105             else:
7106                 non_static_user = users[0]
7107                 static_user = users[1]
7108             self.assertEqual(static_user.nstaticsessions, 3)
7109             self.assertEqual(static_user.nsessions, 0)
7110             self.assertEqual(non_static_user.nstaticsessions, 0)
7111             self.assertEqual(non_static_user.nsessions, 3)
7112
7113         finally:
7114             self.vapi.nat44_forwarding_enable_disable(enable=0)
7115             flags = self.config_flags.NAT_IS_ADDR_ONLY
7116             self.vapi.nat44_add_del_static_mapping(
7117                 is_add=0,
7118                 local_ip_address=real_ip,
7119                 external_ip_address=alias_ip,
7120                 external_sw_if_index=0xFFFFFFFF,
7121                 flags=flags)
7122
7123     def tearDown(self):
7124         super(TestNAT44EndpointDependent, self).tearDown()
7125         if not self.vpp_dead:
7126             self.clear_nat44()
7127             self.vapi.cli("clear logging")
7128
7129     def show_commands_at_teardown(self):
7130         self.logger.info(self.vapi.cli("show errors"))
7131         self.logger.info(self.vapi.cli("show nat44 addresses"))
7132         self.logger.info(self.vapi.cli("show nat44 interfaces"))
7133         self.logger.info(self.vapi.cli("show nat44 static mappings"))
7134         self.logger.info(self.vapi.cli("show nat44 interface address"))
7135         self.logger.info(self.vapi.cli("show nat44 sessions detail"))
7136         self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
7137         self.logger.info(self.vapi.cli("show nat timeouts"))
7138         self.logger.info(self.vapi.cli("debug nat44 fib registration"))
7139
7140
7141 class TestNAT44EndpointDependent3(MethodHolder):
7142     """ Endpoint-Dependent mapping and filtering extra test cases """
7143
7144     max_translations = 50
7145
7146     @classmethod
7147     def setUpConstants(cls):
7148         super(TestNAT44EndpointDependent3, cls).setUpConstants()
7149         cls.vpp_cmdline.extend([
7150             "nat", "{", "endpoint-dependent",
7151             "max translations per thread %d" % cls.max_translations,
7152             "}"
7153         ])
7154
7155     @classmethod
7156     def setUpClass(cls):
7157         super(TestNAT44EndpointDependent3, cls).setUpClass()
7158         cls.vapi.cli("set log class nat level debug")
7159
7160         cls.nat_addr = '10.0.0.3'
7161
7162         cls.create_pg_interfaces(range(2))
7163
7164         for i in cls.pg_interfaces:
7165             i.admin_up()
7166             i.config_ip4()
7167             i.resolve_arp()
7168
7169     def setUp(self):
7170         super(TestNAT44EndpointDependent3, self).setUp()
7171         self.vapi.nat_set_timeouts(
7172             udp=1, tcp_established=7440, tcp_transitory=30, icmp=1)
7173         self.nat44_add_address(self.nat_addr)
7174         flags = self.config_flags.NAT_IS_INSIDE
7175         self.vapi.nat44_interface_add_del_feature(
7176             sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1)
7177         self.vapi.nat44_interface_add_del_feature(
7178             sw_if_index=self.pg1.sw_if_index, is_add=1)
7179
7180     @classmethod
7181     def tearDownClass(cls):
7182         super(TestNAT44EndpointDependent3, cls).tearDownClass()
7183
7184     def init_tcp_session(self, in_if, out_if, sport, ext_dport):
7185         # SYN packet in->out
7186         p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
7187              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
7188              TCP(sport=sport, dport=ext_dport, flags="S"))
7189         in_if.add_stream(p)
7190         self.pg_enable_capture(self.pg_interfaces)
7191         self.pg_start()
7192         capture = out_if.get_capture(1)
7193         p = capture[0]
7194         tcp_port_out = p[TCP].sport
7195
7196         # SYN + ACK packet out->in
7197         p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
7198              IP(src=out_if.remote_ip4, dst=self.nat_addr) /
7199              TCP(sport=ext_dport, dport=tcp_port_out, flags="SA"))
7200         out_if.add_stream(p)
7201         self.pg_enable_capture(self.pg_interfaces)
7202         self.pg_start()
7203         in_if.get_capture(1)
7204
7205         # ACK packet in->out
7206         p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
7207              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
7208              TCP(sport=sport, dport=ext_dport, flags="A"))
7209         in_if.add_stream(p)
7210         self.pg_enable_capture(self.pg_interfaces)
7211         self.pg_start()
7212         out_if.get_capture(1)
7213
7214         return tcp_port_out
7215
7216     def test_lru_cleanup(self):
7217         """ LRU cleanup algorithm """
7218         tcp_port_out = self.init_tcp_session(self.pg0, self.pg1, 2000, 80)
7219         pkts = []
7220         for i in range(0, self.max_translations - 1):
7221             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7222                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
7223                  UDP(sport=7000+i, dport=80))
7224             pkts.append(p)
7225
7226         self.pg0.add_stream(pkts)
7227         self.pg_enable_capture(self.pg_interfaces)
7228         self.pg_start()
7229         self.pg1.get_capture(len(pkts))
7230         self.sleep(1.5, "wait for timeouts")
7231
7232         pkts = []
7233         for i in range(0, self.max_translations - 1):
7234             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7235                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
7236                  ICMP(id=8000+i, type='echo-request'))
7237             pkts.append(p)
7238
7239         self.pg0.add_stream(pkts)
7240         self.pg_enable_capture(self.pg_interfaces)
7241         self.pg_start()
7242         self.pg1.get_capture(len(pkts))
7243
7244
7245 class TestNAT44Out2InDPO(MethodHolder):
7246     """ NAT44 Test Cases using out2in DPO """
7247
7248     @classmethod
7249     def setUpConstants(cls):
7250         super(TestNAT44Out2InDPO, cls).setUpConstants()
7251         cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
7252
7253     @classmethod
7254     def setUpClass(cls):
7255         super(TestNAT44Out2InDPO, cls).setUpClass()
7256         cls.vapi.cli("set log class nat level debug")
7257
7258         cls.tcp_port_in = 6303
7259         cls.tcp_port_out = 6303
7260         cls.udp_port_in = 6304
7261         cls.udp_port_out = 6304
7262         cls.icmp_id_in = 6305
7263         cls.icmp_id_out = 6305
7264         cls.nat_addr = '10.0.0.3'
7265         cls.dst_ip4 = '192.168.70.1'
7266
7267         cls.create_pg_interfaces(range(2))
7268
7269         cls.pg0.admin_up()
7270         cls.pg0.config_ip4()
7271         cls.pg0.resolve_arp()
7272
7273         cls.pg1.admin_up()
7274         cls.pg1.config_ip6()
7275         cls.pg1.resolve_ndp()
7276
7277         r1 = VppIpRoute(cls, "::", 0,
7278                         [VppRoutePath(cls.pg1.remote_ip6,
7279                                       cls.pg1.sw_if_index)],
7280                         register=False)
7281         r1.add_vpp_config()
7282
7283     @classmethod
7284     def tearDownClass(cls):
7285         super(TestNAT44Out2InDPO, cls).tearDownClass()
7286
7287     def configure_xlat(self):
7288         self.dst_ip6_pfx = '1:2:3::'
7289         self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
7290                                               self.dst_ip6_pfx)
7291         self.dst_ip6_pfx_len = 96
7292         self.src_ip6_pfx = '4:5:6::'
7293         self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
7294                                               self.src_ip6_pfx)
7295         self.src_ip6_pfx_len = 96
7296         self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
7297                                  self.src_ip6_pfx_n, self.src_ip6_pfx_len,
7298                                  '\x00\x00\x00\x00', 0)
7299
7300     @unittest.skip('Temporary disabled')
7301     def test_464xlat_ce(self):
7302         """ Test 464XLAT CE with NAT44 """
7303
7304         nat_config = self.vapi.nat_show_config()
7305         self.assertEqual(1, nat_config.out2in_dpo)
7306
7307         self.configure_xlat()
7308
7309         flags = self.config_flags.NAT_IS_INSIDE
7310         self.vapi.nat44_interface_add_del_feature(
7311             sw_if_index=self.pg0.sw_if_index,
7312             flags=flags, is_add=1)
7313         self.vapi.nat44_add_del_address_range(first_ip_address=self.nat_addr_n,
7314                                               last_ip_address=self.nat_addr_n,
7315                                               vrf_id=0xFFFFFFFF, is_add=1)
7316
7317         out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7318                                        self.dst_ip6_pfx_len)
7319         out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
7320                                        self.src_ip6_pfx_len)
7321
7322         try:
7323             pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7324             self.pg0.add_stream(pkts)
7325             self.pg_enable_capture(self.pg_interfaces)
7326             self.pg_start()
7327             capture = self.pg1.get_capture(len(pkts))
7328             self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
7329                                         dst_ip=out_src_ip6)
7330
7331             pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
7332                                               out_dst_ip6)
7333             self.pg1.add_stream(pkts)
7334             self.pg_enable_capture(self.pg_interfaces)
7335             self.pg_start()
7336             capture = self.pg0.get_capture(len(pkts))
7337             self.verify_capture_in(capture, self.pg0)
7338         finally:
7339             self.vapi.nat44_interface_add_del_feature(
7340                 sw_if_index=self.pg0.sw_if_index,
7341                 flags=flags)
7342             self.vapi.nat44_add_del_address_range(
7343                 first_ip_address=self.nat_addr_n,
7344                 last_ip_address=self.nat_addr_n,
7345                 vrf_id=0xFFFFFFFF)
7346
7347     @unittest.skip('Temporary disabled')
7348     def test_464xlat_ce_no_nat(self):
7349         """ Test 464XLAT CE without NAT44 """
7350
7351         self.configure_xlat()
7352
7353         out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7354                                        self.dst_ip6_pfx_len)
7355         out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
7356                                        self.src_ip6_pfx_len)
7357
7358         pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7359         self.pg0.add_stream(pkts)
7360         self.pg_enable_capture(self.pg_interfaces)
7361         self.pg_start()
7362         capture = self.pg1.get_capture(len(pkts))
7363         self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
7364                                     nat_ip=out_dst_ip6, same_port=True)
7365
7366         pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
7367         self.pg1.add_stream(pkts)
7368         self.pg_enable_capture(self.pg_interfaces)
7369         self.pg_start()
7370         capture = self.pg0.get_capture(len(pkts))
7371         self.verify_capture_in(capture, self.pg0)
7372
7373
7374 if __name__ == '__main__':
7375     unittest.main(testRunner=VppTestRunner)