nat: fix tests
[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_interface_addr(self):
2378         """ Acquire NAT44 addresses from interface """
2379         self.vapi.nat44_add_del_interface_addr(
2380             is_add=1,
2381             sw_if_index=self.pg7.sw_if_index)
2382
2383         # no address in NAT pool
2384         addresses = self.vapi.nat44_address_dump()
2385         self.assertEqual(0, len(addresses))
2386
2387         # configure interface address and check NAT address pool
2388         self.pg7.config_ip4()
2389         addresses = self.vapi.nat44_address_dump()
2390         self.assertEqual(1, len(addresses))
2391         self.assertEqual(str(addresses[0].ip_address), self.pg7.local_ip4)
2392
2393         # remove interface address and check NAT address pool
2394         self.pg7.unconfig_ip4()
2395         addresses = self.vapi.nat44_address_dump()
2396         self.assertEqual(0, len(addresses))
2397
2398     def test_interface_addr_static_mapping(self):
2399         """ Static mapping with addresses from interface """
2400         tag = "testTAG"
2401
2402         self.vapi.nat44_add_del_interface_addr(
2403             is_add=1,
2404             sw_if_index=self.pg7.sw_if_index)
2405         self.nat44_add_static_mapping(
2406             '1.2.3.4',
2407             external_sw_if_index=self.pg7.sw_if_index,
2408             tag=tag)
2409
2410         # static mappings with external interface
2411         static_mappings = self.vapi.nat44_static_mapping_dump()
2412         self.assertEqual(1, len(static_mappings))
2413         self.assertEqual(self.pg7.sw_if_index,
2414                          static_mappings[0].external_sw_if_index)
2415         self.assertEqual(static_mappings[0].tag, tag)
2416
2417         # configure interface address and check static mappings
2418         self.pg7.config_ip4()
2419         static_mappings = self.vapi.nat44_static_mapping_dump()
2420         self.assertEqual(2, len(static_mappings))
2421         resolved = False
2422         for sm in static_mappings:
2423             if sm.external_sw_if_index == 0xFFFFFFFF:
2424                 self.assertEqual(str(sm.external_ip_address),
2425                                  self.pg7.local_ip4)
2426                 self.assertEqual(sm.tag, tag)
2427                 resolved = True
2428         self.assertTrue(resolved)
2429
2430         # remove interface address and check static mappings
2431         self.pg7.unconfig_ip4()
2432         static_mappings = self.vapi.nat44_static_mapping_dump()
2433         self.assertEqual(1, len(static_mappings))
2434         self.assertEqual(self.pg7.sw_if_index,
2435                          static_mappings[0].external_sw_if_index)
2436         self.assertEqual(static_mappings[0].tag, tag)
2437
2438         # configure interface address again and check static mappings
2439         self.pg7.config_ip4()
2440         static_mappings = self.vapi.nat44_static_mapping_dump()
2441         self.assertEqual(2, len(static_mappings))
2442         resolved = False
2443         for sm in static_mappings:
2444             if sm.external_sw_if_index == 0xFFFFFFFF:
2445                 self.assertEqual(str(sm.external_ip_address),
2446                                  self.pg7.local_ip4)
2447                 self.assertEqual(sm.tag, tag)
2448                 resolved = True
2449         self.assertTrue(resolved)
2450
2451         # remove static mapping
2452         self.nat44_add_static_mapping(
2453             '1.2.3.4',
2454             external_sw_if_index=self.pg7.sw_if_index,
2455             tag=tag,
2456             is_add=0)
2457         static_mappings = self.vapi.nat44_static_mapping_dump()
2458         self.assertEqual(0, len(static_mappings))
2459
2460     def test_interface_addr_identity_nat(self):
2461         """ Identity NAT with addresses from interface """
2462
2463         port = 53053
2464         self.vapi.nat44_add_del_interface_addr(
2465             is_add=1,
2466             sw_if_index=self.pg7.sw_if_index)
2467         self.vapi.nat44_add_del_identity_mapping(
2468             ip_address=b'0',
2469             sw_if_index=self.pg7.sw_if_index,
2470             port=port,
2471             protocol=IP_PROTOS.tcp,
2472             is_add=1)
2473
2474         # identity mappings with external interface
2475         identity_mappings = self.vapi.nat44_identity_mapping_dump()
2476         self.assertEqual(1, len(identity_mappings))
2477         self.assertEqual(self.pg7.sw_if_index,
2478                          identity_mappings[0].sw_if_index)
2479
2480         # configure interface address and check identity mappings
2481         self.pg7.config_ip4()
2482         identity_mappings = self.vapi.nat44_identity_mapping_dump()
2483         resolved = False
2484         self.assertEqual(2, len(identity_mappings))
2485         for sm in identity_mappings:
2486             if sm.sw_if_index == 0xFFFFFFFF:
2487                 self.assertEqual(str(identity_mappings[0].ip_address),
2488                                  self.pg7.local_ip4)
2489                 self.assertEqual(port, identity_mappings[0].port)
2490                 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2491                 resolved = True
2492         self.assertTrue(resolved)
2493
2494         # remove interface address and check identity mappings
2495         self.pg7.unconfig_ip4()
2496         identity_mappings = self.vapi.nat44_identity_mapping_dump()
2497         self.assertEqual(1, len(identity_mappings))
2498         self.assertEqual(self.pg7.sw_if_index,
2499                          identity_mappings[0].sw_if_index)
2500
2501     def test_ipfix_nat44_sess(self):
2502         """ IPFIX logging NAT44 session created/deleted """
2503         self.ipfix_domain_id = 10
2504         self.ipfix_src_port = 20202
2505         collector_port = 30303
2506         bind_layers(UDP, IPFIX, dport=30303)
2507         self.nat44_add_address(self.nat_addr)
2508         flags = self.config_flags.NAT_IS_INSIDE
2509         self.vapi.nat44_interface_add_del_feature(
2510             sw_if_index=self.pg0.sw_if_index,
2511             flags=flags, is_add=1)
2512         self.vapi.nat44_interface_add_del_feature(
2513             sw_if_index=self.pg1.sw_if_index,
2514             is_add=1)
2515         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2516                                      src_address=self.pg3.local_ip4,
2517                                      path_mtu=512,
2518                                      template_interval=10,
2519                                      collector_port=collector_port)
2520         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2521                                            src_port=self.ipfix_src_port,
2522                                            enable=1)
2523
2524         pkts = self.create_stream_in(self.pg0, self.pg1)
2525         self.pg0.add_stream(pkts)
2526         self.pg_enable_capture(self.pg_interfaces)
2527         self.pg_start()
2528         capture = self.pg1.get_capture(len(pkts))
2529         self.verify_capture_out(capture)
2530         self.nat44_add_address(self.nat_addr, is_add=0)
2531         self.vapi.ipfix_flush()
2532         capture = self.pg3.get_capture(7)
2533         ipfix = IPFIXDecoder()
2534         # first load template
2535         for p in capture:
2536             self.assertTrue(p.haslayer(IPFIX))
2537             self.assertEqual(p[IP].src, self.pg3.local_ip4)
2538             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2539             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2540             self.assertEqual(p[UDP].dport, collector_port)
2541             self.assertEqual(p[IPFIX].observationDomainID,
2542                              self.ipfix_domain_id)
2543             if p.haslayer(Template):
2544                 ipfix.add_template(p.getlayer(Template))
2545         # verify events in data set
2546         for p in capture:
2547             if p.haslayer(Data):
2548                 data = ipfix.decode_data_set(p.getlayer(Set))
2549                 self.verify_ipfix_nat44_ses(data)
2550
2551     def test_ipfix_addr_exhausted(self):
2552         """ IPFIX logging NAT addresses exhausted """
2553         flags = self.config_flags.NAT_IS_INSIDE
2554         self.vapi.nat44_interface_add_del_feature(
2555             sw_if_index=self.pg0.sw_if_index,
2556             flags=flags, is_add=1)
2557         self.vapi.nat44_interface_add_del_feature(
2558             sw_if_index=self.pg1.sw_if_index,
2559             is_add=1)
2560         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2561                                      src_address=self.pg3.local_ip4,
2562                                      path_mtu=512,
2563                                      template_interval=10)
2564         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2565                                            src_port=self.ipfix_src_port,
2566                                            enable=1)
2567
2568         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2569              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2570              TCP(sport=3025))
2571         self.pg0.add_stream(p)
2572         self.pg_enable_capture(self.pg_interfaces)
2573         self.pg_start()
2574         self.pg1.assert_nothing_captured()
2575         sleep(1)
2576         self.vapi.ipfix_flush()
2577         capture = self.pg3.get_capture(7)
2578         ipfix = IPFIXDecoder()
2579         # first load template
2580         for p in capture:
2581             self.assertTrue(p.haslayer(IPFIX))
2582             self.assertEqual(p[IP].src, self.pg3.local_ip4)
2583             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2584             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2585             self.assertEqual(p[UDP].dport, 4739)
2586             self.assertEqual(p[IPFIX].observationDomainID,
2587                              self.ipfix_domain_id)
2588             if p.haslayer(Template):
2589                 ipfix.add_template(p.getlayer(Template))
2590         # verify events in data set
2591         for p in capture:
2592             if p.haslayer(Data):
2593                 data = ipfix.decode_data_set(p.getlayer(Set))
2594                 self.verify_ipfix_addr_exhausted(data)
2595
2596     def test_ipfix_max_sessions(self):
2597         """ IPFIX logging maximum session entries exceeded """
2598         self.nat44_add_address(self.nat_addr)
2599         flags = self.config_flags.NAT_IS_INSIDE
2600         self.vapi.nat44_interface_add_del_feature(
2601             sw_if_index=self.pg0.sw_if_index,
2602             flags=flags, is_add=1)
2603         self.vapi.nat44_interface_add_del_feature(
2604             sw_if_index=self.pg1.sw_if_index,
2605             is_add=1)
2606
2607         max_sessions = self.max_translations
2608
2609         pkts = []
2610         for i in range(0, max_sessions):
2611             src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2612             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2613                  IP(src=src, dst=self.pg1.remote_ip4) /
2614                  TCP(sport=1025))
2615             pkts.append(p)
2616         self.pg0.add_stream(pkts)
2617         self.pg_enable_capture(self.pg_interfaces)
2618         self.pg_start()
2619
2620         self.pg1.get_capture(max_sessions)
2621         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2622                                      src_address=self.pg3.local_ip4,
2623                                      path_mtu=512,
2624                                      template_interval=10)
2625         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2626                                            src_port=self.ipfix_src_port,
2627                                            enable=1)
2628
2629         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2630              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2631              TCP(sport=1025))
2632         self.pg0.add_stream(p)
2633         self.pg_enable_capture(self.pg_interfaces)
2634         self.pg_start()
2635         self.pg1.assert_nothing_captured()
2636         sleep(1)
2637         self.vapi.ipfix_flush()
2638         capture = self.pg3.get_capture(7)
2639         ipfix = IPFIXDecoder()
2640         # first load template
2641         for p in capture:
2642             self.assertTrue(p.haslayer(IPFIX))
2643             self.assertEqual(p[IP].src, self.pg3.local_ip4)
2644             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2645             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2646             self.assertEqual(p[UDP].dport, 4739)
2647             self.assertEqual(p[IPFIX].observationDomainID,
2648                              self.ipfix_domain_id)
2649             if p.haslayer(Template):
2650                 ipfix.add_template(p.getlayer(Template))
2651         # verify events in data set
2652         for p in capture:
2653             if p.haslayer(Data):
2654                 data = ipfix.decode_data_set(p.getlayer(Set))
2655                 self.verify_ipfix_max_sessions(data, max_sessions)
2656
2657     def test_syslog_apmap(self):
2658         """ Test syslog address and port mapping creation and deletion """
2659         self.vapi.syslog_set_filter(
2660             self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
2661         self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
2662         self.nat44_add_address(self.nat_addr)
2663         flags = self.config_flags.NAT_IS_INSIDE
2664         self.vapi.nat44_interface_add_del_feature(
2665             sw_if_index=self.pg0.sw_if_index,
2666             flags=flags, is_add=1)
2667         self.vapi.nat44_interface_add_del_feature(
2668             sw_if_index=self.pg1.sw_if_index,
2669             is_add=1)
2670
2671         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2672              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2673              TCP(sport=self.tcp_port_in, dport=20))
2674         self.pg0.add_stream(p)
2675         self.pg_enable_capture(self.pg_interfaces)
2676         self.pg_start()
2677         capture = self.pg1.get_capture(1)
2678         self.tcp_port_out = capture[0][TCP].sport
2679         capture = self.pg3.get_capture(1)
2680         self.verify_syslog_apmap(capture[0][Raw].load)
2681
2682         self.pg_enable_capture(self.pg_interfaces)
2683         self.pg_start()
2684         self.nat44_add_address(self.nat_addr, is_add=0)
2685         capture = self.pg3.get_capture(1)
2686         self.verify_syslog_apmap(capture[0][Raw].load, False)
2687
2688     def test_pool_addr_fib(self):
2689         """ NAT44 add pool addresses to FIB """
2690         static_addr = '10.0.0.10'
2691         self.nat44_add_address(self.nat_addr)
2692         flags = self.config_flags.NAT_IS_INSIDE
2693         self.vapi.nat44_interface_add_del_feature(
2694             sw_if_index=self.pg0.sw_if_index,
2695             flags=flags, is_add=1)
2696         self.vapi.nat44_interface_add_del_feature(
2697             sw_if_index=self.pg1.sw_if_index,
2698             is_add=1)
2699         self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
2700
2701         # NAT44 address
2702         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2703              ARP(op=ARP.who_has, pdst=self.nat_addr,
2704                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2705         self.pg1.add_stream(p)
2706         self.pg_enable_capture(self.pg_interfaces)
2707         self.pg_start()
2708         capture = self.pg1.get_capture(1)
2709         self.assertTrue(capture[0].haslayer(ARP))
2710         self.assertTrue(capture[0][ARP].op, ARP.is_at)
2711
2712         # 1:1 NAT address
2713         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2714              ARP(op=ARP.who_has, pdst=static_addr,
2715                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2716         self.pg1.add_stream(p)
2717         self.pg_enable_capture(self.pg_interfaces)
2718         self.pg_start()
2719         capture = self.pg1.get_capture(1)
2720         self.assertTrue(capture[0].haslayer(ARP))
2721         self.assertTrue(capture[0][ARP].op, ARP.is_at)
2722
2723         # send ARP to non-NAT44 interface
2724         p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2725              ARP(op=ARP.who_has, pdst=self.nat_addr,
2726                  psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2727         self.pg2.add_stream(p)
2728         self.pg_enable_capture(self.pg_interfaces)
2729         self.pg_start()
2730         self.pg1.assert_nothing_captured()
2731
2732         # remove addresses and verify
2733         self.nat44_add_address(self.nat_addr, is_add=0)
2734         self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2735                                       is_add=0)
2736
2737         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2738              ARP(op=ARP.who_has, pdst=self.nat_addr,
2739                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2740         self.pg1.add_stream(p)
2741         self.pg_enable_capture(self.pg_interfaces)
2742         self.pg_start()
2743         self.pg1.assert_nothing_captured()
2744
2745         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2746              ARP(op=ARP.who_has, pdst=static_addr,
2747                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2748         self.pg1.add_stream(p)
2749         self.pg_enable_capture(self.pg_interfaces)
2750         self.pg_start()
2751         self.pg1.assert_nothing_captured()
2752
2753     def test_vrf_mode(self):
2754         """ NAT44 tenant VRF aware address pool mode """
2755
2756         vrf_id1 = 1
2757         vrf_id2 = 2
2758         nat_ip1 = "10.0.0.10"
2759         nat_ip2 = "10.0.0.11"
2760
2761         self.pg0.unconfig_ip4()
2762         self.pg1.unconfig_ip4()
2763         self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
2764         self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
2765         self.pg0.set_table_ip4(vrf_id1)
2766         self.pg1.set_table_ip4(vrf_id2)
2767         self.pg0.config_ip4()
2768         self.pg1.config_ip4()
2769         self.pg0.resolve_arp()
2770         self.pg1.resolve_arp()
2771
2772         self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2773         self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2774         flags = self.config_flags.NAT_IS_INSIDE
2775         self.vapi.nat44_interface_add_del_feature(
2776             sw_if_index=self.pg0.sw_if_index,
2777             flags=flags, is_add=1)
2778         self.vapi.nat44_interface_add_del_feature(
2779             sw_if_index=self.pg1.sw_if_index,
2780             flags=flags, is_add=1)
2781         self.vapi.nat44_interface_add_del_feature(
2782             sw_if_index=self.pg2.sw_if_index,
2783             is_add=1)
2784
2785         try:
2786             # first VRF
2787             pkts = self.create_stream_in(self.pg0, self.pg2)
2788             self.pg0.add_stream(pkts)
2789             self.pg_enable_capture(self.pg_interfaces)
2790             self.pg_start()
2791             capture = self.pg2.get_capture(len(pkts))
2792             self.verify_capture_out(capture, nat_ip1)
2793
2794             # second VRF
2795             pkts = self.create_stream_in(self.pg1, self.pg2)
2796             self.pg1.add_stream(pkts)
2797             self.pg_enable_capture(self.pg_interfaces)
2798             self.pg_start()
2799             capture = self.pg2.get_capture(len(pkts))
2800             self.verify_capture_out(capture, nat_ip2)
2801
2802         finally:
2803             self.pg0.unconfig_ip4()
2804             self.pg1.unconfig_ip4()
2805             self.pg0.set_table_ip4(0)
2806             self.pg1.set_table_ip4(0)
2807             self.pg0.config_ip4()
2808             self.pg1.config_ip4()
2809             self.pg0.resolve_arp()
2810             self.pg1.resolve_arp()
2811             self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id1})
2812             self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id2})
2813
2814     def test_vrf_feature_independent(self):
2815         """ NAT44 tenant VRF independent address pool mode """
2816
2817         nat_ip1 = "10.0.0.10"
2818         nat_ip2 = "10.0.0.11"
2819
2820         self.nat44_add_address(nat_ip1)
2821         self.nat44_add_address(nat_ip2, vrf_id=99)
2822         flags = self.config_flags.NAT_IS_INSIDE
2823         self.vapi.nat44_interface_add_del_feature(
2824             sw_if_index=self.pg0.sw_if_index,
2825             flags=flags, is_add=1)
2826         self.vapi.nat44_interface_add_del_feature(
2827             sw_if_index=self.pg1.sw_if_index,
2828             flags=flags, is_add=1)
2829         self.vapi.nat44_interface_add_del_feature(
2830             sw_if_index=self.pg2.sw_if_index,
2831             is_add=1)
2832
2833         # first VRF
2834         pkts = self.create_stream_in(self.pg0, self.pg2)
2835         self.pg0.add_stream(pkts)
2836         self.pg_enable_capture(self.pg_interfaces)
2837         self.pg_start()
2838         capture = self.pg2.get_capture(len(pkts))
2839         self.verify_capture_out(capture, nat_ip1)
2840
2841         # second VRF
2842         pkts = self.create_stream_in(self.pg1, self.pg2)
2843         self.pg1.add_stream(pkts)
2844         self.pg_enable_capture(self.pg_interfaces)
2845         self.pg_start()
2846         capture = self.pg2.get_capture(len(pkts))
2847         self.verify_capture_out(capture, nat_ip1)
2848
2849     def create_routes_and_neigbors(self):
2850         r1 = VppIpRoute(self, self.pg7.remote_ip4, 32,
2851                         [VppRoutePath(self.pg7.remote_ip4,
2852                                       self.pg7.sw_if_index)])
2853         r2 = VppIpRoute(self, self.pg8.remote_ip4, 32,
2854                         [VppRoutePath(self.pg8.remote_ip4,
2855                                       self.pg8.sw_if_index)])
2856         r1.add_vpp_config()
2857         r2.add_vpp_config()
2858
2859         n1 = VppNeighbor(self,
2860                          self.pg7.sw_if_index,
2861                          self.pg7.remote_mac,
2862                          self.pg7.remote_ip4,
2863                          is_static=1)
2864         n2 = VppNeighbor(self,
2865                          self.pg8.sw_if_index,
2866                          self.pg8.remote_mac,
2867                          self.pg8.remote_ip4,
2868                          is_static=1)
2869         n1.add_vpp_config()
2870         n2.add_vpp_config()
2871
2872     def test_dynamic_ipless_interfaces(self):
2873         """ NAT44 interfaces without configured IP address """
2874         self.create_routes_and_neigbors()
2875         self.nat44_add_address(self.nat_addr)
2876         flags = self.config_flags.NAT_IS_INSIDE
2877         self.vapi.nat44_interface_add_del_feature(
2878             sw_if_index=self.pg7.sw_if_index,
2879             flags=flags, is_add=1)
2880         self.vapi.nat44_interface_add_del_feature(
2881             sw_if_index=self.pg8.sw_if_index,
2882             is_add=1)
2883
2884         # in2out
2885         pkts = self.create_stream_in(self.pg7, self.pg8)
2886         self.pg7.add_stream(pkts)
2887         self.pg_enable_capture(self.pg_interfaces)
2888         self.pg_start()
2889         capture = self.pg8.get_capture(len(pkts))
2890         self.verify_capture_out(capture)
2891
2892         # out2in
2893         pkts = self.create_stream_out(self.pg8, self.nat_addr)
2894         self.pg8.add_stream(pkts)
2895         self.pg_enable_capture(self.pg_interfaces)
2896         self.pg_start()
2897         capture = self.pg7.get_capture(len(pkts))
2898         self.verify_capture_in(capture, self.pg7)
2899
2900     def test_static_ipless_interfaces(self):
2901         """ NAT44 interfaces without configured IP address - 1:1 NAT """
2902
2903         self.create_routes_and_neigbors()
2904         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2905         flags = self.config_flags.NAT_IS_INSIDE
2906         self.vapi.nat44_interface_add_del_feature(
2907             sw_if_index=self.pg7.sw_if_index,
2908             flags=flags, is_add=1)
2909         self.vapi.nat44_interface_add_del_feature(
2910             sw_if_index=self.pg8.sw_if_index,
2911             is_add=1)
2912
2913         # out2in
2914         pkts = self.create_stream_out(self.pg8)
2915         self.pg8.add_stream(pkts)
2916         self.pg_enable_capture(self.pg_interfaces)
2917         self.pg_start()
2918         capture = self.pg7.get_capture(len(pkts))
2919         self.verify_capture_in(capture, self.pg7)
2920
2921         # in2out
2922         pkts = self.create_stream_in(self.pg7, self.pg8)
2923         self.pg7.add_stream(pkts)
2924         self.pg_enable_capture(self.pg_interfaces)
2925         self.pg_start()
2926         capture = self.pg8.get_capture(len(pkts))
2927         self.verify_capture_out(capture, self.nat_addr, True)
2928
2929     def test_static_with_port_ipless_interfaces(self):
2930         """ NAT44 interfaces without configured IP address - 1:1 NAPT """
2931
2932         self.tcp_port_out = 30606
2933         self.udp_port_out = 30607
2934         self.icmp_id_out = 30608
2935
2936         self.create_routes_and_neigbors()
2937         self.nat44_add_address(self.nat_addr)
2938         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2939                                       self.tcp_port_in, self.tcp_port_out,
2940                                       proto=IP_PROTOS.tcp)
2941         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2942                                       self.udp_port_in, self.udp_port_out,
2943                                       proto=IP_PROTOS.udp)
2944         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2945                                       self.icmp_id_in, self.icmp_id_out,
2946                                       proto=IP_PROTOS.icmp)
2947         flags = self.config_flags.NAT_IS_INSIDE
2948         self.vapi.nat44_interface_add_del_feature(
2949             sw_if_index=self.pg7.sw_if_index,
2950             flags=flags, is_add=1)
2951         self.vapi.nat44_interface_add_del_feature(
2952             sw_if_index=self.pg8.sw_if_index,
2953             is_add=1)
2954
2955         # out2in
2956         pkts = self.create_stream_out(self.pg8)
2957         self.pg8.add_stream(pkts)
2958         self.pg_enable_capture(self.pg_interfaces)
2959         self.pg_start()
2960         capture = self.pg7.get_capture(len(pkts))
2961         self.verify_capture_in(capture, self.pg7)
2962
2963         # in2out
2964         pkts = self.create_stream_in(self.pg7, self.pg8)
2965         self.pg7.add_stream(pkts)
2966         self.pg_enable_capture(self.pg_interfaces)
2967         self.pg_start()
2968         capture = self.pg8.get_capture(len(pkts))
2969         self.verify_capture_out(capture)
2970
2971     def test_static_unknown_proto(self):
2972         """ 1:1 NAT translate packet with unknown protocol """
2973         nat_ip = "10.0.0.10"
2974         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2975         flags = self.config_flags.NAT_IS_INSIDE
2976         self.vapi.nat44_interface_add_del_feature(
2977             sw_if_index=self.pg0.sw_if_index,
2978             flags=flags, is_add=1)
2979         self.vapi.nat44_interface_add_del_feature(
2980             sw_if_index=self.pg1.sw_if_index,
2981             is_add=1)
2982
2983         # in2out
2984         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2985              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2986              GRE() /
2987              IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
2988              TCP(sport=1234, dport=1234))
2989         self.pg0.add_stream(p)
2990         self.pg_enable_capture(self.pg_interfaces)
2991         self.pg_start()
2992         p = self.pg1.get_capture(1)
2993         packet = p[0]
2994         try:
2995             self.assertEqual(packet[IP].src, nat_ip)
2996             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2997             self.assertEqual(packet.haslayer(GRE), 1)
2998             self.assert_packet_checksums_valid(packet)
2999         except:
3000             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3001             raise
3002
3003         # out2in
3004         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3005              IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3006              GRE() /
3007              IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3008              TCP(sport=1234, dport=1234))
3009         self.pg1.add_stream(p)
3010         self.pg_enable_capture(self.pg_interfaces)
3011         self.pg_start()
3012         p = self.pg0.get_capture(1)
3013         packet = p[0]
3014         try:
3015             self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3016             self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3017             self.assertEqual(packet.haslayer(GRE), 1)
3018             self.assert_packet_checksums_valid(packet)
3019         except:
3020             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3021             raise
3022
3023     def test_hairpinning_static_unknown_proto(self):
3024         """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3025
3026         host = self.pg0.remote_hosts[0]
3027         server = self.pg0.remote_hosts[1]
3028
3029         host_nat_ip = "10.0.0.10"
3030         server_nat_ip = "10.0.0.11"
3031
3032         self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3033         self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3034         flags = self.config_flags.NAT_IS_INSIDE
3035         self.vapi.nat44_interface_add_del_feature(
3036             sw_if_index=self.pg0.sw_if_index,
3037             flags=flags, is_add=1)
3038         self.vapi.nat44_interface_add_del_feature(
3039             sw_if_index=self.pg1.sw_if_index,
3040             is_add=1)
3041
3042         # host to server
3043         p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3044              IP(src=host.ip4, dst=server_nat_ip) /
3045              GRE() /
3046              IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3047              TCP(sport=1234, dport=1234))
3048         self.pg0.add_stream(p)
3049         self.pg_enable_capture(self.pg_interfaces)
3050         self.pg_start()
3051         p = self.pg0.get_capture(1)
3052         packet = p[0]
3053         try:
3054             self.assertEqual(packet[IP].src, host_nat_ip)
3055             self.assertEqual(packet[IP].dst, server.ip4)
3056             self.assertEqual(packet.haslayer(GRE), 1)
3057             self.assert_packet_checksums_valid(packet)
3058         except:
3059             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3060             raise
3061
3062         # server to host
3063         p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3064              IP(src=server.ip4, dst=host_nat_ip) /
3065              GRE() /
3066              IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3067              TCP(sport=1234, dport=1234))
3068         self.pg0.add_stream(p)
3069         self.pg_enable_capture(self.pg_interfaces)
3070         self.pg_start()
3071         p = self.pg0.get_capture(1)
3072         packet = p[0]
3073         try:
3074             self.assertEqual(packet[IP].src, server_nat_ip)
3075             self.assertEqual(packet[IP].dst, host.ip4)
3076             self.assertEqual(packet.haslayer(GRE), 1)
3077             self.assert_packet_checksums_valid(packet)
3078         except:
3079             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3080             raise
3081
3082     def test_output_feature(self):
3083         """ NAT44 interface output feature (in2out postrouting) """
3084         self.nat44_add_address(self.nat_addr)
3085         flags = self.config_flags.NAT_IS_INSIDE
3086         self.vapi.nat44_interface_add_del_output_feature(
3087             is_add=1, flags=flags,
3088             sw_if_index=self.pg0.sw_if_index)
3089         self.vapi.nat44_interface_add_del_output_feature(
3090             is_add=1, flags=flags,
3091             sw_if_index=self.pg1.sw_if_index)
3092         self.vapi.nat44_interface_add_del_output_feature(
3093             is_add=1,
3094             sw_if_index=self.pg3.sw_if_index)
3095
3096         # in2out
3097         pkts = self.create_stream_in(self.pg0, self.pg3)
3098         self.pg0.add_stream(pkts)
3099         self.pg_enable_capture(self.pg_interfaces)
3100         self.pg_start()
3101         capture = self.pg3.get_capture(len(pkts))
3102         self.verify_capture_out(capture)
3103
3104         # out2in
3105         pkts = self.create_stream_out(self.pg3)
3106         self.pg3.add_stream(pkts)
3107         self.pg_enable_capture(self.pg_interfaces)
3108         self.pg_start()
3109         capture = self.pg0.get_capture(len(pkts))
3110         self.verify_capture_in(capture, self.pg0)
3111
3112         # from non-NAT interface to NAT inside interface
3113         pkts = self.create_stream_in(self.pg2, self.pg0)
3114         self.pg2.add_stream(pkts)
3115         self.pg_enable_capture(self.pg_interfaces)
3116         self.pg_start()
3117         capture = self.pg0.get_capture(len(pkts))
3118         self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3119
3120     def test_output_feature_vrf_aware(self):
3121         """ NAT44 interface output feature VRF aware (in2out postrouting) """
3122         nat_ip_vrf10 = "10.0.0.10"
3123         nat_ip_vrf20 = "10.0.0.20"
3124
3125         r1 = VppIpRoute(self, self.pg3.remote_ip4, 32,
3126                         [VppRoutePath(self.pg3.remote_ip4,
3127                                       self.pg3.sw_if_index)],
3128                         table_id=10)
3129         r2 = VppIpRoute(self, self.pg3.remote_ip4, 32,
3130                         [VppRoutePath(self.pg3.remote_ip4,
3131                                       self.pg3.sw_if_index)],
3132                         table_id=20)
3133         r1.add_vpp_config()
3134         r2.add_vpp_config()
3135
3136         self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3137         self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3138         flags = self.config_flags.NAT_IS_INSIDE
3139         self.vapi.nat44_interface_add_del_output_feature(
3140             is_add=1, flags=flags,
3141             sw_if_index=self.pg4.sw_if_index)
3142         self.vapi.nat44_interface_add_del_output_feature(
3143             is_add=1, flags=flags,
3144             sw_if_index=self.pg6.sw_if_index)
3145         self.vapi.nat44_interface_add_del_output_feature(
3146             is_add=1,
3147             sw_if_index=self.pg3.sw_if_index)
3148
3149         # in2out VRF 10
3150         pkts = self.create_stream_in(self.pg4, self.pg3)
3151         self.pg4.add_stream(pkts)
3152         self.pg_enable_capture(self.pg_interfaces)
3153         self.pg_start()
3154         capture = self.pg3.get_capture(len(pkts))
3155         self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3156
3157         # out2in VRF 10
3158         pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3159         self.pg3.add_stream(pkts)
3160         self.pg_enable_capture(self.pg_interfaces)
3161         self.pg_start()
3162         capture = self.pg4.get_capture(len(pkts))
3163         self.verify_capture_in(capture, self.pg4)
3164
3165         # in2out VRF 20
3166         pkts = self.create_stream_in(self.pg6, self.pg3)
3167         self.pg6.add_stream(pkts)
3168         self.pg_enable_capture(self.pg_interfaces)
3169         self.pg_start()
3170         capture = self.pg3.get_capture(len(pkts))
3171         self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3172
3173         # out2in VRF 20
3174         pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3175         self.pg3.add_stream(pkts)
3176         self.pg_enable_capture(self.pg_interfaces)
3177         self.pg_start()
3178         capture = self.pg6.get_capture(len(pkts))
3179         self.verify_capture_in(capture, self.pg6)
3180
3181     def test_output_feature_hairpinning(self):
3182         """ NAT44 interface output feature hairpinning (in2out postrouting) """
3183         host = self.pg0.remote_hosts[0]
3184         server = self.pg0.remote_hosts[1]
3185         host_in_port = 1234
3186         host_out_port = 0
3187         server_in_port = 5678
3188         server_out_port = 8765
3189
3190         self.nat44_add_address(self.nat_addr)
3191         flags = self.config_flags.NAT_IS_INSIDE
3192         self.vapi.nat44_interface_add_del_output_feature(
3193             is_add=1, flags=flags,
3194             sw_if_index=self.pg0.sw_if_index)
3195         self.vapi.nat44_interface_add_del_output_feature(
3196             is_add=1,
3197             sw_if_index=self.pg1.sw_if_index)
3198
3199         # add static mapping for server
3200         self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3201                                       server_in_port, server_out_port,
3202                                       proto=IP_PROTOS.tcp)
3203
3204         # send packet from host to server
3205         p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3206              IP(src=host.ip4, dst=self.nat_addr) /
3207              TCP(sport=host_in_port, dport=server_out_port))
3208         self.pg0.add_stream(p)
3209         self.pg_enable_capture(self.pg_interfaces)
3210         self.pg_start()
3211         capture = self.pg0.get_capture(1)
3212         p = capture[0]
3213         try:
3214             ip = p[IP]
3215             tcp = p[TCP]
3216             self.assertEqual(ip.src, self.nat_addr)
3217             self.assertEqual(ip.dst, server.ip4)
3218             self.assertNotEqual(tcp.sport, host_in_port)
3219             self.assertEqual(tcp.dport, server_in_port)
3220             self.assert_packet_checksums_valid(p)
3221             host_out_port = tcp.sport
3222         except:
3223             self.logger.error(ppp("Unexpected or invalid packet:", p))
3224             raise
3225
3226         # send reply from server to host
3227         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3228              IP(src=server.ip4, dst=self.nat_addr) /
3229              TCP(sport=server_in_port, dport=host_out_port))
3230         self.pg0.add_stream(p)
3231         self.pg_enable_capture(self.pg_interfaces)
3232         self.pg_start()
3233         capture = self.pg0.get_capture(1)
3234         p = capture[0]
3235         try:
3236             ip = p[IP]
3237             tcp = p[TCP]
3238             self.assertEqual(ip.src, self.nat_addr)
3239             self.assertEqual(ip.dst, host.ip4)
3240             self.assertEqual(tcp.sport, server_out_port)
3241             self.assertEqual(tcp.dport, host_in_port)
3242             self.assert_packet_checksums_valid(p)
3243         except:
3244             self.logger.error(ppp("Unexpected or invalid packet:", p))
3245             raise
3246
3247     def test_one_armed_nat44(self):
3248         """ One armed NAT44 """
3249         remote_host = self.pg9.remote_hosts[0]
3250         local_host = self.pg9.remote_hosts[1]
3251         external_port = 0
3252
3253         self.nat44_add_address(self.nat_addr)
3254         flags = self.config_flags.NAT_IS_INSIDE
3255         self.vapi.nat44_interface_add_del_feature(
3256             sw_if_index=self.pg9.sw_if_index,
3257             is_add=1)
3258         self.vapi.nat44_interface_add_del_feature(
3259             sw_if_index=self.pg9.sw_if_index,
3260             flags=flags, is_add=1)
3261
3262         # in2out
3263         p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3264              IP(src=local_host.ip4, dst=remote_host.ip4) /
3265              TCP(sport=12345, dport=80))
3266         self.pg9.add_stream(p)
3267         self.pg_enable_capture(self.pg_interfaces)
3268         self.pg_start()
3269         capture = self.pg9.get_capture(1)
3270         p = capture[0]
3271         try:
3272             ip = p[IP]
3273             tcp = p[TCP]
3274             self.assertEqual(ip.src, self.nat_addr)
3275             self.assertEqual(ip.dst, remote_host.ip4)
3276             self.assertNotEqual(tcp.sport, 12345)
3277             external_port = tcp.sport
3278             self.assertEqual(tcp.dport, 80)
3279             self.assert_packet_checksums_valid(p)
3280         except:
3281             self.logger.error(ppp("Unexpected or invalid packet:", p))
3282             raise
3283
3284         # out2in
3285         p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3286              IP(src=remote_host.ip4, dst=self.nat_addr) /
3287              TCP(sport=80, dport=external_port))
3288         self.pg9.add_stream(p)
3289         self.pg_enable_capture(self.pg_interfaces)
3290         self.pg_start()
3291         capture = self.pg9.get_capture(1)
3292         p = capture[0]
3293         try:
3294             ip = p[IP]
3295             tcp = p[TCP]
3296             self.assertEqual(ip.src, remote_host.ip4)
3297             self.assertEqual(ip.dst, local_host.ip4)
3298             self.assertEqual(tcp.sport, 80)
3299             self.assertEqual(tcp.dport, 12345)
3300             self.assert_packet_checksums_valid(p)
3301         except:
3302             self.logger.error(ppp("Unexpected or invalid packet:", p))
3303             raise
3304
3305         err = self.statistics.get_err_counter(
3306             '/err/nat44-classify/next in2out')
3307         self.assertEqual(err, 1)
3308         err = self.statistics.get_err_counter(
3309             '/err/nat44-classify/next out2in')
3310         self.assertEqual(err, 1)
3311
3312     def test_del_session(self):
3313         """ Delete NAT44 session """
3314         self.nat44_add_address(self.nat_addr)
3315         flags = self.config_flags.NAT_IS_INSIDE
3316         self.vapi.nat44_interface_add_del_feature(
3317             sw_if_index=self.pg0.sw_if_index,
3318             flags=flags, is_add=1)
3319         self.vapi.nat44_interface_add_del_feature(
3320             sw_if_index=self.pg1.sw_if_index,
3321             is_add=1)
3322
3323         pkts = self.create_stream_in(self.pg0, self.pg1)
3324         self.pg0.add_stream(pkts)
3325         self.pg_enable_capture(self.pg_interfaces)
3326         self.pg_start()
3327         self.pg1.get_capture(len(pkts))
3328
3329         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3330         nsessions = len(sessions)
3331
3332         self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3333                                     port=sessions[0].inside_port,
3334                                     protocol=sessions[0].protocol,
3335                                     flags=self.config_flags.NAT_IS_INSIDE)
3336         self.vapi.nat44_del_session(address=sessions[1].outside_ip_address,
3337                                     port=sessions[1].outside_port,
3338                                     protocol=sessions[1].protocol)
3339
3340         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3341         self.assertEqual(nsessions - len(sessions), 2)
3342
3343         self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3344                                     port=sessions[0].inside_port,
3345                                     protocol=sessions[0].protocol,
3346                                     flags=self.config_flags.NAT_IS_INSIDE)
3347
3348         self.verify_no_nat44_user()
3349
3350     def test_frag_in_order(self):
3351         """ NAT44 translate fragments arriving in order """
3352
3353         self.nat44_add_address(self.nat_addr)
3354         flags = self.config_flags.NAT_IS_INSIDE
3355         self.vapi.nat44_interface_add_del_feature(
3356             sw_if_index=self.pg0.sw_if_index,
3357             flags=flags, is_add=1)
3358         self.vapi.nat44_interface_add_del_feature(
3359             sw_if_index=self.pg1.sw_if_index,
3360             is_add=1)
3361
3362         self.frag_in_order(proto=IP_PROTOS.tcp)
3363         self.frag_in_order(proto=IP_PROTOS.udp)
3364         self.frag_in_order(proto=IP_PROTOS.icmp)
3365
3366     def test_frag_forwarding(self):
3367         """ NAT44 forwarding fragment test """
3368         self.vapi.nat44_add_del_interface_addr(
3369             is_add=1,
3370             sw_if_index=self.pg1.sw_if_index)
3371         flags = self.config_flags.NAT_IS_INSIDE
3372         self.vapi.nat44_interface_add_del_feature(
3373             sw_if_index=self.pg0.sw_if_index,
3374             flags=flags, is_add=1)
3375         self.vapi.nat44_interface_add_del_feature(
3376             sw_if_index=self.pg1.sw_if_index,
3377             is_add=1)
3378         self.vapi.nat44_forwarding_enable_disable(enable=1)
3379
3380         data = b"A" * 16 + b"B" * 16 + b"C" * 3
3381         pkts = self.create_stream_frag(self.pg1,
3382                                        self.pg0.remote_ip4,
3383                                        4789,
3384                                        4789,
3385                                        data,
3386                                        proto=IP_PROTOS.udp)
3387         self.pg1.add_stream(pkts)
3388         self.pg_enable_capture(self.pg_interfaces)
3389         self.pg_start()
3390         frags = self.pg0.get_capture(len(pkts))
3391         p = self.reass_frags_and_verify(frags,
3392                                         self.pg1.remote_ip4,
3393                                         self.pg0.remote_ip4)
3394         self.assertEqual(p[UDP].sport, 4789)
3395         self.assertEqual(p[UDP].dport, 4789)
3396         self.assertEqual(data, p[Raw].load)
3397
3398     def test_reass_hairpinning(self):
3399         """ NAT44 fragments hairpinning """
3400
3401         self.server = self.pg0.remote_hosts[1]
3402         self.host_in_port = random.randint(1025, 65535)
3403         self.server_in_port = random.randint(1025, 65535)
3404         self.server_out_port = random.randint(1025, 65535)
3405
3406         self.nat44_add_address(self.nat_addr)
3407         flags = self.config_flags.NAT_IS_INSIDE
3408         self.vapi.nat44_interface_add_del_feature(
3409             sw_if_index=self.pg0.sw_if_index,
3410             flags=flags, is_add=1)
3411         self.vapi.nat44_interface_add_del_feature(
3412             sw_if_index=self.pg1.sw_if_index,
3413             is_add=1)
3414         # add static mapping for server
3415         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3416                                       self.server_in_port,
3417                                       self.server_out_port,
3418                                       proto=IP_PROTOS.tcp)
3419         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3420                                       self.server_in_port,
3421                                       self.server_out_port,
3422                                       proto=IP_PROTOS.udp)
3423         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
3424
3425         self.reass_hairpinning(proto=IP_PROTOS.tcp)
3426         self.reass_hairpinning(proto=IP_PROTOS.udp)
3427         self.reass_hairpinning(proto=IP_PROTOS.icmp)
3428
3429     def test_frag_out_of_order(self):
3430         """ NAT44 translate fragments arriving out of order """
3431
3432         self.nat44_add_address(self.nat_addr)
3433         flags = self.config_flags.NAT_IS_INSIDE
3434         self.vapi.nat44_interface_add_del_feature(
3435             sw_if_index=self.pg0.sw_if_index,
3436             flags=flags, is_add=1)
3437         self.vapi.nat44_interface_add_del_feature(
3438             sw_if_index=self.pg1.sw_if_index,
3439             is_add=1)
3440
3441         self.frag_out_of_order(proto=IP_PROTOS.tcp)
3442         self.frag_out_of_order(proto=IP_PROTOS.udp)
3443         self.frag_out_of_order(proto=IP_PROTOS.icmp)
3444
3445     def test_port_restricted(self):
3446         """ Port restricted NAT44 (MAP-E CE) """
3447         self.nat44_add_address(self.nat_addr)
3448         flags = self.config_flags.NAT_IS_INSIDE
3449         self.vapi.nat44_interface_add_del_feature(
3450             sw_if_index=self.pg0.sw_if_index,
3451             flags=flags, is_add=1)
3452         self.vapi.nat44_interface_add_del_feature(
3453             sw_if_index=self.pg1.sw_if_index,
3454             is_add=1)
3455         self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3456                                                   psid_offset=6,
3457                                                   psid_length=6,
3458                                                   psid=10)
3459
3460         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3461              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3462              TCP(sport=4567, dport=22))
3463         self.pg0.add_stream(p)
3464         self.pg_enable_capture(self.pg_interfaces)
3465         self.pg_start()
3466         capture = self.pg1.get_capture(1)
3467         p = capture[0]
3468         try:
3469             ip = p[IP]
3470             tcp = p[TCP]
3471             self.assertEqual(ip.dst, self.pg1.remote_ip4)
3472             self.assertEqual(ip.src, self.nat_addr)
3473             self.assertEqual(tcp.dport, 22)
3474             self.assertNotEqual(tcp.sport, 4567)
3475             self.assertEqual((tcp.sport >> 6) & 63, 10)
3476             self.assert_packet_checksums_valid(p)
3477         except:
3478             self.logger.error(ppp("Unexpected or invalid packet:", p))
3479             raise
3480
3481     def test_port_range(self):
3482         """ External address port range """
3483         self.nat44_add_address(self.nat_addr)
3484         flags = self.config_flags.NAT_IS_INSIDE
3485         self.vapi.nat44_interface_add_del_feature(
3486             sw_if_index=self.pg0.sw_if_index,
3487             flags=flags, is_add=1)
3488         self.vapi.nat44_interface_add_del_feature(
3489             sw_if_index=self.pg1.sw_if_index,
3490             is_add=1)
3491         self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3492                                                   start_port=1025,
3493                                                   end_port=1027)
3494
3495         pkts = []
3496         for port in range(0, 5):
3497             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3498                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3499                  TCP(sport=1125 + port))
3500             pkts.append(p)
3501         self.pg0.add_stream(pkts)
3502         self.pg_enable_capture(self.pg_interfaces)
3503         self.pg_start()
3504         capture = self.pg1.get_capture(3)
3505         for p in capture:
3506             tcp = p[TCP]
3507             self.assertGreaterEqual(tcp.sport, 1025)
3508             self.assertLessEqual(tcp.sport, 1027)
3509
3510     def test_multiple_outside_vrf(self):
3511         """ Multiple outside VRF """
3512         vrf_id1 = 1
3513         vrf_id2 = 2
3514
3515         self.pg1.unconfig_ip4()
3516         self.pg2.unconfig_ip4()
3517         self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
3518         self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
3519         self.pg1.set_table_ip4(vrf_id1)
3520         self.pg2.set_table_ip4(vrf_id2)
3521         self.pg1.config_ip4()
3522         self.pg2.config_ip4()
3523         self.pg1.resolve_arp()
3524         self.pg2.resolve_arp()
3525
3526         self.nat44_add_address(self.nat_addr)
3527         flags = self.config_flags.NAT_IS_INSIDE
3528         self.vapi.nat44_interface_add_del_feature(
3529             sw_if_index=self.pg0.sw_if_index,
3530             flags=flags, is_add=1)
3531         self.vapi.nat44_interface_add_del_feature(
3532             sw_if_index=self.pg1.sw_if_index,
3533             is_add=1)
3534         self.vapi.nat44_interface_add_del_feature(
3535             sw_if_index=self.pg2.sw_if_index,
3536             is_add=1)
3537
3538         try:
3539             # first VRF
3540             pkts = self.create_stream_in(self.pg0, self.pg1)
3541             self.pg0.add_stream(pkts)
3542             self.pg_enable_capture(self.pg_interfaces)
3543             self.pg_start()
3544             capture = self.pg1.get_capture(len(pkts))
3545             self.verify_capture_out(capture, self.nat_addr)
3546
3547             pkts = self.create_stream_out(self.pg1, self.nat_addr)
3548             self.pg1.add_stream(pkts)
3549             self.pg_enable_capture(self.pg_interfaces)
3550             self.pg_start()
3551             capture = self.pg0.get_capture(len(pkts))
3552             self.verify_capture_in(capture, self.pg0)
3553
3554             self.tcp_port_in = 60303
3555             self.udp_port_in = 60304
3556             self.icmp_id_in = 60305
3557
3558             # second VRF
3559             pkts = self.create_stream_in(self.pg0, self.pg2)
3560             self.pg0.add_stream(pkts)
3561             self.pg_enable_capture(self.pg_interfaces)
3562             self.pg_start()
3563             capture = self.pg2.get_capture(len(pkts))
3564             self.verify_capture_out(capture, self.nat_addr)
3565
3566             pkts = self.create_stream_out(self.pg2, self.nat_addr)
3567             self.pg2.add_stream(pkts)
3568             self.pg_enable_capture(self.pg_interfaces)
3569             self.pg_start()
3570             capture = self.pg0.get_capture(len(pkts))
3571             self.verify_capture_in(capture, self.pg0)
3572
3573         finally:
3574             self.nat44_add_address(self.nat_addr, is_add=0)
3575             self.pg1.unconfig_ip4()
3576             self.pg2.unconfig_ip4()
3577             self.pg1.set_table_ip4(0)
3578             self.pg2.set_table_ip4(0)
3579             self.pg1.config_ip4()
3580             self.pg2.config_ip4()
3581             self.pg1.resolve_arp()
3582             self.pg2.resolve_arp()
3583
3584     def test_mss_clamping(self):
3585         """ TCP MSS clamping """
3586         self.nat44_add_address(self.nat_addr)
3587         flags = self.config_flags.NAT_IS_INSIDE
3588         self.vapi.nat44_interface_add_del_feature(
3589             sw_if_index=self.pg0.sw_if_index,
3590             flags=flags, is_add=1)
3591         self.vapi.nat44_interface_add_del_feature(
3592             sw_if_index=self.pg1.sw_if_index,
3593             is_add=1)
3594
3595         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3596              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3597              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3598                  flags="S", options=[('MSS', 1400)]))
3599
3600         self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3601         self.pg0.add_stream(p)
3602         self.pg_enable_capture(self.pg_interfaces)
3603         self.pg_start()
3604         capture = self.pg1.get_capture(1)
3605         # Negotiated MSS value greater than configured - changed
3606         self.verify_mss_value(capture[0], 1000)
3607
3608         self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
3609         self.pg0.add_stream(p)
3610         self.pg_enable_capture(self.pg_interfaces)
3611         self.pg_start()
3612         capture = self.pg1.get_capture(1)
3613         # MSS clamping disabled - negotiated MSS unchanged
3614         self.verify_mss_value(capture[0], 1400)
3615
3616         self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3617         self.pg0.add_stream(p)
3618         self.pg_enable_capture(self.pg_interfaces)
3619         self.pg_start()
3620         capture = self.pg1.get_capture(1)
3621         # Negotiated MSS value smaller than configured - unchanged
3622         self.verify_mss_value(capture[0], 1400)
3623
3624     def test_ha_send(self):
3625         """ Send HA session synchronization events (active) """
3626         flags = self.config_flags.NAT_IS_INSIDE
3627         self.vapi.nat44_interface_add_del_feature(
3628             sw_if_index=self.pg0.sw_if_index,
3629             flags=flags, is_add=1)
3630         self.vapi.nat44_interface_add_del_feature(
3631             sw_if_index=self.pg1.sw_if_index,
3632             is_add=1)
3633         self.nat44_add_address(self.nat_addr)
3634
3635         self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
3636                                       port=12345,
3637                                       path_mtu=512)
3638         self.vapi.nat_ha_set_failover(ip_address=self.pg3.remote_ip4,
3639                                       port=12346, session_refresh_interval=10)
3640         bind_layers(UDP, HANATStateSync, sport=12345)
3641
3642         # create sessions
3643         pkts = self.create_stream_in(self.pg0, self.pg1)
3644         self.pg0.add_stream(pkts)
3645         self.pg_enable_capture(self.pg_interfaces)
3646         self.pg_start()
3647         capture = self.pg1.get_capture(len(pkts))
3648         self.verify_capture_out(capture)
3649         # active send HA events
3650         self.vapi.nat_ha_flush()
3651         stats = self.statistics.get_counter('/nat44/ha/add-event-send')
3652         self.assertEqual(stats[0][0], 3)
3653         capture = self.pg3.get_capture(1)
3654         p = capture[0]
3655         self.assert_packet_checksums_valid(p)
3656         try:
3657             ip = p[IP]
3658             udp = p[UDP]
3659             hanat = p[HANATStateSync]
3660         except IndexError:
3661             self.logger.error(ppp("Invalid packet:", p))
3662             raise
3663         else:
3664             self.assertEqual(ip.src, self.pg3.local_ip4)
3665             self.assertEqual(ip.dst, self.pg3.remote_ip4)
3666             self.assertEqual(udp.sport, 12345)
3667             self.assertEqual(udp.dport, 12346)
3668             self.assertEqual(hanat.version, 1)
3669             self.assertEqual(hanat.thread_index, 0)
3670             self.assertEqual(hanat.count, 3)
3671             seq = hanat.sequence_number
3672             for event in hanat.events:
3673                 self.assertEqual(event.event_type, 1)
3674                 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
3675                 self.assertEqual(event.out_addr, self.nat_addr)
3676                 self.assertEqual(event.fib_index, 0)
3677
3678         # ACK received events
3679         ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3680                IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3681                UDP(sport=12346, dport=12345) /
3682                HANATStateSync(sequence_number=seq, flags='ACK'))
3683         self.pg3.add_stream(ack)
3684         self.pg_start()
3685         stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3686         self.assertEqual(stats[0][0], 1)
3687
3688         # delete one session
3689         self.pg_enable_capture(self.pg_interfaces)
3690         self.vapi.nat44_del_session(address=self.pg0.remote_ip4,
3691                                     port=self.tcp_port_in,
3692                                     protocol=IP_PROTOS.tcp,
3693                                     flags=self.config_flags.NAT_IS_INSIDE)
3694         self.vapi.nat_ha_flush()
3695         stats = self.statistics.get_counter('/nat44/ha/del-event-send')
3696         self.assertEqual(stats[0][0], 1)
3697         capture = self.pg3.get_capture(1)
3698         p = capture[0]
3699         try:
3700             hanat = p[HANATStateSync]
3701         except IndexError:
3702             self.logger.error(ppp("Invalid packet:", p))
3703             raise
3704         else:
3705             self.assertGreater(hanat.sequence_number, seq)
3706
3707         # do not send ACK, active retry send HA event again
3708         self.pg_enable_capture(self.pg_interfaces)
3709         sleep(12)
3710         stats = self.statistics.get_counter('/nat44/ha/retry-count')
3711         self.assertEqual(stats[0][0], 3)
3712         stats = self.statistics.get_counter('/nat44/ha/missed-count')
3713         self.assertEqual(stats[0][0], 1)
3714         capture = self.pg3.get_capture(3)
3715         for packet in capture:
3716             self.assertEqual(packet, p)
3717
3718         # session counters refresh
3719         pkts = self.create_stream_out(self.pg1)
3720         self.pg1.add_stream(pkts)
3721         self.pg_enable_capture(self.pg_interfaces)
3722         self.pg_start()
3723         self.pg0.get_capture(2)
3724         self.vapi.nat_ha_flush()
3725         stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
3726         self.assertEqual(stats[0][0], 2)
3727         capture = self.pg3.get_capture(1)
3728         p = capture[0]
3729         self.assert_packet_checksums_valid(p)
3730         try:
3731             ip = p[IP]
3732             udp = p[UDP]
3733             hanat = p[HANATStateSync]
3734         except IndexError:
3735             self.logger.error(ppp("Invalid packet:", p))
3736             raise
3737         else:
3738             self.assertEqual(ip.src, self.pg3.local_ip4)
3739             self.assertEqual(ip.dst, self.pg3.remote_ip4)
3740             self.assertEqual(udp.sport, 12345)
3741             self.assertEqual(udp.dport, 12346)
3742             self.assertEqual(hanat.version, 1)
3743             self.assertEqual(hanat.count, 2)
3744             seq = hanat.sequence_number
3745             for event in hanat.events:
3746                 self.assertEqual(event.event_type, 3)
3747                 self.assertEqual(event.out_addr, self.nat_addr)
3748                 self.assertEqual(event.fib_index, 0)
3749                 self.assertEqual(event.total_pkts, 2)
3750                 self.assertGreater(event.total_bytes, 0)
3751
3752         ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3753                IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3754                UDP(sport=12346, dport=12345) /
3755                HANATStateSync(sequence_number=seq, flags='ACK'))
3756         self.pg3.add_stream(ack)
3757         self.pg_start()
3758         stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3759         self.assertEqual(stats[0][0], 2)
3760
3761     def test_ha_recv(self):
3762         """ Receive HA session synchronization events (passive) """
3763         self.nat44_add_address(self.nat_addr)
3764         flags = self.config_flags.NAT_IS_INSIDE
3765         self.vapi.nat44_interface_add_del_feature(
3766             sw_if_index=self.pg0.sw_if_index,
3767             flags=flags, is_add=1)
3768         self.vapi.nat44_interface_add_del_feature(
3769             sw_if_index=self.pg1.sw_if_index,
3770             is_add=1)
3771         self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
3772                                       port=12345,
3773                                       path_mtu=512)
3774         bind_layers(UDP, HANATStateSync, sport=12345)
3775
3776         self.tcp_port_out = random.randint(1025, 65535)
3777         self.udp_port_out = random.randint(1025, 65535)
3778
3779         # send HA session add events to failover/passive
3780         p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3781              IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3782              UDP(sport=12346, dport=12345) /
3783              HANATStateSync(sequence_number=1, events=[
3784                  Event(event_type='add', protocol='tcp',
3785                        in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3786                        in_port=self.tcp_port_in, out_port=self.tcp_port_out,
3787                        eh_addr=self.pg1.remote_ip4,
3788                        ehn_addr=self.pg1.remote_ip4,
3789                        eh_port=self.tcp_external_port,
3790                        ehn_port=self.tcp_external_port, fib_index=0),
3791                  Event(event_type='add', protocol='udp',
3792                        in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3793                        in_port=self.udp_port_in, out_port=self.udp_port_out,
3794                        eh_addr=self.pg1.remote_ip4,
3795                        ehn_addr=self.pg1.remote_ip4,
3796                        eh_port=self.udp_external_port,
3797                        ehn_port=self.udp_external_port, fib_index=0)]))
3798
3799         self.pg3.add_stream(p)
3800         self.pg_enable_capture(self.pg_interfaces)
3801         self.pg_start()
3802         # receive ACK
3803         capture = self.pg3.get_capture(1)
3804         p = capture[0]
3805         try:
3806             hanat = p[HANATStateSync]
3807         except IndexError:
3808             self.logger.error(ppp("Invalid packet:", p))
3809             raise
3810         else:
3811             self.assertEqual(hanat.sequence_number, 1)
3812             self.assertEqual(hanat.flags, 'ACK')
3813             self.assertEqual(hanat.version, 1)
3814             self.assertEqual(hanat.thread_index, 0)
3815         stats = self.statistics.get_counter('/nat44/ha/ack-send')
3816         self.assertEqual(stats[0][0], 1)
3817         stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
3818         self.assertEqual(stats[0][0], 2)
3819         users = self.statistics.get_counter('/nat44/total-users')
3820         self.assertEqual(users[0][0], 1)
3821         sessions = self.statistics.get_counter('/nat44/total-sessions')
3822         self.assertEqual(sessions[0][0], 2)
3823         users = self.vapi.nat44_user_dump()
3824         self.assertEqual(len(users), 1)
3825         self.assertEqual(str(users[0].ip_address),
3826                          self.pg0.remote_ip4)
3827         # there should be 2 sessions created by HA
3828         sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
3829                                                      users[0].vrf_id)
3830         self.assertEqual(len(sessions), 2)
3831         for session in sessions:
3832             self.assertEqual(str(session.inside_ip_address),
3833                              self.pg0.remote_ip4)
3834             self.assertEqual(str(session.outside_ip_address),
3835                              self.nat_addr)
3836             self.assertIn(session.inside_port,
3837                           [self.tcp_port_in, self.udp_port_in])
3838             self.assertIn(session.outside_port,
3839                           [self.tcp_port_out, self.udp_port_out])
3840             self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
3841
3842         # send HA session delete event to failover/passive
3843         p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3844              IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3845              UDP(sport=12346, dport=12345) /
3846              HANATStateSync(sequence_number=2, events=[
3847                  Event(event_type='del', protocol='udp',
3848                        in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3849                        in_port=self.udp_port_in, out_port=self.udp_port_out,
3850                        eh_addr=self.pg1.remote_ip4,
3851                        ehn_addr=self.pg1.remote_ip4,
3852                        eh_port=self.udp_external_port,
3853                        ehn_port=self.udp_external_port, fib_index=0)]))
3854
3855         self.pg3.add_stream(p)
3856         self.pg_enable_capture(self.pg_interfaces)
3857         self.pg_start()
3858         # receive ACK
3859         capture = self.pg3.get_capture(1)
3860         p = capture[0]
3861         try:
3862             hanat = p[HANATStateSync]
3863         except IndexError:
3864             self.logger.error(ppp("Invalid packet:", p))
3865             raise
3866         else:
3867             self.assertEqual(hanat.sequence_number, 2)
3868             self.assertEqual(hanat.flags, 'ACK')
3869             self.assertEqual(hanat.version, 1)
3870         users = self.vapi.nat44_user_dump()
3871         self.assertEqual(len(users), 1)
3872         self.assertEqual(str(users[0].ip_address),
3873                          self.pg0.remote_ip4)
3874         # now we should have only 1 session, 1 deleted by HA
3875         sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
3876                                                      users[0].vrf_id)
3877         self.assertEqual(len(sessions), 1)
3878         stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
3879         self.assertEqual(stats[0][0], 1)
3880
3881         stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
3882         self.assertEqual(stats, 2)
3883
3884         # send HA session refresh event to failover/passive
3885         p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3886              IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3887              UDP(sport=12346, dport=12345) /
3888              HANATStateSync(sequence_number=3, events=[
3889                  Event(event_type='refresh', protocol='tcp',
3890                        in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3891                        in_port=self.tcp_port_in, out_port=self.tcp_port_out,
3892                        eh_addr=self.pg1.remote_ip4,
3893                        ehn_addr=self.pg1.remote_ip4,
3894                        eh_port=self.tcp_external_port,
3895                        ehn_port=self.tcp_external_port, fib_index=0,
3896                        total_bytes=1024, total_pkts=2)]))
3897         self.pg3.add_stream(p)
3898         self.pg_enable_capture(self.pg_interfaces)
3899         self.pg_start()
3900         # receive ACK
3901         capture = self.pg3.get_capture(1)
3902         p = capture[0]
3903         try:
3904             hanat = p[HANATStateSync]
3905         except IndexError:
3906             self.logger.error(ppp("Invalid packet:", p))
3907             raise
3908         else:
3909             self.assertEqual(hanat.sequence_number, 3)
3910             self.assertEqual(hanat.flags, 'ACK')
3911             self.assertEqual(hanat.version, 1)
3912         users = self.vapi.nat44_user_dump()
3913         self.assertEqual(len(users), 1)
3914         self.assertEqual(str(users[0].ip_address),
3915                          self.pg0.remote_ip4)
3916         sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
3917                                                      users[0].vrf_id)
3918         self.assertEqual(len(sessions), 1)
3919         session = sessions[0]
3920         self.assertEqual(session.total_bytes, 1024)
3921         self.assertEqual(session.total_pkts, 2)
3922         stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
3923         self.assertEqual(stats[0][0], 1)
3924
3925         stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
3926         self.assertEqual(stats, 3)
3927
3928         # send packet to test session created by HA
3929         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3930              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3931              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
3932         self.pg1.add_stream(p)
3933         self.pg_enable_capture(self.pg_interfaces)
3934         self.pg_start()
3935         capture = self.pg0.get_capture(1)
3936         p = capture[0]
3937         try:
3938             ip = p[IP]
3939             tcp = p[TCP]
3940         except IndexError:
3941             self.logger.error(ppp("Invalid packet:", p))
3942             raise
3943         else:
3944             self.assertEqual(ip.src, self.pg1.remote_ip4)
3945             self.assertEqual(ip.dst, self.pg0.remote_ip4)
3946             self.assertEqual(tcp.sport, self.tcp_external_port)
3947             self.assertEqual(tcp.dport, self.tcp_port_in)
3948
3949     def show_commands_at_teardown(self):
3950         self.logger.info(self.vapi.cli("show nat44 addresses"))
3951         self.logger.info(self.vapi.cli("show nat44 interfaces"))
3952         self.logger.info(self.vapi.cli("show nat44 static mappings"))
3953         self.logger.info(self.vapi.cli("show nat44 interface address"))
3954         self.logger.info(self.vapi.cli("show nat44 sessions detail"))
3955         self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
3956         self.logger.info(self.vapi.cli("show nat timeouts"))
3957         self.logger.info(
3958             self.vapi.cli("show nat addr-port-assignment-alg"))
3959         self.logger.info(self.vapi.cli("show nat ha"))
3960
3961
3962 class TestNAT44EndpointDependent2(MethodHolder):
3963     """ Endpoint-Dependent mapping and filtering test cases """
3964
3965     @classmethod
3966     def tearDownClass(cls):
3967         super(TestNAT44EndpointDependent2, cls).tearDownClass()
3968
3969     def tearDown(self):
3970         super(TestNAT44EndpointDependent2, self).tearDown()
3971
3972     @classmethod
3973     def create_and_add_ip4_table(cls, i, table_id):
3974         cls.vapi.ip_table_add_del(is_add=1, table={'table_id': table_id})
3975         i.set_table_ip4(table_id)
3976
3977     @classmethod
3978     def setUpClass(cls):
3979         super(TestNAT44EndpointDependent2, cls).setUpClass()
3980
3981         cls.create_pg_interfaces(range(3))
3982         cls.interfaces = list(cls.pg_interfaces)
3983
3984         cls.create_and_add_ip4_table(cls.pg1, 10)
3985
3986         for i in cls.interfaces:
3987             i.admin_up()
3988             i.config_ip4()
3989             i.resolve_arp()
3990
3991             i.generate_remote_hosts(1)
3992             i.configure_ipv4_neighbors()
3993
3994     def setUp(self):
3995         super(TestNAT44EndpointDependent2, self).setUp()
3996         flags = self.nat44_config_flags.NAT44_IS_ENDPOINT_DEPENDENT
3997         self.vapi.nat44_plugin_enable_disable(enable=1, flags=flags)
3998
3999     def tearDown(self):
4000         super(TestNAT44EndpointDependent2, self).tearDown()
4001         if not self.vpp_dead:
4002             self.vapi.nat44_plugin_enable_disable(enable=0)
4003             self.vapi.cli("clear logging")
4004
4005     def nat_add_inside_interface(self, i):
4006         self.vapi.nat44_interface_add_del_feature(
4007             flags=self.config_flags.NAT_IS_INSIDE,
4008             sw_if_index=i.sw_if_index, is_add=1)
4009
4010     def nat_add_outside_interface(self, i):
4011         self.vapi.nat44_interface_add_del_feature(
4012             flags=self.config_flags.NAT_IS_OUTSIDE,
4013             sw_if_index=i.sw_if_index, is_add=1)
4014
4015     def nat_add_interface_address(self, i):
4016         self.nat_addr = i.local_ip4
4017         self.vapi.nat44_add_del_interface_addr(
4018             sw_if_index=i.sw_if_index, is_add=1)
4019
4020     def nat_add_address(self, address, vrf_id=0xFFFFFFFF):
4021         self.nat_addr = address
4022         self.nat44_add_address(address, vrf_id=vrf_id)
4023
4024     def cli(self, command):
4025         result = self.vapi.cli(command)
4026         self.logger.info(result)
4027         # print(result)
4028
4029     def show_configuration(self):
4030         self.cli("show interface")
4031         self.cli("show interface address")
4032         self.cli("show nat44 addresses")
4033         self.cli("show nat44 interfaces")
4034
4035     def create_tcp_stream(self, in_if, out_if, count):
4036         """
4037         Create tcp packet stream
4038
4039         :param in_if: Inside interface
4040         :param out_if: Outside interface
4041         :param count: count of packets to generate
4042         """
4043         pkts = []
4044         port = 6303
4045
4046         for i in range(count):
4047             p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4048                  IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=64) /
4049                  TCP(sport=port + i, dport=20))
4050             pkts.append(p)
4051
4052         return pkts
4053
4054     def test_session_limit_per_vrf(self):
4055
4056         inside = self.pg0
4057         inside_vrf10 = self.pg1
4058         outside = self.pg2
4059
4060         limit = 5
4061
4062         # 2 interfaces pg0, pg1 (vrf10, limit 1 tcp session)
4063         # non existing vrf_id makes process core dump
4064         self.vapi.nat44_set_session_limit(session_limit=limit, vrf_id=10)
4065
4066         self.nat_add_inside_interface(inside)
4067         self.nat_add_inside_interface(inside_vrf10)
4068         self.nat_add_outside_interface(outside)
4069
4070         # vrf independent
4071         self.nat_add_interface_address(outside)
4072
4073         # BUG: causing core dump - when bad vrf_id is specified
4074         # self.nat44_add_address(outside.local_ip4, vrf_id=20)
4075
4076         self.show_configuration()
4077
4078         stream = self.create_tcp_stream(inside_vrf10, outside, limit * 2)
4079         inside_vrf10.add_stream(stream)
4080
4081         self.pg_enable_capture(self.pg_interfaces)
4082         self.pg_start()
4083
4084         capture = outside.get_capture(limit)
4085
4086         stream = self.create_tcp_stream(inside, outside, limit * 2)
4087         inside.add_stream(stream)
4088
4089         self.pg_enable_capture(self.pg_interfaces)
4090         self.pg_start()
4091
4092         capture = outside.get_capture(len(stream))
4093
4094
4095 class TestNAT44EndpointDependent(MethodHolder):
4096     """ Endpoint-Dependent mapping and filtering test cases """
4097
4098     @classmethod
4099     def setUpClass(cls):
4100         super(TestNAT44EndpointDependent, cls).setUpClass()
4101         cls.vapi.cli("set log class nat level debug")
4102
4103         cls.tcp_port_in = 6303
4104         cls.tcp_port_out = 6303
4105         cls.udp_port_in = 6304
4106         cls.udp_port_out = 6304
4107         cls.icmp_id_in = 6305
4108         cls.icmp_id_out = 6305
4109         cls.nat_addr = '10.0.0.3'
4110         cls.ipfix_src_port = 4739
4111         cls.ipfix_domain_id = 1
4112         cls.tcp_external_port = 80
4113
4114         cls.create_pg_interfaces(range(9))
4115         cls.interfaces = list(cls.pg_interfaces[0:3])
4116
4117         for i in cls.interfaces:
4118             i.admin_up()
4119             i.config_ip4()
4120             i.resolve_arp()
4121
4122         cls.pg0.generate_remote_hosts(3)
4123         cls.pg0.configure_ipv4_neighbors()
4124
4125         cls.pg3.admin_up()
4126
4127         cls.pg4.generate_remote_hosts(2)
4128         cls.pg4.config_ip4()
4129         cls.vapi.sw_interface_add_del_address(
4130             sw_if_index=cls.pg4.sw_if_index,
4131             prefix="10.0.0.1/24")
4132
4133         cls.pg4.admin_up()
4134         cls.pg4.resolve_arp()
4135         cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4136         cls.pg4.resolve_arp()
4137
4138         zero_ip4 = socket.inet_pton(socket.AF_INET, "0.0.0.0")
4139         cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 1})
4140
4141         cls.pg5._local_ip4 = "10.1.1.1"
4142         cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4143         cls.pg5.set_table_ip4(1)
4144         cls.pg5.config_ip4()
4145         cls.pg5.admin_up()
4146         r1 = VppIpRoute(cls, cls.pg5.remote_ip4, 32,
4147                         [VppRoutePath("0.0.0.0",
4148                                       cls.pg5.sw_if_index)],
4149                         table_id=1,
4150                         register=False)
4151         r1.add_vpp_config()
4152
4153         cls.pg6._local_ip4 = "10.1.2.1"
4154         cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4155         cls.pg6.set_table_ip4(1)
4156         cls.pg6.config_ip4()
4157         cls.pg6.admin_up()
4158
4159         r2 = VppIpRoute(cls, cls.pg6.remote_ip4, 32,
4160                         [VppRoutePath("0.0.0.0",
4161                                       cls.pg6.sw_if_index)],
4162                         table_id=1,
4163                         register=False)
4164         r3 = VppIpRoute(cls, cls.pg6.remote_ip4, 16,
4165                         [VppRoutePath("0.0.0.0",
4166                                       0xffffffff,
4167                                       nh_table_id=1)],
4168                         table_id=0,
4169                         register=False)
4170         r4 = VppIpRoute(cls, "0.0.0.0", 0,
4171                         [VppRoutePath("0.0.0.0", 0xffffffff,
4172                                       nh_table_id=0)],
4173                         table_id=1,
4174                         register=False)
4175         r5 = VppIpRoute(cls, "0.0.0.0", 0,
4176                         [VppRoutePath(cls.pg1.local_ip4,
4177                                       cls.pg1.sw_if_index)],
4178                         register=False)
4179         r2.add_vpp_config()
4180         r3.add_vpp_config()
4181         r4.add_vpp_config()
4182         r5.add_vpp_config()
4183
4184         cls.pg5.resolve_arp()
4185         cls.pg6.resolve_arp()
4186
4187         cls.pg7.admin_up()
4188         cls.pg7.config_ip4()
4189         cls.pg7.resolve_arp()
4190         cls.pg7.generate_remote_hosts(3)
4191         cls.pg7.configure_ipv4_neighbors()
4192
4193         cls.pg8.admin_up()
4194         cls.pg8.config_ip4()
4195         cls.pg8.resolve_arp()
4196
4197     @classmethod
4198     def tearDownClass(cls):
4199         super(TestNAT44EndpointDependent, cls).tearDownClass()
4200
4201     def setUp(self):
4202         super(TestNAT44EndpointDependent, self).setUp()
4203         flags = self.nat44_config_flags.NAT44_IS_ENDPOINT_DEPENDENT
4204         self.vapi.nat44_plugin_enable_disable(enable=1, flags=flags)
4205         self.vapi.nat_set_timeouts(
4206             udp=300, tcp_established=7440,
4207             tcp_transitory=240, icmp=60)
4208
4209     def tearDown(self):
4210         super(TestNAT44EndpointDependent, self).tearDown()
4211         if not self.vpp_dead:
4212             self.vapi.nat44_plugin_enable_disable(enable=0)
4213             self.vapi.cli("clear logging")
4214
4215     def test_frag_in_order(self):
4216         """ NAT44 translate fragments arriving in order """
4217         self.nat44_add_address(self.nat_addr)
4218         flags = self.config_flags.NAT_IS_INSIDE
4219         self.vapi.nat44_interface_add_del_feature(
4220             sw_if_index=self.pg0.sw_if_index,
4221             flags=flags, is_add=1)
4222         self.vapi.nat44_interface_add_del_feature(
4223             sw_if_index=self.pg1.sw_if_index,
4224             is_add=1)
4225         self.frag_in_order(proto=IP_PROTOS.tcp, ignore_port=True)
4226         self.frag_in_order(proto=IP_PROTOS.udp, ignore_port=True)
4227         self.frag_in_order(proto=IP_PROTOS.icmp, ignore_port=True)
4228
4229     def test_frag_in_order_dont_translate(self):
4230         """ NAT44 don't translate fragments arriving in order """
4231         flags = self.config_flags.NAT_IS_INSIDE
4232         self.vapi.nat44_interface_add_del_feature(
4233             sw_if_index=self.pg0.sw_if_index,
4234             flags=flags, is_add=1)
4235         self.vapi.nat44_interface_add_del_feature(
4236             sw_if_index=self.pg1.sw_if_index,
4237             is_add=1)
4238         self.vapi.nat44_forwarding_enable_disable(enable=True)
4239         self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4240
4241     def test_frag_out_of_order(self):
4242         """ NAT44 translate fragments arriving out of order """
4243         self.nat44_add_address(self.nat_addr)
4244         flags = self.config_flags.NAT_IS_INSIDE
4245         self.vapi.nat44_interface_add_del_feature(
4246             sw_if_index=self.pg0.sw_if_index,
4247             flags=flags, is_add=1)
4248         self.vapi.nat44_interface_add_del_feature(
4249             sw_if_index=self.pg1.sw_if_index,
4250             is_add=1)
4251         self.frag_out_of_order(proto=IP_PROTOS.tcp, ignore_port=True)
4252         self.frag_out_of_order(proto=IP_PROTOS.udp, ignore_port=True)
4253         self.frag_out_of_order(proto=IP_PROTOS.icmp, ignore_port=True)
4254
4255     def test_frag_out_of_order_dont_translate(self):
4256         """ NAT44 don't translate fragments arriving out of order """
4257         flags = self.config_flags.NAT_IS_INSIDE
4258         self.vapi.nat44_interface_add_del_feature(
4259             sw_if_index=self.pg0.sw_if_index,
4260             flags=flags, is_add=1)
4261         self.vapi.nat44_interface_add_del_feature(
4262             sw_if_index=self.pg1.sw_if_index,
4263             is_add=1)
4264         self.vapi.nat44_forwarding_enable_disable(enable=True)
4265         self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4266
4267     def test_frag_in_order_in_plus_out(self):
4268         """ in+out interface fragments in order """
4269         flags = self.config_flags.NAT_IS_INSIDE
4270         self.vapi.nat44_interface_add_del_feature(
4271             sw_if_index=self.pg0.sw_if_index,
4272             is_add=1)
4273         self.vapi.nat44_interface_add_del_feature(
4274             sw_if_index=self.pg0.sw_if_index,
4275             flags=flags, is_add=1)
4276         self.vapi.nat44_interface_add_del_feature(
4277             sw_if_index=self.pg1.sw_if_index,
4278             is_add=1)
4279         self.vapi.nat44_interface_add_del_feature(
4280             sw_if_index=self.pg1.sw_if_index,
4281             flags=flags, is_add=1)
4282
4283         self.server = self.pg1.remote_hosts[0]
4284
4285         self.server_in_addr = self.server.ip4
4286         self.server_out_addr = '11.11.11.11'
4287         self.server_in_port = random.randint(1025, 65535)
4288         self.server_out_port = random.randint(1025, 65535)
4289
4290         self.nat44_add_address(self.server_out_addr)
4291
4292         # add static mappings for server
4293         self.nat44_add_static_mapping(self.server_in_addr,
4294                                       self.server_out_addr,
4295                                       self.server_in_port,
4296                                       self.server_out_port,
4297                                       proto=IP_PROTOS.tcp)
4298         self.nat44_add_static_mapping(self.server_in_addr,
4299                                       self.server_out_addr,
4300                                       self.server_in_port,
4301                                       self.server_out_port,
4302                                       proto=IP_PROTOS.udp)
4303         self.nat44_add_static_mapping(self.server_in_addr,
4304                                       self.server_out_addr,
4305                                       proto=IP_PROTOS.icmp)
4306
4307         self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4308         self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4309         self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4310
4311     def test_frag_out_of_order_in_plus_out(self):
4312         """ in+out interface fragments out of order """
4313         flags = self.config_flags.NAT_IS_INSIDE
4314         self.vapi.nat44_interface_add_del_feature(
4315             sw_if_index=self.pg0.sw_if_index,
4316             is_add=1)
4317         self.vapi.nat44_interface_add_del_feature(
4318             sw_if_index=self.pg0.sw_if_index,
4319             flags=flags, is_add=1)
4320         self.vapi.nat44_interface_add_del_feature(
4321             sw_if_index=self.pg1.sw_if_index,
4322             is_add=1)
4323         self.vapi.nat44_interface_add_del_feature(
4324             sw_if_index=self.pg1.sw_if_index,
4325             flags=flags, is_add=1)
4326
4327         self.server = self.pg1.remote_hosts[0]
4328
4329         self.server_in_addr = self.server.ip4
4330         self.server_out_addr = '11.11.11.11'
4331         self.server_in_port = random.randint(1025, 65535)
4332         self.server_out_port = random.randint(1025, 65535)
4333
4334         self.nat44_add_address(self.server_out_addr)
4335
4336         # add static mappings for server
4337         self.nat44_add_static_mapping(self.server_in_addr,
4338                                       self.server_out_addr,
4339                                       self.server_in_port,
4340                                       self.server_out_port,
4341                                       proto=IP_PROTOS.tcp)
4342         self.nat44_add_static_mapping(self.server_in_addr,
4343                                       self.server_out_addr,
4344                                       self.server_in_port,
4345                                       self.server_out_port,
4346                                       proto=IP_PROTOS.udp)
4347         self.nat44_add_static_mapping(self.server_in_addr,
4348                                       self.server_out_addr,
4349                                       proto=IP_PROTOS.icmp)
4350
4351         self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4352         self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4353         self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4354
4355     def test_reass_hairpinning(self):
4356         """ NAT44 fragments hairpinning """
4357         self.server = self.pg0.remote_hosts[1]
4358         self.host_in_port = random.randint(1025, 65535)
4359         self.server_in_port = random.randint(1025, 65535)
4360         self.server_out_port = random.randint(1025, 65535)
4361
4362         self.nat44_add_address(self.nat_addr)
4363         flags = self.config_flags.NAT_IS_INSIDE
4364         self.vapi.nat44_interface_add_del_feature(
4365             sw_if_index=self.pg0.sw_if_index,
4366             flags=flags, is_add=1)
4367         self.vapi.nat44_interface_add_del_feature(
4368             sw_if_index=self.pg1.sw_if_index,
4369             is_add=1)
4370         # add static mapping for server
4371         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4372                                       self.server_in_port,
4373                                       self.server_out_port,
4374                                       proto=IP_PROTOS.tcp)
4375         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4376                                       self.server_in_port,
4377                                       self.server_out_port,
4378                                       proto=IP_PROTOS.udp)
4379         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
4380
4381         self.reass_hairpinning(proto=IP_PROTOS.tcp, ignore_port=True)
4382         self.reass_hairpinning(proto=IP_PROTOS.udp, ignore_port=True)
4383         self.reass_hairpinning(proto=IP_PROTOS.icmp, ignore_port=True)
4384
4385     def test_clear_sessions(self):
4386         """ NAT44 ED session clearing test """
4387
4388         self.nat44_add_address(self.nat_addr)
4389         flags = self.config_flags.NAT_IS_INSIDE
4390         self.vapi.nat44_interface_add_del_feature(
4391             sw_if_index=self.pg0.sw_if_index,
4392             flags=flags, is_add=1)
4393         self.vapi.nat44_interface_add_del_feature(
4394             sw_if_index=self.pg1.sw_if_index,
4395             is_add=1)
4396
4397         nat_config = self.vapi.nat_show_config()
4398         self.assertEqual(1, nat_config.endpoint_dependent)
4399
4400         pkts = self.create_stream_in(self.pg0, self.pg1)
4401         self.pg0.add_stream(pkts)
4402         self.pg_enable_capture(self.pg_interfaces)
4403         self.pg_start()
4404         capture = self.pg1.get_capture(len(pkts))
4405         self.verify_capture_out(capture, ignore_port=True)
4406
4407         sessions = self.statistics.get_counter('/nat44/total-sessions')
4408         self.assertTrue(sessions[0][0] > 0)
4409         self.logger.info("sessions before clearing: %s" % sessions[0][0])
4410
4411         # just for testing purposes
4412         self.logger.info(self.vapi.cli("show nat44 summary"))
4413
4414         self.vapi.cli("clear nat44 sessions")
4415
4416         self.logger.info(self.vapi.cli("show nat44 summary"))
4417
4418         sessions = self.statistics.get_counter('/nat44/total-sessions')
4419         self.assertEqual(sessions[0][0], 0)
4420         self.logger.info("sessions after clearing: %s" % sessions[0][0])
4421
4422     def test_dynamic(self):
4423         """ NAT44 dynamic translation test """
4424
4425         self.nat44_add_address(self.nat_addr)
4426         flags = self.config_flags.NAT_IS_INSIDE
4427         self.vapi.nat44_interface_add_del_feature(
4428             sw_if_index=self.pg0.sw_if_index,
4429             flags=flags, is_add=1)
4430         self.vapi.nat44_interface_add_del_feature(
4431             sw_if_index=self.pg1.sw_if_index,
4432             is_add=1)
4433
4434         nat_config = self.vapi.nat_show_config()
4435         self.assertEqual(1, nat_config.endpoint_dependent)
4436
4437         # in2out
4438         tcpn = self.statistics.get_counter('/nat44/ed/in2out/slowpath/tcp')[0]
4439         udpn = self.statistics.get_counter('/nat44/ed/in2out/slowpath/udp')[0]
4440         icmpn = self.statistics.get_counter(
4441             '/nat44/ed/in2out/slowpath/icmp')[0]
4442         drops = self.statistics.get_counter(
4443             '/nat44/ed/in2out/slowpath/drops')[0]
4444
4445         pkts = self.create_stream_in(self.pg0, self.pg1)
4446         self.pg0.add_stream(pkts)
4447         self.pg_enable_capture(self.pg_interfaces)
4448         self.pg_start()
4449         capture = self.pg1.get_capture(len(pkts))
4450         self.verify_capture_out(capture, ignore_port=True)
4451
4452         if_idx = self.pg0.sw_if_index
4453         cnt = self.statistics.get_counter('/nat44/ed/in2out/slowpath/tcp')[0]
4454         self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
4455         cnt = self.statistics.get_counter('/nat44/ed/in2out/slowpath/udp')[0]
4456         self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
4457         cnt = self.statistics.get_counter('/nat44/ed/in2out/slowpath/icmp')[0]
4458         self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
4459         cnt = self.statistics.get_counter('/nat44/ed/in2out/slowpath/drops')[0]
4460         self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
4461
4462         # out2in
4463         tcpn = self.statistics.get_counter('/nat44/ed/out2in/fastpath/tcp')[0]
4464         udpn = self.statistics.get_counter('/nat44/ed/out2in/fastpath/udp')[0]
4465         icmpn = self.statistics.get_counter(
4466             '/nat44/ed/out2in/slowpath/icmp')[0]
4467         drops = self.statistics.get_counter(
4468             '/nat44/ed/out2in/fastpath/drops')[0]
4469
4470         pkts = self.create_stream_out(self.pg1)
4471         self.pg1.add_stream(pkts)
4472         self.pg_enable_capture(self.pg_interfaces)
4473         self.pg_start()
4474         capture = self.pg0.get_capture(len(pkts))
4475         self.verify_capture_in(capture, self.pg0)
4476
4477         if_idx = self.pg1.sw_if_index
4478         cnt = self.statistics.get_counter('/nat44/ed/out2in/fastpath/tcp')[0]
4479         self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
4480         cnt = self.statistics.get_counter('/nat44/ed/out2in/fastpath/udp')[0]
4481         self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
4482         cnt = self.statistics.get_counter('/nat44/ed/out2in/slowpath/icmp')[0]
4483         self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
4484         cnt = self.statistics.get_counter('/nat44/ed/out2in/fastpath/drops')[0]
4485         self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
4486
4487         sessions = self.statistics.get_counter('/nat44/total-sessions')
4488         self.assertEqual(sessions[0][0], 3)
4489
4490     def test_dynamic_out_of_ports(self):
4491         """ NAT44 dynamic translation test: out of ports """
4492
4493         flags = self.config_flags.NAT_IS_INSIDE
4494         self.vapi.nat44_interface_add_del_feature(
4495             sw_if_index=self.pg0.sw_if_index,
4496             flags=flags, is_add=1)
4497         self.vapi.nat44_interface_add_del_feature(
4498             sw_if_index=self.pg1.sw_if_index,
4499             is_add=1)
4500
4501         nat_config = self.vapi.nat_show_config()
4502         self.assertEqual(1, nat_config.endpoint_dependent)
4503
4504         # in2out and no NAT addresses added
4505         err_old = self.statistics.get_err_counter(
4506             '/err/nat44-ed-in2out-slowpath/out of ports')
4507
4508         pkts = self.create_stream_in(self.pg0, self.pg1)
4509         self.pg0.add_stream(pkts)
4510         self.pg_enable_capture(self.pg_interfaces)
4511         self.pg_start()
4512         self.pg1.get_capture(0, timeout=1)
4513
4514         err_new = self.statistics.get_err_counter(
4515             '/err/nat44-ed-in2out-slowpath/out of ports')
4516
4517         self.assertEqual(err_new - err_old, len(pkts))
4518
4519         # in2out after NAT addresses added
4520         self.nat44_add_address(self.nat_addr)
4521
4522         err_old = self.statistics.get_err_counter(
4523             '/err/nat44-ed-in2out-slowpath/out of ports')
4524
4525         pkts = self.create_stream_in(self.pg0, self.pg1)
4526         self.pg0.add_stream(pkts)
4527         self.pg_enable_capture(self.pg_interfaces)
4528         self.pg_start()
4529         capture = self.pg1.get_capture(len(pkts))
4530         self.verify_capture_out(capture, ignore_port=True)
4531
4532         err_new = self.statistics.get_err_counter(
4533             '/err/nat44-ed-in2out-slowpath/out of ports')
4534
4535         self.assertEqual(err_new, err_old)
4536
4537     def test_dynamic_output_feature_vrf(self):
4538         """ NAT44 dynamic translation test: output-feature, VRF"""
4539
4540         # other then default (0)
4541         new_vrf_id = 22
4542
4543         self.nat44_add_address(self.nat_addr)
4544         flags = self.config_flags.NAT_IS_INSIDE
4545         self.vapi.nat44_interface_add_del_output_feature(
4546             sw_if_index=self.pg7.sw_if_index,
4547             flags=flags, is_add=1)
4548         self.vapi.nat44_interface_add_del_output_feature(
4549             sw_if_index=self.pg8.sw_if_index,
4550             is_add=1)
4551
4552         try:
4553             self.vapi.ip_table_add_del(is_add=1,
4554                                        table={'table_id': new_vrf_id})
4555
4556             self.pg7.unconfig_ip4()
4557             self.pg7.set_table_ip4(new_vrf_id)
4558             self.pg7.config_ip4()
4559             self.pg7.resolve_arp()
4560
4561             self.pg8.unconfig_ip4()
4562             self.pg8.set_table_ip4(new_vrf_id)
4563             self.pg8.config_ip4()
4564             self.pg8.resolve_arp()
4565
4566             nat_config = self.vapi.nat_show_config()
4567             self.assertEqual(1, nat_config.endpoint_dependent)
4568
4569             # in2out
4570             tcpn = self.statistics.get_counter(
4571                 '/nat44/ed/in2out/slowpath/tcp')[0]
4572             udpn = self.statistics.get_counter(
4573                 '/nat44/ed/in2out/slowpath/udp')[0]
4574             icmpn = self.statistics.get_counter(
4575                 '/nat44/ed/in2out/slowpath/icmp')[0]
4576             drops = self.statistics.get_counter(
4577                 '/nat44/ed/in2out/slowpath/drops')[0]
4578
4579             pkts = self.create_stream_in(self.pg7, self.pg8)
4580             self.pg7.add_stream(pkts)
4581             self.pg_enable_capture(self.pg_interfaces)
4582             self.pg_start()
4583             capture = self.pg8.get_capture(len(pkts))
4584             self.verify_capture_out(capture, ignore_port=True)
4585
4586             if_idx = self.pg7.sw_if_index
4587             cnt = self.statistics.get_counter(
4588                 '/nat44/ed/in2out/slowpath/tcp')[0]
4589             self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
4590             cnt = self.statistics.get_counter(
4591                 '/nat44/ed/in2out/slowpath/udp')[0]
4592             self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
4593             cnt = self.statistics.get_counter(
4594                 '/nat44/ed/in2out/slowpath/icmp')[0]
4595             self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
4596             cnt = self.statistics.get_counter(
4597                 '/nat44/ed/in2out/slowpath/drops')[0]
4598             self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
4599
4600             # out2in
4601             tcpn = self.statistics.get_counter(
4602                 '/nat44/ed/out2in/fastpath/tcp')[0]
4603             udpn = self.statistics.get_counter(
4604                 '/nat44/ed/out2in/fastpath/udp')[0]
4605             icmpn = self.statistics.get_counter(
4606                 '/nat44/ed/out2in/slowpath/icmp')[0]
4607             drops = self.statistics.get_counter(
4608                 '/nat44/ed/out2in/fastpath/drops')[0]
4609
4610             pkts = self.create_stream_out(self.pg8)
4611             self.pg8.add_stream(pkts)
4612             self.pg_enable_capture(self.pg_interfaces)
4613             self.pg_start()
4614             capture = self.pg7.get_capture(len(pkts))
4615             self.verify_capture_in(capture, self.pg7)
4616
4617             if_idx = self.pg8.sw_if_index
4618             cnt = self.statistics.get_counter(
4619                 '/nat44/ed/out2in/fastpath/tcp')[0]
4620             self.assertEqual(cnt[if_idx] - tcpn[if_idx], 2)
4621             cnt = self.statistics.get_counter(
4622                 '/nat44/ed/out2in/fastpath/udp')[0]
4623             self.assertEqual(cnt[if_idx] - udpn[if_idx], 1)
4624             cnt = self.statistics.get_counter(
4625                 '/nat44/ed/out2in/slowpath/icmp')[0]
4626             self.assertEqual(cnt[if_idx] - icmpn[if_idx], 1)
4627             cnt = self.statistics.get_counter(
4628                 '/nat44/ed/out2in/fastpath/drops')[0]
4629             self.assertEqual(cnt[if_idx] - drops[if_idx], 0)
4630
4631             sessions = self.statistics.get_counter('/nat44/total-sessions')
4632             self.assertEqual(sessions[0][0], 3)
4633
4634         finally:
4635             self.pg7.unconfig_ip4()
4636             self.pg7.set_table_ip4(1)
4637             self.pg7.config_ip4()
4638             self.pg7.resolve_arp()
4639
4640             self.pg8.unconfig_ip4()
4641             self.pg8.set_table_ip4(1)
4642             self.pg8.config_ip4()
4643             self.pg8.resolve_arp()
4644
4645             self.vapi.ip_table_add_del(is_add=0,
4646                                        table={'table_id': new_vrf_id})
4647
4648     def test_forwarding(self):
4649         """ NAT44 forwarding test """
4650
4651         flags = self.config_flags.NAT_IS_INSIDE
4652         self.vapi.nat44_interface_add_del_feature(
4653             sw_if_index=self.pg0.sw_if_index,
4654             flags=flags, is_add=1)
4655         self.vapi.nat44_interface_add_del_feature(
4656             sw_if_index=self.pg1.sw_if_index,
4657             is_add=1)
4658         self.vapi.nat44_forwarding_enable_disable(enable=1)
4659
4660         real_ip = self.pg0.remote_ip4
4661         alias_ip = self.nat_addr
4662         flags = self.config_flags.NAT_IS_ADDR_ONLY
4663         self.vapi.nat44_add_del_static_mapping(is_add=1,
4664                                                local_ip_address=real_ip,
4665                                                external_ip_address=alias_ip,
4666                                                external_sw_if_index=0xFFFFFFFF,
4667                                                flags=flags)
4668
4669         try:
4670             # in2out - static mapping match
4671
4672             pkts = self.create_stream_out(self.pg1)
4673             self.pg1.add_stream(pkts)
4674             self.pg_enable_capture(self.pg_interfaces)
4675             self.pg_start()
4676             capture = self.pg0.get_capture(len(pkts))
4677             self.verify_capture_in(capture, self.pg0)
4678
4679             pkts = self.create_stream_in(self.pg0, self.pg1)
4680             self.pg0.add_stream(pkts)
4681             self.pg_enable_capture(self.pg_interfaces)
4682             self.pg_start()
4683             capture = self.pg1.get_capture(len(pkts))
4684             self.verify_capture_out(capture, same_port=True)
4685
4686             # in2out - no static mapping match
4687
4688             host0 = self.pg0.remote_hosts[0]
4689             self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4690             try:
4691                 pkts = self.create_stream_out(self.pg1,
4692                                               dst_ip=self.pg0.remote_ip4,
4693                                               use_inside_ports=True)
4694                 self.pg1.add_stream(pkts)
4695                 self.pg_enable_capture(self.pg_interfaces)
4696                 self.pg_start()
4697                 capture = self.pg0.get_capture(len(pkts))
4698                 self.verify_capture_in(capture, self.pg0)
4699
4700                 pkts = self.create_stream_in(self.pg0, self.pg1)
4701                 self.pg0.add_stream(pkts)
4702                 self.pg_enable_capture(self.pg_interfaces)
4703                 self.pg_start()
4704                 capture = self.pg1.get_capture(len(pkts))
4705                 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4706                                         same_port=True)
4707             finally:
4708                 self.pg0.remote_hosts[0] = host0
4709
4710             user = self.pg0.remote_hosts[1]
4711             sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4712             self.assertEqual(len(sessions), 3)
4713             self.assertTrue(sessions[0].flags &
4714                             self.config_flags.NAT_IS_EXT_HOST_VALID)
4715             self.vapi.nat44_del_session(
4716                 address=sessions[0].inside_ip_address,
4717                 port=sessions[0].inside_port,
4718                 protocol=sessions[0].protocol,
4719                 flags=(self.config_flags.NAT_IS_INSIDE |
4720                        self.config_flags.NAT_IS_EXT_HOST_VALID),
4721                 ext_host_address=sessions[0].ext_host_address,
4722                 ext_host_port=sessions[0].ext_host_port)
4723             sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4724             self.assertEqual(len(sessions), 2)
4725
4726         finally:
4727             self.vapi.nat44_forwarding_enable_disable(enable=0)
4728             flags = self.config_flags.NAT_IS_ADDR_ONLY
4729             self.vapi.nat44_add_del_static_mapping(
4730                 is_add=0,
4731                 local_ip_address=real_ip,
4732                 external_ip_address=alias_ip,
4733                 external_sw_if_index=0xFFFFFFFF,
4734                 flags=flags)
4735
4736     def test_static_lb(self):
4737         """ NAT44 local service load balancing """
4738         external_addr_n = self.nat_addr
4739         external_port = 80
4740         local_port = 8080
4741         server1 = self.pg0.remote_hosts[0]
4742         server2 = self.pg0.remote_hosts[1]
4743
4744         locals = [{'addr': server1.ip4,
4745                    'port': local_port,
4746                    'probability': 70,
4747                    'vrf_id': 0},
4748                   {'addr': server2.ip4,
4749                    'port': local_port,
4750                    'probability': 30,
4751                    'vrf_id': 0}]
4752
4753         self.nat44_add_address(self.nat_addr)
4754         self.vapi.nat44_add_del_lb_static_mapping(
4755             is_add=1,
4756             external_addr=external_addr_n,
4757             external_port=external_port,
4758             protocol=IP_PROTOS.tcp,
4759             local_num=len(locals),
4760             locals=locals)
4761         flags = self.config_flags.NAT_IS_INSIDE
4762         self.vapi.nat44_interface_add_del_feature(
4763             sw_if_index=self.pg0.sw_if_index,
4764             flags=flags, is_add=1)
4765         self.vapi.nat44_interface_add_del_feature(
4766             sw_if_index=self.pg1.sw_if_index,
4767             is_add=1)
4768
4769         # from client to service
4770         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4771              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4772              TCP(sport=12345, dport=external_port))
4773         self.pg1.add_stream(p)
4774         self.pg_enable_capture(self.pg_interfaces)
4775         self.pg_start()
4776         capture = self.pg0.get_capture(1)
4777         p = capture[0]
4778         server = None
4779         try:
4780             ip = p[IP]
4781             tcp = p[TCP]
4782             self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4783             if ip.dst == server1.ip4:
4784                 server = server1
4785             else:
4786                 server = server2
4787             self.assertEqual(tcp.dport, local_port)
4788             self.assert_packet_checksums_valid(p)
4789         except:
4790             self.logger.error(ppp("Unexpected or invalid packet:", p))
4791             raise
4792
4793         # from service back to client
4794         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4795              IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4796              TCP(sport=local_port, dport=12345))
4797         self.pg0.add_stream(p)
4798         self.pg_enable_capture(self.pg_interfaces)
4799         self.pg_start()
4800         capture = self.pg1.get_capture(1)
4801         p = capture[0]
4802         try:
4803             ip = p[IP]
4804             tcp = p[TCP]
4805             self.assertEqual(ip.src, self.nat_addr)
4806             self.assertEqual(tcp.sport, external_port)
4807             self.assert_packet_checksums_valid(p)
4808         except:
4809             self.logger.error(ppp("Unexpected or invalid packet:", p))
4810             raise
4811
4812         sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
4813         self.assertEqual(len(sessions), 1)
4814         self.assertTrue(sessions[0].flags &
4815                         self.config_flags.NAT_IS_EXT_HOST_VALID)
4816         self.vapi.nat44_del_session(
4817             address=sessions[0].inside_ip_address,
4818             port=sessions[0].inside_port,
4819             protocol=sessions[0].protocol,
4820             flags=(self.config_flags.NAT_IS_INSIDE |
4821                    self.config_flags.NAT_IS_EXT_HOST_VALID),
4822             ext_host_address=sessions[0].ext_host_address,
4823             ext_host_port=sessions[0].ext_host_port)
4824         sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
4825         self.assertEqual(len(sessions), 0)
4826
4827     def test_static_lb_multi_clients(self):
4828         """ NAT44 local service load balancing - multiple clients"""
4829
4830         external_addr = self.nat_addr
4831         external_port = 80
4832         local_port = 8080
4833         server1 = self.pg0.remote_hosts[0]
4834         server2 = self.pg0.remote_hosts[1]
4835         server3 = self.pg0.remote_hosts[2]
4836
4837         locals = [{'addr': server1.ip4,
4838                    'port': local_port,
4839                    'probability': 90,
4840                    'vrf_id': 0},
4841                   {'addr': server2.ip4,
4842                    'port': local_port,
4843                    'probability': 10,
4844                    'vrf_id': 0}]
4845
4846         flags = self.config_flags.NAT_IS_INSIDE
4847         self.vapi.nat44_interface_add_del_feature(
4848             sw_if_index=self.pg0.sw_if_index,
4849             flags=flags, is_add=1)
4850         self.vapi.nat44_interface_add_del_feature(
4851             sw_if_index=self.pg1.sw_if_index,
4852             is_add=1)
4853
4854         self.nat44_add_address(self.nat_addr)
4855         self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
4856                                                   external_addr=external_addr,
4857                                                   external_port=external_port,
4858                                                   protocol=IP_PROTOS.tcp,
4859                                                   local_num=len(locals),
4860                                                   locals=locals)
4861
4862         server1_n = 0
4863         server2_n = 0
4864         clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4865         pkts = []
4866         for client in clients:
4867             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4868                  IP(src=client, dst=self.nat_addr) /
4869                  TCP(sport=12345, dport=external_port))
4870             pkts.append(p)
4871         self.pg1.add_stream(pkts)
4872         self.pg_enable_capture(self.pg_interfaces)
4873         self.pg_start()
4874         capture = self.pg0.get_capture(len(pkts))
4875         for p in capture:
4876             if p[IP].dst == server1.ip4:
4877                 server1_n += 1
4878             else:
4879                 server2_n += 1
4880         self.assertGreater(server1_n, server2_n)
4881
4882         local = {
4883             'addr': server3.ip4,
4884             'port': local_port,
4885             'probability': 20,
4886             'vrf_id': 0
4887         }
4888
4889         # add new back-end
4890         self.vapi.nat44_lb_static_mapping_add_del_local(
4891             is_add=1,
4892             external_addr=external_addr,
4893             external_port=external_port,
4894             local=local,
4895             protocol=IP_PROTOS.tcp)
4896         server1_n = 0
4897         server2_n = 0
4898         server3_n = 0
4899         clients = ip4_range(self.pg1.remote_ip4, 60, 110)
4900         pkts = []
4901         for client in clients:
4902             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4903                  IP(src=client, dst=self.nat_addr) /
4904                  TCP(sport=12346, dport=external_port))
4905             pkts.append(p)
4906         self.assertGreater(len(pkts), 0)
4907         self.pg1.add_stream(pkts)
4908         self.pg_enable_capture(self.pg_interfaces)
4909         self.pg_start()
4910         capture = self.pg0.get_capture(len(pkts))
4911         for p in capture:
4912             if p[IP].dst == server1.ip4:
4913                 server1_n += 1
4914             elif p[IP].dst == server2.ip4:
4915                 server2_n += 1
4916             else:
4917                 server3_n += 1
4918         self.assertGreater(server1_n, 0)
4919         self.assertGreater(server2_n, 0)
4920         self.assertGreater(server3_n, 0)
4921
4922         local = {
4923             'addr': server2.ip4,
4924             'port': local_port,
4925             'probability': 10,
4926             'vrf_id': 0
4927         }
4928
4929         # remove one back-end
4930         self.vapi.nat44_lb_static_mapping_add_del_local(
4931             is_add=0,
4932             external_addr=external_addr,
4933             external_port=external_port,
4934             local=local,
4935             protocol=IP_PROTOS.tcp)
4936         server1_n = 0
4937         server2_n = 0
4938         server3_n = 0
4939         self.pg1.add_stream(pkts)
4940         self.pg_enable_capture(self.pg_interfaces)
4941         self.pg_start()
4942         capture = self.pg0.get_capture(len(pkts))
4943         for p in capture:
4944             if p[IP].dst == server1.ip4:
4945                 server1_n += 1
4946             elif p[IP].dst == server2.ip4:
4947                 server2_n += 1
4948             else:
4949                 server3_n += 1
4950         self.assertGreater(server1_n, 0)
4951         self.assertEqual(server2_n, 0)
4952         self.assertGreater(server3_n, 0)
4953
4954     def test_static_lb_2(self):
4955         """ NAT44 local service load balancing (asymmetrical rule) """
4956         external_addr = self.nat_addr
4957         external_port = 80
4958         local_port = 8080
4959         server1 = self.pg0.remote_hosts[0]
4960         server2 = self.pg0.remote_hosts[1]
4961
4962         locals = [{'addr': server1.ip4,
4963                    'port': local_port,
4964                    'probability': 70,
4965                    'vrf_id': 0},
4966                   {'addr': server2.ip4,
4967                    'port': local_port,
4968                    'probability': 30,
4969                    'vrf_id': 0}]
4970
4971         self.vapi.nat44_forwarding_enable_disable(enable=1)
4972         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
4973         self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
4974                                                   external_addr=external_addr,
4975                                                   external_port=external_port,
4976                                                   protocol=IP_PROTOS.tcp,
4977                                                   local_num=len(locals),
4978                                                   locals=locals)
4979         flags = self.config_flags.NAT_IS_INSIDE
4980         self.vapi.nat44_interface_add_del_feature(
4981             sw_if_index=self.pg0.sw_if_index,
4982             flags=flags, is_add=1)
4983         self.vapi.nat44_interface_add_del_feature(
4984             sw_if_index=self.pg1.sw_if_index,
4985             is_add=1)
4986
4987         # from client to service
4988         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4989              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4990              TCP(sport=12345, dport=external_port))
4991         self.pg1.add_stream(p)
4992         self.pg_enable_capture(self.pg_interfaces)
4993         self.pg_start()
4994         capture = self.pg0.get_capture(1)
4995         p = capture[0]
4996         server = None
4997         try:
4998             ip = p[IP]
4999             tcp = p[TCP]
5000             self.assertIn(ip.dst, [server1.ip4, server2.ip4])
5001             if ip.dst == server1.ip4:
5002                 server = server1
5003             else:
5004                 server = server2
5005             self.assertEqual(tcp.dport, local_port)
5006             self.assert_packet_checksums_valid(p)
5007         except:
5008             self.logger.error(ppp("Unexpected or invalid packet:", p))
5009             raise
5010
5011         # from service back to client
5012         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
5013              IP(src=server.ip4, dst=self.pg1.remote_ip4) /
5014              TCP(sport=local_port, dport=12345))
5015         self.pg0.add_stream(p)
5016         self.pg_enable_capture(self.pg_interfaces)
5017         self.pg_start()
5018         capture = self.pg1.get_capture(1)
5019         p = capture[0]
5020         try:
5021             ip = p[IP]
5022             tcp = p[TCP]
5023             self.assertEqual(ip.src, self.nat_addr)
5024             self.assertEqual(tcp.sport, external_port)
5025             self.assert_packet_checksums_valid(p)
5026         except:
5027             self.logger.error(ppp("Unexpected or invalid packet:", p))
5028             raise
5029
5030         # from client to server (no translation)
5031         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5032              IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
5033              TCP(sport=12346, dport=local_port))
5034         self.pg1.add_stream(p)
5035         self.pg_enable_capture(self.pg_interfaces)
5036         self.pg_start()
5037         capture = self.pg0.get_capture(1)
5038         p = capture[0]
5039         server = None
5040         try:
5041             ip = p[IP]
5042             tcp = p[TCP]
5043             self.assertEqual(ip.dst, server1.ip4)
5044             self.assertEqual(tcp.dport, local_port)
5045             self.assert_packet_checksums_valid(p)
5046         except:
5047             self.logger.error(ppp("Unexpected or invalid packet:", p))
5048             raise
5049
5050         # from service back to client (no translation)
5051         p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
5052              IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
5053              TCP(sport=local_port, dport=12346))
5054         self.pg0.add_stream(p)
5055         self.pg_enable_capture(self.pg_interfaces)
5056         self.pg_start()
5057         capture = self.pg1.get_capture(1)
5058         p = capture[0]
5059         try:
5060             ip = p[IP]
5061             tcp = p[TCP]
5062             self.assertEqual(ip.src, server1.ip4)
5063             self.assertEqual(tcp.sport, local_port)
5064             self.assert_packet_checksums_valid(p)
5065         except:
5066             self.logger.error(ppp("Unexpected or invalid packet:", p))
5067             raise
5068
5069     def test_lb_affinity(self):
5070         """ NAT44 local service load balancing affinity """
5071         external_addr = self.nat_addr
5072         external_port = 80
5073         local_port = 8080
5074         server1 = self.pg0.remote_hosts[0]
5075         server2 = self.pg0.remote_hosts[1]
5076
5077         locals = [{'addr': server1.ip4,
5078                    'port': local_port,
5079                    'probability': 50,
5080                    'vrf_id': 0},
5081                   {'addr': server2.ip4,
5082                    'port': local_port,
5083                    'probability': 50,
5084                    'vrf_id': 0}]
5085
5086         self.nat44_add_address(self.nat_addr)
5087         self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
5088                                                   external_addr=external_addr,
5089                                                   external_port=external_port,
5090                                                   protocol=IP_PROTOS.tcp,
5091                                                   affinity=10800,
5092                                                   local_num=len(locals),
5093                                                   locals=locals)
5094         flags = self.config_flags.NAT_IS_INSIDE
5095         self.vapi.nat44_interface_add_del_feature(
5096             sw_if_index=self.pg0.sw_if_index,
5097             flags=flags, is_add=1)
5098         self.vapi.nat44_interface_add_del_feature(
5099             sw_if_index=self.pg1.sw_if_index,
5100             is_add=1)
5101
5102         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5103              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5104              TCP(sport=1025, dport=external_port))
5105         self.pg1.add_stream(p)
5106         self.pg_enable_capture(self.pg_interfaces)
5107         self.pg_start()
5108         capture = self.pg0.get_capture(1)
5109         backend = capture[0][IP].dst
5110
5111         sessions = self.vapi.nat44_user_session_dump(backend, 0)
5112         self.assertEqual(len(sessions), 1)
5113         self.assertTrue(sessions[0].flags &
5114                         self.config_flags.NAT_IS_EXT_HOST_VALID)
5115         self.vapi.nat44_del_session(
5116             address=sessions[0].inside_ip_address,
5117             port=sessions[0].inside_port,
5118             protocol=sessions[0].protocol,
5119             flags=(self.config_flags.NAT_IS_INSIDE |
5120                    self.config_flags.NAT_IS_EXT_HOST_VALID),
5121             ext_host_address=sessions[0].ext_host_address,
5122             ext_host_port=sessions[0].ext_host_port)
5123
5124         pkts = []
5125         for port in range(1030, 1100):
5126             p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5127                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5128                  TCP(sport=port, dport=external_port))
5129             pkts.append(p)
5130         self.pg1.add_stream(pkts)
5131         self.pg_enable_capture(self.pg_interfaces)
5132         self.pg_start()
5133         capture = self.pg0.get_capture(len(pkts))
5134         for p in capture:
5135             self.assertEqual(p[IP].dst, backend)
5136
5137     def test_unknown_proto(self):
5138         """ NAT44 translate packet with unknown protocol """
5139         self.nat44_add_address(self.nat_addr)
5140         flags = self.config_flags.NAT_IS_INSIDE
5141         self.vapi.nat44_interface_add_del_feature(
5142             sw_if_index=self.pg0.sw_if_index,
5143             flags=flags, is_add=1)
5144         self.vapi.nat44_interface_add_del_feature(
5145             sw_if_index=self.pg1.sw_if_index,
5146             is_add=1)
5147
5148         # in2out
5149         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5150              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5151              TCP(sport=self.tcp_port_in, dport=20))
5152         self.pg0.add_stream(p)
5153         self.pg_enable_capture(self.pg_interfaces)
5154         self.pg_start()
5155         p = self.pg1.get_capture(1)
5156
5157         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5158              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5159              GRE() /
5160              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5161              TCP(sport=1234, dport=1234))
5162         self.pg0.add_stream(p)
5163         self.pg_enable_capture(self.pg_interfaces)
5164         self.pg_start()
5165         p = self.pg1.get_capture(1)
5166         packet = p[0]
5167         try:
5168             self.assertEqual(packet[IP].src, self.nat_addr)
5169             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5170             self.assertEqual(packet.haslayer(GRE), 1)
5171             self.assert_packet_checksums_valid(packet)
5172         except:
5173             self.logger.error(ppp("Unexpected or invalid packet:", packet))
5174             raise
5175
5176         # out2in
5177         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5178              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5179              GRE() /
5180              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5181              TCP(sport=1234, dport=1234))
5182         self.pg1.add_stream(p)
5183         self.pg_enable_capture(self.pg_interfaces)
5184         self.pg_start()
5185         p = self.pg0.get_capture(1)
5186         packet = p[0]
5187         try:
5188             self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
5189             self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
5190             self.assertEqual(packet.haslayer(GRE), 1)
5191             self.assert_packet_checksums_valid(packet)
5192         except:
5193             self.logger.error(ppp("Unexpected or invalid packet:", packet))
5194             raise
5195
5196     def test_hairpinning_unknown_proto(self):
5197         """ NAT44 translate packet with unknown protocol - hairpinning """
5198         host = self.pg0.remote_hosts[0]
5199         server = self.pg0.remote_hosts[1]
5200         host_in_port = 1234
5201         server_out_port = 8765
5202         server_nat_ip = "10.0.0.11"
5203
5204         self.nat44_add_address(self.nat_addr)
5205         flags = self.config_flags.NAT_IS_INSIDE
5206         self.vapi.nat44_interface_add_del_feature(
5207             sw_if_index=self.pg0.sw_if_index,
5208             flags=flags, is_add=1)
5209         self.vapi.nat44_interface_add_del_feature(
5210             sw_if_index=self.pg1.sw_if_index,
5211             is_add=1)
5212
5213         # add static mapping for server
5214         self.nat44_add_static_mapping(server.ip4, server_nat_ip)
5215
5216         # host to server
5217         p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
5218              IP(src=host.ip4, dst=server_nat_ip) /
5219              TCP(sport=host_in_port, dport=server_out_port))
5220         self.pg0.add_stream(p)
5221         self.pg_enable_capture(self.pg_interfaces)
5222         self.pg_start()
5223         self.pg0.get_capture(1)
5224
5225         p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5226              IP(src=host.ip4, dst=server_nat_ip) /
5227              GRE() /
5228              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5229              TCP(sport=1234, dport=1234))
5230         self.pg0.add_stream(p)
5231         self.pg_enable_capture(self.pg_interfaces)
5232         self.pg_start()
5233         p = self.pg0.get_capture(1)
5234         packet = p[0]
5235         try:
5236             self.assertEqual(packet[IP].src, self.nat_addr)
5237             self.assertEqual(packet[IP].dst, server.ip4)
5238             self.assertEqual(packet.haslayer(GRE), 1)
5239             self.assert_packet_checksums_valid(packet)
5240         except:
5241             self.logger.error(ppp("Unexpected or invalid packet:", packet))
5242             raise
5243
5244         # server to host
5245         p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5246              IP(src=server.ip4, dst=self.nat_addr) /
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.pg0.get_capture(1)
5254         packet = p[0]
5255         try:
5256             self.assertEqual(packet[IP].src, server_nat_ip)
5257             self.assertEqual(packet[IP].dst, host.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     def test_output_feature_and_service(self):
5265         """ NAT44 interface output feature and services """
5266         external_addr = '1.2.3.4'
5267         external_port = 80
5268         local_port = 8080
5269
5270         self.vapi.nat44_forwarding_enable_disable(enable=1)
5271         self.nat44_add_address(self.nat_addr)
5272         flags = self.config_flags.NAT_IS_ADDR_ONLY
5273         self.vapi.nat44_add_del_identity_mapping(
5274             ip_address=self.pg1.remote_ip4, sw_if_index=0xFFFFFFFF,
5275             flags=flags, is_add=1)
5276         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5277         self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5278                                       local_port, external_port,
5279                                       proto=IP_PROTOS.tcp, flags=flags)
5280         flags = self.config_flags.NAT_IS_INSIDE
5281         self.vapi.nat44_interface_add_del_feature(
5282             sw_if_index=self.pg0.sw_if_index,
5283             is_add=1)
5284         self.vapi.nat44_interface_add_del_feature(
5285             sw_if_index=self.pg0.sw_if_index,
5286             flags=flags, is_add=1)
5287         self.vapi.nat44_interface_add_del_output_feature(
5288             is_add=1,
5289             sw_if_index=self.pg1.sw_if_index)
5290
5291         # from client to service
5292         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5293              IP(src=self.pg1.remote_ip4, dst=external_addr) /
5294              TCP(sport=12345, dport=external_port))
5295         self.pg1.add_stream(p)
5296         self.pg_enable_capture(self.pg_interfaces)
5297         self.pg_start()
5298         capture = self.pg0.get_capture(1)
5299         p = capture[0]
5300         try:
5301             ip = p[IP]
5302             tcp = p[TCP]
5303             self.assertEqual(ip.dst, self.pg0.remote_ip4)
5304             self.assertEqual(tcp.dport, local_port)
5305             self.assert_packet_checksums_valid(p)
5306         except:
5307             self.logger.error(ppp("Unexpected or invalid packet:", p))
5308             raise
5309
5310         # from service back to client
5311         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5312              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5313              TCP(sport=local_port, dport=12345))
5314         self.pg0.add_stream(p)
5315         self.pg_enable_capture(self.pg_interfaces)
5316         self.pg_start()
5317         capture = self.pg1.get_capture(1)
5318         p = capture[0]
5319         try:
5320             ip = p[IP]
5321             tcp = p[TCP]
5322             self.assertEqual(ip.src, external_addr)
5323             self.assertEqual(tcp.sport, external_port)
5324             self.assert_packet_checksums_valid(p)
5325         except:
5326             self.logger.error(ppp("Unexpected or invalid packet:", p))
5327             raise
5328
5329         # from local network host to external network
5330         pkts = self.create_stream_in(self.pg0, self.pg1)
5331         self.pg0.add_stream(pkts)
5332         self.pg_enable_capture(self.pg_interfaces)
5333         self.pg_start()
5334         capture = self.pg1.get_capture(len(pkts))
5335         self.verify_capture_out(capture, ignore_port=True)
5336         pkts = self.create_stream_in(self.pg0, self.pg1)
5337         self.pg0.add_stream(pkts)
5338         self.pg_enable_capture(self.pg_interfaces)
5339         self.pg_start()
5340         capture = self.pg1.get_capture(len(pkts))
5341         self.verify_capture_out(capture, ignore_port=True)
5342
5343         # from external network back to local network host
5344         pkts = self.create_stream_out(self.pg1)
5345         self.pg1.add_stream(pkts)
5346         self.pg_enable_capture(self.pg_interfaces)
5347         self.pg_start()
5348         capture = self.pg0.get_capture(len(pkts))
5349         self.verify_capture_in(capture, self.pg0)
5350
5351     def test_output_feature_and_service2(self):
5352         """ NAT44 interface output feature and service host direct access """
5353         self.vapi.nat44_forwarding_enable_disable(enable=1)
5354         self.nat44_add_address(self.nat_addr)
5355         self.vapi.nat44_interface_add_del_output_feature(
5356             is_add=1,
5357             sw_if_index=self.pg1.sw_if_index)
5358
5359         # session initiated from service host - translate
5360         pkts = self.create_stream_in(self.pg0, self.pg1)
5361         self.pg0.add_stream(pkts)
5362         self.pg_enable_capture(self.pg_interfaces)
5363         self.pg_start()
5364         capture = self.pg1.get_capture(len(pkts))
5365         self.verify_capture_out(capture, ignore_port=True)
5366
5367         pkts = self.create_stream_out(self.pg1)
5368         self.pg1.add_stream(pkts)
5369         self.pg_enable_capture(self.pg_interfaces)
5370         self.pg_start()
5371         capture = self.pg0.get_capture(len(pkts))
5372         self.verify_capture_in(capture, self.pg0)
5373
5374         # session initiated from remote host - do not translate
5375         self.tcp_port_in = 60303
5376         self.udp_port_in = 60304
5377         self.icmp_id_in = 60305
5378         pkts = self.create_stream_out(self.pg1,
5379                                       self.pg0.remote_ip4,
5380                                       use_inside_ports=True)
5381         self.pg1.add_stream(pkts)
5382         self.pg_enable_capture(self.pg_interfaces)
5383         self.pg_start()
5384         capture = self.pg0.get_capture(len(pkts))
5385         self.verify_capture_in(capture, self.pg0)
5386
5387         pkts = self.create_stream_in(self.pg0, self.pg1)
5388         self.pg0.add_stream(pkts)
5389         self.pg_enable_capture(self.pg_interfaces)
5390         self.pg_start()
5391         capture = self.pg1.get_capture(len(pkts))
5392         self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5393                                 same_port=True)
5394
5395     def test_output_feature_and_service3(self):
5396         """ NAT44 interface output feature and DST NAT """
5397         external_addr = '1.2.3.4'
5398         external_port = 80
5399         local_port = 8080
5400
5401         self.vapi.nat44_forwarding_enable_disable(enable=1)
5402         self.nat44_add_address(self.nat_addr)
5403         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5404         self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5405                                       local_port, external_port,
5406                                       proto=IP_PROTOS.tcp, flags=flags)
5407         flags = self.config_flags.NAT_IS_INSIDE
5408         self.vapi.nat44_interface_add_del_feature(
5409             sw_if_index=self.pg0.sw_if_index,
5410             is_add=1)
5411         self.vapi.nat44_interface_add_del_feature(
5412             sw_if_index=self.pg0.sw_if_index,
5413             flags=flags, is_add=1)
5414         self.vapi.nat44_interface_add_del_output_feature(
5415             is_add=1,
5416             sw_if_index=self.pg1.sw_if_index)
5417
5418         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5419              IP(src=self.pg0.remote_ip4, dst=external_addr) /
5420              TCP(sport=12345, dport=external_port))
5421         self.pg0.add_stream(p)
5422         self.pg_enable_capture(self.pg_interfaces)
5423         self.pg_start()
5424         capture = self.pg1.get_capture(1)
5425         p = capture[0]
5426         try:
5427             ip = p[IP]
5428             tcp = p[TCP]
5429             self.assertEqual(ip.src, self.pg0.remote_ip4)
5430             self.assertEqual(tcp.sport, 12345)
5431             self.assertEqual(ip.dst, self.pg1.remote_ip4)
5432             self.assertEqual(tcp.dport, local_port)
5433             self.assert_packet_checksums_valid(p)
5434         except:
5435             self.logger.error(ppp("Unexpected or invalid packet:", p))
5436             raise
5437
5438         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5439              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5440              TCP(sport=local_port, dport=12345))
5441         self.pg1.add_stream(p)
5442         self.pg_enable_capture(self.pg_interfaces)
5443         self.pg_start()
5444         capture = self.pg0.get_capture(1)
5445         p = capture[0]
5446         try:
5447             ip = p[IP]
5448             tcp = p[TCP]
5449             self.assertEqual(ip.src, external_addr)
5450             self.assertEqual(tcp.sport, external_port)
5451             self.assertEqual(ip.dst, self.pg0.remote_ip4)
5452             self.assertEqual(tcp.dport, 12345)
5453             self.assert_packet_checksums_valid(p)
5454         except:
5455             self.logger.error(ppp("Unexpected or invalid packet:", p))
5456             raise
5457
5458     def test_next_src_nat(self):
5459         """ On way back forward packet to nat44-in2out node. """
5460         twice_nat_addr = '10.0.1.3'
5461         external_port = 80
5462         local_port = 8080
5463         post_twice_nat_port = 0
5464
5465         self.vapi.nat44_forwarding_enable_disable(enable=1)
5466         self.nat44_add_address(twice_nat_addr, twice_nat=1)
5467         flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5468                  self.config_flags.NAT_IS_SELF_TWICE_NAT)
5469         self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5470                                       local_port, external_port,
5471                                       proto=IP_PROTOS.tcp, vrf_id=1,
5472                                       flags=flags)
5473         self.vapi.nat44_interface_add_del_feature(
5474             sw_if_index=self.pg6.sw_if_index,
5475             is_add=1)
5476
5477         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5478              IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5479              TCP(sport=12345, dport=external_port))
5480         self.pg6.add_stream(p)
5481         self.pg_enable_capture(self.pg_interfaces)
5482         self.pg_start()
5483         capture = self.pg6.get_capture(1)
5484         p = capture[0]
5485         try:
5486             ip = p[IP]
5487             tcp = p[TCP]
5488             self.assertEqual(ip.src, twice_nat_addr)
5489             self.assertNotEqual(tcp.sport, 12345)
5490             post_twice_nat_port = tcp.sport
5491             self.assertEqual(ip.dst, self.pg6.remote_ip4)
5492             self.assertEqual(tcp.dport, local_port)
5493             self.assert_packet_checksums_valid(p)
5494         except:
5495             self.logger.error(ppp("Unexpected or invalid packet:", p))
5496             raise
5497
5498         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5499              IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5500              TCP(sport=local_port, dport=post_twice_nat_port))
5501         self.pg6.add_stream(p)
5502         self.pg_enable_capture(self.pg_interfaces)
5503         self.pg_start()
5504         capture = self.pg6.get_capture(1)
5505         p = capture[0]
5506         try:
5507             ip = p[IP]
5508             tcp = p[TCP]
5509             self.assertEqual(ip.src, self.pg1.remote_ip4)
5510             self.assertEqual(tcp.sport, external_port)
5511             self.assertEqual(ip.dst, self.pg6.remote_ip4)
5512             self.assertEqual(tcp.dport, 12345)
5513             self.assert_packet_checksums_valid(p)
5514         except:
5515             self.logger.error(ppp("Unexpected or invalid packet:", p))
5516             raise
5517
5518     def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5519                          client_id=None):
5520         twice_nat_addr = '10.0.1.3'
5521
5522         port_in = 8080
5523         if lb:
5524             if not same_pg:
5525                 port_in1 = port_in
5526                 port_in2 = port_in
5527             else:
5528                 port_in1 = port_in + 1
5529                 port_in2 = port_in + 2
5530
5531         port_out = 80
5532         eh_port_out = 4567
5533
5534         server1 = self.pg0.remote_hosts[0]
5535         server2 = self.pg0.remote_hosts[1]
5536         if lb and same_pg:
5537             server2 = server1
5538         if not lb:
5539             server = server1
5540
5541         pg0 = self.pg0
5542         if same_pg:
5543             pg1 = self.pg0
5544         else:
5545             pg1 = self.pg1
5546
5547         eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5548                         client_id == 1)
5549
5550         self.nat44_add_address(self.nat_addr)
5551         self.nat44_add_address(twice_nat_addr, twice_nat=1)
5552
5553         flags = 0
5554         if self_twice_nat:
5555             flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
5556         else:
5557             flags |= self.config_flags.NAT_IS_TWICE_NAT
5558
5559         if not lb:
5560             self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5561                                           port_in, port_out,
5562                                           proto=IP_PROTOS.tcp,
5563                                           flags=flags)
5564         else:
5565             locals = [{'addr': server1.ip4,
5566                        'port': port_in1,
5567                        'probability': 50,
5568                        'vrf_id': 0},
5569                       {'addr': server2.ip4,
5570                        'port': port_in2,
5571                        'probability': 50,
5572                        'vrf_id': 0}]
5573             out_addr = self.nat_addr
5574
5575             self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5576                                                       external_addr=out_addr,
5577                                                       external_port=port_out,
5578                                                       protocol=IP_PROTOS.tcp,
5579                                                       local_num=len(locals),
5580                                                       locals=locals)
5581         flags = self.config_flags.NAT_IS_INSIDE
5582         self.vapi.nat44_interface_add_del_feature(
5583             sw_if_index=pg0.sw_if_index,
5584             flags=flags, is_add=1)
5585         self.vapi.nat44_interface_add_del_feature(
5586             sw_if_index=pg1.sw_if_index,
5587             is_add=1)
5588
5589         if same_pg:
5590             if not lb:
5591                 client = server
5592             else:
5593                 assert client_id is not None
5594                 if client_id == 1:
5595                     client = self.pg0.remote_hosts[0]
5596                 elif client_id == 2:
5597                     client = self.pg0.remote_hosts[1]
5598         else:
5599             client = pg1.remote_hosts[0]
5600         p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5601              IP(src=client.ip4, dst=self.nat_addr) /
5602              TCP(sport=eh_port_out, dport=port_out))
5603         pg1.add_stream(p)
5604         self.pg_enable_capture(self.pg_interfaces)
5605         self.pg_start()
5606         capture = pg0.get_capture(1)
5607         p = capture[0]
5608         try:
5609             ip = p[IP]
5610             tcp = p[TCP]
5611             if lb:
5612                 if ip.dst == server1.ip4:
5613                     server = server1
5614                     port_in = port_in1
5615                 else:
5616                     server = server2
5617                     port_in = port_in2
5618             self.assertEqual(ip.dst, server.ip4)
5619             if lb and same_pg:
5620                 self.assertIn(tcp.dport, [port_in1, port_in2])
5621             else:
5622                 self.assertEqual(tcp.dport, port_in)
5623             if eh_translate:
5624                 self.assertEqual(ip.src, twice_nat_addr)
5625                 self.assertNotEqual(tcp.sport, eh_port_out)
5626             else:
5627                 self.assertEqual(ip.src, client.ip4)
5628                 self.assertEqual(tcp.sport, eh_port_out)
5629             eh_addr_in = ip.src
5630             eh_port_in = tcp.sport
5631             saved_port_in = tcp.dport
5632             self.assert_packet_checksums_valid(p)
5633         except:
5634             self.logger.error(ppp("Unexpected or invalid packet:", p))
5635             raise
5636
5637         p = (Ether(src=server.mac, dst=pg0.local_mac) /
5638              IP(src=server.ip4, dst=eh_addr_in) /
5639              TCP(sport=saved_port_in, dport=eh_port_in))
5640         pg0.add_stream(p)
5641         self.pg_enable_capture(self.pg_interfaces)
5642         self.pg_start()
5643         capture = pg1.get_capture(1)
5644         p = capture[0]
5645         try:
5646             ip = p[IP]
5647             tcp = p[TCP]
5648             self.assertEqual(ip.dst, client.ip4)
5649             self.assertEqual(ip.src, self.nat_addr)
5650             self.assertEqual(tcp.dport, eh_port_out)
5651             self.assertEqual(tcp.sport, port_out)
5652             self.assert_packet_checksums_valid(p)
5653         except:
5654             self.logger.error(ppp("Unexpected or invalid packet:", p))
5655             raise
5656
5657         if eh_translate:
5658             sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5659             self.assertEqual(len(sessions), 1)
5660             self.assertTrue(sessions[0].flags &
5661                             self.config_flags.NAT_IS_EXT_HOST_VALID)
5662             self.assertTrue(sessions[0].flags &
5663                             self.config_flags.NAT_IS_TWICE_NAT)
5664             self.logger.info(self.vapi.cli("show nat44 sessions detail"))
5665             self.vapi.nat44_del_session(
5666                 address=sessions[0].inside_ip_address,
5667                 port=sessions[0].inside_port,
5668                 protocol=sessions[0].protocol,
5669                 flags=(self.config_flags.NAT_IS_INSIDE |
5670                        self.config_flags.NAT_IS_EXT_HOST_VALID),
5671                 ext_host_address=sessions[0].ext_host_nat_address,
5672                 ext_host_port=sessions[0].ext_host_nat_port)
5673             sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5674             self.assertEqual(len(sessions), 0)
5675
5676     def test_twice_nat(self):
5677         """ Twice NAT44 """
5678         self.twice_nat_common()
5679
5680     def test_self_twice_nat_positive(self):
5681         """ Self Twice NAT44 (positive test) """
5682         self.twice_nat_common(self_twice_nat=True, same_pg=True)
5683
5684     def test_self_twice_nat_negative(self):
5685         """ Self Twice NAT44 (negative test) """
5686         self.twice_nat_common(self_twice_nat=True)
5687
5688     def test_twice_nat_lb(self):
5689         """ Twice NAT44 local service load balancing """
5690         self.twice_nat_common(lb=True)
5691
5692     def test_self_twice_nat_lb_positive(self):
5693         """ Self Twice NAT44 local service load balancing (positive test) """
5694         self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5695                               client_id=1)
5696
5697     def test_self_twice_nat_lb_negative(self):
5698         """ Self Twice NAT44 local service load balancing (negative test) """
5699         self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5700                               client_id=2)
5701
5702     def test_twice_nat_interface_addr(self):
5703         """ Acquire twice NAT44 addresses from interface """
5704         flags = self.config_flags.NAT_IS_TWICE_NAT
5705         self.vapi.nat44_add_del_interface_addr(
5706             is_add=1,
5707             sw_if_index=self.pg3.sw_if_index,
5708             flags=flags)
5709
5710         # no address in NAT pool
5711         adresses = self.vapi.nat44_address_dump()
5712         self.assertEqual(0, len(adresses))
5713
5714         # configure interface address and check NAT address pool
5715         self.pg3.config_ip4()
5716         adresses = self.vapi.nat44_address_dump()
5717         self.assertEqual(1, len(adresses))
5718         self.assertEqual(str(adresses[0].ip_address),
5719                          self.pg3.local_ip4)
5720         self.assertEqual(adresses[0].flags, flags)
5721
5722         # remove interface address and check NAT address pool
5723         self.pg3.unconfig_ip4()
5724         adresses = self.vapi.nat44_address_dump()
5725         self.assertEqual(0, len(adresses))
5726
5727     def test_tcp_close(self):
5728         """ Close TCP session from inside network - output feature """
5729         self.vapi.nat44_forwarding_enable_disable(enable=1)
5730         self.nat44_add_address(self.pg1.local_ip4)
5731         twice_nat_addr = '10.0.1.3'
5732         service_ip = '192.168.16.150'
5733         self.nat44_add_address(twice_nat_addr, twice_nat=1)
5734         flags = self.config_flags.NAT_IS_INSIDE
5735         self.vapi.nat44_interface_add_del_feature(
5736             sw_if_index=self.pg0.sw_if_index,
5737             is_add=1)
5738         self.vapi.nat44_interface_add_del_feature(
5739             sw_if_index=self.pg0.sw_if_index,
5740             flags=flags, is_add=1)
5741         self.vapi.nat44_interface_add_del_output_feature(
5742             is_add=1,
5743             sw_if_index=self.pg1.sw_if_index)
5744         flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5745                  self.config_flags.NAT_IS_TWICE_NAT)
5746         self.nat44_add_static_mapping(self.pg0.remote_ip4,
5747                                       service_ip,
5748                                       80,
5749                                       80,
5750                                       proto=IP_PROTOS.tcp,
5751                                       flags=flags)
5752         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5753         start_sessnum = len(sessions)
5754
5755         # SYN packet out->in
5756         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5757              IP(src=self.pg1.remote_ip4, dst=service_ip) /
5758              TCP(sport=33898, dport=80, flags="S"))
5759         self.pg1.add_stream(p)
5760         self.pg_enable_capture(self.pg_interfaces)
5761         self.pg_start()
5762         capture = self.pg0.get_capture(1)
5763         p = capture[0]
5764         tcp_port = p[TCP].sport
5765
5766         # SYN + ACK packet in->out
5767         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5768              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5769              TCP(sport=80, dport=tcp_port, flags="SA"))
5770         self.pg0.add_stream(p)
5771         self.pg_enable_capture(self.pg_interfaces)
5772         self.pg_start()
5773         self.pg1.get_capture(1)
5774
5775         # ACK packet out->in
5776         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5777              IP(src=self.pg1.remote_ip4, dst=service_ip) /
5778              TCP(sport=33898, dport=80, flags="A"))
5779         self.pg1.add_stream(p)
5780         self.pg_enable_capture(self.pg_interfaces)
5781         self.pg_start()
5782         self.pg0.get_capture(1)
5783
5784         # FIN packet in -> out
5785         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5786              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5787              TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5788         self.pg0.add_stream(p)
5789         self.pg_enable_capture(self.pg_interfaces)
5790         self.pg_start()
5791         self.pg1.get_capture(1)
5792
5793         # FIN+ACK packet out -> in
5794         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5795              IP(src=self.pg1.remote_ip4, dst=service_ip) /
5796              TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5797         self.pg1.add_stream(p)
5798         self.pg_enable_capture(self.pg_interfaces)
5799         self.pg_start()
5800         self.pg0.get_capture(1)
5801
5802         # ACK packet in -> out
5803         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5804              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5805              TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5806         self.pg0.add_stream(p)
5807         self.pg_enable_capture(self.pg_interfaces)
5808         self.pg_start()
5809         self.pg1.get_capture(1)
5810
5811         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4,
5812                                                      0)
5813         self.assertEqual(len(sessions) - start_sessnum, 0)
5814
5815     def test_tcp_session_close_in(self):
5816         """ Close TCP session from inside network """
5817         self.tcp_port_out = 10505
5818         self.nat44_add_address(self.nat_addr)
5819         flags = self.config_flags.NAT_IS_TWICE_NAT
5820         self.nat44_add_static_mapping(self.pg0.remote_ip4,
5821                                       self.nat_addr,
5822                                       self.tcp_port_in,
5823                                       self.tcp_port_out,
5824                                       proto=IP_PROTOS.tcp,
5825                                       flags=flags)
5826         flags = self.config_flags.NAT_IS_INSIDE
5827         self.vapi.nat44_interface_add_del_feature(
5828             sw_if_index=self.pg0.sw_if_index,
5829             flags=flags, is_add=1)
5830         self.vapi.nat44_interface_add_del_feature(
5831             sw_if_index=self.pg1.sw_if_index,
5832             is_add=1)
5833
5834         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5835         start_sessnum = len(sessions)
5836
5837         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
5838                                    tcp_transitory=2, icmp=5)
5839
5840         self.initiate_tcp_session(self.pg0, self.pg1)
5841
5842         # FIN packet in -> out
5843         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5844              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5845              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5846                  flags="FA", seq=100, ack=300))
5847         self.pg0.add_stream(p)
5848         self.pg_enable_capture(self.pg_interfaces)
5849         self.pg_start()
5850         self.pg1.get_capture(1)
5851
5852         pkts = []
5853
5854         # ACK packet out -> in
5855         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5856              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5857              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5858                  flags="A", seq=300, ack=101))
5859         pkts.append(p)
5860
5861         # FIN packet out -> in
5862         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5863              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5864              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5865                  flags="FA", seq=300, ack=101))
5866         pkts.append(p)
5867
5868         self.pg1.add_stream(pkts)
5869         self.pg_enable_capture(self.pg_interfaces)
5870         self.pg_start()
5871         self.pg0.get_capture(2)
5872
5873         # ACK packet in -> out
5874         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5875              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5876              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5877                  flags="A", seq=101, ack=301))
5878         self.pg0.add_stream(p)
5879         self.pg_enable_capture(self.pg_interfaces)
5880         self.pg_start()
5881         self.pg1.get_capture(1)
5882
5883         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5884         self.assertEqual(len(sessions) - start_sessnum, 1)
5885
5886         stats = self.statistics.get_counter(
5887             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
5888         out2in_drops = stats[0]
5889         stats = self.statistics.get_counter(
5890             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
5891         in2out_drops = stats[0]
5892
5893         # extra FIN packet out -> in - this should be dropped
5894         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5895              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5896              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5897                  flags="FA", seq=300, ack=101))
5898
5899         self.pg1.add_stream(p)
5900         self.pg_enable_capture(self.pg_interfaces)
5901         self.pg_start()
5902         self.pg0.assert_nothing_captured()
5903
5904         # extra ACK packet in -> out - this should be dropped
5905         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5906              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5907              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5908                  flags="A", seq=101, ack=301))
5909         self.pg0.add_stream(p)
5910         self.pg_enable_capture(self.pg_interfaces)
5911         self.pg_start()
5912         self.pg1.assert_nothing_captured()
5913
5914         stats = self.statistics.get_counter(
5915             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
5916         self.assertEqual(stats[0] - out2in_drops, 1)
5917         stats = self.statistics.get_counter(
5918             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
5919         self.assertEqual(stats[0] - in2out_drops, 1)
5920
5921         self.sleep(3)
5922         # extra ACK packet in -> out - this will cause session to be wiped
5923         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5924              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5925              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5926                  flags="A", seq=101, ack=301))
5927         self.pg0.add_stream(p)
5928         self.pg_enable_capture(self.pg_interfaces)
5929         self.pg_start()
5930         self.pg1.assert_nothing_captured()
5931         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5932         self.assertEqual(len(sessions) - start_sessnum, 0)
5933
5934     def test_tcp_session_close_out(self):
5935         """ Close TCP session from outside network """
5936         self.tcp_port_out = 10505
5937         self.nat44_add_address(self.nat_addr)
5938         flags = self.config_flags.NAT_IS_TWICE_NAT
5939         self.nat44_add_static_mapping(self.pg0.remote_ip4,
5940                                       self.nat_addr,
5941                                       self.tcp_port_in,
5942                                       self.tcp_port_out,
5943                                       proto=IP_PROTOS.tcp,
5944                                       flags=flags)
5945         flags = self.config_flags.NAT_IS_INSIDE
5946         self.vapi.nat44_interface_add_del_feature(
5947             sw_if_index=self.pg0.sw_if_index,
5948             flags=flags, is_add=1)
5949         self.vapi.nat44_interface_add_del_feature(
5950             sw_if_index=self.pg1.sw_if_index,
5951             is_add=1)
5952
5953         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5954         start_sessnum = len(sessions)
5955
5956         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
5957                                    tcp_transitory=2, icmp=5)
5958
5959         self.initiate_tcp_session(self.pg0, self.pg1)
5960
5961         # FIN packet out -> in
5962         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5963              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5964              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5965                  flags="FA", seq=100, ack=300))
5966         self.pg1.add_stream(p)
5967         self.pg_enable_capture(self.pg_interfaces)
5968         self.pg_start()
5969         self.pg0.get_capture(1)
5970
5971         # FIN+ACK packet in -> out
5972         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5973              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5974              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5975                  flags="FA", seq=300, ack=101))
5976
5977         self.pg0.add_stream(p)
5978         self.pg_enable_capture(self.pg_interfaces)
5979         self.pg_start()
5980         self.pg1.get_capture(1)
5981
5982         # ACK 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="A", seq=101, ack=301))
5987         self.pg1.add_stream(p)
5988         self.pg_enable_capture(self.pg_interfaces)
5989         self.pg_start()
5990         self.pg0.get_capture(1)
5991
5992         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5993         self.assertEqual(len(sessions) - start_sessnum, 1)
5994
5995         stats = self.statistics.get_counter(
5996             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
5997         out2in_drops = stats[0]
5998         stats = self.statistics.get_counter(
5999             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6000         in2out_drops = stats[0]
6001
6002         # extra FIN packet out -> in - this should be dropped
6003         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6004              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6005              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6006                  flags="FA", seq=300, ack=101))
6007
6008         self.pg1.add_stream(p)
6009         self.pg_enable_capture(self.pg_interfaces)
6010         self.pg_start()
6011         self.pg0.assert_nothing_captured()
6012
6013         # extra ACK packet in -> out - this should be dropped
6014         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6015              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6016              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6017                  flags="A", seq=101, ack=301))
6018         self.pg0.add_stream(p)
6019         self.pg_enable_capture(self.pg_interfaces)
6020         self.pg_start()
6021         self.pg1.assert_nothing_captured()
6022
6023         stats = self.statistics.get_counter(
6024             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6025         self.assertEqual(stats[0] - out2in_drops, 1)
6026         stats = self.statistics.get_counter(
6027             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6028         self.assertEqual(stats[0] - in2out_drops, 1)
6029
6030         self.sleep(3)
6031         # extra ACK packet in -> out - this will cause session to be wiped
6032         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6033              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6034              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6035                  flags="A", seq=101, ack=301))
6036         self.pg0.add_stream(p)
6037         self.pg_enable_capture(self.pg_interfaces)
6038         self.pg_start()
6039         self.pg1.assert_nothing_captured()
6040         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6041         self.assertEqual(len(sessions) - start_sessnum, 0)
6042
6043     def test_tcp_session_close_simultaneous(self):
6044         """ Close TCP session from inside network """
6045         self.tcp_port_out = 10505
6046         self.nat44_add_address(self.nat_addr)
6047         flags = self.config_flags.NAT_IS_TWICE_NAT
6048         self.nat44_add_static_mapping(self.pg0.remote_ip4,
6049                                       self.nat_addr,
6050                                       self.tcp_port_in,
6051                                       self.tcp_port_out,
6052                                       proto=IP_PROTOS.tcp,
6053                                       flags=flags)
6054         flags = self.config_flags.NAT_IS_INSIDE
6055         self.vapi.nat44_interface_add_del_feature(
6056             sw_if_index=self.pg0.sw_if_index,
6057             flags=flags, is_add=1)
6058         self.vapi.nat44_interface_add_del_feature(
6059             sw_if_index=self.pg1.sw_if_index,
6060             is_add=1)
6061
6062         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6063         start_sessnum = len(sessions)
6064
6065         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6066                                    tcp_transitory=2, icmp=5)
6067
6068         self.initiate_tcp_session(self.pg0, self.pg1)
6069
6070         # FIN packet in -> out
6071         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6072              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6073              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6074                  flags="FA", seq=100, ack=300))
6075         self.pg0.add_stream(p)
6076         self.pg_enable_capture(self.pg_interfaces)
6077         self.pg_start()
6078         self.pg1.get_capture(1)
6079
6080         # FIN packet out -> in
6081         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6082              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6083              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6084                  flags="FA", seq=300, ack=100))
6085         self.pg1.add_stream(p)
6086         self.pg_enable_capture(self.pg_interfaces)
6087         self.pg_start()
6088         self.pg0.get_capture(1)
6089
6090         # ACK packet in -> out
6091         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6092              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6093              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6094                  flags="A", seq=101, ack=301))
6095         self.pg0.add_stream(p)
6096         self.pg_enable_capture(self.pg_interfaces)
6097         self.pg_start()
6098         self.pg1.get_capture(1)
6099
6100         # ACK packet out -> in
6101         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6102              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6103              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6104                  flags="A", seq=301, ack=101))
6105         self.pg1.add_stream(p)
6106         self.pg_enable_capture(self.pg_interfaces)
6107         self.pg_start()
6108         self.pg0.get_capture(1)
6109
6110         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6111         self.assertEqual(len(sessions) - start_sessnum, 1)
6112
6113         stats = self.statistics.get_counter(
6114             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6115         out2in_drops = stats[0]
6116         stats = self.statistics.get_counter(
6117             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6118         in2out_drops = stats[0]
6119
6120         # extra FIN packet out -> in - this should be dropped
6121         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6122              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6123              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6124                  flags="FA", seq=300, ack=101))
6125
6126         self.pg1.add_stream(p)
6127         self.pg_enable_capture(self.pg_interfaces)
6128         self.pg_start()
6129         self.pg0.assert_nothing_captured()
6130
6131         # extra ACK packet in -> out - this should be dropped
6132         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6133              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6134              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6135                  flags="A", seq=101, ack=301))
6136         self.pg0.add_stream(p)
6137         self.pg_enable_capture(self.pg_interfaces)
6138         self.pg_start()
6139         self.pg1.assert_nothing_captured()
6140
6141         stats = self.statistics.get_counter(
6142             '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6143         self.assertEqual(stats[0] - out2in_drops, 1)
6144         stats = self.statistics.get_counter(
6145             '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6146         self.assertEqual(stats[0] - in2out_drops, 1)
6147
6148         self.sleep(3)
6149         # extra ACK packet in -> out - this will cause session to be wiped
6150         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6151              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6152              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6153                  flags="A", seq=101, ack=301))
6154         self.pg0.add_stream(p)
6155         self.pg_enable_capture(self.pg_interfaces)
6156         self.pg_start()
6157         self.pg1.assert_nothing_captured()
6158         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6159         self.assertEqual(len(sessions) - start_sessnum, 0)
6160
6161     def test_one_armed_nat44_static(self):
6162         """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
6163         remote_host = self.pg4.remote_hosts[0]
6164         local_host = self.pg4.remote_hosts[1]
6165         external_port = 80
6166         local_port = 8080
6167         eh_port_in = 0
6168
6169         self.vapi.nat44_forwarding_enable_disable(enable=1)
6170         self.nat44_add_address(self.nat_addr, twice_nat=1)
6171         flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
6172                  self.config_flags.NAT_IS_TWICE_NAT)
6173         self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
6174                                       local_port, external_port,
6175                                       proto=IP_PROTOS.tcp, flags=flags)
6176         flags = self.config_flags.NAT_IS_INSIDE
6177         self.vapi.nat44_interface_add_del_feature(
6178             sw_if_index=self.pg4.sw_if_index,
6179             is_add=1)
6180         self.vapi.nat44_interface_add_del_feature(
6181             sw_if_index=self.pg4.sw_if_index,
6182             flags=flags, is_add=1)
6183
6184         # from client to service
6185         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6186              IP(src=remote_host.ip4, dst=self.nat_addr) /
6187              TCP(sport=12345, dport=external_port))
6188         self.pg4.add_stream(p)
6189         self.pg_enable_capture(self.pg_interfaces)
6190         self.pg_start()
6191         capture = self.pg4.get_capture(1)
6192         p = capture[0]
6193         try:
6194             ip = p[IP]
6195             tcp = p[TCP]
6196             self.assertEqual(ip.dst, local_host.ip4)
6197             self.assertEqual(ip.src, self.nat_addr)
6198             self.assertEqual(tcp.dport, local_port)
6199             self.assertNotEqual(tcp.sport, 12345)
6200             eh_port_in = tcp.sport
6201             self.assert_packet_checksums_valid(p)
6202         except:
6203             self.logger.error(ppp("Unexpected or invalid packet:", p))
6204             raise
6205
6206         # from service back to client
6207         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6208              IP(src=local_host.ip4, dst=self.nat_addr) /
6209              TCP(sport=local_port, dport=eh_port_in))
6210         self.pg4.add_stream(p)
6211         self.pg_enable_capture(self.pg_interfaces)
6212         self.pg_start()
6213         capture = self.pg4.get_capture(1)
6214         p = capture[0]
6215         try:
6216             ip = p[IP]
6217             tcp = p[TCP]
6218             self.assertEqual(ip.src, self.nat_addr)
6219             self.assertEqual(ip.dst, remote_host.ip4)
6220             self.assertEqual(tcp.sport, external_port)
6221             self.assertEqual(tcp.dport, 12345)
6222             self.assert_packet_checksums_valid(p)
6223         except:
6224             self.logger.error(ppp("Unexpected or invalid packet:", p))
6225             raise
6226
6227     def test_static_with_port_out2(self):
6228         """ 1:1 NAPT asymmetrical rule """
6229
6230         external_port = 80
6231         local_port = 8080
6232
6233         self.vapi.nat44_forwarding_enable_disable(enable=1)
6234         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6235         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
6236                                       local_port, external_port,
6237                                       proto=IP_PROTOS.tcp, flags=flags)
6238         flags = self.config_flags.NAT_IS_INSIDE
6239         self.vapi.nat44_interface_add_del_feature(
6240             sw_if_index=self.pg0.sw_if_index,
6241             flags=flags, is_add=1)
6242         self.vapi.nat44_interface_add_del_feature(
6243             sw_if_index=self.pg1.sw_if_index,
6244             is_add=1)
6245
6246         # from client to service
6247         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6248              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6249              TCP(sport=12345, dport=external_port))
6250         self.pg1.add_stream(p)
6251         self.pg_enable_capture(self.pg_interfaces)
6252         self.pg_start()
6253         capture = self.pg0.get_capture(1)
6254         p = capture[0]
6255         try:
6256             ip = p[IP]
6257             tcp = p[TCP]
6258             self.assertEqual(ip.dst, self.pg0.remote_ip4)
6259             self.assertEqual(tcp.dport, local_port)
6260             self.assert_packet_checksums_valid(p)
6261         except:
6262             self.logger.error(ppp("Unexpected or invalid packet:", p))
6263             raise
6264
6265         # ICMP error
6266         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6267              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6268              ICMP(type=11) / capture[0][IP])
6269         self.pg0.add_stream(p)
6270         self.pg_enable_capture(self.pg_interfaces)
6271         self.pg_start()
6272         capture = self.pg1.get_capture(1)
6273         p = capture[0]
6274         try:
6275             self.assertEqual(p[IP].src, self.nat_addr)
6276             inner = p[IPerror]
6277             self.assertEqual(inner.dst, self.nat_addr)
6278             self.assertEqual(inner[TCPerror].dport, external_port)
6279         except:
6280             self.logger.error(ppp("Unexpected or invalid packet:", p))
6281             raise
6282
6283         # from service back to client
6284         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6285              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6286              TCP(sport=local_port, dport=12345))
6287         self.pg0.add_stream(p)
6288         self.pg_enable_capture(self.pg_interfaces)
6289         self.pg_start()
6290         capture = self.pg1.get_capture(1)
6291         p = capture[0]
6292         try:
6293             ip = p[IP]
6294             tcp = p[TCP]
6295             self.assertEqual(ip.src, self.nat_addr)
6296             self.assertEqual(tcp.sport, external_port)
6297             self.assert_packet_checksums_valid(p)
6298         except:
6299             self.logger.error(ppp("Unexpected or invalid packet:", p))
6300             raise
6301
6302         # ICMP error
6303         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6304              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6305              ICMP(type=11) / capture[0][IP])
6306         self.pg1.add_stream(p)
6307         self.pg_enable_capture(self.pg_interfaces)
6308         self.pg_start()
6309         capture = self.pg0.get_capture(1)
6310         p = capture[0]
6311         try:
6312             self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
6313             inner = p[IPerror]
6314             self.assertEqual(inner.src, self.pg0.remote_ip4)
6315             self.assertEqual(inner[TCPerror].sport, local_port)
6316         except:
6317             self.logger.error(ppp("Unexpected or invalid packet:", p))
6318             raise
6319
6320         # from client to server (no translation)
6321         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6322              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
6323              TCP(sport=12346, dport=local_port))
6324         self.pg1.add_stream(p)
6325         self.pg_enable_capture(self.pg_interfaces)
6326         self.pg_start()
6327         capture = self.pg0.get_capture(1)
6328         p = capture[0]
6329         try:
6330             ip = p[IP]
6331             tcp = p[TCP]
6332             self.assertEqual(ip.dst, self.pg0.remote_ip4)
6333             self.assertEqual(tcp.dport, local_port)
6334             self.assert_packet_checksums_valid(p)
6335         except:
6336             self.logger.error(ppp("Unexpected or invalid packet:", p))
6337             raise
6338
6339         # from service back to client (no translation)
6340         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6341              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6342              TCP(sport=local_port, dport=12346))
6343         self.pg0.add_stream(p)
6344         self.pg_enable_capture(self.pg_interfaces)
6345         self.pg_start()
6346         capture = self.pg1.get_capture(1)
6347         p = capture[0]
6348         try:
6349             ip = p[IP]
6350             tcp = p[TCP]
6351             self.assertEqual(ip.src, self.pg0.remote_ip4)
6352             self.assertEqual(tcp.sport, local_port)
6353             self.assert_packet_checksums_valid(p)
6354         except:
6355             self.logger.error(ppp("Unexpected or invalid packet:", p))
6356             raise
6357
6358     def test_output_feature(self):
6359         """ NAT44 interface output feature (in2out postrouting) """
6360         self.vapi.nat44_forwarding_enable_disable(enable=1)
6361         self.nat44_add_address(self.nat_addr)
6362         self.vapi.nat44_interface_add_del_feature(
6363             sw_if_index=self.pg0.sw_if_index,
6364             is_add=1)
6365         self.vapi.nat44_interface_add_del_output_feature(
6366             is_add=1,
6367             sw_if_index=self.pg1.sw_if_index)
6368
6369         # in2out
6370         pkts = self.create_stream_in(self.pg0, self.pg1)
6371         self.pg0.add_stream(pkts)
6372         self.pg_enable_capture(self.pg_interfaces)
6373         self.pg_start()
6374         capture = self.pg1.get_capture(len(pkts))
6375         self.verify_capture_out(capture, ignore_port=True)
6376
6377         # out2in
6378         pkts = self.create_stream_out(self.pg1)
6379         self.pg1.add_stream(pkts)
6380         self.pg_enable_capture(self.pg_interfaces)
6381         self.pg_start()
6382         capture = self.pg0.get_capture(len(pkts))
6383         self.verify_capture_in(capture, self.pg0)
6384
6385     def test_output_feature_stateful_acl(self):
6386         """ NAT44 endpoint-dependent output feature works with stateful ACL """
6387         self.nat44_add_address(self.nat_addr)
6388         self.vapi.nat44_interface_add_del_output_feature(
6389             sw_if_index=self.pg0.sw_if_index,
6390             flags=self.config_flags.NAT_IS_INSIDE,
6391             is_add=1)
6392         self.vapi.nat44_interface_add_del_output_feature(
6393             sw_if_index=self.pg1.sw_if_index,
6394             flags=self.config_flags.NAT_IS_OUTSIDE,
6395             is_add=1)
6396
6397         # First ensure that the NAT is working sans ACL
6398
6399         # send packets out2in, no sessions yet so packets should drop
6400         pkts_out2in = self.create_stream_out(self.pg1)
6401         self.send_and_assert_no_replies(self.pg1, pkts_out2in)
6402
6403         # send packets into inside intf, ensure received via outside intf
6404         pkts_in2out = self.create_stream_in(self.pg0, self.pg1)
6405         capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
6406                                        len(pkts_in2out))
6407         self.verify_capture_out(capture, ignore_port=True)
6408
6409         # send out2in again, with sessions created it should work now
6410         pkts_out2in = self.create_stream_out(self.pg1)
6411         capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
6412                                        len(pkts_out2in))
6413         self.verify_capture_in(capture, self.pg0)
6414
6415         # Create an ACL blocking everything
6416         out2in_deny_rule = AclRule(is_permit=0)
6417         out2in_acl = VppAcl(self, rules=[out2in_deny_rule])
6418         out2in_acl.add_vpp_config()
6419
6420         # create an ACL to permit/reflect everything
6421         in2out_reflect_rule = AclRule(is_permit=2)
6422         in2out_acl = VppAcl(self, rules=[in2out_reflect_rule])
6423         in2out_acl.add_vpp_config()
6424
6425         # apply as input acl on interface and confirm it blocks everything
6426         acl_if = VppAclInterface(self, sw_if_index=self.pg1.sw_if_index,
6427                                  n_input=1, acls=[out2in_acl])
6428         acl_if.add_vpp_config()
6429         self.send_and_assert_no_replies(self.pg1, pkts_out2in)
6430
6431         # apply output acl
6432         acl_if.acls = [out2in_acl, in2out_acl]
6433         acl_if.add_vpp_config()
6434         # send in2out to generate ACL state (NAT state was created earlier)
6435         capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
6436                                        len(pkts_in2out))
6437         self.verify_capture_out(capture, ignore_port=True)
6438
6439         # send out2in again. ACL state exists so it should work now.
6440         # TCP packets with the syn flag set also need the ack flag
6441         for p in pkts_out2in:
6442             if p.haslayer(TCP) and p[TCP].flags & 0x02:
6443                 p[TCP].flags |= 0x10
6444         capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
6445                                        len(pkts_out2in))
6446         self.verify_capture_in(capture, self.pg0)
6447         self.logger.info(self.vapi.cli("show trace"))
6448
6449     def test_multiple_vrf(self):
6450         """ Multiple VRF setup """
6451         external_addr = '1.2.3.4'
6452         external_port = 80
6453         local_port = 8080
6454         port = 0
6455
6456         self.vapi.nat44_forwarding_enable_disable(enable=1)
6457         self.nat44_add_address(self.nat_addr)
6458         flags = self.config_flags.NAT_IS_INSIDE
6459         self.vapi.nat44_interface_add_del_feature(
6460             sw_if_index=self.pg0.sw_if_index,
6461             is_add=1)
6462         self.vapi.nat44_interface_add_del_feature(
6463             sw_if_index=self.pg0.sw_if_index,
6464             is_add=1, flags=flags)
6465         self.vapi.nat44_interface_add_del_output_feature(
6466             sw_if_index=self.pg1.sw_if_index,
6467             is_add=1)
6468         self.vapi.nat44_interface_add_del_feature(
6469             sw_if_index=self.pg5.sw_if_index,
6470             is_add=1)
6471         self.vapi.nat44_interface_add_del_feature(
6472             sw_if_index=self.pg5.sw_if_index,
6473             is_add=1, flags=flags)
6474         self.vapi.nat44_interface_add_del_feature(
6475             sw_if_index=self.pg6.sw_if_index,
6476             is_add=1)
6477         flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6478         self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
6479                                       local_port, external_port, vrf_id=1,
6480                                       proto=IP_PROTOS.tcp, flags=flags)
6481         self.nat44_add_static_mapping(
6482             self.pg0.remote_ip4,
6483             external_sw_if_index=self.pg0.sw_if_index,
6484             local_port=local_port,
6485             vrf_id=0,
6486             external_port=external_port,
6487             proto=IP_PROTOS.tcp,
6488             flags=flags
6489         )
6490
6491         # from client to service (both VRF1)
6492         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6493              IP(src=self.pg6.remote_ip4, dst=external_addr) /
6494              TCP(sport=12345, dport=external_port))
6495         self.pg6.add_stream(p)
6496         self.pg_enable_capture(self.pg_interfaces)
6497         self.pg_start()
6498         capture = self.pg5.get_capture(1)
6499         p = capture[0]
6500         try:
6501             ip = p[IP]
6502             tcp = p[TCP]
6503             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6504             self.assertEqual(tcp.dport, local_port)
6505             self.assert_packet_checksums_valid(p)
6506         except:
6507             self.logger.error(ppp("Unexpected or invalid packet:", p))
6508             raise
6509
6510         # from service back to client (both VRF1)
6511         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6512              IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6513              TCP(sport=local_port, dport=12345))
6514         self.pg5.add_stream(p)
6515         self.pg_enable_capture(self.pg_interfaces)
6516         self.pg_start()
6517         capture = self.pg6.get_capture(1)
6518         p = capture[0]
6519         try:
6520             ip = p[IP]
6521             tcp = p[TCP]
6522             self.assertEqual(ip.src, external_addr)
6523             self.assertEqual(tcp.sport, external_port)
6524             self.assert_packet_checksums_valid(p)
6525         except:
6526             self.logger.error(ppp("Unexpected or invalid packet:", p))
6527             raise
6528
6529         # dynamic NAT from VRF1 to VRF0 (output-feature)
6530         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6531              IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6532              TCP(sport=2345, dport=22))
6533         self.pg5.add_stream(p)
6534         self.pg_enable_capture(self.pg_interfaces)
6535         self.pg_start()
6536         capture = self.pg1.get_capture(1)
6537         p = capture[0]
6538         try:
6539             ip = p[IP]
6540             tcp = p[TCP]
6541             self.assertEqual(ip.src, self.nat_addr)
6542             self.assert_packet_checksums_valid(p)
6543             port = tcp.sport
6544         except:
6545             self.logger.error(ppp("Unexpected or invalid packet:", p))
6546             raise
6547
6548         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6549              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6550              TCP(sport=22, dport=port))
6551         self.pg1.add_stream(p)
6552         self.pg_enable_capture(self.pg_interfaces)
6553         self.pg_start()
6554         capture = self.pg5.get_capture(1)
6555         p = capture[0]
6556         try:
6557             ip = p[IP]
6558             tcp = p[TCP]
6559             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6560             self.assertEqual(tcp.dport, 2345)
6561             self.assert_packet_checksums_valid(p)
6562         except:
6563             self.logger.error(ppp("Unexpected or invalid packet:", p))
6564             raise
6565
6566         # from client VRF1 to service VRF0
6567         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6568              IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6569              TCP(sport=12346, dport=external_port))
6570         self.pg6.add_stream(p)
6571         self.pg_enable_capture(self.pg_interfaces)
6572         self.pg_start()
6573         capture = self.pg0.get_capture(1)
6574         p = capture[0]
6575         try:
6576             ip = p[IP]
6577             tcp = p[TCP]
6578             self.assertEqual(ip.dst, self.pg0.remote_ip4)
6579             self.assertEqual(tcp.dport, local_port)
6580             self.assert_packet_checksums_valid(p)
6581         except:
6582             self.logger.error(ppp("Unexpected or invalid packet:", p))
6583             raise
6584
6585         # from service VRF0 back to client VRF1
6586         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6587              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6588              TCP(sport=local_port, dport=12346))
6589         self.pg0.add_stream(p)
6590         self.pg_enable_capture(self.pg_interfaces)
6591         self.pg_start()
6592         capture = self.pg6.get_capture(1)
6593         p = capture[0]
6594         try:
6595             ip = p[IP]
6596             tcp = p[TCP]
6597             self.assertEqual(ip.src, self.pg0.local_ip4)
6598             self.assertEqual(tcp.sport, external_port)
6599             self.assert_packet_checksums_valid(p)
6600         except:
6601             self.logger.error(ppp("Unexpected or invalid packet:", p))
6602             raise
6603
6604         # from client VRF0 to service VRF1
6605         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6606              IP(src=self.pg0.remote_ip4, dst=external_addr) /
6607              TCP(sport=12347, dport=external_port))
6608         self.pg0.add_stream(p)
6609         self.pg_enable_capture(self.pg_interfaces)
6610         self.pg_start()
6611         capture = self.pg5.get_capture(1)
6612         p = capture[0]
6613         try:
6614             ip = p[IP]
6615             tcp = p[TCP]
6616             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6617             self.assertEqual(tcp.dport, local_port)
6618             self.assert_packet_checksums_valid(p)
6619         except:
6620             self.logger.error(ppp("Unexpected or invalid packet:", p))
6621             raise
6622
6623         # from service VRF1 back to client VRF0
6624         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6625              IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6626              TCP(sport=local_port, dport=12347))
6627         self.pg5.add_stream(p)
6628         self.pg_enable_capture(self.pg_interfaces)
6629         self.pg_start()
6630         capture = self.pg0.get_capture(1)
6631         p = capture[0]
6632         try:
6633             ip = p[IP]
6634             tcp = p[TCP]
6635             self.assertEqual(ip.src, external_addr)
6636             self.assertEqual(tcp.sport, external_port)
6637             self.assert_packet_checksums_valid(p)
6638         except:
6639             self.logger.error(ppp("Unexpected or invalid packet:", p))
6640             raise
6641
6642         # from client to server (both VRF1, no translation)
6643         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6644              IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6645              TCP(sport=12348, dport=local_port))
6646         self.pg6.add_stream(p)
6647         self.pg_enable_capture(self.pg_interfaces)
6648         self.pg_start()
6649         capture = self.pg5.get_capture(1)
6650         p = capture[0]
6651         try:
6652             ip = p[IP]
6653             tcp = p[TCP]
6654             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6655             self.assertEqual(tcp.dport, local_port)
6656             self.assert_packet_checksums_valid(p)
6657         except:
6658             self.logger.error(ppp("Unexpected or invalid packet:", p))
6659             raise
6660
6661         # from server back to client (both VRF1, no translation)
6662         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6663              IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6664              TCP(sport=local_port, dport=12348))
6665         self.pg5.add_stream(p)
6666         self.pg_enable_capture(self.pg_interfaces)
6667         self.pg_start()
6668         capture = self.pg6.get_capture(1)
6669         p = capture[0]
6670         try:
6671             ip = p[IP]
6672             tcp = p[TCP]
6673             self.assertEqual(ip.src, self.pg5.remote_ip4)
6674             self.assertEqual(tcp.sport, local_port)
6675             self.assert_packet_checksums_valid(p)
6676         except:
6677             self.logger.error(ppp("Unexpected or invalid packet:", p))
6678             raise
6679
6680         # from client VRF1 to server VRF0 (no translation)
6681         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6682              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6683              TCP(sport=local_port, dport=12349))
6684         self.pg0.add_stream(p)
6685         self.pg_enable_capture(self.pg_interfaces)
6686         self.pg_start()
6687         capture = self.pg6.get_capture(1)
6688         p = capture[0]
6689         try:
6690             ip = p[IP]
6691             tcp = p[TCP]
6692             self.assertEqual(ip.src, self.pg0.remote_ip4)
6693             self.assertEqual(tcp.sport, local_port)
6694             self.assert_packet_checksums_valid(p)
6695         except:
6696             self.logger.error(ppp("Unexpected or invalid packet:", p))
6697             raise
6698
6699         # from server VRF0 back to client VRF1 (no translation)
6700         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6701              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6702              TCP(sport=local_port, dport=12349))
6703         self.pg0.add_stream(p)
6704         self.pg_enable_capture(self.pg_interfaces)
6705         self.pg_start()
6706         capture = self.pg6.get_capture(1)
6707         p = capture[0]
6708         try:
6709             ip = p[IP]
6710             tcp = p[TCP]
6711             self.assertEqual(ip.src, self.pg0.remote_ip4)
6712             self.assertEqual(tcp.sport, local_port)
6713             self.assert_packet_checksums_valid(p)
6714         except:
6715             self.logger.error(ppp("Unexpected or invalid packet:", p))
6716             raise
6717
6718         # from client VRF0 to server VRF1 (no translation)
6719         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6720              IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6721              TCP(sport=12344, dport=local_port))
6722         self.pg0.add_stream(p)
6723         self.pg_enable_capture(self.pg_interfaces)
6724         self.pg_start()
6725         capture = self.pg5.get_capture(1)
6726         p = capture[0]
6727         try:
6728             ip = p[IP]
6729             tcp = p[TCP]
6730             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6731             self.assertEqual(tcp.dport, local_port)
6732             self.assert_packet_checksums_valid(p)
6733         except:
6734             self.logger.error(ppp("Unexpected or invalid packet:", p))
6735             raise
6736
6737         # from server VRF1 back to client VRF0 (no translation)
6738         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6739              IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6740              TCP(sport=local_port, dport=12344))
6741         self.pg5.add_stream(p)
6742         self.pg_enable_capture(self.pg_interfaces)
6743         self.pg_start()
6744         capture = self.pg0.get_capture(1)
6745         p = capture[0]
6746         try:
6747             ip = p[IP]
6748             tcp = p[TCP]
6749             self.assertEqual(ip.src, self.pg5.remote_ip4)
6750             self.assertEqual(tcp.sport, local_port)
6751             self.assert_packet_checksums_valid(p)
6752         except:
6753             self.logger.error(ppp("Unexpected or invalid packet:", p))
6754             raise
6755
6756     def test_session_rst_timeout(self):
6757         """ NAT44 session RST timeouts """
6758         self.nat44_add_address(self.nat_addr)
6759         flags = self.config_flags.NAT_IS_INSIDE
6760         self.vapi.nat44_interface_add_del_feature(
6761             sw_if_index=self.pg0.sw_if_index,
6762             flags=flags, is_add=1)
6763         self.vapi.nat44_interface_add_del_feature(
6764             sw_if_index=self.pg1.sw_if_index,
6765             is_add=1)
6766         self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6767                                    tcp_transitory=5, icmp=60)
6768
6769         self.initiate_tcp_session(self.pg0, self.pg1)
6770         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6771              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6772              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6773                  flags="R"))
6774         self.pg0.add_stream(p)
6775         self.pg_enable_capture(self.pg_interfaces)
6776         self.pg_start()
6777         self.pg1.get_capture(1)
6778
6779         sleep(6)
6780
6781         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6782              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6783              TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6784                  flags="S"))
6785         self.pg0.add_stream(p)
6786         self.pg_enable_capture(self.pg_interfaces)
6787         self.pg_start()
6788         self.pg1.get_capture(1)
6789
6790     def test_syslog_sess(self):
6791         """ Test syslog session creation and deletion """
6792         self.vapi.syslog_set_filter(
6793             self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
6794         self.vapi.syslog_set_sender(self.pg2.local_ip4, self.pg2.remote_ip4)
6795         self.nat44_add_address(self.nat_addr)
6796         flags = self.config_flags.NAT_IS_INSIDE
6797         self.vapi.nat44_interface_add_del_feature(
6798             sw_if_index=self.pg0.sw_if_index,
6799             flags=flags, is_add=1)
6800         self.vapi.nat44_interface_add_del_feature(
6801             sw_if_index=self.pg1.sw_if_index,
6802             is_add=1)
6803
6804         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6805              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6806              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6807         self.pg0.add_stream(p)
6808         self.pg_enable_capture(self.pg_interfaces)
6809         self.pg_start()
6810         capture = self.pg1.get_capture(1)
6811         self.tcp_port_out = capture[0][TCP].sport
6812         capture = self.pg2.get_capture(1)
6813         self.verify_syslog_sess(capture[0][Raw].load)
6814
6815         self.pg_enable_capture(self.pg_interfaces)
6816         self.pg_start()
6817         self.nat44_add_address(self.nat_addr, is_add=0)
6818         capture = self.pg2.get_capture(1)
6819         self.verify_syslog_sess(capture[0][Raw].load, False)
6820
6821     def test_ed_users_dump(self):
6822         """ API test - nat44_user_dump """
6823         flags = self.config_flags.NAT_IS_INSIDE
6824         self.vapi.nat44_interface_add_del_feature(
6825             sw_if_index=self.pg0.sw_if_index,
6826             flags=flags, is_add=1)
6827         self.vapi.nat44_interface_add_del_feature(
6828             sw_if_index=self.pg1.sw_if_index,
6829             is_add=1)
6830         self.vapi.nat44_forwarding_enable_disable(enable=1)
6831
6832         real_ip = self.pg0.remote_ip4
6833         alias_ip = self.nat_addr
6834         flags = self.config_flags.NAT_IS_ADDR_ONLY
6835         self.vapi.nat44_add_del_static_mapping(is_add=1,
6836                                                local_ip_address=real_ip,
6837                                                external_ip_address=alias_ip,
6838                                                external_sw_if_index=0xFFFFFFFF,
6839                                                flags=flags)
6840
6841         users = self.vapi.nat44_user_dump()
6842         self.assertEqual(len(users), 0)
6843         try:
6844             # in2out - static mapping match
6845
6846             pkts = self.create_stream_out(self.pg1)
6847             self.pg1.add_stream(pkts)
6848             self.pg_enable_capture(self.pg_interfaces)
6849             self.pg_start()
6850             capture = self.pg0.get_capture(len(pkts))
6851             self.verify_capture_in(capture, self.pg0)
6852
6853             pkts = self.create_stream_in(self.pg0, self.pg1)
6854             self.pg0.add_stream(pkts)
6855             self.pg_enable_capture(self.pg_interfaces)
6856             self.pg_start()
6857             capture = self.pg1.get_capture(len(pkts))
6858             self.verify_capture_out(capture, same_port=True)
6859
6860             users = self.vapi.nat44_user_dump()
6861             self.assertEqual(len(users), 1)
6862             static_user = users[0]
6863             self.assertEqual(static_user.nstaticsessions, 3)
6864             self.assertEqual(static_user.nsessions, 0)
6865
6866             # in2out - no static mapping match
6867
6868             host0 = self.pg0.remote_hosts[0]
6869             self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
6870             try:
6871                 pkts = self.create_stream_out(self.pg1,
6872                                               dst_ip=self.pg0.remote_ip4,
6873                                               use_inside_ports=True)
6874                 self.pg1.add_stream(pkts)
6875                 self.pg_enable_capture(self.pg_interfaces)
6876                 self.pg_start()
6877                 capture = self.pg0.get_capture(len(pkts))
6878                 self.verify_capture_in(capture, self.pg0)
6879
6880                 pkts = self.create_stream_in(self.pg0, self.pg1)
6881                 self.pg0.add_stream(pkts)
6882                 self.pg_enable_capture(self.pg_interfaces)
6883                 self.pg_start()
6884                 capture = self.pg1.get_capture(len(pkts))
6885                 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
6886                                         same_port=True)
6887             finally:
6888                 self.pg0.remote_hosts[0] = host0
6889
6890             users = self.vapi.nat44_user_dump()
6891             self.assertEqual(len(users), 2)
6892             if str(users[0].ip_address) == self.pg0.remote_hosts[0].ip4:
6893                 non_static_user = users[1]
6894                 static_user = users[0]
6895             else:
6896                 non_static_user = users[0]
6897                 static_user = users[1]
6898             self.assertEqual(static_user.nstaticsessions, 3)
6899             self.assertEqual(static_user.nsessions, 0)
6900             self.assertEqual(non_static_user.nstaticsessions, 0)
6901             self.assertEqual(non_static_user.nsessions, 3)
6902
6903             users = self.vapi.nat44_user_dump()
6904             self.assertEqual(len(users), 2)
6905             if str(users[0].ip_address) == self.pg0.remote_hosts[0].ip4:
6906                 non_static_user = users[1]
6907                 static_user = users[0]
6908             else:
6909                 non_static_user = users[0]
6910                 static_user = users[1]
6911             self.assertEqual(static_user.nstaticsessions, 3)
6912             self.assertEqual(static_user.nsessions, 0)
6913             self.assertEqual(non_static_user.nstaticsessions, 0)
6914             self.assertEqual(non_static_user.nsessions, 3)
6915
6916         finally:
6917             self.vapi.nat44_forwarding_enable_disable(enable=0)
6918             flags = self.config_flags.NAT_IS_ADDR_ONLY
6919             self.vapi.nat44_add_del_static_mapping(
6920                 is_add=0,
6921                 local_ip_address=real_ip,
6922                 external_ip_address=alias_ip,
6923                 external_sw_if_index=0xFFFFFFFF,
6924                 flags=flags)
6925
6926     def show_commands_at_teardown(self):
6927         self.logger.info(self.vapi.cli("show errors"))
6928         self.logger.info(self.vapi.cli("show nat44 addresses"))
6929         self.logger.info(self.vapi.cli("show nat44 interfaces"))
6930         self.logger.info(self.vapi.cli("show nat44 static mappings"))
6931         self.logger.info(self.vapi.cli("show nat44 interface address"))
6932         self.logger.info(self.vapi.cli("show nat44 sessions detail"))
6933         self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
6934         self.logger.info(self.vapi.cli("show nat timeouts"))
6935         self.logger.info(self.vapi.cli("debug nat44 fib registration"))
6936
6937
6938 class TestNAT44EndpointDependent3(MethodHolder):
6939     """ Endpoint-Dependent mapping and filtering extra test cases """
6940
6941     max_translations = 50
6942
6943     @classmethod
6944     def setUpClass(cls):
6945         super(TestNAT44EndpointDependent3, cls).setUpClass()
6946         cls.vapi.cli("set log class nat level debug")
6947
6948         cls.nat_addr = '10.0.0.3'
6949
6950         cls.create_pg_interfaces(range(2))
6951
6952         for i in cls.pg_interfaces:
6953             i.admin_up()
6954             i.config_ip4()
6955             i.resolve_arp()
6956
6957     def setUp(self):
6958         super(TestNAT44EndpointDependent3, self).setUp()
6959         flags = self.nat44_config_flags.NAT44_IS_ENDPOINT_DEPENDENT
6960         self.vapi.nat44_plugin_enable_disable(
6961             sessions=self.max_translations,
6962             flags=flags, enable=1)
6963         self.vapi.nat_set_timeouts(
6964             udp=1, tcp_established=7440, tcp_transitory=30, icmp=1)
6965
6966         self.nat44_add_address(self.nat_addr)
6967         flags = self.config_flags.NAT_IS_INSIDE
6968         self.vapi.nat44_interface_add_del_feature(
6969             sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1)
6970         self.vapi.nat44_interface_add_del_feature(
6971             sw_if_index=self.pg1.sw_if_index, is_add=1)
6972
6973     @classmethod
6974     def tearDownClass(cls):
6975         super(TestNAT44EndpointDependent3, cls).tearDownClass()
6976
6977     def tearDown(self):
6978         super(TestNAT44EndpointDependent3, self).tearDown()
6979         if not self.vpp_dead:
6980             self.vapi.nat44_plugin_enable_disable(enable=0)
6981             self.vapi.cli("clear logging")
6982
6983     def init_tcp_session(self, in_if, out_if, sport, ext_dport):
6984         # SYN packet in->out
6985         p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
6986              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
6987              TCP(sport=sport, dport=ext_dport, flags="S"))
6988         in_if.add_stream(p)
6989         self.pg_enable_capture(self.pg_interfaces)
6990         self.pg_start()
6991         capture = out_if.get_capture(1)
6992         p = capture[0]
6993         tcp_port_out = p[TCP].sport
6994
6995         # SYN + ACK packet out->in
6996         p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
6997              IP(src=out_if.remote_ip4, dst=self.nat_addr) /
6998              TCP(sport=ext_dport, dport=tcp_port_out, flags="SA"))
6999         out_if.add_stream(p)
7000         self.pg_enable_capture(self.pg_interfaces)
7001         self.pg_start()
7002         in_if.get_capture(1)
7003
7004         # ACK packet in->out
7005         p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
7006              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
7007              TCP(sport=sport, dport=ext_dport, flags="A"))
7008         in_if.add_stream(p)
7009         self.pg_enable_capture(self.pg_interfaces)
7010         self.pg_start()
7011         out_if.get_capture(1)
7012
7013         return tcp_port_out
7014
7015     def test_lru_cleanup(self):
7016         """ LRU cleanup algorithm """
7017         tcp_port_out = self.init_tcp_session(self.pg0, self.pg1, 2000, 80)
7018         pkts = []
7019         for i in range(0, self.max_translations - 1):
7020             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7021                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
7022                  UDP(sport=7000+i, dport=80))
7023             pkts.append(p)
7024
7025         self.pg0.add_stream(pkts)
7026         self.pg_enable_capture(self.pg_interfaces)
7027         self.pg_start()
7028         self.pg1.get_capture(len(pkts))
7029         self.sleep(1.5, "wait for timeouts")
7030
7031         pkts = []
7032         for i in range(0, self.max_translations - 1):
7033             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7034                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
7035                  ICMP(id=8000+i, type='echo-request'))
7036             pkts.append(p)
7037
7038         self.pg0.add_stream(pkts)
7039         self.pg_enable_capture(self.pg_interfaces)
7040         self.pg_start()
7041         self.pg1.get_capture(len(pkts))
7042
7043
7044 class TestNAT44Out2InDPO(MethodHolder):
7045     """ NAT44 Test Cases using out2in DPO """
7046
7047     @classmethod
7048     def setUpClass(cls):
7049         super(TestNAT44Out2InDPO, cls).setUpClass()
7050         cls.vapi.cli("set log class nat level debug")
7051
7052         cls.tcp_port_in = 6303
7053         cls.tcp_port_out = 6303
7054         cls.udp_port_in = 6304
7055         cls.udp_port_out = 6304
7056         cls.icmp_id_in = 6305
7057         cls.icmp_id_out = 6305
7058         cls.nat_addr = '10.0.0.3'
7059         cls.dst_ip4 = '192.168.70.1'
7060
7061         cls.create_pg_interfaces(range(2))
7062
7063         cls.pg0.admin_up()
7064         cls.pg0.config_ip4()
7065         cls.pg0.resolve_arp()
7066
7067         cls.pg1.admin_up()
7068         cls.pg1.config_ip6()
7069         cls.pg1.resolve_ndp()
7070
7071         r1 = VppIpRoute(cls, "::", 0,
7072                         [VppRoutePath(cls.pg1.remote_ip6,
7073                                       cls.pg1.sw_if_index)],
7074                         register=False)
7075         r1.add_vpp_config()
7076
7077     @classmethod
7078     def tearDownClass(cls):
7079         super(TestNAT44Out2InDPO, cls).tearDownClass()
7080
7081     def setUp(self):
7082         super(TestNAT44Out2InDPO, self).setUp()
7083         flags = self.nat44_config_flags.NAT44_API_IS_OUT2IN_DPO
7084         self.vapi.nat44_plugin_enable_disable(enable=1, flags=flags)
7085
7086     def tearDown(self):
7087         super(TestNAT44Out2InDPO, self).tearDown()
7088         if not self.vpp_dead:
7089             self.vapi.nat44_plugin_enable_disable(enable=0)
7090             self.vapi.cli("clear logging")
7091
7092     def configure_xlat(self):
7093         self.dst_ip6_pfx = '1:2:3::'
7094         self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
7095                                               self.dst_ip6_pfx)
7096         self.dst_ip6_pfx_len = 96
7097         self.src_ip6_pfx = '4:5:6::'
7098         self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
7099                                               self.src_ip6_pfx)
7100         self.src_ip6_pfx_len = 96
7101         self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
7102                                  self.src_ip6_pfx_n, self.src_ip6_pfx_len,
7103                                  '\x00\x00\x00\x00', 0)
7104
7105     @unittest.skip('Temporary disabled')
7106     def test_464xlat_ce(self):
7107         """ Test 464XLAT CE with NAT44 """
7108
7109         nat_config = self.vapi.nat_show_config()
7110         self.assertEqual(1, nat_config.out2in_dpo)
7111
7112         self.configure_xlat()
7113
7114         flags = self.config_flags.NAT_IS_INSIDE
7115         self.vapi.nat44_interface_add_del_feature(
7116             sw_if_index=self.pg0.sw_if_index,
7117             flags=flags, is_add=1)
7118         self.vapi.nat44_add_del_address_range(first_ip_address=self.nat_addr_n,
7119                                               last_ip_address=self.nat_addr_n,
7120                                               vrf_id=0xFFFFFFFF, is_add=1)
7121
7122         out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7123                                        self.dst_ip6_pfx_len)
7124         out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
7125                                        self.src_ip6_pfx_len)
7126
7127         try:
7128             pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7129             self.pg0.add_stream(pkts)
7130             self.pg_enable_capture(self.pg_interfaces)
7131             self.pg_start()
7132             capture = self.pg1.get_capture(len(pkts))
7133             self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
7134                                         dst_ip=out_src_ip6)
7135
7136             pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
7137                                               out_dst_ip6)
7138             self.pg1.add_stream(pkts)
7139             self.pg_enable_capture(self.pg_interfaces)
7140             self.pg_start()
7141             capture = self.pg0.get_capture(len(pkts))
7142             self.verify_capture_in(capture, self.pg0)
7143         finally:
7144             self.vapi.nat44_interface_add_del_feature(
7145                 sw_if_index=self.pg0.sw_if_index,
7146                 flags=flags)
7147             self.vapi.nat44_add_del_address_range(
7148                 first_ip_address=self.nat_addr_n,
7149                 last_ip_address=self.nat_addr_n,
7150                 vrf_id=0xFFFFFFFF)
7151
7152     @unittest.skip('Temporary disabled')
7153     def test_464xlat_ce_no_nat(self):
7154         """ Test 464XLAT CE without NAT44 """
7155
7156         self.configure_xlat()
7157
7158         out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7159                                        self.dst_ip6_pfx_len)
7160         out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
7161                                        self.src_ip6_pfx_len)
7162
7163         pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7164         self.pg0.add_stream(pkts)
7165         self.pg_enable_capture(self.pg_interfaces)
7166         self.pg_start()
7167         capture = self.pg1.get_capture(len(pkts))
7168         self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
7169                                     nat_ip=out_dst_ip6, same_port=True)
7170
7171         pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
7172         self.pg1.add_stream(pkts)
7173         self.pg_enable_capture(self.pg_interfaces)
7174         self.pg_start()
7175         capture = self.pg0.get_capture(len(pkts))
7176         self.verify_capture_in(capture, self.pg0)
7177
7178
7179 if __name__ == '__main__':
7180     unittest.main(testRunner=VppTestRunner)