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