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