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