NAT44: fix bug in TCP close with output-feature interface (VPP-1493)
[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         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
1939         self.assertEqual(len(sessions), 0)
1940         self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n,
1941                                                  vrf_id=1)
1942         identity_mappings = self.vapi.nat44_identity_mapping_dump()
1943         self.assertEqual(len(identity_mappings), 2)
1944
1945     def test_multiple_inside_interfaces(self):
1946         """ NAT44 multiple non-overlapping address space inside interfaces """
1947
1948         self.nat44_add_address(self.nat_addr)
1949         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1950         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1951         self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1952                                                   is_inside=0)
1953
1954         # between two NAT44 inside interfaces (no translation)
1955         pkts = self.create_stream_in(self.pg0, self.pg1)
1956         self.pg0.add_stream(pkts)
1957         self.pg_enable_capture(self.pg_interfaces)
1958         self.pg_start()
1959         capture = self.pg1.get_capture(len(pkts))
1960         self.verify_capture_no_translation(capture, self.pg0, self.pg1)
1961
1962         # from NAT44 inside to interface without NAT44 feature (no translation)
1963         pkts = self.create_stream_in(self.pg0, self.pg2)
1964         self.pg0.add_stream(pkts)
1965         self.pg_enable_capture(self.pg_interfaces)
1966         self.pg_start()
1967         capture = self.pg2.get_capture(len(pkts))
1968         self.verify_capture_no_translation(capture, self.pg0, self.pg2)
1969
1970         # in2out 1st interface
1971         pkts = self.create_stream_in(self.pg0, self.pg3)
1972         self.pg0.add_stream(pkts)
1973         self.pg_enable_capture(self.pg_interfaces)
1974         self.pg_start()
1975         capture = self.pg3.get_capture(len(pkts))
1976         self.verify_capture_out(capture)
1977
1978         # out2in 1st interface
1979         pkts = self.create_stream_out(self.pg3)
1980         self.pg3.add_stream(pkts)
1981         self.pg_enable_capture(self.pg_interfaces)
1982         self.pg_start()
1983         capture = self.pg0.get_capture(len(pkts))
1984         self.verify_capture_in(capture, self.pg0)
1985
1986         # in2out 2nd interface
1987         pkts = self.create_stream_in(self.pg1, self.pg3)
1988         self.pg1.add_stream(pkts)
1989         self.pg_enable_capture(self.pg_interfaces)
1990         self.pg_start()
1991         capture = self.pg3.get_capture(len(pkts))
1992         self.verify_capture_out(capture)
1993
1994         # out2in 2nd interface
1995         pkts = self.create_stream_out(self.pg3)
1996         self.pg3.add_stream(pkts)
1997         self.pg_enable_capture(self.pg_interfaces)
1998         self.pg_start()
1999         capture = self.pg1.get_capture(len(pkts))
2000         self.verify_capture_in(capture, self.pg1)
2001
2002     def test_inside_overlapping_interfaces(self):
2003         """ NAT44 multiple inside interfaces with overlapping address space """
2004
2005         static_nat_ip = "10.0.0.10"
2006         self.nat44_add_address(self.nat_addr)
2007         self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2008                                                   is_inside=0)
2009         self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
2010         self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
2011         self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
2012         self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2013                                       vrf_id=20)
2014
2015         # between NAT44 inside interfaces with same VRF (no translation)
2016         pkts = self.create_stream_in(self.pg4, self.pg5)
2017         self.pg4.add_stream(pkts)
2018         self.pg_enable_capture(self.pg_interfaces)
2019         self.pg_start()
2020         capture = self.pg5.get_capture(len(pkts))
2021         self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2022
2023         # between NAT44 inside interfaces with different VRF (hairpinning)
2024         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2025              IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2026              TCP(sport=1234, dport=5678))
2027         self.pg4.add_stream(p)
2028         self.pg_enable_capture(self.pg_interfaces)
2029         self.pg_start()
2030         capture = self.pg6.get_capture(1)
2031         p = capture[0]
2032         try:
2033             ip = p[IP]
2034             tcp = p[TCP]
2035             self.assertEqual(ip.src, self.nat_addr)
2036             self.assertEqual(ip.dst, self.pg6.remote_ip4)
2037             self.assertNotEqual(tcp.sport, 1234)
2038             self.assertEqual(tcp.dport, 5678)
2039         except:
2040             self.logger.error(ppp("Unexpected or invalid packet:", p))
2041             raise
2042
2043         # in2out 1st interface
2044         pkts = self.create_stream_in(self.pg4, self.pg3)
2045         self.pg4.add_stream(pkts)
2046         self.pg_enable_capture(self.pg_interfaces)
2047         self.pg_start()
2048         capture = self.pg3.get_capture(len(pkts))
2049         self.verify_capture_out(capture)
2050
2051         # out2in 1st interface
2052         pkts = self.create_stream_out(self.pg3)
2053         self.pg3.add_stream(pkts)
2054         self.pg_enable_capture(self.pg_interfaces)
2055         self.pg_start()
2056         capture = self.pg4.get_capture(len(pkts))
2057         self.verify_capture_in(capture, self.pg4)
2058
2059         # in2out 2nd interface
2060         pkts = self.create_stream_in(self.pg5, self.pg3)
2061         self.pg5.add_stream(pkts)
2062         self.pg_enable_capture(self.pg_interfaces)
2063         self.pg_start()
2064         capture = self.pg3.get_capture(len(pkts))
2065         self.verify_capture_out(capture)
2066
2067         # out2in 2nd interface
2068         pkts = self.create_stream_out(self.pg3)
2069         self.pg3.add_stream(pkts)
2070         self.pg_enable_capture(self.pg_interfaces)
2071         self.pg_start()
2072         capture = self.pg5.get_capture(len(pkts))
2073         self.verify_capture_in(capture, self.pg5)
2074
2075         # pg5 session dump
2076         addresses = self.vapi.nat44_address_dump()
2077         self.assertEqual(len(addresses), 1)
2078         sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
2079         self.assertEqual(len(sessions), 3)
2080         for session in sessions:
2081             self.assertFalse(session.is_static)
2082             self.assertEqual(session.inside_ip_address[0:4],
2083                              self.pg5.remote_ip4n)
2084             self.assertEqual(session.outside_ip_address,
2085                              addresses[0].ip_address)
2086         self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2087         self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2088         self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2089         self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2090         self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2091         self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2092         self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2093         self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2094         self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2095
2096         # in2out 3rd interface
2097         pkts = self.create_stream_in(self.pg6, self.pg3)
2098         self.pg6.add_stream(pkts)
2099         self.pg_enable_capture(self.pg_interfaces)
2100         self.pg_start()
2101         capture = self.pg3.get_capture(len(pkts))
2102         self.verify_capture_out(capture, static_nat_ip, True)
2103
2104         # out2in 3rd interface
2105         pkts = self.create_stream_out(self.pg3, static_nat_ip)
2106         self.pg3.add_stream(pkts)
2107         self.pg_enable_capture(self.pg_interfaces)
2108         self.pg_start()
2109         capture = self.pg6.get_capture(len(pkts))
2110         self.verify_capture_in(capture, self.pg6)
2111
2112         # general user and session dump verifications
2113         users = self.vapi.nat44_user_dump()
2114         self.assertTrue(len(users) >= 3)
2115         addresses = self.vapi.nat44_address_dump()
2116         self.assertEqual(len(addresses), 1)
2117         for user in users:
2118             sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2119                                                          user.vrf_id)
2120             for session in sessions:
2121                 self.assertEqual(user.ip_address, session.inside_ip_address)
2122                 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2123                 self.assertTrue(session.protocol in
2124                                 [IP_PROTOS.tcp, IP_PROTOS.udp,
2125                                  IP_PROTOS.icmp])
2126                 self.assertFalse(session.ext_host_valid)
2127
2128         # pg4 session dump
2129         sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
2130         self.assertTrue(len(sessions) >= 4)
2131         for session in sessions:
2132             self.assertFalse(session.is_static)
2133             self.assertEqual(session.inside_ip_address[0:4],
2134                              self.pg4.remote_ip4n)
2135             self.assertEqual(session.outside_ip_address,
2136                              addresses[0].ip_address)
2137
2138         # pg6 session dump
2139         sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
2140         self.assertTrue(len(sessions) >= 3)
2141         for session in sessions:
2142             self.assertTrue(session.is_static)
2143             self.assertEqual(session.inside_ip_address[0:4],
2144                              self.pg6.remote_ip4n)
2145             self.assertEqual(map(ord, session.outside_ip_address[0:4]),
2146                              map(int, static_nat_ip.split('.')))
2147             self.assertTrue(session.inside_port in
2148                             [self.tcp_port_in, self.udp_port_in,
2149                              self.icmp_id_in])
2150
2151     def test_hairpinning(self):
2152         """ NAT44 hairpinning - 1:1 NAPT """
2153
2154         host = self.pg0.remote_hosts[0]
2155         server = self.pg0.remote_hosts[1]
2156         host_in_port = 1234
2157         host_out_port = 0
2158         server_in_port = 5678
2159         server_out_port = 8765
2160
2161         self.nat44_add_address(self.nat_addr)
2162         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2163         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2164                                                   is_inside=0)
2165         # add static mapping for server
2166         self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2167                                       server_in_port, server_out_port,
2168                                       proto=IP_PROTOS.tcp)
2169
2170         # send packet from host to server
2171         p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2172              IP(src=host.ip4, dst=self.nat_addr) /
2173              TCP(sport=host_in_port, dport=server_out_port))
2174         self.pg0.add_stream(p)
2175         self.pg_enable_capture(self.pg_interfaces)
2176         self.pg_start()
2177         capture = self.pg0.get_capture(1)
2178         p = capture[0]
2179         try:
2180             ip = p[IP]
2181             tcp = p[TCP]
2182             self.assertEqual(ip.src, self.nat_addr)
2183             self.assertEqual(ip.dst, server.ip4)
2184             self.assertNotEqual(tcp.sport, host_in_port)
2185             self.assertEqual(tcp.dport, server_in_port)
2186             self.assert_packet_checksums_valid(p)
2187             host_out_port = tcp.sport
2188         except:
2189             self.logger.error(ppp("Unexpected or invalid packet:", p))
2190             raise
2191
2192         # send reply from server to host
2193         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2194              IP(src=server.ip4, dst=self.nat_addr) /
2195              TCP(sport=server_in_port, dport=host_out_port))
2196         self.pg0.add_stream(p)
2197         self.pg_enable_capture(self.pg_interfaces)
2198         self.pg_start()
2199         capture = self.pg0.get_capture(1)
2200         p = capture[0]
2201         try:
2202             ip = p[IP]
2203             tcp = p[TCP]
2204             self.assertEqual(ip.src, self.nat_addr)
2205             self.assertEqual(ip.dst, host.ip4)
2206             self.assertEqual(tcp.sport, server_out_port)
2207             self.assertEqual(tcp.dport, host_in_port)
2208             self.assert_packet_checksums_valid(p)
2209         except:
2210             self.logger.error(ppp("Unexpected or invalid packet:", p))
2211             raise
2212
2213     def test_hairpinning2(self):
2214         """ NAT44 hairpinning - 1:1 NAT"""
2215
2216         server1_nat_ip = "10.0.0.10"
2217         server2_nat_ip = "10.0.0.11"
2218         host = self.pg0.remote_hosts[0]
2219         server1 = self.pg0.remote_hosts[1]
2220         server2 = self.pg0.remote_hosts[2]
2221         server_tcp_port = 22
2222         server_udp_port = 20
2223
2224         self.nat44_add_address(self.nat_addr)
2225         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2226         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2227                                                   is_inside=0)
2228
2229         # add static mapping for servers
2230         self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2231         self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
2232
2233         # host to server1
2234         pkts = []
2235         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2236              IP(src=host.ip4, dst=server1_nat_ip) /
2237              TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2238         pkts.append(p)
2239         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2240              IP(src=host.ip4, dst=server1_nat_ip) /
2241              UDP(sport=self.udp_port_in, dport=server_udp_port))
2242         pkts.append(p)
2243         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2244              IP(src=host.ip4, dst=server1_nat_ip) /
2245              ICMP(id=self.icmp_id_in, type='echo-request'))
2246         pkts.append(p)
2247         self.pg0.add_stream(pkts)
2248         self.pg_enable_capture(self.pg_interfaces)
2249         self.pg_start()
2250         capture = self.pg0.get_capture(len(pkts))
2251         for packet in capture:
2252             try:
2253                 self.assertEqual(packet[IP].src, self.nat_addr)
2254                 self.assertEqual(packet[IP].dst, server1.ip4)
2255                 if packet.haslayer(TCP):
2256                     self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2257                     self.assertEqual(packet[TCP].dport, server_tcp_port)
2258                     self.tcp_port_out = packet[TCP].sport
2259                     self.assert_packet_checksums_valid(packet)
2260                 elif packet.haslayer(UDP):
2261                     self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2262                     self.assertEqual(packet[UDP].dport, server_udp_port)
2263                     self.udp_port_out = packet[UDP].sport
2264                 else:
2265                     self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2266                     self.icmp_id_out = packet[ICMP].id
2267             except:
2268                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2269                 raise
2270
2271         # server1 to host
2272         pkts = []
2273         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2274              IP(src=server1.ip4, dst=self.nat_addr) /
2275              TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2276         pkts.append(p)
2277         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2278              IP(src=server1.ip4, dst=self.nat_addr) /
2279              UDP(sport=server_udp_port, dport=self.udp_port_out))
2280         pkts.append(p)
2281         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2282              IP(src=server1.ip4, dst=self.nat_addr) /
2283              ICMP(id=self.icmp_id_out, type='echo-reply'))
2284         pkts.append(p)
2285         self.pg0.add_stream(pkts)
2286         self.pg_enable_capture(self.pg_interfaces)
2287         self.pg_start()
2288         capture = self.pg0.get_capture(len(pkts))
2289         for packet in capture:
2290             try:
2291                 self.assertEqual(packet[IP].src, server1_nat_ip)
2292                 self.assertEqual(packet[IP].dst, host.ip4)
2293                 if packet.haslayer(TCP):
2294                     self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2295                     self.assertEqual(packet[TCP].sport, server_tcp_port)
2296                     self.assert_packet_checksums_valid(packet)
2297                 elif packet.haslayer(UDP):
2298                     self.assertEqual(packet[UDP].dport, self.udp_port_in)
2299                     self.assertEqual(packet[UDP].sport, server_udp_port)
2300                 else:
2301                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2302             except:
2303                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2304                 raise
2305
2306         # server2 to server1
2307         pkts = []
2308         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2309              IP(src=server2.ip4, dst=server1_nat_ip) /
2310              TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2311         pkts.append(p)
2312         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2313              IP(src=server2.ip4, dst=server1_nat_ip) /
2314              UDP(sport=self.udp_port_in, dport=server_udp_port))
2315         pkts.append(p)
2316         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2317              IP(src=server2.ip4, dst=server1_nat_ip) /
2318              ICMP(id=self.icmp_id_in, type='echo-request'))
2319         pkts.append(p)
2320         self.pg0.add_stream(pkts)
2321         self.pg_enable_capture(self.pg_interfaces)
2322         self.pg_start()
2323         capture = self.pg0.get_capture(len(pkts))
2324         for packet in capture:
2325             try:
2326                 self.assertEqual(packet[IP].src, server2_nat_ip)
2327                 self.assertEqual(packet[IP].dst, server1.ip4)
2328                 if packet.haslayer(TCP):
2329                     self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2330                     self.assertEqual(packet[TCP].dport, server_tcp_port)
2331                     self.tcp_port_out = packet[TCP].sport
2332                     self.assert_packet_checksums_valid(packet)
2333                 elif packet.haslayer(UDP):
2334                     self.assertEqual(packet[UDP].sport, self.udp_port_in)
2335                     self.assertEqual(packet[UDP].dport, server_udp_port)
2336                     self.udp_port_out = packet[UDP].sport
2337                 else:
2338                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2339                     self.icmp_id_out = packet[ICMP].id
2340             except:
2341                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2342                 raise
2343
2344         # server1 to server2
2345         pkts = []
2346         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2347              IP(src=server1.ip4, dst=server2_nat_ip) /
2348              TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2349         pkts.append(p)
2350         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2351              IP(src=server1.ip4, dst=server2_nat_ip) /
2352              UDP(sport=server_udp_port, dport=self.udp_port_out))
2353         pkts.append(p)
2354         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2355              IP(src=server1.ip4, dst=server2_nat_ip) /
2356              ICMP(id=self.icmp_id_out, type='echo-reply'))
2357         pkts.append(p)
2358         self.pg0.add_stream(pkts)
2359         self.pg_enable_capture(self.pg_interfaces)
2360         self.pg_start()
2361         capture = self.pg0.get_capture(len(pkts))
2362         for packet in capture:
2363             try:
2364                 self.assertEqual(packet[IP].src, server1_nat_ip)
2365                 self.assertEqual(packet[IP].dst, server2.ip4)
2366                 if packet.haslayer(TCP):
2367                     self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2368                     self.assertEqual(packet[TCP].sport, server_tcp_port)
2369                     self.assert_packet_checksums_valid(packet)
2370                 elif packet.haslayer(UDP):
2371                     self.assertEqual(packet[UDP].dport, self.udp_port_in)
2372                     self.assertEqual(packet[UDP].sport, server_udp_port)
2373                 else:
2374                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2375             except:
2376                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2377                 raise
2378
2379     def test_max_translations_per_user(self):
2380         """ MAX translations per user - recycle the least recently used """
2381
2382         self.nat44_add_address(self.nat_addr)
2383         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2384         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2385                                                   is_inside=0)
2386
2387         # get maximum number of translations per user
2388         nat44_config = self.vapi.nat_show_config()
2389
2390         # send more than maximum number of translations per user packets
2391         pkts_num = nat44_config.max_translations_per_user + 5
2392         pkts = []
2393         for port in range(0, pkts_num):
2394             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2395                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2396                  TCP(sport=1025 + port))
2397             pkts.append(p)
2398         self.pg0.add_stream(pkts)
2399         self.pg_enable_capture(self.pg_interfaces)
2400         self.pg_start()
2401
2402         # verify number of translated packet
2403         self.pg1.get_capture(pkts_num)
2404
2405         users = self.vapi.nat44_user_dump()
2406         for user in users:
2407             if user.ip_address == self.pg0.remote_ip4n:
2408                 self.assertEqual(user.nsessions,
2409                                  nat44_config.max_translations_per_user)
2410                 self.assertEqual(user.nstaticsessions, 0)
2411
2412         tcp_port = 22
2413         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2414                                       tcp_port, tcp_port,
2415                                       proto=IP_PROTOS.tcp)
2416         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2417              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2418              TCP(sport=tcp_port))
2419         self.pg0.add_stream(p)
2420         self.pg_enable_capture(self.pg_interfaces)
2421         self.pg_start()
2422         self.pg1.get_capture(1)
2423         users = self.vapi.nat44_user_dump()
2424         for user in users:
2425             if user.ip_address == self.pg0.remote_ip4n:
2426                 self.assertEqual(user.nsessions,
2427                                  nat44_config.max_translations_per_user - 1)
2428                 self.assertEqual(user.nstaticsessions, 1)
2429
2430     def test_interface_addr(self):
2431         """ Acquire NAT44 addresses from interface """
2432         self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2433
2434         # no address in NAT pool
2435         adresses = self.vapi.nat44_address_dump()
2436         self.assertEqual(0, len(adresses))
2437
2438         # configure interface address and check NAT address pool
2439         self.pg7.config_ip4()
2440         adresses = self.vapi.nat44_address_dump()
2441         self.assertEqual(1, len(adresses))
2442         self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
2443
2444         # remove interface address and check NAT address pool
2445         self.pg7.unconfig_ip4()
2446         adresses = self.vapi.nat44_address_dump()
2447         self.assertEqual(0, len(adresses))
2448
2449     def test_interface_addr_static_mapping(self):
2450         """ Static mapping with addresses from interface """
2451         tag = "testTAG"
2452
2453         self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2454         self.nat44_add_static_mapping(
2455             '1.2.3.4',
2456             external_sw_if_index=self.pg7.sw_if_index,
2457             tag=tag)
2458
2459         # static mappings with external interface
2460         static_mappings = self.vapi.nat44_static_mapping_dump()
2461         self.assertEqual(1, len(static_mappings))
2462         self.assertEqual(self.pg7.sw_if_index,
2463                          static_mappings[0].external_sw_if_index)
2464         self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2465
2466         # configure interface address and check static mappings
2467         self.pg7.config_ip4()
2468         static_mappings = self.vapi.nat44_static_mapping_dump()
2469         self.assertEqual(2, len(static_mappings))
2470         resolved = False
2471         for sm in static_mappings:
2472             if sm.external_sw_if_index == 0xFFFFFFFF:
2473                 self.assertEqual(sm.external_ip_address[0:4],
2474                                  self.pg7.local_ip4n)
2475                 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2476                 resolved = True
2477         self.assertTrue(resolved)
2478
2479         # remove interface address and check static mappings
2480         self.pg7.unconfig_ip4()
2481         static_mappings = self.vapi.nat44_static_mapping_dump()
2482         self.assertEqual(1, len(static_mappings))
2483         self.assertEqual(self.pg7.sw_if_index,
2484                          static_mappings[0].external_sw_if_index)
2485         self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2486
2487         # configure interface address again and check static mappings
2488         self.pg7.config_ip4()
2489         static_mappings = self.vapi.nat44_static_mapping_dump()
2490         self.assertEqual(2, len(static_mappings))
2491         resolved = False
2492         for sm in static_mappings:
2493             if sm.external_sw_if_index == 0xFFFFFFFF:
2494                 self.assertEqual(sm.external_ip_address[0:4],
2495                                  self.pg7.local_ip4n)
2496                 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2497                 resolved = True
2498         self.assertTrue(resolved)
2499
2500         # remove static mapping
2501         self.nat44_add_static_mapping(
2502             '1.2.3.4',
2503             external_sw_if_index=self.pg7.sw_if_index,
2504             tag=tag,
2505             is_add=0)
2506         static_mappings = self.vapi.nat44_static_mapping_dump()
2507         self.assertEqual(0, len(static_mappings))
2508
2509     def test_interface_addr_identity_nat(self):
2510         """ Identity NAT with addresses from interface """
2511
2512         port = 53053
2513         self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2514         self.vapi.nat44_add_del_identity_mapping(
2515             sw_if_index=self.pg7.sw_if_index,
2516             port=port,
2517             protocol=IP_PROTOS.tcp,
2518             addr_only=0)
2519
2520         # identity mappings with external interface
2521         identity_mappings = self.vapi.nat44_identity_mapping_dump()
2522         self.assertEqual(1, len(identity_mappings))
2523         self.assertEqual(self.pg7.sw_if_index,
2524                          identity_mappings[0].sw_if_index)
2525
2526         # configure interface address and check identity mappings
2527         self.pg7.config_ip4()
2528         identity_mappings = self.vapi.nat44_identity_mapping_dump()
2529         resolved = False
2530         self.assertEqual(2, len(identity_mappings))
2531         for sm in identity_mappings:
2532             if sm.sw_if_index == 0xFFFFFFFF:
2533                 self.assertEqual(identity_mappings[0].ip_address,
2534                                  self.pg7.local_ip4n)
2535                 self.assertEqual(port, identity_mappings[0].port)
2536                 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2537                 resolved = True
2538         self.assertTrue(resolved)
2539
2540         # remove interface address and check identity mappings
2541         self.pg7.unconfig_ip4()
2542         identity_mappings = self.vapi.nat44_identity_mapping_dump()
2543         self.assertEqual(1, len(identity_mappings))
2544         self.assertEqual(self.pg7.sw_if_index,
2545                          identity_mappings[0].sw_if_index)
2546
2547     def test_ipfix_nat44_sess(self):
2548         """ IPFIX logging NAT44 session created/delted """
2549         self.ipfix_domain_id = 10
2550         self.ipfix_src_port = 20202
2551         colector_port = 30303
2552         bind_layers(UDP, IPFIX, dport=30303)
2553         self.nat44_add_address(self.nat_addr)
2554         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2555         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2556                                                   is_inside=0)
2557         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2558                                      src_address=self.pg3.local_ip4n,
2559                                      path_mtu=512,
2560                                      template_interval=10,
2561                                      collector_port=colector_port)
2562         self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2563                             src_port=self.ipfix_src_port)
2564
2565         pkts = self.create_stream_in(self.pg0, self.pg1)
2566         self.pg0.add_stream(pkts)
2567         self.pg_enable_capture(self.pg_interfaces)
2568         self.pg_start()
2569         capture = self.pg1.get_capture(len(pkts))
2570         self.verify_capture_out(capture)
2571         self.nat44_add_address(self.nat_addr, is_add=0)
2572         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
2573         capture = self.pg3.get_capture(9)
2574         ipfix = IPFIXDecoder()
2575         # first load template
2576         for p in capture:
2577             self.assertTrue(p.haslayer(IPFIX))
2578             self.assertEqual(p[IP].src, self.pg3.local_ip4)
2579             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2580             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2581             self.assertEqual(p[UDP].dport, colector_port)
2582             self.assertEqual(p[IPFIX].observationDomainID,
2583                              self.ipfix_domain_id)
2584             if p.haslayer(Template):
2585                 ipfix.add_template(p.getlayer(Template))
2586         # verify events in data set
2587         for p in capture:
2588             if p.haslayer(Data):
2589                 data = ipfix.decode_data_set(p.getlayer(Set))
2590                 self.verify_ipfix_nat44_ses(data)
2591
2592     def test_ipfix_addr_exhausted(self):
2593         """ IPFIX logging NAT addresses exhausted """
2594         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2595         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2596                                                   is_inside=0)
2597         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2598                                      src_address=self.pg3.local_ip4n,
2599                                      path_mtu=512,
2600                                      template_interval=10)
2601         self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2602                             src_port=self.ipfix_src_port)
2603
2604         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2605              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2606              TCP(sport=3025))
2607         self.pg0.add_stream(p)
2608         self.pg_enable_capture(self.pg_interfaces)
2609         self.pg_start()
2610         self.pg1.assert_nothing_captured()
2611         sleep(1)
2612         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
2613         capture = self.pg3.get_capture(9)
2614         ipfix = IPFIXDecoder()
2615         # first load template
2616         for p in capture:
2617             self.assertTrue(p.haslayer(IPFIX))
2618             self.assertEqual(p[IP].src, self.pg3.local_ip4)
2619             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2620             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2621             self.assertEqual(p[UDP].dport, 4739)
2622             self.assertEqual(p[IPFIX].observationDomainID,
2623                              self.ipfix_domain_id)
2624             if p.haslayer(Template):
2625                 ipfix.add_template(p.getlayer(Template))
2626         # verify events in data set
2627         for p in capture:
2628             if p.haslayer(Data):
2629                 data = ipfix.decode_data_set(p.getlayer(Set))
2630                 self.verify_ipfix_addr_exhausted(data)
2631
2632     @unittest.skipUnless(running_extended_tests(), "part of extended tests")
2633     def test_ipfix_max_sessions(self):
2634         """ IPFIX logging maximum session entries exceeded """
2635         self.nat44_add_address(self.nat_addr)
2636         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2637         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2638                                                   is_inside=0)
2639
2640         nat44_config = self.vapi.nat_show_config()
2641         max_sessions = 10 * nat44_config.translation_buckets
2642
2643         pkts = []
2644         for i in range(0, max_sessions):
2645             src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2646             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2647                  IP(src=src, dst=self.pg1.remote_ip4) /
2648                  TCP(sport=1025))
2649             pkts.append(p)
2650         self.pg0.add_stream(pkts)
2651         self.pg_enable_capture(self.pg_interfaces)
2652         self.pg_start()
2653
2654         self.pg1.get_capture(max_sessions)
2655         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2656                                      src_address=self.pg3.local_ip4n,
2657                                      path_mtu=512,
2658                                      template_interval=10)
2659         self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2660                             src_port=self.ipfix_src_port)
2661
2662         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2663              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2664              TCP(sport=1025))
2665         self.pg0.add_stream(p)
2666         self.pg_enable_capture(self.pg_interfaces)
2667         self.pg_start()
2668         self.pg1.assert_nothing_captured()
2669         sleep(1)
2670         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
2671         capture = self.pg3.get_capture(9)
2672         ipfix = IPFIXDecoder()
2673         # first load template
2674         for p in capture:
2675             self.assertTrue(p.haslayer(IPFIX))
2676             self.assertEqual(p[IP].src, self.pg3.local_ip4)
2677             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2678             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2679             self.assertEqual(p[UDP].dport, 4739)
2680             self.assertEqual(p[IPFIX].observationDomainID,
2681                              self.ipfix_domain_id)
2682             if p.haslayer(Template):
2683                 ipfix.add_template(p.getlayer(Template))
2684         # verify events in data set
2685         for p in capture:
2686             if p.haslayer(Data):
2687                 data = ipfix.decode_data_set(p.getlayer(Set))
2688                 self.verify_ipfix_max_sessions(data, max_sessions)
2689
2690     def test_pool_addr_fib(self):
2691         """ NAT44 add pool addresses to FIB """
2692         static_addr = '10.0.0.10'
2693         self.nat44_add_address(self.nat_addr)
2694         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2695         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2696                                                   is_inside=0)
2697         self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
2698
2699         # NAT44 address
2700         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2701              ARP(op=ARP.who_has, pdst=self.nat_addr,
2702                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2703         self.pg1.add_stream(p)
2704         self.pg_enable_capture(self.pg_interfaces)
2705         self.pg_start()
2706         capture = self.pg1.get_capture(1)
2707         self.assertTrue(capture[0].haslayer(ARP))
2708         self.assertTrue(capture[0][ARP].op, ARP.is_at)
2709
2710         # 1:1 NAT address
2711         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2712              ARP(op=ARP.who_has, pdst=static_addr,
2713                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2714         self.pg1.add_stream(p)
2715         self.pg_enable_capture(self.pg_interfaces)
2716         self.pg_start()
2717         capture = self.pg1.get_capture(1)
2718         self.assertTrue(capture[0].haslayer(ARP))
2719         self.assertTrue(capture[0][ARP].op, ARP.is_at)
2720
2721         # send ARP to non-NAT44 interface
2722         p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2723              ARP(op=ARP.who_has, pdst=self.nat_addr,
2724                  psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2725         self.pg2.add_stream(p)
2726         self.pg_enable_capture(self.pg_interfaces)
2727         self.pg_start()
2728         self.pg1.assert_nothing_captured()
2729
2730         # remove addresses and verify
2731         self.nat44_add_address(self.nat_addr, is_add=0)
2732         self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2733                                       is_add=0)
2734
2735         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2736              ARP(op=ARP.who_has, pdst=self.nat_addr,
2737                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2738         self.pg1.add_stream(p)
2739         self.pg_enable_capture(self.pg_interfaces)
2740         self.pg_start()
2741         self.pg1.assert_nothing_captured()
2742
2743         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2744              ARP(op=ARP.who_has, pdst=static_addr,
2745                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2746         self.pg1.add_stream(p)
2747         self.pg_enable_capture(self.pg_interfaces)
2748         self.pg_start()
2749         self.pg1.assert_nothing_captured()
2750
2751     def test_vrf_mode(self):
2752         """ NAT44 tenant VRF aware address pool mode """
2753
2754         vrf_id1 = 1
2755         vrf_id2 = 2
2756         nat_ip1 = "10.0.0.10"
2757         nat_ip2 = "10.0.0.11"
2758
2759         self.pg0.unconfig_ip4()
2760         self.pg1.unconfig_ip4()
2761         self.vapi.ip_table_add_del(vrf_id1, is_add=1)
2762         self.vapi.ip_table_add_del(vrf_id2, is_add=1)
2763         self.pg0.set_table_ip4(vrf_id1)
2764         self.pg1.set_table_ip4(vrf_id2)
2765         self.pg0.config_ip4()
2766         self.pg1.config_ip4()
2767         self.pg0.resolve_arp()
2768         self.pg1.resolve_arp()
2769
2770         self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2771         self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2772         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2773         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2774         self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2775                                                   is_inside=0)
2776
2777         try:
2778             # first VRF
2779             pkts = self.create_stream_in(self.pg0, self.pg2)
2780             self.pg0.add_stream(pkts)
2781             self.pg_enable_capture(self.pg_interfaces)
2782             self.pg_start()
2783             capture = self.pg2.get_capture(len(pkts))
2784             self.verify_capture_out(capture, nat_ip1)
2785
2786             # second VRF
2787             pkts = self.create_stream_in(self.pg1, self.pg2)
2788             self.pg1.add_stream(pkts)
2789             self.pg_enable_capture(self.pg_interfaces)
2790             self.pg_start()
2791             capture = self.pg2.get_capture(len(pkts))
2792             self.verify_capture_out(capture, nat_ip2)
2793
2794         finally:
2795             self.pg0.unconfig_ip4()
2796             self.pg1.unconfig_ip4()
2797             self.pg0.set_table_ip4(0)
2798             self.pg1.set_table_ip4(0)
2799             self.pg0.config_ip4()
2800             self.pg1.config_ip4()
2801             self.pg0.resolve_arp()
2802             self.pg1.resolve_arp()
2803             self.vapi.ip_table_add_del(vrf_id1, is_add=0)
2804             self.vapi.ip_table_add_del(vrf_id2, is_add=0)
2805
2806     def test_vrf_feature_independent(self):
2807         """ NAT44 tenant VRF independent address pool mode """
2808
2809         nat_ip1 = "10.0.0.10"
2810         nat_ip2 = "10.0.0.11"
2811
2812         self.nat44_add_address(nat_ip1)
2813         self.nat44_add_address(nat_ip2, vrf_id=99)
2814         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2815         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2816         self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2817                                                   is_inside=0)
2818
2819         # first VRF
2820         pkts = self.create_stream_in(self.pg0, self.pg2)
2821         self.pg0.add_stream(pkts)
2822         self.pg_enable_capture(self.pg_interfaces)
2823         self.pg_start()
2824         capture = self.pg2.get_capture(len(pkts))
2825         self.verify_capture_out(capture, nat_ip1)
2826
2827         # second VRF
2828         pkts = self.create_stream_in(self.pg1, self.pg2)
2829         self.pg1.add_stream(pkts)
2830         self.pg_enable_capture(self.pg_interfaces)
2831         self.pg_start()
2832         capture = self.pg2.get_capture(len(pkts))
2833         self.verify_capture_out(capture, nat_ip1)
2834
2835     def test_dynamic_ipless_interfaces(self):
2836         """ NAT44 interfaces without configured IP address """
2837
2838         self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
2839                                       mactobinary(self.pg7.remote_mac),
2840                                       self.pg7.remote_ip4n,
2841                                       is_static=1)
2842         self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
2843                                       mactobinary(self.pg8.remote_mac),
2844                                       self.pg8.remote_ip4n,
2845                                       is_static=1)
2846
2847         self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2848                                    dst_address_length=32,
2849                                    next_hop_address=self.pg7.remote_ip4n,
2850                                    next_hop_sw_if_index=self.pg7.sw_if_index)
2851         self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2852                                    dst_address_length=32,
2853                                    next_hop_address=self.pg8.remote_ip4n,
2854                                    next_hop_sw_if_index=self.pg8.sw_if_index)
2855
2856         self.nat44_add_address(self.nat_addr)
2857         self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2858         self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2859                                                   is_inside=0)
2860
2861         # in2out
2862         pkts = self.create_stream_in(self.pg7, self.pg8)
2863         self.pg7.add_stream(pkts)
2864         self.pg_enable_capture(self.pg_interfaces)
2865         self.pg_start()
2866         capture = self.pg8.get_capture(len(pkts))
2867         self.verify_capture_out(capture)
2868
2869         # out2in
2870         pkts = self.create_stream_out(self.pg8, self.nat_addr)
2871         self.pg8.add_stream(pkts)
2872         self.pg_enable_capture(self.pg_interfaces)
2873         self.pg_start()
2874         capture = self.pg7.get_capture(len(pkts))
2875         self.verify_capture_in(capture, self.pg7)
2876
2877     def test_static_ipless_interfaces(self):
2878         """ NAT44 interfaces without configured IP address - 1:1 NAT """
2879
2880         self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
2881                                       mactobinary(self.pg7.remote_mac),
2882                                       self.pg7.remote_ip4n,
2883                                       is_static=1)
2884         self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
2885                                       mactobinary(self.pg8.remote_mac),
2886                                       self.pg8.remote_ip4n,
2887                                       is_static=1)
2888
2889         self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2890                                    dst_address_length=32,
2891                                    next_hop_address=self.pg7.remote_ip4n,
2892                                    next_hop_sw_if_index=self.pg7.sw_if_index)
2893         self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2894                                    dst_address_length=32,
2895                                    next_hop_address=self.pg8.remote_ip4n,
2896                                    next_hop_sw_if_index=self.pg8.sw_if_index)
2897
2898         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
2899         self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2900         self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2901                                                   is_inside=0)
2902
2903         # out2in
2904         pkts = self.create_stream_out(self.pg8)
2905         self.pg8.add_stream(pkts)
2906         self.pg_enable_capture(self.pg_interfaces)
2907         self.pg_start()
2908         capture = self.pg7.get_capture(len(pkts))
2909         self.verify_capture_in(capture, self.pg7)
2910
2911         # in2out
2912         pkts = self.create_stream_in(self.pg7, self.pg8)
2913         self.pg7.add_stream(pkts)
2914         self.pg_enable_capture(self.pg_interfaces)
2915         self.pg_start()
2916         capture = self.pg8.get_capture(len(pkts))
2917         self.verify_capture_out(capture, self.nat_addr, True)
2918
2919     def test_static_with_port_ipless_interfaces(self):
2920         """ NAT44 interfaces without configured IP address - 1:1 NAPT """
2921
2922         self.tcp_port_out = 30606
2923         self.udp_port_out = 30607
2924         self.icmp_id_out = 30608
2925
2926         self.vapi.ip_neighbor_add_del(self.pg7.sw_if_index,
2927                                       mactobinary(self.pg7.remote_mac),
2928                                       self.pg7.remote_ip4n,
2929                                       is_static=1)
2930         self.vapi.ip_neighbor_add_del(self.pg8.sw_if_index,
2931                                       mactobinary(self.pg8.remote_mac),
2932                                       self.pg8.remote_ip4n,
2933                                       is_static=1)
2934
2935         self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2936                                    dst_address_length=32,
2937                                    next_hop_address=self.pg7.remote_ip4n,
2938                                    next_hop_sw_if_index=self.pg7.sw_if_index)
2939         self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2940                                    dst_address_length=32,
2941                                    next_hop_address=self.pg8.remote_ip4n,
2942                                    next_hop_sw_if_index=self.pg8.sw_if_index)
2943
2944         self.nat44_add_address(self.nat_addr)
2945         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2946                                       self.tcp_port_in, self.tcp_port_out,
2947                                       proto=IP_PROTOS.tcp)
2948         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2949                                       self.udp_port_in, self.udp_port_out,
2950                                       proto=IP_PROTOS.udp)
2951         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
2952                                       self.icmp_id_in, self.icmp_id_out,
2953                                       proto=IP_PROTOS.icmp)
2954         self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2955         self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2956                                                   is_inside=0)
2957
2958         # out2in
2959         pkts = self.create_stream_out(self.pg8)
2960         self.pg8.add_stream(pkts)
2961         self.pg_enable_capture(self.pg_interfaces)
2962         self.pg_start()
2963         capture = self.pg7.get_capture(len(pkts))
2964         self.verify_capture_in(capture, self.pg7)
2965
2966         # in2out
2967         pkts = self.create_stream_in(self.pg7, self.pg8)
2968         self.pg7.add_stream(pkts)
2969         self.pg_enable_capture(self.pg_interfaces)
2970         self.pg_start()
2971         capture = self.pg8.get_capture(len(pkts))
2972         self.verify_capture_out(capture)
2973
2974     def test_static_unknown_proto(self):
2975         """ 1:1 NAT translate packet with unknown protocol """
2976         nat_ip = "10.0.0.10"
2977         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2978         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2979         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2980                                                   is_inside=0)
2981
2982         # in2out
2983         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2984              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2985              GRE() /
2986              IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
2987              TCP(sport=1234, dport=1234))
2988         self.pg0.add_stream(p)
2989         self.pg_enable_capture(self.pg_interfaces)
2990         self.pg_start()
2991         p = self.pg1.get_capture(1)
2992         packet = p[0]
2993         try:
2994             self.assertEqual(packet[IP].src, nat_ip)
2995             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2996             self.assertTrue(packet.haslayer(GRE))
2997             self.assert_packet_checksums_valid(packet)
2998         except:
2999             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3000             raise
3001
3002         # out2in
3003         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3004              IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3005              GRE() /
3006              IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3007              TCP(sport=1234, dport=1234))
3008         self.pg1.add_stream(p)
3009         self.pg_enable_capture(self.pg_interfaces)
3010         self.pg_start()
3011         p = self.pg0.get_capture(1)
3012         packet = p[0]
3013         try:
3014             self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3015             self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3016             self.assertTrue(packet.haslayer(GRE))
3017             self.assert_packet_checksums_valid(packet)
3018         except:
3019             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3020             raise
3021
3022     def test_hairpinning_static_unknown_proto(self):
3023         """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3024
3025         host = self.pg0.remote_hosts[0]
3026         server = self.pg0.remote_hosts[1]
3027
3028         host_nat_ip = "10.0.0.10"
3029         server_nat_ip = "10.0.0.11"
3030
3031         self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3032         self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3033         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3034         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3035                                                   is_inside=0)
3036
3037         # host to server
3038         p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3039              IP(src=host.ip4, dst=server_nat_ip) /
3040              GRE() /
3041              IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3042              TCP(sport=1234, dport=1234))
3043         self.pg0.add_stream(p)
3044         self.pg_enable_capture(self.pg_interfaces)
3045         self.pg_start()
3046         p = self.pg0.get_capture(1)
3047         packet = p[0]
3048         try:
3049             self.assertEqual(packet[IP].src, host_nat_ip)
3050             self.assertEqual(packet[IP].dst, server.ip4)
3051             self.assertTrue(packet.haslayer(GRE))
3052             self.assert_packet_checksums_valid(packet)
3053         except:
3054             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3055             raise
3056
3057         # server to host
3058         p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3059              IP(src=server.ip4, dst=host_nat_ip) /
3060              GRE() /
3061              IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3062              TCP(sport=1234, dport=1234))
3063         self.pg0.add_stream(p)
3064         self.pg_enable_capture(self.pg_interfaces)
3065         self.pg_start()
3066         p = self.pg0.get_capture(1)
3067         packet = p[0]
3068         try:
3069             self.assertEqual(packet[IP].src, server_nat_ip)
3070             self.assertEqual(packet[IP].dst, host.ip4)
3071             self.assertTrue(packet.haslayer(GRE))
3072             self.assert_packet_checksums_valid(packet)
3073         except:
3074             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3075             raise
3076
3077     def test_output_feature(self):
3078         """ NAT44 interface output feature (in2out postrouting) """
3079         self.nat44_add_address(self.nat_addr)
3080         self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3081         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
3082         self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3083                                                          is_inside=0)
3084
3085         # in2out
3086         pkts = self.create_stream_in(self.pg0, self.pg3)
3087         self.pg0.add_stream(pkts)
3088         self.pg_enable_capture(self.pg_interfaces)
3089         self.pg_start()
3090         capture = self.pg3.get_capture(len(pkts))
3091         self.verify_capture_out(capture)
3092
3093         # out2in
3094         pkts = self.create_stream_out(self.pg3)
3095         self.pg3.add_stream(pkts)
3096         self.pg_enable_capture(self.pg_interfaces)
3097         self.pg_start()
3098         capture = self.pg0.get_capture(len(pkts))
3099         self.verify_capture_in(capture, self.pg0)
3100
3101         # from non-NAT interface to NAT inside interface
3102         pkts = self.create_stream_in(self.pg2, self.pg0)
3103         self.pg2.add_stream(pkts)
3104         self.pg_enable_capture(self.pg_interfaces)
3105         self.pg_start()
3106         capture = self.pg0.get_capture(len(pkts))
3107         self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3108
3109     def test_output_feature_vrf_aware(self):
3110         """ NAT44 interface output feature VRF aware (in2out postrouting) """
3111         nat_ip_vrf10 = "10.0.0.10"
3112         nat_ip_vrf20 = "10.0.0.20"
3113
3114         self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3115                                    dst_address_length=32,
3116                                    next_hop_address=self.pg3.remote_ip4n,
3117                                    next_hop_sw_if_index=self.pg3.sw_if_index,
3118                                    table_id=10)
3119         self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3120                                    dst_address_length=32,
3121                                    next_hop_address=self.pg3.remote_ip4n,
3122                                    next_hop_sw_if_index=self.pg3.sw_if_index,
3123                                    table_id=20)
3124
3125         self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3126         self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3127         self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
3128         self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
3129         self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3130                                                          is_inside=0)
3131
3132         # in2out VRF 10
3133         pkts = self.create_stream_in(self.pg4, self.pg3)
3134         self.pg4.add_stream(pkts)
3135         self.pg_enable_capture(self.pg_interfaces)
3136         self.pg_start()
3137         capture = self.pg3.get_capture(len(pkts))
3138         self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3139
3140         # out2in VRF 10
3141         pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3142         self.pg3.add_stream(pkts)
3143         self.pg_enable_capture(self.pg_interfaces)
3144         self.pg_start()
3145         capture = self.pg4.get_capture(len(pkts))
3146         self.verify_capture_in(capture, self.pg4)
3147
3148         # in2out VRF 20
3149         pkts = self.create_stream_in(self.pg6, self.pg3)
3150         self.pg6.add_stream(pkts)
3151         self.pg_enable_capture(self.pg_interfaces)
3152         self.pg_start()
3153         capture = self.pg3.get_capture(len(pkts))
3154         self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3155
3156         # out2in VRF 20
3157         pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3158         self.pg3.add_stream(pkts)
3159         self.pg_enable_capture(self.pg_interfaces)
3160         self.pg_start()
3161         capture = self.pg6.get_capture(len(pkts))
3162         self.verify_capture_in(capture, self.pg6)
3163
3164     def test_output_feature_hairpinning(self):
3165         """ NAT44 interface output feature hairpinning (in2out postrouting) """
3166         host = self.pg0.remote_hosts[0]
3167         server = self.pg0.remote_hosts[1]
3168         host_in_port = 1234
3169         host_out_port = 0
3170         server_in_port = 5678
3171         server_out_port = 8765
3172
3173         self.nat44_add_address(self.nat_addr)
3174         self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3175         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3176                                                          is_inside=0)
3177
3178         # add static mapping for server
3179         self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3180                                       server_in_port, server_out_port,
3181                                       proto=IP_PROTOS.tcp)
3182
3183         # send packet from host to server
3184         p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3185              IP(src=host.ip4, dst=self.nat_addr) /
3186              TCP(sport=host_in_port, dport=server_out_port))
3187         self.pg0.add_stream(p)
3188         self.pg_enable_capture(self.pg_interfaces)
3189         self.pg_start()
3190         capture = self.pg0.get_capture(1)
3191         p = capture[0]
3192         try:
3193             ip = p[IP]
3194             tcp = p[TCP]
3195             self.assertEqual(ip.src, self.nat_addr)
3196             self.assertEqual(ip.dst, server.ip4)
3197             self.assertNotEqual(tcp.sport, host_in_port)
3198             self.assertEqual(tcp.dport, server_in_port)
3199             self.assert_packet_checksums_valid(p)
3200             host_out_port = tcp.sport
3201         except:
3202             self.logger.error(ppp("Unexpected or invalid packet:", p))
3203             raise
3204
3205         # send reply from server to host
3206         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3207              IP(src=server.ip4, dst=self.nat_addr) /
3208              TCP(sport=server_in_port, dport=host_out_port))
3209         self.pg0.add_stream(p)
3210         self.pg_enable_capture(self.pg_interfaces)
3211         self.pg_start()
3212         capture = self.pg0.get_capture(1)
3213         p = capture[0]
3214         try:
3215             ip = p[IP]
3216             tcp = p[TCP]
3217             self.assertEqual(ip.src, self.nat_addr)
3218             self.assertEqual(ip.dst, host.ip4)
3219             self.assertEqual(tcp.sport, server_out_port)
3220             self.assertEqual(tcp.dport, host_in_port)
3221             self.assert_packet_checksums_valid(p)
3222         except:
3223             self.logger.error(ppp("Unexpected or invalid packet:", p))
3224             raise
3225
3226     def test_one_armed_nat44(self):
3227         """ One armed NAT44 """
3228         remote_host = self.pg9.remote_hosts[0]
3229         local_host = self.pg9.remote_hosts[1]
3230         external_port = 0
3231
3232         self.nat44_add_address(self.nat_addr)
3233         self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3234         self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3235                                                   is_inside=0)
3236
3237         # in2out
3238         p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3239              IP(src=local_host.ip4, dst=remote_host.ip4) /
3240              TCP(sport=12345, dport=80))
3241         self.pg9.add_stream(p)
3242         self.pg_enable_capture(self.pg_interfaces)
3243         self.pg_start()
3244         capture = self.pg9.get_capture(1)
3245         p = capture[0]
3246         try:
3247             ip = p[IP]
3248             tcp = p[TCP]
3249             self.assertEqual(ip.src, self.nat_addr)
3250             self.assertEqual(ip.dst, remote_host.ip4)
3251             self.assertNotEqual(tcp.sport, 12345)
3252             external_port = tcp.sport
3253             self.assertEqual(tcp.dport, 80)
3254             self.assert_packet_checksums_valid(p)
3255         except:
3256             self.logger.error(ppp("Unexpected or invalid packet:", p))
3257             raise
3258
3259         # out2in
3260         p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3261              IP(src=remote_host.ip4, dst=self.nat_addr) /
3262              TCP(sport=80, dport=external_port))
3263         self.pg9.add_stream(p)
3264         self.pg_enable_capture(self.pg_interfaces)
3265         self.pg_start()
3266         capture = self.pg9.get_capture(1)
3267         p = capture[0]
3268         try:
3269             ip = p[IP]
3270             tcp = p[TCP]
3271             self.assertEqual(ip.src, remote_host.ip4)
3272             self.assertEqual(ip.dst, local_host.ip4)
3273             self.assertEqual(tcp.sport, 80)
3274             self.assertEqual(tcp.dport, 12345)
3275             self.assert_packet_checksums_valid(p)
3276         except:
3277             self.logger.error(ppp("Unexpected or invalid packet:", p))
3278             raise
3279
3280     def test_del_session(self):
3281         """ Delete NAT44 session """
3282         self.nat44_add_address(self.nat_addr)
3283         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3284         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3285                                                   is_inside=0)
3286
3287         pkts = self.create_stream_in(self.pg0, self.pg1)
3288         self.pg0.add_stream(pkts)
3289         self.pg_enable_capture(self.pg_interfaces)
3290         self.pg_start()
3291         self.pg1.get_capture(len(pkts))
3292
3293         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3294         nsessions = len(sessions)
3295
3296         self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3297                                     sessions[0].inside_port,
3298                                     sessions[0].protocol)
3299         self.vapi.nat44_del_session(sessions[1].outside_ip_address,
3300                                     sessions[1].outside_port,
3301                                     sessions[1].protocol,
3302                                     is_in=0)
3303
3304         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3305         self.assertEqual(nsessions - len(sessions), 2)
3306
3307         self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3308                                     sessions[0].inside_port,
3309                                     sessions[0].protocol)
3310
3311         self.verify_no_nat44_user()
3312
3313     def test_set_get_reass(self):
3314         """ NAT44 set/get virtual fragmentation reassembly """
3315         reas_cfg1 = self.vapi.nat_get_reass()
3316
3317         self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3318                                 max_reass=reas_cfg1.ip4_max_reass * 2,
3319                                 max_frag=reas_cfg1.ip4_max_frag * 2)
3320
3321         reas_cfg2 = self.vapi.nat_get_reass()
3322
3323         self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3324         self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3325         self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3326
3327         self.vapi.nat_set_reass(drop_frag=1)
3328         self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3329
3330     def test_frag_in_order(self):
3331         """ NAT44 translate fragments arriving in order """
3332
3333         self.nat44_add_address(self.nat_addr)
3334         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3335         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3336                                                   is_inside=0)
3337
3338         self.frag_in_order(proto=IP_PROTOS.tcp)
3339         self.frag_in_order(proto=IP_PROTOS.udp)
3340         self.frag_in_order(proto=IP_PROTOS.icmp)
3341
3342     def test_reass_hairpinning(self):
3343         """ NAT44 fragments hairpinning """
3344
3345         self.server = self.pg0.remote_hosts[1]
3346         self.host_in_port = random.randint(1025, 65535)
3347         self.server_in_port = random.randint(1025, 65535)
3348         self.server_out_port = random.randint(1025, 65535)
3349
3350         self.nat44_add_address(self.nat_addr)
3351         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3352         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3353                                                   is_inside=0)
3354         # add static mapping for server
3355         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3356                                       self.server_in_port,
3357                                       self.server_out_port,
3358                                       proto=IP_PROTOS.tcp)
3359         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3360                                       self.server_in_port,
3361                                       self.server_out_port,
3362                                       proto=IP_PROTOS.udp)
3363         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
3364
3365         self.reass_hairpinning(proto=IP_PROTOS.tcp)
3366         self.reass_hairpinning(proto=IP_PROTOS.udp)
3367         self.reass_hairpinning(proto=IP_PROTOS.icmp)
3368
3369     def test_frag_out_of_order(self):
3370         """ NAT44 translate fragments arriving out of order """
3371
3372         self.nat44_add_address(self.nat_addr)
3373         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3374         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3375                                                   is_inside=0)
3376
3377         self.frag_out_of_order(proto=IP_PROTOS.tcp)
3378         self.frag_out_of_order(proto=IP_PROTOS.udp)
3379         self.frag_out_of_order(proto=IP_PROTOS.icmp)
3380
3381     def test_port_restricted(self):
3382         """ Port restricted NAT44 (MAP-E CE) """
3383         self.nat44_add_address(self.nat_addr)
3384         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3385         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3386                                                   is_inside=0)
3387         self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3388                                                   psid_offset=6,
3389                                                   psid_length=6,
3390                                                   psid=10)
3391
3392         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3393              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3394              TCP(sport=4567, dport=22))
3395         self.pg0.add_stream(p)
3396         self.pg_enable_capture(self.pg_interfaces)
3397         self.pg_start()
3398         capture = self.pg1.get_capture(1)
3399         p = capture[0]
3400         try:
3401             ip = p[IP]
3402             tcp = p[TCP]
3403             self.assertEqual(ip.dst, self.pg1.remote_ip4)
3404             self.assertEqual(ip.src, self.nat_addr)
3405             self.assertEqual(tcp.dport, 22)
3406             self.assertNotEqual(tcp.sport, 4567)
3407             self.assertEqual((tcp.sport >> 6) & 63, 10)
3408             self.assert_packet_checksums_valid(p)
3409         except:
3410             self.logger.error(ppp("Unexpected or invalid packet:", p))
3411             raise
3412
3413     def test_port_range(self):
3414         """ External address port range """
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         self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3420                                                   start_port=1025,
3421                                                   end_port=1027)
3422
3423         pkts = []
3424         for port in range(0, 5):
3425             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3426                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3427                  TCP(sport=1125 + port))
3428             pkts.append(p)
3429         self.pg0.add_stream(pkts)
3430         self.pg_enable_capture(self.pg_interfaces)
3431         self.pg_start()
3432         capture = self.pg1.get_capture(3)
3433         for p in capture:
3434             tcp = p[TCP]
3435             self.assertGreaterEqual(tcp.sport, 1025)
3436             self.assertLessEqual(tcp.sport, 1027)
3437
3438     def test_ipfix_max_frags(self):
3439         """ IPFIX logging maximum fragments pending reassembly exceeded """
3440         self.nat44_add_address(self.nat_addr)
3441         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3442         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3443                                                   is_inside=0)
3444         self.vapi.nat_set_reass(max_frag=1)
3445         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
3446                                      src_address=self.pg3.local_ip4n,
3447                                      path_mtu=512,
3448                                      template_interval=10)
3449         self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
3450                             src_port=self.ipfix_src_port)
3451
3452         data = "A" * 4 + "B" * 16 + "C" * 3
3453         self.tcp_port_in = random.randint(1025, 65535)
3454         pkts = self.create_stream_frag(self.pg0,
3455                                        self.pg1.remote_ip4,
3456                                        self.tcp_port_in,
3457                                        20,
3458                                        data)
3459         pkts.reverse()
3460         self.pg0.add_stream(pkts)
3461         self.pg_enable_capture(self.pg_interfaces)
3462         self.pg_start()
3463         self.pg1.assert_nothing_captured()
3464         sleep(1)
3465         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
3466         capture = self.pg3.get_capture(9)
3467         ipfix = IPFIXDecoder()
3468         # first load template
3469         for p in capture:
3470             self.assertTrue(p.haslayer(IPFIX))
3471             self.assertEqual(p[IP].src, self.pg3.local_ip4)
3472             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
3473             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
3474             self.assertEqual(p[UDP].dport, 4739)
3475             self.assertEqual(p[IPFIX].observationDomainID,
3476                              self.ipfix_domain_id)
3477             if p.haslayer(Template):
3478                 ipfix.add_template(p.getlayer(Template))
3479         # verify events in data set
3480         for p in capture:
3481             if p.haslayer(Data):
3482                 data = ipfix.decode_data_set(p.getlayer(Set))
3483                 self.verify_ipfix_max_fragments_ip4(data, 1,
3484                                                     self.pg0.remote_ip4n)
3485
3486     def test_multiple_outside_vrf(self):
3487         """ Multiple outside VRF """
3488         vrf_id1 = 1
3489         vrf_id2 = 2
3490
3491         self.pg1.unconfig_ip4()
3492         self.pg2.unconfig_ip4()
3493         self.vapi.ip_table_add_del(vrf_id1, is_add=1)
3494         self.vapi.ip_table_add_del(vrf_id2, is_add=1)
3495         self.pg1.set_table_ip4(vrf_id1)
3496         self.pg2.set_table_ip4(vrf_id2)
3497         self.pg1.config_ip4()
3498         self.pg2.config_ip4()
3499         self.pg1.resolve_arp()
3500         self.pg2.resolve_arp()
3501
3502         self.nat44_add_address(self.nat_addr)
3503         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3504         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3505                                                   is_inside=0)
3506         self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
3507                                                   is_inside=0)
3508
3509         try:
3510             # first VRF
3511             pkts = self.create_stream_in(self.pg0, self.pg1)
3512             self.pg0.add_stream(pkts)
3513             self.pg_enable_capture(self.pg_interfaces)
3514             self.pg_start()
3515             capture = self.pg1.get_capture(len(pkts))
3516             self.verify_capture_out(capture, self.nat_addr)
3517
3518             pkts = self.create_stream_out(self.pg1, self.nat_addr)
3519             self.pg1.add_stream(pkts)
3520             self.pg_enable_capture(self.pg_interfaces)
3521             self.pg_start()
3522             capture = self.pg0.get_capture(len(pkts))
3523             self.verify_capture_in(capture, self.pg0)
3524
3525             self.tcp_port_in = 60303
3526             self.udp_port_in = 60304
3527             self.icmp_id_in = 60305
3528
3529             # second VRF
3530             pkts = self.create_stream_in(self.pg0, self.pg2)
3531             self.pg0.add_stream(pkts)
3532             self.pg_enable_capture(self.pg_interfaces)
3533             self.pg_start()
3534             capture = self.pg2.get_capture(len(pkts))
3535             self.verify_capture_out(capture, self.nat_addr)
3536
3537             pkts = self.create_stream_out(self.pg2, self.nat_addr)
3538             self.pg2.add_stream(pkts)
3539             self.pg_enable_capture(self.pg_interfaces)
3540             self.pg_start()
3541             capture = self.pg0.get_capture(len(pkts))
3542             self.verify_capture_in(capture, self.pg0)
3543
3544         finally:
3545             self.pg1.unconfig_ip4()
3546             self.pg2.unconfig_ip4()
3547             self.pg1.set_table_ip4(0)
3548             self.pg2.set_table_ip4(0)
3549             self.pg1.config_ip4()
3550             self.pg2.config_ip4()
3551             self.pg1.resolve_arp()
3552             self.pg2.resolve_arp()
3553
3554     @unittest.skipUnless(running_extended_tests(), "part of extended tests")
3555     def test_session_timeout(self):
3556         """ NAT44 session timeouts """
3557         self.nat44_add_address(self.nat_addr)
3558         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3559         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3560                                                   is_inside=0)
3561         self.vapi.nat_set_timeouts(udp=5)
3562
3563         max_sessions = 1000
3564         pkts = []
3565         for i in range(0, max_sessions):
3566             src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3567             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3568                  IP(src=src, dst=self.pg1.remote_ip4) /
3569                  UDP(sport=1025, dport=53))
3570             pkts.append(p)
3571         self.pg0.add_stream(pkts)
3572         self.pg_enable_capture(self.pg_interfaces)
3573         self.pg_start()
3574         self.pg1.get_capture(max_sessions)
3575
3576         sleep(6)
3577
3578         pkts = []
3579         for i in range(0, max_sessions):
3580             src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3581             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3582                  IP(src=src, dst=self.pg1.remote_ip4) /
3583                  UDP(sport=1026, dport=53))
3584             pkts.append(p)
3585         self.pg0.add_stream(pkts)
3586         self.pg_enable_capture(self.pg_interfaces)
3587         self.pg_start()
3588         self.pg1.get_capture(max_sessions)
3589
3590         nsessions = 0
3591         users = self.vapi.nat44_user_dump()
3592         for user in users:
3593             nsessions = nsessions + user.nsessions
3594         self.assertLess(nsessions, 2 * max_sessions)
3595
3596     def test_mss_clamping(self):
3597         """ TCP MSS clamping """
3598         self.nat44_add_address(self.nat_addr)
3599         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3600         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3601                                                   is_inside=0)
3602
3603         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3604              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3605              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3606                  flags="S", options=[('MSS', 1400)]))
3607
3608         self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3609         self.pg0.add_stream(p)
3610         self.pg_enable_capture(self.pg_interfaces)
3611         self.pg_start()
3612         capture = self.pg1.get_capture(1)
3613         # Negotiated MSS value greater than configured - changed
3614         self.verify_mss_value(capture[0], 1000)
3615
3616         self.vapi.nat_set_mss_clamping(enable=0)
3617         self.pg0.add_stream(p)
3618         self.pg_enable_capture(self.pg_interfaces)
3619         self.pg_start()
3620         capture = self.pg1.get_capture(1)
3621         # MSS clamping disabled - negotiated MSS unchanged
3622         self.verify_mss_value(capture[0], 1400)
3623
3624         self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3625         self.pg0.add_stream(p)
3626         self.pg_enable_capture(self.pg_interfaces)
3627         self.pg_start()
3628         capture = self.pg1.get_capture(1)
3629         # Negotiated MSS value smaller than configured - unchanged
3630         self.verify_mss_value(capture[0], 1400)
3631
3632     def tearDown(self):
3633         super(TestNAT44, self).tearDown()
3634         if not self.vpp_dead:
3635             self.logger.info(self.vapi.cli("show nat44 addresses"))
3636             self.logger.info(self.vapi.cli("show nat44 interfaces"))
3637             self.logger.info(self.vapi.cli("show nat44 static mappings"))
3638             self.logger.info(self.vapi.cli("show nat44 interface address"))
3639             self.logger.info(self.vapi.cli("show nat44 sessions detail"))
3640             self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
3641             self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
3642             self.logger.info(self.vapi.cli("show nat timeouts"))
3643             self.logger.info(
3644                 self.vapi.cli("show nat addr-port-assignment-alg"))
3645             self.clear_nat44()
3646             self.vapi.cli("clear logging")
3647
3648
3649 class TestNAT44EndpointDependent(MethodHolder):
3650     """ Endpoint-Dependent mapping and filtering test cases """
3651
3652     @classmethod
3653     def setUpConstants(cls):
3654         super(TestNAT44EndpointDependent, cls).setUpConstants()
3655         cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
3656
3657     @classmethod
3658     def setUpClass(cls):
3659         super(TestNAT44EndpointDependent, cls).setUpClass()
3660         cls.vapi.cli("set log class nat level debug")
3661         try:
3662             cls.tcp_port_in = 6303
3663             cls.tcp_port_out = 6303
3664             cls.udp_port_in = 6304
3665             cls.udp_port_out = 6304
3666             cls.icmp_id_in = 6305
3667             cls.icmp_id_out = 6305
3668             cls.nat_addr = '10.0.0.3'
3669             cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
3670             cls.ipfix_src_port = 4739
3671             cls.ipfix_domain_id = 1
3672             cls.tcp_external_port = 80
3673
3674             cls.create_pg_interfaces(range(7))
3675             cls.interfaces = list(cls.pg_interfaces[0:3])
3676
3677             for i in cls.interfaces:
3678                 i.admin_up()
3679                 i.config_ip4()
3680                 i.resolve_arp()
3681
3682             cls.pg0.generate_remote_hosts(3)
3683             cls.pg0.configure_ipv4_neighbors()
3684
3685             cls.pg3.admin_up()
3686
3687             cls.pg4.generate_remote_hosts(2)
3688             cls.pg4.config_ip4()
3689             ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
3690             cls.vapi.sw_interface_add_del_address(cls.pg4.sw_if_index,
3691                                                   ip_addr_n,
3692                                                   24)
3693             cls.pg4.admin_up()
3694             cls.pg4.resolve_arp()
3695             cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
3696             cls.pg4.resolve_arp()
3697
3698             zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
3699             cls.vapi.ip_table_add_del(1, is_add=1)
3700
3701             cls.pg5._local_ip4 = "10.1.1.1"
3702             cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
3703                                                    cls.pg5.local_ip4)
3704             cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
3705             cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
3706                 socket.AF_INET, cls.pg5.remote_ip4)
3707             cls.pg5.set_table_ip4(1)
3708             cls.pg5.config_ip4()
3709             cls.pg5.admin_up()
3710             cls.vapi.ip_add_del_route(dst_address=cls.pg5.remote_ip4n,
3711                                       dst_address_length=32,
3712                                       table_id=1,
3713                                       next_hop_sw_if_index=cls.pg5.sw_if_index,
3714                                       next_hop_address=zero_ip4n)
3715
3716             cls.pg6._local_ip4 = "10.1.2.1"
3717             cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
3718                                                    cls.pg6.local_ip4)
3719             cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
3720             cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
3721                 socket.AF_INET, cls.pg6.remote_ip4)
3722             cls.pg6.set_table_ip4(1)
3723             cls.pg6.config_ip4()
3724             cls.pg6.admin_up()
3725             cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
3726                                       dst_address_length=32,
3727                                       table_id=1,
3728                                       next_hop_sw_if_index=cls.pg6.sw_if_index,
3729                                       next_hop_address=zero_ip4n)
3730
3731             cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
3732                                       dst_address_length=16,
3733                                       next_hop_address=zero_ip4n,
3734                                       table_id=0,
3735                                       next_hop_table_id=1)
3736             cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
3737                                       dst_address_length=0,
3738                                       next_hop_address=zero_ip4n,
3739                                       table_id=1,
3740                                       next_hop_table_id=0)
3741             cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
3742                                       dst_address_length=0,
3743                                       table_id=0,
3744                                       next_hop_sw_if_index=cls.pg1.sw_if_index,
3745                                       next_hop_address=cls.pg1.local_ip4n)
3746
3747             cls.pg5.resolve_arp()
3748             cls.pg6.resolve_arp()
3749
3750         except Exception:
3751             super(TestNAT44EndpointDependent, cls).tearDownClass()
3752             raise
3753
3754     def test_frag_in_order(self):
3755         """ NAT44 translate fragments arriving in order """
3756         self.nat44_add_address(self.nat_addr)
3757         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3758         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3759                                                   is_inside=0)
3760         self.frag_in_order(proto=IP_PROTOS.tcp)
3761         self.frag_in_order(proto=IP_PROTOS.udp)
3762         self.frag_in_order(proto=IP_PROTOS.icmp)
3763
3764     def test_frag_in_order_dont_translate(self):
3765         """ NAT44 don't translate fragments arriving in order """
3766         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3767         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3768                                                   is_inside=0)
3769         self.vapi.nat44_forwarding_enable_disable(enable=True)
3770         self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
3771
3772     def test_frag_out_of_order(self):
3773         """ NAT44 translate fragments arriving out of order """
3774         self.nat44_add_address(self.nat_addr)
3775         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3776         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3777                                                   is_inside=0)
3778         self.frag_out_of_order(proto=IP_PROTOS.tcp)
3779         self.frag_out_of_order(proto=IP_PROTOS.udp)
3780         self.frag_out_of_order(proto=IP_PROTOS.icmp)
3781
3782     def test_frag_out_of_order_dont_translate(self):
3783         """ NAT44 don't translate fragments arriving out of order """
3784         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3785         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3786                                                   is_inside=0)
3787         self.vapi.nat44_forwarding_enable_disable(enable=True)
3788         self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
3789
3790     def test_frag_in_order_in_plus_out(self):
3791         """ in+out interface fragments in order """
3792         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3793         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3794                                                   is_inside=0)
3795         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3796         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3797                                                   is_inside=0)
3798
3799         self.server = self.pg1.remote_hosts[0]
3800
3801         self.server_in_addr = self.server.ip4
3802         self.server_out_addr = '11.11.11.11'
3803         self.server_in_port = random.randint(1025, 65535)
3804         self.server_out_port = random.randint(1025, 65535)
3805
3806         self.nat44_add_address(self.server_out_addr)
3807
3808         # add static mappings for server
3809         self.nat44_add_static_mapping(self.server_in_addr,
3810                                       self.server_out_addr,
3811                                       self.server_in_port,
3812                                       self.server_out_port,
3813                                       proto=IP_PROTOS.tcp)
3814         self.nat44_add_static_mapping(self.server_in_addr,
3815                                       self.server_out_addr,
3816                                       self.server_in_port,
3817                                       self.server_out_port,
3818                                       proto=IP_PROTOS.udp)
3819         self.nat44_add_static_mapping(self.server_in_addr,
3820                                       self.server_out_addr,
3821                                       proto=IP_PROTOS.icmp)
3822
3823         self.vapi.nat_set_reass(timeout=10)
3824
3825         self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
3826         self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
3827         self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
3828
3829     def test_frag_out_of_order_in_plus_out(self):
3830         """ in+out interface fragments out of order """
3831         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3832         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3833                                                   is_inside=0)
3834         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3835         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3836                                                   is_inside=0)
3837
3838         self.server = self.pg1.remote_hosts[0]
3839
3840         self.server_in_addr = self.server.ip4
3841         self.server_out_addr = '11.11.11.11'
3842         self.server_in_port = random.randint(1025, 65535)
3843         self.server_out_port = random.randint(1025, 65535)
3844
3845         self.nat44_add_address(self.server_out_addr)
3846
3847         # add static mappings for server
3848         self.nat44_add_static_mapping(self.server_in_addr,
3849                                       self.server_out_addr,
3850                                       self.server_in_port,
3851                                       self.server_out_port,
3852                                       proto=IP_PROTOS.tcp)
3853         self.nat44_add_static_mapping(self.server_in_addr,
3854                                       self.server_out_addr,
3855                                       self.server_in_port,
3856                                       self.server_out_port,
3857                                       proto=IP_PROTOS.udp)
3858         self.nat44_add_static_mapping(self.server_in_addr,
3859                                       self.server_out_addr,
3860                                       proto=IP_PROTOS.icmp)
3861
3862         self.vapi.nat_set_reass(timeout=10)
3863
3864         self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
3865         self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
3866         self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
3867
3868     def test_reass_hairpinning(self):
3869         """ NAT44 fragments hairpinning """
3870         self.server = self.pg0.remote_hosts[1]
3871         self.host_in_port = random.randint(1025, 65535)
3872         self.server_in_port = random.randint(1025, 65535)
3873         self.server_out_port = random.randint(1025, 65535)
3874
3875         self.nat44_add_address(self.nat_addr)
3876         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3877         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3878                                                   is_inside=0)
3879         # add static mapping for server
3880         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3881                                       self.server_in_port,
3882                                       self.server_out_port,
3883                                       proto=IP_PROTOS.tcp)
3884         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3885                                       self.server_in_port,
3886                                       self.server_out_port,
3887                                       proto=IP_PROTOS.udp)
3888         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
3889
3890         self.reass_hairpinning(proto=IP_PROTOS.tcp)
3891         self.reass_hairpinning(proto=IP_PROTOS.udp)
3892         self.reass_hairpinning(proto=IP_PROTOS.icmp)
3893
3894     def test_dynamic(self):
3895         """ NAT44 dynamic translation test """
3896
3897         self.nat44_add_address(self.nat_addr)
3898         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3899         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3900                                                   is_inside=0)
3901
3902         nat_config = self.vapi.nat_show_config()
3903         self.assertEqual(1, nat_config.endpoint_dependent)
3904
3905         # in2out
3906         pkts = self.create_stream_in(self.pg0, self.pg1)
3907         self.pg0.add_stream(pkts)
3908         self.pg_enable_capture(self.pg_interfaces)
3909         self.pg_start()
3910         capture = self.pg1.get_capture(len(pkts))
3911         self.verify_capture_out(capture)
3912
3913         # out2in
3914         pkts = self.create_stream_out(self.pg1)
3915         self.pg1.add_stream(pkts)
3916         self.pg_enable_capture(self.pg_interfaces)
3917         self.pg_start()
3918         capture = self.pg0.get_capture(len(pkts))
3919         self.verify_capture_in(capture, self.pg0)
3920
3921     def test_forwarding(self):
3922         """ NAT44 forwarding test """
3923
3924         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3925         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3926                                                   is_inside=0)
3927         self.vapi.nat44_forwarding_enable_disable(1)
3928
3929         real_ip = self.pg0.remote_ip4n
3930         alias_ip = self.nat_addr_n
3931         self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
3932                                                external_ip=alias_ip)
3933
3934         try:
3935             # in2out - static mapping match
3936
3937             pkts = self.create_stream_out(self.pg1)
3938             self.pg1.add_stream(pkts)
3939             self.pg_enable_capture(self.pg_interfaces)
3940             self.pg_start()
3941             capture = self.pg0.get_capture(len(pkts))
3942             self.verify_capture_in(capture, self.pg0)
3943
3944             pkts = self.create_stream_in(self.pg0, self.pg1)
3945             self.pg0.add_stream(pkts)
3946             self.pg_enable_capture(self.pg_interfaces)
3947             self.pg_start()
3948             capture = self.pg1.get_capture(len(pkts))
3949             self.verify_capture_out(capture, same_port=True)
3950
3951             # in2out - no static mapping match
3952
3953             host0 = self.pg0.remote_hosts[0]
3954             self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
3955             try:
3956                 pkts = self.create_stream_out(self.pg1,
3957                                               dst_ip=self.pg0.remote_ip4,
3958                                               use_inside_ports=True)
3959                 self.pg1.add_stream(pkts)
3960                 self.pg_enable_capture(self.pg_interfaces)
3961                 self.pg_start()
3962                 capture = self.pg0.get_capture(len(pkts))
3963                 self.verify_capture_in(capture, self.pg0)
3964
3965                 pkts = self.create_stream_in(self.pg0, self.pg1)
3966                 self.pg0.add_stream(pkts)
3967                 self.pg_enable_capture(self.pg_interfaces)
3968                 self.pg_start()
3969                 capture = self.pg1.get_capture(len(pkts))
3970                 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
3971                                         same_port=True)
3972             finally:
3973                 self.pg0.remote_hosts[0] = host0
3974
3975             user = self.pg0.remote_hosts[1]
3976             sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
3977             self.assertEqual(len(sessions), 3)
3978             self.assertTrue(sessions[0].ext_host_valid)
3979             self.vapi.nat44_del_session(
3980                 sessions[0].inside_ip_address,
3981                 sessions[0].inside_port,
3982                 sessions[0].protocol,
3983                 ext_host_address=sessions[0].ext_host_address,
3984                 ext_host_port=sessions[0].ext_host_port)
3985             sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
3986             self.assertEqual(len(sessions), 2)
3987
3988         finally:
3989             self.vapi.nat44_forwarding_enable_disable(0)
3990             self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
3991                                                    external_ip=alias_ip,
3992                                                    is_add=0)
3993
3994     def test_static_lb(self):
3995         """ NAT44 local service load balancing """
3996         external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
3997         external_port = 80
3998         local_port = 8080
3999         server1 = self.pg0.remote_hosts[0]
4000         server2 = self.pg0.remote_hosts[1]
4001
4002         locals = [{'addr': server1.ip4n,
4003                    'port': local_port,
4004                    'probability': 70,
4005                    'vrf_id': 0},
4006                   {'addr': server2.ip4n,
4007                    'port': local_port,
4008                    'probability': 30,
4009                    'vrf_id': 0}]
4010
4011         self.nat44_add_address(self.nat_addr)
4012         self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4013                                                   external_port,
4014                                                   IP_PROTOS.tcp,
4015                                                   local_num=len(locals),
4016                                                   locals=locals)
4017         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4018         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4019                                                   is_inside=0)
4020
4021         # from client to service
4022         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4023              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4024              TCP(sport=12345, dport=external_port))
4025         self.pg1.add_stream(p)
4026         self.pg_enable_capture(self.pg_interfaces)
4027         self.pg_start()
4028         capture = self.pg0.get_capture(1)
4029         p = capture[0]
4030         server = None
4031         try:
4032             ip = p[IP]
4033             tcp = p[TCP]
4034             self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4035             if ip.dst == server1.ip4:
4036                 server = server1
4037             else:
4038                 server = server2
4039             self.assertEqual(tcp.dport, local_port)
4040             self.assert_packet_checksums_valid(p)
4041         except:
4042             self.logger.error(ppp("Unexpected or invalid packet:", p))
4043             raise
4044
4045         # from service back to client
4046         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4047              IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4048              TCP(sport=local_port, dport=12345))
4049         self.pg0.add_stream(p)
4050         self.pg_enable_capture(self.pg_interfaces)
4051         self.pg_start()
4052         capture = self.pg1.get_capture(1)
4053         p = capture[0]
4054         try:
4055             ip = p[IP]
4056             tcp = p[TCP]
4057             self.assertEqual(ip.src, self.nat_addr)
4058             self.assertEqual(tcp.sport, external_port)
4059             self.assert_packet_checksums_valid(p)
4060         except:
4061             self.logger.error(ppp("Unexpected or invalid packet:", p))
4062             raise
4063
4064         sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4065         self.assertEqual(len(sessions), 1)
4066         self.assertTrue(sessions[0].ext_host_valid)
4067         self.vapi.nat44_del_session(
4068             sessions[0].inside_ip_address,
4069             sessions[0].inside_port,
4070             sessions[0].protocol,
4071             ext_host_address=sessions[0].ext_host_address,
4072             ext_host_port=sessions[0].ext_host_port)
4073         sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4074         self.assertEqual(len(sessions), 0)
4075
4076     @unittest.skipUnless(running_extended_tests(), "part of extended tests")
4077     def test_static_lb_multi_clients(self):
4078         """ NAT44 local service load balancing - multiple clients"""
4079
4080         external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4081         external_port = 80
4082         local_port = 8080
4083         server1 = self.pg0.remote_hosts[0]
4084         server2 = self.pg0.remote_hosts[1]
4085
4086         locals = [{'addr': server1.ip4n,
4087                    'port': local_port,
4088                    'probability': 90,
4089                    'vrf_id': 0},
4090                   {'addr': server2.ip4n,
4091                    'port': local_port,
4092                    'probability': 10,
4093                    'vrf_id': 0}]
4094
4095         self.nat44_add_address(self.nat_addr)
4096         self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4097                                                   external_port,
4098                                                   IP_PROTOS.tcp,
4099                                                   local_num=len(locals),
4100                                                   locals=locals)
4101         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4102         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4103                                                   is_inside=0)
4104
4105         server1_n = 0
4106         server2_n = 0
4107         clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4108         pkts = []
4109         for client in clients:
4110             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4111                  IP(src=client, dst=self.nat_addr) /
4112                  TCP(sport=12345, dport=external_port))
4113             pkts.append(p)
4114         self.pg1.add_stream(pkts)
4115         self.pg_enable_capture(self.pg_interfaces)
4116         self.pg_start()
4117         capture = self.pg0.get_capture(len(pkts))
4118         for p in capture:
4119             if p[IP].dst == server1.ip4:
4120                 server1_n += 1
4121             else:
4122                 server2_n += 1
4123         self.assertTrue(server1_n > server2_n)
4124
4125     def test_static_lb_2(self):
4126         """ NAT44 local service load balancing (asymmetrical rule) """
4127         external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4128         external_port = 80
4129         local_port = 8080
4130         server1 = self.pg0.remote_hosts[0]
4131         server2 = self.pg0.remote_hosts[1]
4132
4133         locals = [{'addr': server1.ip4n,
4134                    'port': local_port,
4135                    'probability': 70,
4136                    'vrf_id': 0},
4137                   {'addr': server2.ip4n,
4138                    'port': local_port,
4139                    'probability': 30,
4140                    'vrf_id': 0}]
4141
4142         self.vapi.nat44_forwarding_enable_disable(1)
4143         self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4144                                                   external_port,
4145                                                   IP_PROTOS.tcp,
4146                                                   out2in_only=1,
4147                                                   local_num=len(locals),
4148                                                   locals=locals)
4149         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4150         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4151                                                   is_inside=0)
4152
4153         # from client to service
4154         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4155              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4156              TCP(sport=12345, dport=external_port))
4157         self.pg1.add_stream(p)
4158         self.pg_enable_capture(self.pg_interfaces)
4159         self.pg_start()
4160         capture = self.pg0.get_capture(1)
4161         p = capture[0]
4162         server = None
4163         try:
4164             ip = p[IP]
4165             tcp = p[TCP]
4166             self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4167             if ip.dst == server1.ip4:
4168                 server = server1
4169             else:
4170                 server = server2
4171             self.assertEqual(tcp.dport, local_port)
4172             self.assert_packet_checksums_valid(p)
4173         except:
4174             self.logger.error(ppp("Unexpected or invalid packet:", p))
4175             raise
4176
4177         # from service back to client
4178         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4179              IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4180              TCP(sport=local_port, dport=12345))
4181         self.pg0.add_stream(p)
4182         self.pg_enable_capture(self.pg_interfaces)
4183         self.pg_start()
4184         capture = self.pg1.get_capture(1)
4185         p = capture[0]
4186         try:
4187             ip = p[IP]
4188             tcp = p[TCP]
4189             self.assertEqual(ip.src, self.nat_addr)
4190             self.assertEqual(tcp.sport, external_port)
4191             self.assert_packet_checksums_valid(p)
4192         except:
4193             self.logger.error(ppp("Unexpected or invalid packet:", p))
4194             raise
4195
4196         # from client to server (no translation)
4197         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4198              IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
4199              TCP(sport=12346, dport=local_port))
4200         self.pg1.add_stream(p)
4201         self.pg_enable_capture(self.pg_interfaces)
4202         self.pg_start()
4203         capture = self.pg0.get_capture(1)
4204         p = capture[0]
4205         server = None
4206         try:
4207             ip = p[IP]
4208             tcp = p[TCP]
4209             self.assertEqual(ip.dst, server1.ip4)
4210             self.assertEqual(tcp.dport, local_port)
4211             self.assert_packet_checksums_valid(p)
4212         except:
4213             self.logger.error(ppp("Unexpected or invalid packet:", p))
4214             raise
4215
4216         # from service back to client (no translation)
4217         p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
4218              IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
4219              TCP(sport=local_port, dport=12346))
4220         self.pg0.add_stream(p)
4221         self.pg_enable_capture(self.pg_interfaces)
4222         self.pg_start()
4223         capture = self.pg1.get_capture(1)
4224         p = capture[0]
4225         try:
4226             ip = p[IP]
4227             tcp = p[TCP]
4228             self.assertEqual(ip.src, server1.ip4)
4229             self.assertEqual(tcp.sport, local_port)
4230             self.assert_packet_checksums_valid(p)
4231         except:
4232             self.logger.error(ppp("Unexpected or invalid packet:", p))
4233             raise
4234
4235     def test_lb_affinity(self):
4236         """ NAT44 local service load balancing affinity """
4237         external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4238         external_port = 80
4239         local_port = 8080
4240         server1 = self.pg0.remote_hosts[0]
4241         server2 = self.pg0.remote_hosts[1]
4242
4243         locals = [{'addr': server1.ip4n,
4244                    'port': local_port,
4245                    'probability': 50,
4246                    'vrf_id': 0},
4247                   {'addr': server2.ip4n,
4248                    'port': local_port,
4249                    'probability': 50,
4250                    'vrf_id': 0}]
4251
4252         self.nat44_add_address(self.nat_addr)
4253         self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4254                                                   external_port,
4255                                                   IP_PROTOS.tcp,
4256                                                   affinity=10800,
4257                                                   local_num=len(locals),
4258                                                   locals=locals)
4259         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4260         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4261                                                   is_inside=0)
4262
4263         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4264              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4265              TCP(sport=1025, dport=external_port))
4266         self.pg1.add_stream(p)
4267         self.pg_enable_capture(self.pg_interfaces)
4268         self.pg_start()
4269         capture = self.pg0.get_capture(1)
4270         backend = capture[0][IP].dst
4271
4272         sessions = self.vapi.nat44_user_session_dump(
4273             socket.inet_pton(socket.AF_INET, backend), 0)
4274         self.assertEqual(len(sessions), 1)
4275         self.assertTrue(sessions[0].ext_host_valid)
4276         self.vapi.nat44_del_session(
4277             sessions[0].inside_ip_address,
4278             sessions[0].inside_port,
4279             sessions[0].protocol,
4280             ext_host_address=sessions[0].ext_host_address,
4281             ext_host_port=sessions[0].ext_host_port)
4282
4283         pkts = []
4284         for port in range(1030, 1100):
4285             p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4286                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4287                  TCP(sport=port, dport=external_port))
4288             pkts.append(p)
4289         self.pg1.add_stream(pkts)
4290         self.pg_enable_capture(self.pg_interfaces)
4291         self.pg_start()
4292         capture = self.pg0.get_capture(len(pkts))
4293         for p in capture:
4294             self.assertEqual(p[IP].dst, backend)
4295
4296     def test_unknown_proto(self):
4297         """ NAT44 translate packet with unknown protocol """
4298         self.nat44_add_address(self.nat_addr)
4299         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4300         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4301                                                   is_inside=0)
4302
4303         # in2out
4304         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4305              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4306              TCP(sport=self.tcp_port_in, dport=20))
4307         self.pg0.add_stream(p)
4308         self.pg_enable_capture(self.pg_interfaces)
4309         self.pg_start()
4310         p = self.pg1.get_capture(1)
4311
4312         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4313              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4314              GRE() /
4315              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4316              TCP(sport=1234, dport=1234))
4317         self.pg0.add_stream(p)
4318         self.pg_enable_capture(self.pg_interfaces)
4319         self.pg_start()
4320         p = self.pg1.get_capture(1)
4321         packet = p[0]
4322         try:
4323             self.assertEqual(packet[IP].src, self.nat_addr)
4324             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
4325             self.assertTrue(packet.haslayer(GRE))
4326             self.assert_packet_checksums_valid(packet)
4327         except:
4328             self.logger.error(ppp("Unexpected or invalid packet:", packet))
4329             raise
4330
4331         # out2in
4332         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4333              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4334              GRE() /
4335              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4336              TCP(sport=1234, dport=1234))
4337         self.pg1.add_stream(p)
4338         self.pg_enable_capture(self.pg_interfaces)
4339         self.pg_start()
4340         p = self.pg0.get_capture(1)
4341         packet = p[0]
4342         try:
4343             self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
4344             self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
4345             self.assertTrue(packet.haslayer(GRE))
4346             self.assert_packet_checksums_valid(packet)
4347         except:
4348             self.logger.error(ppp("Unexpected or invalid packet:", packet))
4349             raise
4350
4351     def test_hairpinning_unknown_proto(self):
4352         """ NAT44 translate packet with unknown protocol - hairpinning """
4353         host = self.pg0.remote_hosts[0]
4354         server = self.pg0.remote_hosts[1]
4355         host_in_port = 1234
4356         server_out_port = 8765
4357         server_nat_ip = "10.0.0.11"
4358
4359         self.nat44_add_address(self.nat_addr)
4360         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4361         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4362                                                   is_inside=0)
4363
4364         # add static mapping for server
4365         self.nat44_add_static_mapping(server.ip4, server_nat_ip)
4366
4367         # host to server
4368         p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
4369              IP(src=host.ip4, dst=server_nat_ip) /
4370              TCP(sport=host_in_port, dport=server_out_port))
4371         self.pg0.add_stream(p)
4372         self.pg_enable_capture(self.pg_interfaces)
4373         self.pg_start()
4374         self.pg0.get_capture(1)
4375
4376         p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
4377              IP(src=host.ip4, dst=server_nat_ip) /
4378              GRE() /
4379              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4380              TCP(sport=1234, dport=1234))
4381         self.pg0.add_stream(p)
4382         self.pg_enable_capture(self.pg_interfaces)
4383         self.pg_start()
4384         p = self.pg0.get_capture(1)
4385         packet = p[0]
4386         try:
4387             self.assertEqual(packet[IP].src, self.nat_addr)
4388             self.assertEqual(packet[IP].dst, server.ip4)
4389             self.assertTrue(packet.haslayer(GRE))
4390             self.assert_packet_checksums_valid(packet)
4391         except:
4392             self.logger.error(ppp("Unexpected or invalid packet:", packet))
4393             raise
4394
4395         # server to host
4396         p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
4397              IP(src=server.ip4, dst=self.nat_addr) /
4398              GRE() /
4399              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4400              TCP(sport=1234, dport=1234))
4401         self.pg0.add_stream(p)
4402         self.pg_enable_capture(self.pg_interfaces)
4403         self.pg_start()
4404         p = self.pg0.get_capture(1)
4405         packet = p[0]
4406         try:
4407             self.assertEqual(packet[IP].src, server_nat_ip)
4408             self.assertEqual(packet[IP].dst, host.ip4)
4409             self.assertTrue(packet.haslayer(GRE))
4410             self.assert_packet_checksums_valid(packet)
4411         except:
4412             self.logger.error(ppp("Unexpected or invalid packet:", packet))
4413             raise
4414
4415     def test_output_feature_and_service(self):
4416         """ NAT44 interface output feature and services """
4417         external_addr = '1.2.3.4'
4418         external_port = 80
4419         local_port = 8080
4420
4421         self.vapi.nat44_forwarding_enable_disable(1)
4422         self.nat44_add_address(self.nat_addr)
4423         self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
4424         self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
4425                                       local_port, external_port,
4426                                       proto=IP_PROTOS.tcp, out2in_only=1)
4427         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4428         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4429                                                   is_inside=0)
4430         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4431                                                          is_inside=0)
4432
4433         # from client to service
4434         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4435              IP(src=self.pg1.remote_ip4, dst=external_addr) /
4436              TCP(sport=12345, dport=external_port))
4437         self.pg1.add_stream(p)
4438         self.pg_enable_capture(self.pg_interfaces)
4439         self.pg_start()
4440         capture = self.pg0.get_capture(1)
4441         p = capture[0]
4442         try:
4443             ip = p[IP]
4444             tcp = p[TCP]
4445             self.assertEqual(ip.dst, self.pg0.remote_ip4)
4446             self.assertEqual(tcp.dport, local_port)
4447             self.assert_packet_checksums_valid(p)
4448         except:
4449             self.logger.error(ppp("Unexpected or invalid packet:", p))
4450             raise
4451
4452         # from service back to client
4453         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4454              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4455              TCP(sport=local_port, dport=12345))
4456         self.pg0.add_stream(p)
4457         self.pg_enable_capture(self.pg_interfaces)
4458         self.pg_start()
4459         capture = self.pg1.get_capture(1)
4460         p = capture[0]
4461         try:
4462             ip = p[IP]
4463             tcp = p[TCP]
4464             self.assertEqual(ip.src, external_addr)
4465             self.assertEqual(tcp.sport, external_port)
4466             self.assert_packet_checksums_valid(p)
4467         except:
4468             self.logger.error(ppp("Unexpected or invalid packet:", p))
4469             raise
4470
4471         # from local network host to external network
4472         pkts = self.create_stream_in(self.pg0, self.pg1)
4473         self.pg0.add_stream(pkts)
4474         self.pg_enable_capture(self.pg_interfaces)
4475         self.pg_start()
4476         capture = self.pg1.get_capture(len(pkts))
4477         self.verify_capture_out(capture)
4478         pkts = self.create_stream_in(self.pg0, self.pg1)
4479         self.pg0.add_stream(pkts)
4480         self.pg_enable_capture(self.pg_interfaces)
4481         self.pg_start()
4482         capture = self.pg1.get_capture(len(pkts))
4483         self.verify_capture_out(capture)
4484
4485         # from external network back to local network host
4486         pkts = self.create_stream_out(self.pg1)
4487         self.pg1.add_stream(pkts)
4488         self.pg_enable_capture(self.pg_interfaces)
4489         self.pg_start()
4490         capture = self.pg0.get_capture(len(pkts))
4491         self.verify_capture_in(capture, self.pg0)
4492
4493     def test_output_feature_and_service2(self):
4494         """ NAT44 interface output feature and service host direct access """
4495         self.vapi.nat44_forwarding_enable_disable(1)
4496         self.nat44_add_address(self.nat_addr)
4497         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4498                                                          is_inside=0)
4499
4500         # session initiaded from service host - translate
4501         pkts = self.create_stream_in(self.pg0, self.pg1)
4502         self.pg0.add_stream(pkts)
4503         self.pg_enable_capture(self.pg_interfaces)
4504         self.pg_start()
4505         capture = self.pg1.get_capture(len(pkts))
4506         self.verify_capture_out(capture)
4507
4508         pkts = self.create_stream_out(self.pg1)
4509         self.pg1.add_stream(pkts)
4510         self.pg_enable_capture(self.pg_interfaces)
4511         self.pg_start()
4512         capture = self.pg0.get_capture(len(pkts))
4513         self.verify_capture_in(capture, self.pg0)
4514
4515         # session initiaded from remote host - do not translate
4516         self.tcp_port_in = 60303
4517         self.udp_port_in = 60304
4518         self.icmp_id_in = 60305
4519         pkts = self.create_stream_out(self.pg1,
4520                                       self.pg0.remote_ip4,
4521                                       use_inside_ports=True)
4522         self.pg1.add_stream(pkts)
4523         self.pg_enable_capture(self.pg_interfaces)
4524         self.pg_start()
4525         capture = self.pg0.get_capture(len(pkts))
4526         self.verify_capture_in(capture, self.pg0)
4527
4528         pkts = self.create_stream_in(self.pg0, self.pg1)
4529         self.pg0.add_stream(pkts)
4530         self.pg_enable_capture(self.pg_interfaces)
4531         self.pg_start()
4532         capture = self.pg1.get_capture(len(pkts))
4533         self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4534                                 same_port=True)
4535
4536     def test_output_feature_and_service3(self):
4537         """ NAT44 interface output feature and DST NAT """
4538         external_addr = '1.2.3.4'
4539         external_port = 80
4540         local_port = 8080
4541
4542         self.vapi.nat44_forwarding_enable_disable(1)
4543         self.nat44_add_address(self.nat_addr)
4544         self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
4545                                       local_port, external_port,
4546                                       proto=IP_PROTOS.tcp, out2in_only=1)
4547         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4548         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4549                                                   is_inside=0)
4550         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4551                                                          is_inside=0)
4552
4553         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4554              IP(src=self.pg0.remote_ip4, dst=external_addr) /
4555              TCP(sport=12345, dport=external_port))
4556         self.pg0.add_stream(p)
4557         self.pg_enable_capture(self.pg_interfaces)
4558         self.pg_start()
4559         capture = self.pg1.get_capture(1)
4560         p = capture[0]
4561         try:
4562             ip = p[IP]
4563             tcp = p[TCP]
4564             self.assertEqual(ip.src, self.pg0.remote_ip4)
4565             self.assertEqual(tcp.sport, 12345)
4566             self.assertEqual(ip.dst, self.pg1.remote_ip4)
4567             self.assertEqual(tcp.dport, local_port)
4568             self.assert_packet_checksums_valid(p)
4569         except:
4570             self.logger.error(ppp("Unexpected or invalid packet:", p))
4571             raise
4572
4573         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4574              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
4575              TCP(sport=local_port, dport=12345))
4576         self.pg1.add_stream(p)
4577         self.pg_enable_capture(self.pg_interfaces)
4578         self.pg_start()
4579         capture = self.pg0.get_capture(1)
4580         p = capture[0]
4581         try:
4582             ip = p[IP]
4583             tcp = p[TCP]
4584             self.assertEqual(ip.src, external_addr)
4585             self.assertEqual(tcp.sport, external_port)
4586             self.assertEqual(ip.dst, self.pg0.remote_ip4)
4587             self.assertEqual(tcp.dport, 12345)
4588             self.assert_packet_checksums_valid(p)
4589         except:
4590             self.logger.error(ppp("Unexpected or invalid packet:", p))
4591             raise
4592
4593     def test_next_src_nat(self):
4594         """ On way back forward packet to nat44-in2out node. """
4595         twice_nat_addr = '10.0.1.3'
4596         external_port = 80
4597         local_port = 8080
4598         post_twice_nat_port = 0
4599
4600         self.vapi.nat44_forwarding_enable_disable(1)
4601         self.nat44_add_address(twice_nat_addr, twice_nat=1)
4602         self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
4603                                       local_port, external_port,
4604                                       proto=IP_PROTOS.tcp, out2in_only=1,
4605                                       self_twice_nat=1, vrf_id=1)
4606         self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
4607                                                   is_inside=0)
4608
4609         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4610              IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
4611              TCP(sport=12345, dport=external_port))
4612         self.pg6.add_stream(p)
4613         self.pg_enable_capture(self.pg_interfaces)
4614         self.pg_start()
4615         capture = self.pg6.get_capture(1)
4616         p = capture[0]
4617         try:
4618             ip = p[IP]
4619             tcp = p[TCP]
4620             self.assertEqual(ip.src, twice_nat_addr)
4621             self.assertNotEqual(tcp.sport, 12345)
4622             post_twice_nat_port = tcp.sport
4623             self.assertEqual(ip.dst, self.pg6.remote_ip4)
4624             self.assertEqual(tcp.dport, local_port)
4625             self.assert_packet_checksums_valid(p)
4626         except:
4627             self.logger.error(ppp("Unexpected or invalid packet:", p))
4628             raise
4629
4630         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4631              IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
4632              TCP(sport=local_port, dport=post_twice_nat_port))
4633         self.pg6.add_stream(p)
4634         self.pg_enable_capture(self.pg_interfaces)
4635         self.pg_start()
4636         capture = self.pg6.get_capture(1)
4637         p = capture[0]
4638         try:
4639             ip = p[IP]
4640             tcp = p[TCP]
4641             self.assertEqual(ip.src, self.pg1.remote_ip4)
4642             self.assertEqual(tcp.sport, external_port)
4643             self.assertEqual(ip.dst, self.pg6.remote_ip4)
4644             self.assertEqual(tcp.dport, 12345)
4645             self.assert_packet_checksums_valid(p)
4646         except:
4647             self.logger.error(ppp("Unexpected or invalid packet:", p))
4648             raise
4649
4650     def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
4651                          client_id=None):
4652         twice_nat_addr = '10.0.1.3'
4653
4654         port_in = 8080
4655         if lb:
4656             if not same_pg:
4657                 port_in1 = port_in
4658                 port_in2 = port_in
4659             else:
4660                 port_in1 = port_in+1
4661                 port_in2 = port_in+2
4662
4663         port_out = 80
4664         eh_port_out = 4567
4665
4666         server1 = self.pg0.remote_hosts[0]
4667         server2 = self.pg0.remote_hosts[1]
4668         if lb and same_pg:
4669             server2 = server1
4670         if not lb:
4671             server = server1
4672
4673         pg0 = self.pg0
4674         if same_pg:
4675             pg1 = self.pg0
4676         else:
4677             pg1 = self.pg1
4678
4679         eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
4680                         client_id == 1)
4681
4682         self.nat44_add_address(self.nat_addr)
4683         self.nat44_add_address(twice_nat_addr, twice_nat=1)
4684         if not lb:
4685             self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
4686                                           port_in, port_out,
4687                                           proto=IP_PROTOS.tcp,
4688                                           twice_nat=int(not self_twice_nat),
4689                                           self_twice_nat=int(self_twice_nat))
4690         else:
4691             locals = [{'addr': server1.ip4n,
4692                        'port': port_in1,
4693                        'probability': 50,
4694                        'vrf_id': 0},
4695                       {'addr': server2.ip4n,
4696                        'port': port_in2,
4697                        'probability': 50,
4698                        'vrf_id': 0}]
4699             out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4700             self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
4701                                                       port_out,
4702                                                       IP_PROTOS.tcp,
4703                                                       twice_nat=int(
4704                                                           not self_twice_nat),
4705                                                       self_twice_nat=int(
4706                                                           self_twice_nat),
4707                                                       local_num=len(locals),
4708                                                       locals=locals)
4709         self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
4710         self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
4711                                                   is_inside=0)
4712
4713         if same_pg:
4714             if not lb:
4715                 client = server
4716             else:
4717                 assert client_id is not None
4718                 if client_id == 1:
4719                     client = self.pg0.remote_hosts[0]
4720                 elif client_id == 2:
4721                     client = self.pg0.remote_hosts[1]
4722         else:
4723             client = pg1.remote_hosts[0]
4724         p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
4725              IP(src=client.ip4, dst=self.nat_addr) /
4726              TCP(sport=eh_port_out, dport=port_out))
4727         pg1.add_stream(p)
4728         self.pg_enable_capture(self.pg_interfaces)
4729         self.pg_start()
4730         capture = pg0.get_capture(1)
4731         p = capture[0]
4732         try:
4733             ip = p[IP]
4734             tcp = p[TCP]
4735             if lb:
4736                 if ip.dst == server1.ip4:
4737                     server = server1
4738                     port_in = port_in1
4739                 else:
4740                     server = server2
4741                     port_in = port_in2
4742             self.assertEqual(ip.dst, server.ip4)
4743             if lb and same_pg:
4744                 self.assertIn(tcp.dport, [port_in1, port_in2])
4745             else:
4746                 self.assertEqual(tcp.dport, port_in)
4747             if eh_translate:
4748                 self.assertEqual(ip.src, twice_nat_addr)
4749                 self.assertNotEqual(tcp.sport, eh_port_out)
4750             else:
4751                 self.assertEqual(ip.src, client.ip4)
4752                 self.assertEqual(tcp.sport, eh_port_out)
4753             eh_addr_in = ip.src
4754             eh_port_in = tcp.sport
4755             saved_port_in = tcp.dport
4756             self.assert_packet_checksums_valid(p)
4757         except:
4758             self.logger.error(ppp("Unexpected or invalid packet:", p))
4759             raise
4760
4761         p = (Ether(src=server.mac, dst=pg0.local_mac) /
4762              IP(src=server.ip4, dst=eh_addr_in) /
4763              TCP(sport=saved_port_in, dport=eh_port_in))
4764         pg0.add_stream(p)
4765         self.pg_enable_capture(self.pg_interfaces)
4766         self.pg_start()
4767         capture = pg1.get_capture(1)
4768         p = capture[0]
4769         try:
4770             ip = p[IP]
4771             tcp = p[TCP]
4772             self.assertEqual(ip.dst, client.ip4)
4773             self.assertEqual(ip.src, self.nat_addr)
4774             self.assertEqual(tcp.dport, eh_port_out)
4775             self.assertEqual(tcp.sport, port_out)
4776             self.assert_packet_checksums_valid(p)
4777         except:
4778             self.logger.error(ppp("Unexpected or invalid packet:", p))
4779             raise
4780
4781         if eh_translate:
4782             sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4783             self.assertEqual(len(sessions), 1)
4784             self.assertTrue(sessions[0].ext_host_valid)
4785             self.assertTrue(sessions[0].is_twicenat)
4786             self.vapi.nat44_del_session(
4787                 sessions[0].inside_ip_address,
4788                 sessions[0].inside_port,
4789                 sessions[0].protocol,
4790                 ext_host_address=sessions[0].ext_host_nat_address,
4791                 ext_host_port=sessions[0].ext_host_nat_port)
4792             sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4793             self.assertEqual(len(sessions), 0)
4794
4795     def test_twice_nat(self):
4796         """ Twice NAT44 """
4797         self.twice_nat_common()
4798
4799     def test_self_twice_nat_positive(self):
4800         """ Self Twice NAT44 (positive test) """
4801         self.twice_nat_common(self_twice_nat=True, same_pg=True)
4802
4803     def test_self_twice_nat_negative(self):
4804         """ Self Twice NAT44 (negative test) """
4805         self.twice_nat_common(self_twice_nat=True)
4806
4807     def test_twice_nat_lb(self):
4808         """ Twice NAT44 local service load balancing """
4809         self.twice_nat_common(lb=True)
4810
4811     def test_self_twice_nat_lb_positive(self):
4812         """ Self Twice NAT44 local service load balancing (positive test) """
4813         self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4814                               client_id=1)
4815
4816     def test_self_twice_nat_lb_negative(self):
4817         """ Self Twice NAT44 local service load balancing (negative test) """
4818         self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
4819                               client_id=2)
4820
4821     def test_twice_nat_interface_addr(self):
4822         """ Acquire twice NAT44 addresses from interface """
4823         self.vapi.nat44_add_interface_addr(self.pg3.sw_if_index, twice_nat=1)
4824
4825         # no address in NAT pool
4826         adresses = self.vapi.nat44_address_dump()
4827         self.assertEqual(0, len(adresses))
4828
4829         # configure interface address and check NAT address pool
4830         self.pg3.config_ip4()
4831         adresses = self.vapi.nat44_address_dump()
4832         self.assertEqual(1, len(adresses))
4833         self.assertEqual(adresses[0].ip_address[0:4], self.pg3.local_ip4n)
4834         self.assertEqual(adresses[0].twice_nat, 1)
4835
4836         # remove interface address and check NAT address pool
4837         self.pg3.unconfig_ip4()
4838         adresses = self.vapi.nat44_address_dump()
4839         self.assertEqual(0, len(adresses))
4840
4841     def test_tcp_close(self):
4842         """ Close TCP session from inside network - output feature """
4843         self.vapi.nat44_forwarding_enable_disable(1)
4844         self.nat44_add_address(self.pg1.local_ip4)
4845         twice_nat_addr = '10.0.1.3'
4846         service_ip = '192.168.16.150'
4847         self.nat44_add_address(twice_nat_addr, twice_nat=1)
4848         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4849         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4850                                                   is_inside=0)
4851         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4852                                                          is_inside=0)
4853         self.nat44_add_static_mapping(self.pg0.remote_ip4,
4854                                       service_ip,
4855                                       80,
4856                                       80,
4857                                       proto=IP_PROTOS.tcp,
4858                                       out2in_only=1,
4859                                       twice_nat=1)
4860         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4861         start_sessnum = len(sessions)
4862
4863         # SYN packet out->in
4864         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4865              IP(src=self.pg1.remote_ip4, dst=service_ip) /
4866              TCP(sport=33898, dport=80, flags="S"))
4867         self.pg1.add_stream(p)
4868         self.pg_enable_capture(self.pg_interfaces)
4869         self.pg_start()
4870         capture = self.pg0.get_capture(1)
4871         p = capture[0]
4872         tcp_port = p[TCP].sport
4873
4874         # SYN + ACK packet in->out
4875         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4876              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
4877              TCP(sport=80, dport=tcp_port, flags="SA"))
4878         self.pg0.add_stream(p)
4879         self.pg_enable_capture(self.pg_interfaces)
4880         self.pg_start()
4881         self.pg1.get_capture(1)
4882
4883         # ACK packet out->in
4884         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4885              IP(src=self.pg1.remote_ip4, dst=service_ip) /
4886              TCP(sport=33898, dport=80, flags="A"))
4887         self.pg1.add_stream(p)
4888         self.pg_enable_capture(self.pg_interfaces)
4889         self.pg_start()
4890         self.pg0.get_capture(1)
4891
4892         # FIN packet in -> out
4893         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4894              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
4895              TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
4896         self.pg0.add_stream(p)
4897         self.pg_enable_capture(self.pg_interfaces)
4898         self.pg_start()
4899         self.pg1.get_capture(1)
4900
4901         # FIN+ACK packet out -> in
4902         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4903              IP(src=self.pg1.remote_ip4, dst=service_ip) /
4904              TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
4905         self.pg1.add_stream(p)
4906         self.pg_enable_capture(self.pg_interfaces)
4907         self.pg_start()
4908         self.pg0.get_capture(1)
4909
4910         # ACK packet in -> out
4911         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4912              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
4913              TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
4914         self.pg0.add_stream(p)
4915         self.pg_enable_capture(self.pg_interfaces)
4916         self.pg_start()
4917         self.pg1.get_capture(1)
4918
4919         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4920                                                      0)
4921         self.assertEqual(len(sessions) - start_sessnum, 0)
4922
4923     def test_tcp_session_close_in(self):
4924         """ Close TCP session from inside network """
4925         self.tcp_port_out = 10505
4926         self.nat44_add_address(self.nat_addr)
4927         self.nat44_add_static_mapping(self.pg0.remote_ip4,
4928                                       self.nat_addr,
4929                                       self.tcp_port_in,
4930                                       self.tcp_port_out,
4931                                       proto=IP_PROTOS.tcp,
4932                                       twice_nat=1)
4933         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4934         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4935                                                   is_inside=0)
4936
4937         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
4938         start_sessnum = len(sessions)
4939
4940         self.initiate_tcp_session(self.pg0, self.pg1)
4941
4942         # FIN packet in -> out
4943         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4944              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4945              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4946                  flags="FA", seq=100, ack=300))
4947         self.pg0.add_stream(p)
4948         self.pg_enable_capture(self.pg_interfaces)
4949         self.pg_start()
4950         self.pg1.get_capture(1)
4951
4952         pkts = []
4953
4954         # ACK packet out -> in
4955         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4956              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4957              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4958                  flags="A", seq=300, ack=101))
4959         pkts.append(p)
4960
4961         # FIN packet out -> in
4962         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4963              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4964              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
4965                  flags="FA", seq=300, ack=101))
4966         pkts.append(p)
4967
4968         self.pg1.add_stream(pkts)
4969         self.pg_enable_capture(self.pg_interfaces)
4970         self.pg_start()
4971         self.pg0.get_capture(2)
4972
4973         # ACK packet in -> out
4974         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4975              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4976              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4977                  flags="A", seq=101, ack=301))
4978         self.pg0.add_stream(p)
4979         self.pg_enable_capture(self.pg_interfaces)
4980         self.pg_start()
4981         self.pg1.get_capture(1)
4982
4983         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
4984                                                      0)
4985         self.assertEqual(len(sessions) - start_sessnum, 0)
4986
4987     def test_tcp_session_close_out(self):
4988         """ Close TCP session from outside network """
4989         self.tcp_port_out = 10505
4990         self.nat44_add_address(self.nat_addr)
4991         self.nat44_add_static_mapping(self.pg0.remote_ip4,
4992                                       self.nat_addr,
4993                                       self.tcp_port_in,
4994                                       self.tcp_port_out,
4995                                       proto=IP_PROTOS.tcp,
4996                                       twice_nat=1)
4997         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4998         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4999                                                   is_inside=0)
5000
5001         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5002         start_sessnum = len(sessions)
5003
5004         self.initiate_tcp_session(self.pg0, self.pg1)
5005
5006         # FIN packet out -> in
5007         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5008              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5009              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5010                  flags="FA", seq=100, ack=300))
5011         self.pg1.add_stream(p)
5012         self.pg_enable_capture(self.pg_interfaces)
5013         self.pg_start()
5014         self.pg0.get_capture(1)
5015
5016         # FIN+ACK packet in -> out
5017         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5018              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5019              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5020                  flags="FA", seq=300, ack=101))
5021
5022         self.pg0.add_stream(p)
5023         self.pg_enable_capture(self.pg_interfaces)
5024         self.pg_start()
5025         self.pg1.get_capture(1)
5026
5027         # ACK packet out -> in
5028         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5029              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5030              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5031                  flags="A", seq=101, ack=301))
5032         self.pg1.add_stream(p)
5033         self.pg_enable_capture(self.pg_interfaces)
5034         self.pg_start()
5035         self.pg0.get_capture(1)
5036
5037         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5038                                                      0)
5039         self.assertEqual(len(sessions) - start_sessnum, 0)
5040
5041     def test_tcp_session_close_simultaneous(self):
5042         """ Close TCP session from inside network """
5043         self.tcp_port_out = 10505
5044         self.nat44_add_address(self.nat_addr)
5045         self.nat44_add_static_mapping(self.pg0.remote_ip4,
5046                                       self.nat_addr,
5047                                       self.tcp_port_in,
5048                                       self.tcp_port_out,
5049                                       proto=IP_PROTOS.tcp,
5050                                       twice_nat=1)
5051         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5052         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5053                                                   is_inside=0)
5054
5055         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5056         start_sessnum = len(sessions)
5057
5058         self.initiate_tcp_session(self.pg0, self.pg1)
5059
5060         # FIN packet in -> out
5061         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5062              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5063              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5064                  flags="FA", seq=100, ack=300))
5065         self.pg0.add_stream(p)
5066         self.pg_enable_capture(self.pg_interfaces)
5067         self.pg_start()
5068         self.pg1.get_capture(1)
5069
5070         # FIN packet out -> in
5071         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5072              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5073              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5074                  flags="FA", seq=300, ack=100))
5075         self.pg1.add_stream(p)
5076         self.pg_enable_capture(self.pg_interfaces)
5077         self.pg_start()
5078         self.pg0.get_capture(1)
5079
5080         # ACK packet in -> out
5081         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5082              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5083              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5084                  flags="A", seq=101, ack=301))
5085         self.pg0.add_stream(p)
5086         self.pg_enable_capture(self.pg_interfaces)
5087         self.pg_start()
5088         self.pg1.get_capture(1)
5089
5090         # ACK packet out -> in
5091         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5092              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5093              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5094                  flags="A", seq=301, ack=101))
5095         self.pg1.add_stream(p)
5096         self.pg_enable_capture(self.pg_interfaces)
5097         self.pg_start()
5098         self.pg0.get_capture(1)
5099
5100         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5101                                                      0)
5102         self.assertEqual(len(sessions) - start_sessnum, 0)
5103
5104     def test_one_armed_nat44_static(self):
5105         """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
5106         remote_host = self.pg4.remote_hosts[0]
5107         local_host = self.pg4.remote_hosts[1]
5108         external_port = 80
5109         local_port = 8080
5110         eh_port_in = 0
5111
5112         self.vapi.nat44_forwarding_enable_disable(1)
5113         self.nat44_add_address(self.nat_addr, twice_nat=1)
5114         self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
5115                                       local_port, external_port,
5116                                       proto=IP_PROTOS.tcp, out2in_only=1,
5117                                       twice_nat=1)
5118         self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
5119         self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
5120                                                   is_inside=0)
5121
5122         # from client to service
5123         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5124              IP(src=remote_host.ip4, dst=self.nat_addr) /
5125              TCP(sport=12345, dport=external_port))
5126         self.pg4.add_stream(p)
5127         self.pg_enable_capture(self.pg_interfaces)
5128         self.pg_start()
5129         capture = self.pg4.get_capture(1)
5130         p = capture[0]
5131         try:
5132             ip = p[IP]
5133             tcp = p[TCP]
5134             self.assertEqual(ip.dst, local_host.ip4)
5135             self.assertEqual(ip.src, self.nat_addr)
5136             self.assertEqual(tcp.dport, local_port)
5137             self.assertNotEqual(tcp.sport, 12345)
5138             eh_port_in = tcp.sport
5139             self.assert_packet_checksums_valid(p)
5140         except:
5141             self.logger.error(ppp("Unexpected or invalid packet:", p))
5142             raise
5143
5144         # from service back to client
5145         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5146              IP(src=local_host.ip4, dst=self.nat_addr) /
5147              TCP(sport=local_port, dport=eh_port_in))
5148         self.pg4.add_stream(p)
5149         self.pg_enable_capture(self.pg_interfaces)
5150         self.pg_start()
5151         capture = self.pg4.get_capture(1)
5152         p = capture[0]
5153         try:
5154             ip = p[IP]
5155             tcp = p[TCP]
5156             self.assertEqual(ip.src, self.nat_addr)
5157             self.assertEqual(ip.dst, remote_host.ip4)
5158             self.assertEqual(tcp.sport, external_port)
5159             self.assertEqual(tcp.dport, 12345)
5160             self.assert_packet_checksums_valid(p)
5161         except:
5162             self.logger.error(ppp("Unexpected or invalid packet:", p))
5163             raise
5164
5165     def test_static_with_port_out2(self):
5166         """ 1:1 NAPT asymmetrical rule """
5167
5168         external_port = 80
5169         local_port = 8080
5170
5171         self.vapi.nat44_forwarding_enable_disable(1)
5172         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
5173                                       local_port, external_port,
5174                                       proto=IP_PROTOS.tcp, out2in_only=1)
5175         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5176         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5177                                                   is_inside=0)
5178
5179         # from client to service
5180         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5181              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5182              TCP(sport=12345, dport=external_port))
5183         self.pg1.add_stream(p)
5184         self.pg_enable_capture(self.pg_interfaces)
5185         self.pg_start()
5186         capture = self.pg0.get_capture(1)
5187         p = capture[0]
5188         try:
5189             ip = p[IP]
5190             tcp = p[TCP]
5191             self.assertEqual(ip.dst, self.pg0.remote_ip4)
5192             self.assertEqual(tcp.dport, local_port)
5193             self.assert_packet_checksums_valid(p)
5194         except:
5195             self.logger.error(ppp("Unexpected or invalid packet:", p))
5196             raise
5197
5198         # ICMP error
5199         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5200              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5201              ICMP(type=11) / capture[0][IP])
5202         self.pg0.add_stream(p)
5203         self.pg_enable_capture(self.pg_interfaces)
5204         self.pg_start()
5205         capture = self.pg1.get_capture(1)
5206         p = capture[0]
5207         try:
5208             self.assertEqual(p[IP].src, self.nat_addr)
5209             inner = p[IPerror]
5210             self.assertEqual(inner.dst, self.nat_addr)
5211             self.assertEqual(inner[TCPerror].dport, external_port)
5212         except:
5213             self.logger.error(ppp("Unexpected or invalid packet:", p))
5214             raise
5215
5216         # from service back to client
5217         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5218              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5219              TCP(sport=local_port, dport=12345))
5220         self.pg0.add_stream(p)
5221         self.pg_enable_capture(self.pg_interfaces)
5222         self.pg_start()
5223         capture = self.pg1.get_capture(1)
5224         p = capture[0]
5225         try:
5226             ip = p[IP]
5227             tcp = p[TCP]
5228             self.assertEqual(ip.src, self.nat_addr)
5229             self.assertEqual(tcp.sport, external_port)
5230             self.assert_packet_checksums_valid(p)
5231         except:
5232             self.logger.error(ppp("Unexpected or invalid packet:", p))
5233             raise
5234
5235         # ICMP error
5236         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5237              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5238              ICMP(type=11) / capture[0][IP])
5239         self.pg1.add_stream(p)
5240         self.pg_enable_capture(self.pg_interfaces)
5241         self.pg_start()
5242         capture = self.pg0.get_capture(1)
5243         p = capture[0]
5244         try:
5245             self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
5246             inner = p[IPerror]
5247             self.assertEqual(inner.src, self.pg0.remote_ip4)
5248             self.assertEqual(inner[TCPerror].sport, local_port)
5249         except:
5250             self.logger.error(ppp("Unexpected or invalid packet:", p))
5251             raise
5252
5253         # from client to server (no translation)
5254         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5255              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5256              TCP(sport=12346, dport=local_port))
5257         self.pg1.add_stream(p)
5258         self.pg_enable_capture(self.pg_interfaces)
5259         self.pg_start()
5260         capture = self.pg0.get_capture(1)
5261         p = capture[0]
5262         try:
5263             ip = p[IP]
5264             tcp = p[TCP]
5265             self.assertEqual(ip.dst, self.pg0.remote_ip4)
5266             self.assertEqual(tcp.dport, local_port)
5267             self.assert_packet_checksums_valid(p)
5268         except:
5269             self.logger.error(ppp("Unexpected or invalid packet:", p))
5270             raise
5271
5272         # from service back to client (no translation)
5273         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5274              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5275              TCP(sport=local_port, dport=12346))
5276         self.pg0.add_stream(p)
5277         self.pg_enable_capture(self.pg_interfaces)
5278         self.pg_start()
5279         capture = self.pg1.get_capture(1)
5280         p = capture[0]
5281         try:
5282             ip = p[IP]
5283             tcp = p[TCP]
5284             self.assertEqual(ip.src, self.pg0.remote_ip4)
5285             self.assertEqual(tcp.sport, local_port)
5286             self.assert_packet_checksums_valid(p)
5287         except:
5288             self.logger.error(ppp("Unexpected or invalid packet:", p))
5289             raise
5290
5291     def test_output_feature(self):
5292         """ NAT44 interface output feature (in2out postrouting) """
5293         self.vapi.nat44_forwarding_enable_disable(1)
5294         self.nat44_add_address(self.nat_addr)
5295         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5296                                                   is_inside=0)
5297         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5298                                                          is_inside=0)
5299
5300         # in2out
5301         pkts = self.create_stream_in(self.pg0, self.pg1)
5302         self.pg0.add_stream(pkts)
5303         self.pg_enable_capture(self.pg_interfaces)
5304         self.pg_start()
5305         capture = self.pg1.get_capture(len(pkts))
5306         self.verify_capture_out(capture)
5307
5308         # out2in
5309         pkts = self.create_stream_out(self.pg1)
5310         self.pg1.add_stream(pkts)
5311         self.pg_enable_capture(self.pg_interfaces)
5312         self.pg_start()
5313         capture = self.pg0.get_capture(len(pkts))
5314         self.verify_capture_in(capture, self.pg0)
5315
5316     def test_multiple_vrf(self):
5317         """ Multiple VRF setup """
5318         external_addr = '1.2.3.4'
5319         external_port = 80
5320         local_port = 8080
5321         port = 0
5322
5323         self.vapi.nat44_forwarding_enable_disable(1)
5324         self.nat44_add_address(self.nat_addr)
5325         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5326         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5327                                                   is_inside=0)
5328         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5329                                                          is_inside=0)
5330         self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
5331         self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index,
5332                                                   is_inside=0)
5333         self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
5334                                                   is_inside=0)
5335         self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
5336                                       local_port, external_port, vrf_id=1,
5337                                       proto=IP_PROTOS.tcp, out2in_only=1)
5338         self.nat44_add_static_mapping(
5339              self.pg0.remote_ip4, external_sw_if_index=self.pg0.sw_if_index,
5340              local_port=local_port, vrf_id=0, external_port=external_port,
5341              proto=IP_PROTOS.tcp, out2in_only=1)
5342
5343         # from client to service (both VRF1)
5344         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5345              IP(src=self.pg6.remote_ip4, dst=external_addr) /
5346              TCP(sport=12345, dport=external_port))
5347         self.pg6.add_stream(p)
5348         self.pg_enable_capture(self.pg_interfaces)
5349         self.pg_start()
5350         capture = self.pg5.get_capture(1)
5351         p = capture[0]
5352         try:
5353             ip = p[IP]
5354             tcp = p[TCP]
5355             self.assertEqual(ip.dst, self.pg5.remote_ip4)
5356             self.assertEqual(tcp.dport, local_port)
5357             self.assert_packet_checksums_valid(p)
5358         except:
5359             self.logger.error(ppp("Unexpected or invalid packet:", p))
5360             raise
5361
5362         # from service back to client (both VRF1)
5363         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5364              IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
5365              TCP(sport=local_port, dport=12345))
5366         self.pg5.add_stream(p)
5367         self.pg_enable_capture(self.pg_interfaces)
5368         self.pg_start()
5369         capture = self.pg6.get_capture(1)
5370         p = capture[0]
5371         try:
5372             ip = p[IP]
5373             tcp = p[TCP]
5374             self.assertEqual(ip.src, external_addr)
5375             self.assertEqual(tcp.sport, external_port)
5376             self.assert_packet_checksums_valid(p)
5377         except:
5378             self.logger.error(ppp("Unexpected or invalid packet:", p))
5379             raise
5380
5381         # dynamic NAT from VRF1 to VRF0 (output-feature)
5382         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5383              IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
5384              TCP(sport=2345, dport=22))
5385         self.pg5.add_stream(p)
5386         self.pg_enable_capture(self.pg_interfaces)
5387         self.pg_start()
5388         capture = self.pg1.get_capture(1)
5389         p = capture[0]
5390         try:
5391             ip = p[IP]
5392             tcp = p[TCP]
5393             self.assertEqual(ip.src, self.nat_addr)
5394             self.assertNotEqual(tcp.sport, 2345)
5395             self.assert_packet_checksums_valid(p)
5396             port = tcp.sport
5397         except:
5398             self.logger.error(ppp("Unexpected or invalid packet:", p))
5399             raise
5400
5401         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5402              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5403              TCP(sport=22, dport=port))
5404         self.pg1.add_stream(p)
5405         self.pg_enable_capture(self.pg_interfaces)
5406         self.pg_start()
5407         capture = self.pg5.get_capture(1)
5408         p = capture[0]
5409         try:
5410             ip = p[IP]
5411             tcp = p[TCP]
5412             self.assertEqual(ip.dst, self.pg5.remote_ip4)
5413             self.assertEqual(tcp.dport, 2345)
5414             self.assert_packet_checksums_valid(p)
5415         except:
5416             self.logger.error(ppp("Unexpected or invalid packet:", p))
5417             raise
5418
5419         # from client VRF1 to service VRF0
5420         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5421              IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
5422              TCP(sport=12346, dport=external_port))
5423         self.pg6.add_stream(p)
5424         self.pg_enable_capture(self.pg_interfaces)
5425         self.pg_start()
5426         capture = self.pg0.get_capture(1)
5427         p = capture[0]
5428         try:
5429             ip = p[IP]
5430             tcp = p[TCP]
5431             self.assertEqual(ip.dst, self.pg0.remote_ip4)
5432             self.assertEqual(tcp.dport, local_port)
5433             self.assert_packet_checksums_valid(p)
5434         except:
5435             self.logger.error(ppp("Unexpected or invalid packet:", p))
5436             raise
5437
5438         # from service VRF0 back to client VRF1
5439         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5440              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
5441              TCP(sport=local_port, dport=12346))
5442         self.pg0.add_stream(p)
5443         self.pg_enable_capture(self.pg_interfaces)
5444         self.pg_start()
5445         capture = self.pg6.get_capture(1)
5446         p = capture[0]
5447         try:
5448             ip = p[IP]
5449             tcp = p[TCP]
5450             self.assertEqual(ip.src, self.pg0.local_ip4)
5451             self.assertEqual(tcp.sport, external_port)
5452             self.assert_packet_checksums_valid(p)
5453         except:
5454             self.logger.error(ppp("Unexpected or invalid packet:", p))
5455             raise
5456
5457         # from client VRF0 to service VRF1
5458         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5459              IP(src=self.pg0.remote_ip4, dst=external_addr) /
5460              TCP(sport=12347, dport=external_port))
5461         self.pg0.add_stream(p)
5462         self.pg_enable_capture(self.pg_interfaces)
5463         self.pg_start()
5464         capture = self.pg5.get_capture(1)
5465         p = capture[0]
5466         try:
5467             ip = p[IP]
5468             tcp = p[TCP]
5469             self.assertEqual(ip.dst, self.pg5.remote_ip4)
5470             self.assertEqual(tcp.dport, local_port)
5471             self.assert_packet_checksums_valid(p)
5472         except:
5473             self.logger.error(ppp("Unexpected or invalid packet:", p))
5474             raise
5475
5476         # from service VRF1 back to client VRF0
5477         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5478              IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
5479              TCP(sport=local_port, dport=12347))
5480         self.pg5.add_stream(p)
5481         self.pg_enable_capture(self.pg_interfaces)
5482         self.pg_start()
5483         capture = self.pg0.get_capture(1)
5484         p = capture[0]
5485         try:
5486             ip = p[IP]
5487             tcp = p[TCP]
5488             self.assertEqual(ip.src, external_addr)
5489             self.assertEqual(tcp.sport, external_port)
5490             self.assert_packet_checksums_valid(p)
5491         except:
5492             self.logger.error(ppp("Unexpected or invalid packet:", p))
5493             raise
5494
5495         # from client to server (both VRF1, no translation)
5496         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5497              IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
5498              TCP(sport=12348, dport=local_port))
5499         self.pg6.add_stream(p)
5500         self.pg_enable_capture(self.pg_interfaces)
5501         self.pg_start()
5502         capture = self.pg5.get_capture(1)
5503         p = capture[0]
5504         try:
5505             ip = p[IP]
5506             tcp = p[TCP]
5507             self.assertEqual(ip.dst, self.pg5.remote_ip4)
5508             self.assertEqual(tcp.dport, local_port)
5509             self.assert_packet_checksums_valid(p)
5510         except:
5511             self.logger.error(ppp("Unexpected or invalid packet:", p))
5512             raise
5513
5514         # from server back to client (both VRF1, no translation)
5515         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5516              IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
5517              TCP(sport=local_port, dport=12348))
5518         self.pg5.add_stream(p)
5519         self.pg_enable_capture(self.pg_interfaces)
5520         self.pg_start()
5521         capture = self.pg6.get_capture(1)
5522         p = capture[0]
5523         try:
5524             ip = p[IP]
5525             tcp = p[TCP]
5526             self.assertEqual(ip.src, self.pg5.remote_ip4)
5527             self.assertEqual(tcp.sport, local_port)
5528             self.assert_packet_checksums_valid(p)
5529         except:
5530             self.logger.error(ppp("Unexpected or invalid packet:", p))
5531             raise
5532
5533         # from client VRF1 to server VRF0 (no translation)
5534         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5535              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
5536              TCP(sport=local_port, dport=12349))
5537         self.pg0.add_stream(p)
5538         self.pg_enable_capture(self.pg_interfaces)
5539         self.pg_start()
5540         capture = self.pg6.get_capture(1)
5541         p = capture[0]
5542         try:
5543             ip = p[IP]
5544             tcp = p[TCP]
5545             self.assertEqual(ip.src, self.pg0.remote_ip4)
5546             self.assertEqual(tcp.sport, local_port)
5547             self.assert_packet_checksums_valid(p)
5548         except:
5549             self.logger.error(ppp("Unexpected or invalid packet:", p))
5550             raise
5551
5552         # from server VRF0 back to client VRF1 (no translation)
5553         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5554              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
5555              TCP(sport=local_port, dport=12349))
5556         self.pg0.add_stream(p)
5557         self.pg_enable_capture(self.pg_interfaces)
5558         self.pg_start()
5559         capture = self.pg6.get_capture(1)
5560         p = capture[0]
5561         try:
5562             ip = p[IP]
5563             tcp = p[TCP]
5564             self.assertEqual(ip.src, self.pg0.remote_ip4)
5565             self.assertEqual(tcp.sport, local_port)
5566             self.assert_packet_checksums_valid(p)
5567         except:
5568             self.logger.error(ppp("Unexpected or invalid packet:", p))
5569             raise
5570
5571         # from client VRF0 to server VRF1 (no translation)
5572         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5573              IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
5574              TCP(sport=12344, dport=local_port))
5575         self.pg0.add_stream(p)
5576         self.pg_enable_capture(self.pg_interfaces)
5577         self.pg_start()
5578         capture = self.pg5.get_capture(1)
5579         p = capture[0]
5580         try:
5581             ip = p[IP]
5582             tcp = p[TCP]
5583             self.assertEqual(ip.dst, self.pg5.remote_ip4)
5584             self.assertEqual(tcp.dport, local_port)
5585             self.assert_packet_checksums_valid(p)
5586         except:
5587             self.logger.error(ppp("Unexpected or invalid packet:", p))
5588             raise
5589
5590         # from server VRF1 back to client VRF0 (no translation)
5591         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5592              IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
5593              TCP(sport=local_port, dport=12344))
5594         self.pg5.add_stream(p)
5595         self.pg_enable_capture(self.pg_interfaces)
5596         self.pg_start()
5597         capture = self.pg0.get_capture(1)
5598         p = capture[0]
5599         try:
5600             ip = p[IP]
5601             tcp = p[TCP]
5602             self.assertEqual(ip.src, self.pg5.remote_ip4)
5603             self.assertEqual(tcp.sport, local_port)
5604             self.assert_packet_checksums_valid(p)
5605         except:
5606             self.logger.error(ppp("Unexpected or invalid packet:", p))
5607             raise
5608
5609     @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5610     def test_session_timeout(self):
5611         """ NAT44 session timeouts """
5612         self.nat44_add_address(self.nat_addr)
5613         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5614         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5615                                                   is_inside=0)
5616         self.vapi.nat_set_timeouts(icmp=5)
5617
5618         max_sessions = 1000
5619         pkts = []
5620         for i in range(0, max_sessions):
5621             src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
5622             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5623                  IP(src=src, dst=self.pg1.remote_ip4) /
5624                  ICMP(id=1025, type='echo-request'))
5625             pkts.append(p)
5626         self.pg0.add_stream(pkts)
5627         self.pg_enable_capture(self.pg_interfaces)
5628         self.pg_start()
5629         self.pg1.get_capture(max_sessions)
5630
5631         sleep(10)
5632
5633         pkts = []
5634         for i in range(0, max_sessions):
5635             src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
5636             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5637                  IP(src=src, dst=self.pg1.remote_ip4) /
5638                  ICMP(id=1026, type='echo-request'))
5639             pkts.append(p)
5640         self.pg0.add_stream(pkts)
5641         self.pg_enable_capture(self.pg_interfaces)
5642         self.pg_start()
5643         self.pg1.get_capture(max_sessions)
5644
5645         nsessions = 0
5646         users = self.vapi.nat44_user_dump()
5647         for user in users:
5648             nsessions = nsessions + user.nsessions
5649         self.assertLess(nsessions, 2 * max_sessions)
5650
5651     @unittest.skipUnless(running_extended_tests(), "part of extended tests")
5652     def test_session_limit_per_user(self):
5653         """ Maximum sessions per user limit """
5654         self.nat44_add_address(self.nat_addr)
5655         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5656         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5657                                                   is_inside=0)
5658         self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
5659                                      src_address=self.pg2.local_ip4n,
5660                                      path_mtu=512,
5661                                      template_interval=10)
5662         self.vapi.nat_set_timeouts(udp=5)
5663
5664         # get maximum number of translations per user
5665         nat44_config = self.vapi.nat_show_config()
5666
5667         pkts = []
5668         for port in range(0, nat44_config.max_translations_per_user):
5669             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5670                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5671                  UDP(sport=1025 + port, dport=1025 + port))
5672             pkts.append(p)
5673
5674         self.pg0.add_stream(pkts)
5675         self.pg_enable_capture(self.pg_interfaces)
5676         self.pg_start()
5677         capture = self.pg1.get_capture(len(pkts))
5678
5679         self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5680                             src_port=self.ipfix_src_port)
5681
5682         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5683              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5684              UDP(sport=3001, dport=3002))
5685         self.pg0.add_stream(p)
5686         self.pg_enable_capture(self.pg_interfaces)
5687         self.pg_start()
5688         capture = self.pg1.assert_nothing_captured()
5689
5690         # verify IPFIX logging
5691         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
5692         sleep(1)
5693         capture = self.pg2.get_capture(10)
5694         ipfix = IPFIXDecoder()
5695         # first load template
5696         for p in capture:
5697             self.assertTrue(p.haslayer(IPFIX))
5698             if p.haslayer(Template):
5699                 ipfix.add_template(p.getlayer(Template))
5700         # verify events in data set
5701         for p in capture:
5702             if p.haslayer(Data):
5703                 data = ipfix.decode_data_set(p.getlayer(Set))
5704                 self.verify_ipfix_max_entries_per_user(
5705                     data,
5706                     nat44_config.max_translations_per_user,
5707                     self.pg0.remote_ip4n)
5708
5709         sleep(6)
5710         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5711              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5712              UDP(sport=3001, dport=3002))
5713         self.pg0.add_stream(p)
5714         self.pg_enable_capture(self.pg_interfaces)
5715         self.pg_start()
5716         self.pg1.get_capture(1)
5717
5718     def tearDown(self):
5719         super(TestNAT44EndpointDependent, self).tearDown()
5720         if not self.vpp_dead:
5721             self.logger.info(self.vapi.cli("show nat44 addresses"))
5722             self.logger.info(self.vapi.cli("show nat44 interfaces"))
5723             self.logger.info(self.vapi.cli("show nat44 static mappings"))
5724             self.logger.info(self.vapi.cli("show nat44 interface address"))
5725             self.logger.info(self.vapi.cli("show nat44 sessions detail"))
5726             self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
5727             self.logger.info(self.vapi.cli("show nat timeouts"))
5728             self.clear_nat44()
5729             self.vapi.cli("clear logging")
5730
5731
5732 class TestNAT44Out2InDPO(MethodHolder):
5733     """ NAT44 Test Cases using out2in DPO """
5734
5735     @classmethod
5736     def setUpConstants(cls):
5737         super(TestNAT44Out2InDPO, cls).setUpConstants()
5738         cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
5739
5740     @classmethod
5741     def setUpClass(cls):
5742         super(TestNAT44Out2InDPO, cls).setUpClass()
5743         cls.vapi.cli("set log class nat level debug")
5744
5745         try:
5746             cls.tcp_port_in = 6303
5747             cls.tcp_port_out = 6303
5748             cls.udp_port_in = 6304
5749             cls.udp_port_out = 6304
5750             cls.icmp_id_in = 6305
5751             cls.icmp_id_out = 6305
5752             cls.nat_addr = '10.0.0.3'
5753             cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
5754             cls.dst_ip4 = '192.168.70.1'
5755
5756             cls.create_pg_interfaces(range(2))
5757
5758             cls.pg0.admin_up()
5759             cls.pg0.config_ip4()
5760             cls.pg0.resolve_arp()
5761
5762             cls.pg1.admin_up()
5763             cls.pg1.config_ip6()
5764             cls.pg1.resolve_ndp()
5765
5766             cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00'*16,
5767                                       dst_address_length=0,
5768                                       next_hop_address=cls.pg1.remote_ip6n,
5769                                       next_hop_sw_if_index=cls.pg1.sw_if_index)
5770
5771         except Exception:
5772             super(TestNAT44Out2InDPO, cls).tearDownClass()
5773             raise
5774
5775     def configure_xlat(self):
5776         self.dst_ip6_pfx = '1:2:3::'
5777         self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
5778                                               self.dst_ip6_pfx)
5779         self.dst_ip6_pfx_len = 96
5780         self.src_ip6_pfx = '4:5:6::'
5781         self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
5782                                               self.src_ip6_pfx)
5783         self.src_ip6_pfx_len = 96
5784         self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
5785                                  self.src_ip6_pfx_n, self.src_ip6_pfx_len,
5786                                  '\x00\x00\x00\x00', 0, is_translation=1,
5787                                  is_rfc6052=1)
5788
5789     def test_464xlat_ce(self):
5790         """ Test 464XLAT CE with NAT44 """
5791
5792         nat_config = self.vapi.nat_show_config()
5793         self.assertEqual(1, nat_config.out2in_dpo)
5794
5795         self.configure_xlat()
5796
5797         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5798         self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
5799
5800         out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
5801                                        self.dst_ip6_pfx_len)
5802         out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
5803                                        self.src_ip6_pfx_len)
5804
5805         try:
5806             pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
5807             self.pg0.add_stream(pkts)
5808             self.pg_enable_capture(self.pg_interfaces)
5809             self.pg_start()
5810             capture = self.pg1.get_capture(len(pkts))
5811             self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
5812                                         dst_ip=out_src_ip6)
5813
5814             pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
5815                                               out_dst_ip6)
5816             self.pg1.add_stream(pkts)
5817             self.pg_enable_capture(self.pg_interfaces)
5818             self.pg_start()
5819             capture = self.pg0.get_capture(len(pkts))
5820             self.verify_capture_in(capture, self.pg0)
5821         finally:
5822             self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5823                                                       is_add=0)
5824             self.vapi.nat44_add_del_address_range(self.nat_addr_n,
5825                                                   self.nat_addr_n, is_add=0)
5826
5827     def test_464xlat_ce_no_nat(self):
5828         """ Test 464XLAT CE without NAT44 """
5829
5830         self.configure_xlat()
5831
5832         out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
5833                                        self.dst_ip6_pfx_len)
5834         out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
5835                                        self.src_ip6_pfx_len)
5836
5837         pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
5838         self.pg0.add_stream(pkts)
5839         self.pg_enable_capture(self.pg_interfaces)
5840         self.pg_start()
5841         capture = self.pg1.get_capture(len(pkts))
5842         self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
5843                                     nat_ip=out_dst_ip6, same_port=True)
5844
5845         pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
5846         self.pg1.add_stream(pkts)
5847         self.pg_enable_capture(self.pg_interfaces)
5848         self.pg_start()
5849         capture = self.pg0.get_capture(len(pkts))
5850         self.verify_capture_in(capture, self.pg0)
5851
5852
5853 class TestDeterministicNAT(MethodHolder):
5854     """ Deterministic NAT Test Cases """
5855
5856     @classmethod
5857     def setUpConstants(cls):
5858         super(TestDeterministicNAT, cls).setUpConstants()
5859         cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
5860
5861     @classmethod
5862     def setUpClass(cls):
5863         super(TestDeterministicNAT, cls).setUpClass()
5864         cls.vapi.cli("set log class nat level debug")
5865
5866         try:
5867             cls.tcp_port_in = 6303
5868             cls.tcp_external_port = 6303
5869             cls.udp_port_in = 6304
5870             cls.udp_external_port = 6304
5871             cls.icmp_id_in = 6305
5872             cls.nat_addr = '10.0.0.3'
5873
5874             cls.create_pg_interfaces(range(3))
5875             cls.interfaces = list(cls.pg_interfaces)
5876
5877             for i in cls.interfaces:
5878                 i.admin_up()
5879                 i.config_ip4()
5880                 i.resolve_arp()
5881
5882             cls.pg0.generate_remote_hosts(2)
5883             cls.pg0.configure_ipv4_neighbors()
5884
5885         except Exception:
5886             super(TestDeterministicNAT, cls).tearDownClass()
5887             raise
5888
5889     def create_stream_in(self, in_if, out_if, ttl=64):
5890         """
5891         Create packet stream for inside network
5892
5893         :param in_if: Inside interface
5894         :param out_if: Outside interface
5895         :param ttl: TTL of generated packets
5896         """
5897         pkts = []
5898         # TCP
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              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
5902         pkts.append(p)
5903
5904         # UDP
5905         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5906              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
5907              UDP(sport=self.udp_port_in, dport=self.udp_external_port))
5908         pkts.append(p)
5909
5910         # ICMP
5911         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
5912              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
5913              ICMP(id=self.icmp_id_in, type='echo-request'))
5914         pkts.append(p)
5915
5916         return pkts
5917
5918     def create_stream_out(self, out_if, dst_ip=None, ttl=64):
5919         """
5920         Create packet stream for outside network
5921
5922         :param out_if: Outside interface
5923         :param dst_ip: Destination IP address (Default use global NAT address)
5924         :param ttl: TTL of generated packets
5925         """
5926         if dst_ip is None:
5927             dst_ip = self.nat_addr
5928         pkts = []
5929         # TCP
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              TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
5933         pkts.append(p)
5934
5935         # UDP
5936         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5937              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
5938              UDP(dport=self.udp_port_out, sport=self.udp_external_port))
5939         pkts.append(p)
5940
5941         # ICMP
5942         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
5943              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
5944              ICMP(id=self.icmp_external_id, type='echo-reply'))
5945         pkts.append(p)
5946
5947         return pkts
5948
5949     def verify_capture_out(self, capture, nat_ip=None):
5950         """
5951         Verify captured packets on outside network
5952
5953         :param capture: Captured packets
5954         :param nat_ip: Translated IP address (Default use global NAT address)
5955         :param same_port: Sorce port number is not translated (Default False)
5956         """
5957         if nat_ip is None:
5958             nat_ip = self.nat_addr
5959         for packet in capture:
5960             try:
5961                 self.assertEqual(packet[IP].src, nat_ip)
5962                 if packet.haslayer(TCP):
5963                     self.tcp_port_out = packet[TCP].sport
5964                 elif packet.haslayer(UDP):
5965                     self.udp_port_out = packet[UDP].sport
5966                 else:
5967                     self.icmp_external_id = packet[ICMP].id
5968             except:
5969                 self.logger.error(ppp("Unexpected or invalid packet "
5970                                       "(outside network):", packet))
5971                 raise
5972
5973     def test_deterministic_mode(self):
5974         """ NAT plugin run deterministic mode """
5975         in_addr = '172.16.255.0'
5976         out_addr = '172.17.255.50'
5977         in_addr_t = '172.16.255.20'
5978         in_addr_n = socket.inet_aton(in_addr)
5979         out_addr_n = socket.inet_aton(out_addr)
5980         in_addr_t_n = socket.inet_aton(in_addr_t)
5981         in_plen = 24
5982         out_plen = 32
5983
5984         nat_config = self.vapi.nat_show_config()
5985         self.assertEqual(1, nat_config.deterministic)
5986
5987         self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
5988
5989         rep1 = self.vapi.nat_det_forward(in_addr_t_n)
5990         self.assertEqual(rep1.out_addr[:4], out_addr_n)
5991         rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
5992         self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
5993
5994         deterministic_mappings = self.vapi.nat_det_map_dump()
5995         self.assertEqual(len(deterministic_mappings), 1)
5996         dsm = deterministic_mappings[0]
5997         self.assertEqual(in_addr_n, dsm.in_addr[:4])
5998         self.assertEqual(in_plen, dsm.in_plen)
5999         self.assertEqual(out_addr_n, dsm.out_addr[:4])
6000         self.assertEqual(out_plen, dsm.out_plen)
6001
6002         self.clear_nat_det()
6003         deterministic_mappings = self.vapi.nat_det_map_dump()
6004         self.assertEqual(len(deterministic_mappings), 0)
6005
6006     def test_set_timeouts(self):
6007         """ Set deterministic NAT timeouts """
6008         timeouts_before = self.vapi.nat_get_timeouts()
6009
6010         self.vapi.nat_set_timeouts(timeouts_before.udp + 10,
6011                                    timeouts_before.tcp_established + 10,
6012                                    timeouts_before.tcp_transitory + 10,
6013                                    timeouts_before.icmp + 10)
6014
6015         timeouts_after = self.vapi.nat_get_timeouts()
6016
6017         self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
6018         self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
6019         self.assertNotEqual(timeouts_before.tcp_established,
6020                             timeouts_after.tcp_established)
6021         self.assertNotEqual(timeouts_before.tcp_transitory,
6022                             timeouts_after.tcp_transitory)
6023
6024     def test_det_in(self):
6025         """ Deterministic NAT translation test (TCP, UDP, ICMP) """
6026
6027         nat_ip = "10.0.0.10"
6028
6029         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6030                                       32,
6031                                       socket.inet_aton(nat_ip),
6032                                       32)
6033         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6034         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6035                                                   is_inside=0)
6036
6037         # in2out
6038         pkts = self.create_stream_in(self.pg0, self.pg1)
6039         self.pg0.add_stream(pkts)
6040         self.pg_enable_capture(self.pg_interfaces)
6041         self.pg_start()
6042         capture = self.pg1.get_capture(len(pkts))
6043         self.verify_capture_out(capture, nat_ip)
6044
6045         # out2in
6046         pkts = self.create_stream_out(self.pg1, nat_ip)
6047         self.pg1.add_stream(pkts)
6048         self.pg_enable_capture(self.pg_interfaces)
6049         self.pg_start()
6050         capture = self.pg0.get_capture(len(pkts))
6051         self.verify_capture_in(capture, self.pg0)
6052
6053         # session dump test
6054         sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
6055         self.assertEqual(len(sessions), 3)
6056
6057         # TCP session
6058         s = sessions[0]
6059         self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6060         self.assertEqual(s.in_port, self.tcp_port_in)
6061         self.assertEqual(s.out_port, self.tcp_port_out)
6062         self.assertEqual(s.ext_port, self.tcp_external_port)
6063
6064         # UDP session
6065         s = sessions[1]
6066         self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6067         self.assertEqual(s.in_port, self.udp_port_in)
6068         self.assertEqual(s.out_port, self.udp_port_out)
6069         self.assertEqual(s.ext_port, self.udp_external_port)
6070
6071         # ICMP session
6072         s = sessions[2]
6073         self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6074         self.assertEqual(s.in_port, self.icmp_id_in)
6075         self.assertEqual(s.out_port, self.icmp_external_id)
6076
6077     def test_multiple_users(self):
6078         """ Deterministic NAT multiple users """
6079
6080         nat_ip = "10.0.0.10"
6081         port_in = 80
6082         external_port = 6303
6083
6084         host0 = self.pg0.remote_hosts[0]
6085         host1 = self.pg0.remote_hosts[1]
6086
6087         self.vapi.nat_det_add_del_map(host0.ip4n,
6088                                       24,
6089                                       socket.inet_aton(nat_ip),
6090                                       32)
6091         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6092         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6093                                                   is_inside=0)
6094
6095         # host0 to out
6096         p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
6097              IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
6098              TCP(sport=port_in, dport=external_port))
6099         self.pg0.add_stream(p)
6100         self.pg_enable_capture(self.pg_interfaces)
6101         self.pg_start()
6102         capture = self.pg1.get_capture(1)
6103         p = capture[0]
6104         try:
6105             ip = p[IP]
6106             tcp = p[TCP]
6107             self.assertEqual(ip.src, nat_ip)
6108             self.assertEqual(ip.dst, self.pg1.remote_ip4)
6109             self.assertEqual(tcp.dport, external_port)
6110             port_out0 = tcp.sport
6111         except:
6112             self.logger.error(ppp("Unexpected or invalid packet:", p))
6113             raise
6114
6115         # host1 to out
6116         p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
6117              IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
6118              TCP(sport=port_in, dport=external_port))
6119         self.pg0.add_stream(p)
6120         self.pg_enable_capture(self.pg_interfaces)
6121         self.pg_start()
6122         capture = self.pg1.get_capture(1)
6123         p = capture[0]
6124         try:
6125             ip = p[IP]
6126             tcp = p[TCP]
6127             self.assertEqual(ip.src, nat_ip)
6128             self.assertEqual(ip.dst, self.pg1.remote_ip4)
6129             self.assertEqual(tcp.dport, external_port)
6130             port_out1 = tcp.sport
6131         except:
6132             self.logger.error(ppp("Unexpected or invalid packet:", p))
6133             raise
6134
6135         dms = self.vapi.nat_det_map_dump()
6136         self.assertEqual(1, len(dms))
6137         self.assertEqual(2, dms[0].ses_num)
6138
6139         # out to host0
6140         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6141              IP(src=self.pg1.remote_ip4, dst=nat_ip) /
6142              TCP(sport=external_port, dport=port_out0))
6143         self.pg1.add_stream(p)
6144         self.pg_enable_capture(self.pg_interfaces)
6145         self.pg_start()
6146         capture = self.pg0.get_capture(1)
6147         p = capture[0]
6148         try:
6149             ip = p[IP]
6150             tcp = p[TCP]
6151             self.assertEqual(ip.src, self.pg1.remote_ip4)
6152             self.assertEqual(ip.dst, host0.ip4)
6153             self.assertEqual(tcp.dport, port_in)
6154             self.assertEqual(tcp.sport, external_port)
6155         except:
6156             self.logger.error(ppp("Unexpected or invalid packet:", p))
6157             raise
6158
6159         # out to host1
6160         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6161              IP(src=self.pg1.remote_ip4, dst=nat_ip) /
6162              TCP(sport=external_port, dport=port_out1))
6163         self.pg1.add_stream(p)
6164         self.pg_enable_capture(self.pg_interfaces)
6165         self.pg_start()
6166         capture = self.pg0.get_capture(1)
6167         p = capture[0]
6168         try:
6169             ip = p[IP]
6170             tcp = p[TCP]
6171             self.assertEqual(ip.src, self.pg1.remote_ip4)
6172             self.assertEqual(ip.dst, host1.ip4)
6173             self.assertEqual(tcp.dport, port_in)
6174             self.assertEqual(tcp.sport, external_port)
6175         except:
6176             self.logger.error(ppp("Unexpected or invalid packet", p))
6177             raise
6178
6179         # session close api test
6180         self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
6181                                             port_out1,
6182                                             self.pg1.remote_ip4n,
6183                                             external_port)
6184         dms = self.vapi.nat_det_map_dump()
6185         self.assertEqual(dms[0].ses_num, 1)
6186
6187         self.vapi.nat_det_close_session_in(host0.ip4n,
6188                                            port_in,
6189                                            self.pg1.remote_ip4n,
6190                                            external_port)
6191         dms = self.vapi.nat_det_map_dump()
6192         self.assertEqual(dms[0].ses_num, 0)
6193
6194     def test_tcp_session_close_detection_in(self):
6195         """ Deterministic NAT TCP session close from inside network """
6196         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6197                                       32,
6198                                       socket.inet_aton(self.nat_addr),
6199                                       32)
6200         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6201         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6202                                                   is_inside=0)
6203
6204         self.initiate_tcp_session(self.pg0, self.pg1)
6205
6206         # close the session from inside
6207         try:
6208             # FIN packet in -> out
6209             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6210                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6211                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6212                      flags="F"))
6213             self.pg0.add_stream(p)
6214             self.pg_enable_capture(self.pg_interfaces)
6215             self.pg_start()
6216             self.pg1.get_capture(1)
6217
6218             pkts = []
6219
6220             # ACK packet out -> in
6221             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6222                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6223                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6224                      flags="A"))
6225             pkts.append(p)
6226
6227             # FIN packet out -> in
6228             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6229                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6230                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6231                      flags="F"))
6232             pkts.append(p)
6233
6234             self.pg1.add_stream(pkts)
6235             self.pg_enable_capture(self.pg_interfaces)
6236             self.pg_start()
6237             self.pg0.get_capture(2)
6238
6239             # ACK packet in -> out
6240             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6241                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6242                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6243                      flags="A"))
6244             self.pg0.add_stream(p)
6245             self.pg_enable_capture(self.pg_interfaces)
6246             self.pg_start()
6247             self.pg1.get_capture(1)
6248
6249             # Check if deterministic NAT44 closed the session
6250             dms = self.vapi.nat_det_map_dump()
6251             self.assertEqual(0, dms[0].ses_num)
6252         except:
6253             self.logger.error("TCP session termination failed")
6254             raise
6255
6256     def test_tcp_session_close_detection_out(self):
6257         """ Deterministic NAT TCP session close from outside network """
6258         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6259                                       32,
6260                                       socket.inet_aton(self.nat_addr),
6261                                       32)
6262         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6263         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6264                                                   is_inside=0)
6265
6266         self.initiate_tcp_session(self.pg0, self.pg1)
6267
6268         # close the session from outside
6269         try:
6270             # FIN packet out -> in
6271             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6272                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6273                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6274                      flags="F"))
6275             self.pg1.add_stream(p)
6276             self.pg_enable_capture(self.pg_interfaces)
6277             self.pg_start()
6278             self.pg0.get_capture(1)
6279
6280             pkts = []
6281
6282             # ACK packet in -> out
6283             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6284                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6285                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6286                      flags="A"))
6287             pkts.append(p)
6288
6289             # ACK packet in -> out
6290             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6291                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6292                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6293                      flags="F"))
6294             pkts.append(p)
6295
6296             self.pg0.add_stream(pkts)
6297             self.pg_enable_capture(self.pg_interfaces)
6298             self.pg_start()
6299             self.pg1.get_capture(2)
6300
6301             # ACK packet out -> in
6302             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6303                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6304                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6305                      flags="A"))
6306             self.pg1.add_stream(p)
6307             self.pg_enable_capture(self.pg_interfaces)
6308             self.pg_start()
6309             self.pg0.get_capture(1)
6310
6311             # Check if deterministic NAT44 closed the session
6312             dms = self.vapi.nat_det_map_dump()
6313             self.assertEqual(0, dms[0].ses_num)
6314         except:
6315             self.logger.error("TCP session termination failed")
6316             raise
6317
6318     @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6319     def test_session_timeout(self):
6320         """ Deterministic NAT session timeouts """
6321         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6322                                       32,
6323                                       socket.inet_aton(self.nat_addr),
6324                                       32)
6325         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6326         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6327                                                   is_inside=0)
6328
6329         self.initiate_tcp_session(self.pg0, self.pg1)
6330         self.vapi.nat_set_timeouts(5, 5, 5, 5)
6331         pkts = self.create_stream_in(self.pg0, self.pg1)
6332         self.pg0.add_stream(pkts)
6333         self.pg_enable_capture(self.pg_interfaces)
6334         self.pg_start()
6335         capture = self.pg1.get_capture(len(pkts))
6336         sleep(15)
6337
6338         dms = self.vapi.nat_det_map_dump()
6339         self.assertEqual(0, dms[0].ses_num)
6340
6341     @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6342     def test_session_limit_per_user(self):
6343         """ Deterministic NAT maximum sessions per user limit """
6344         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6345                                       32,
6346                                       socket.inet_aton(self.nat_addr),
6347                                       32)
6348         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6349         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6350                                                   is_inside=0)
6351         self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
6352                                      src_address=self.pg2.local_ip4n,
6353                                      path_mtu=512,
6354                                      template_interval=10)
6355         self.vapi.nat_ipfix()
6356
6357         pkts = []
6358         for port in range(1025, 2025):
6359             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6360                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6361                  UDP(sport=port, dport=port))
6362             pkts.append(p)
6363
6364         self.pg0.add_stream(pkts)
6365         self.pg_enable_capture(self.pg_interfaces)
6366         self.pg_start()
6367         capture = self.pg1.get_capture(len(pkts))
6368
6369         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6370              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6371              UDP(sport=3001, dport=3002))
6372         self.pg0.add_stream(p)
6373         self.pg_enable_capture(self.pg_interfaces)
6374         self.pg_start()
6375         capture = self.pg1.assert_nothing_captured()
6376
6377         # verify ICMP error packet
6378         capture = self.pg0.get_capture(1)
6379         p = capture[0]
6380         self.assertTrue(p.haslayer(ICMP))
6381         icmp = p[ICMP]
6382         self.assertEqual(icmp.type, 3)
6383         self.assertEqual(icmp.code, 1)
6384         self.assertTrue(icmp.haslayer(IPerror))
6385         inner_ip = icmp[IPerror]
6386         self.assertEqual(inner_ip[UDPerror].sport, 3001)
6387         self.assertEqual(inner_ip[UDPerror].dport, 3002)
6388
6389         dms = self.vapi.nat_det_map_dump()
6390
6391         self.assertEqual(1000, dms[0].ses_num)
6392
6393         # verify IPFIX logging
6394         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
6395         sleep(1)
6396         capture = self.pg2.get_capture(2)
6397         ipfix = IPFIXDecoder()
6398         # first load template
6399         for p in capture:
6400             self.assertTrue(p.haslayer(IPFIX))
6401             if p.haslayer(Template):
6402                 ipfix.add_template(p.getlayer(Template))
6403         # verify events in data set
6404         for p in capture:
6405             if p.haslayer(Data):
6406                 data = ipfix.decode_data_set(p.getlayer(Set))
6407                 self.verify_ipfix_max_entries_per_user(data,
6408                                                        1000,
6409                                                        self.pg0.remote_ip4n)
6410
6411     def clear_nat_det(self):
6412         """
6413         Clear deterministic NAT configuration.
6414         """
6415         self.vapi.nat_ipfix(enable=0)
6416         self.vapi.nat_set_timeouts()
6417         deterministic_mappings = self.vapi.nat_det_map_dump()
6418         for dsm in deterministic_mappings:
6419             self.vapi.nat_det_add_del_map(dsm.in_addr,
6420                                           dsm.in_plen,
6421                                           dsm.out_addr,
6422                                           dsm.out_plen,
6423                                           is_add=0)
6424
6425         interfaces = self.vapi.nat44_interface_dump()
6426         for intf in interfaces:
6427             self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
6428                                                       intf.is_inside,
6429                                                       is_add=0)
6430
6431     def tearDown(self):
6432         super(TestDeterministicNAT, self).tearDown()
6433         if not self.vpp_dead:
6434             self.logger.info(self.vapi.cli("show nat44 interfaces"))
6435             self.logger.info(self.vapi.cli("show nat timeouts"))
6436             self.logger.info(
6437                 self.vapi.cli("show nat44 deterministic mappings"))
6438             self.logger.info(
6439                 self.vapi.cli("show nat44 deterministic sessions"))
6440             self.clear_nat_det()
6441
6442
6443 class TestNAT64(MethodHolder):
6444     """ NAT64 Test Cases """
6445
6446     @classmethod
6447     def setUpConstants(cls):
6448         super(TestNAT64, cls).setUpConstants()
6449         cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
6450                                 "nat64 st hash buckets 256", "}"])
6451
6452     @classmethod
6453     def setUpClass(cls):
6454         super(TestNAT64, cls).setUpClass()
6455
6456         try:
6457             cls.tcp_port_in = 6303
6458             cls.tcp_port_out = 6303
6459             cls.udp_port_in = 6304
6460             cls.udp_port_out = 6304
6461             cls.icmp_id_in = 6305
6462             cls.icmp_id_out = 6305
6463             cls.nat_addr = '10.0.0.3'
6464             cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
6465             cls.vrf1_id = 10
6466             cls.vrf1_nat_addr = '10.0.10.3'
6467             cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
6468                                                    cls.vrf1_nat_addr)
6469             cls.ipfix_src_port = 4739
6470             cls.ipfix_domain_id = 1
6471
6472             cls.create_pg_interfaces(range(6))
6473             cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
6474             cls.ip6_interfaces.append(cls.pg_interfaces[2])
6475             cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
6476
6477             cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
6478
6479             cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
6480
6481             cls.pg0.generate_remote_hosts(2)
6482
6483             for i in cls.ip6_interfaces:
6484                 i.admin_up()
6485                 i.config_ip6()
6486                 i.configure_ipv6_neighbors()
6487
6488             for i in cls.ip4_interfaces:
6489                 i.admin_up()
6490                 i.config_ip4()
6491                 i.resolve_arp()
6492
6493             cls.pg3.admin_up()
6494             cls.pg3.config_ip4()
6495             cls.pg3.resolve_arp()
6496             cls.pg3.config_ip6()
6497             cls.pg3.configure_ipv6_neighbors()
6498
6499             cls.pg5.admin_up()
6500             cls.pg5.config_ip6()
6501
6502         except Exception:
6503             super(TestNAT64, cls).tearDownClass()
6504             raise
6505
6506     def test_nat64_inside_interface_handles_neighbor_advertisement(self):
6507         """ NAT64 inside interface handles Neighbor Advertisement """
6508
6509         self.vapi.nat64_add_del_interface(self.pg5.sw_if_index)
6510
6511         # Try to send ping
6512         ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
6513                 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
6514                 ICMPv6EchoRequest())
6515         pkts = [ping]
6516         self.pg5.add_stream(pkts)
6517         self.pg_enable_capture(self.pg_interfaces)
6518         self.pg_start()
6519
6520         # Wait for Neighbor Solicitation
6521         capture = self.pg5.get_capture(len(pkts))
6522         packet = capture[0]
6523         try:
6524             self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
6525             self.assertTrue(packet.haslayer(ICMPv6ND_NS))
6526             tgt = packet[ICMPv6ND_NS].tgt
6527         except:
6528             self.logger.error(ppp("Unexpected or invalid packet:", packet))
6529             raise
6530
6531         # Send Neighbor Advertisement
6532         p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
6533              IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
6534              ICMPv6ND_NA(tgt=tgt) /
6535              ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
6536         pkts = [p]
6537         self.pg5.add_stream(pkts)
6538         self.pg_enable_capture(self.pg_interfaces)
6539         self.pg_start()
6540
6541         # Try to send ping again
6542         pkts = [ping]
6543         self.pg5.add_stream(pkts)
6544         self.pg_enable_capture(self.pg_interfaces)
6545         self.pg_start()
6546
6547         # Wait for ping reply
6548         capture = self.pg5.get_capture(len(pkts))
6549         packet = capture[0]
6550         try:
6551             self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
6552             self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
6553             self.assertTrue(packet.haslayer(ICMPv6EchoReply))
6554         except:
6555             self.logger.error(ppp("Unexpected or invalid packet:", packet))
6556             raise
6557
6558     def test_pool(self):
6559         """ Add/delete address to NAT64 pool """
6560         nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
6561
6562         self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
6563
6564         addresses = self.vapi.nat64_pool_addr_dump()
6565         self.assertEqual(len(addresses), 1)
6566         self.assertEqual(addresses[0].address, nat_addr)
6567
6568         self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
6569
6570         addresses = self.vapi.nat64_pool_addr_dump()
6571         self.assertEqual(len(addresses), 0)
6572
6573     def test_interface(self):
6574         """ Enable/disable NAT64 feature on the interface """
6575         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6576         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6577
6578         interfaces = self.vapi.nat64_interface_dump()
6579         self.assertEqual(len(interfaces), 2)
6580         pg0_found = False
6581         pg1_found = False
6582         for intf in interfaces:
6583             if intf.sw_if_index == self.pg0.sw_if_index:
6584                 self.assertEqual(intf.is_inside, 1)
6585                 pg0_found = True
6586             elif intf.sw_if_index == self.pg1.sw_if_index:
6587                 self.assertEqual(intf.is_inside, 0)
6588                 pg1_found = True
6589         self.assertTrue(pg0_found)
6590         self.assertTrue(pg1_found)
6591
6592         features = self.vapi.cli("show interface features pg0")
6593         self.assertNotEqual(features.find('nat64-in2out'), -1)
6594         features = self.vapi.cli("show interface features pg1")
6595         self.assertNotEqual(features.find('nat64-out2in'), -1)
6596
6597         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
6598         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
6599
6600         interfaces = self.vapi.nat64_interface_dump()
6601         self.assertEqual(len(interfaces), 0)
6602
6603     def test_static_bib(self):
6604         """ Add/delete static BIB entry """
6605         in_addr = socket.inet_pton(socket.AF_INET6,
6606                                    '2001:db8:85a3::8a2e:370:7334')
6607         out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
6608         in_port = 1234
6609         out_port = 5678
6610         proto = IP_PROTOS.tcp
6611
6612         self.vapi.nat64_add_del_static_bib(in_addr,
6613                                            out_addr,
6614                                            in_port,
6615                                            out_port,
6616                                            proto)
6617         bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
6618         static_bib_num = 0
6619         for bibe in bib:
6620             if bibe.is_static:
6621                 static_bib_num += 1
6622                 self.assertEqual(bibe.i_addr, in_addr)
6623                 self.assertEqual(bibe.o_addr, out_addr)
6624                 self.assertEqual(bibe.i_port, in_port)
6625                 self.assertEqual(bibe.o_port, out_port)
6626         self.assertEqual(static_bib_num, 1)
6627
6628         self.vapi.nat64_add_del_static_bib(in_addr,
6629                                            out_addr,
6630                                            in_port,
6631                                            out_port,
6632                                            proto,
6633                                            is_add=0)
6634         bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
6635         static_bib_num = 0
6636         for bibe in bib:
6637             if bibe.is_static:
6638                 static_bib_num += 1
6639         self.assertEqual(static_bib_num, 0)
6640
6641     def test_set_timeouts(self):
6642         """ Set NAT64 timeouts """
6643         # verify default values
6644         timeouts = self.vapi.nat_get_timeouts()
6645         self.assertEqual(timeouts.udp, 300)
6646         self.assertEqual(timeouts.icmp, 60)
6647         self.assertEqual(timeouts.tcp_transitory, 240)
6648         self.assertEqual(timeouts.tcp_established, 7440)
6649
6650         # set and verify custom values
6651         self.vapi.nat_set_timeouts(udp=200, icmp=30, tcp_transitory=250,
6652                                    tcp_established=7450)
6653         timeouts = self.vapi.nat_get_timeouts()
6654         self.assertEqual(timeouts.udp, 200)
6655         self.assertEqual(timeouts.icmp, 30)
6656         self.assertEqual(timeouts.tcp_transitory, 250)
6657         self.assertEqual(timeouts.tcp_established, 7450)
6658
6659     def test_dynamic(self):
6660         """ NAT64 dynamic translation test """
6661         self.tcp_port_in = 6303
6662         self.udp_port_in = 6304
6663         self.icmp_id_in = 6305
6664
6665         ses_num_start = self.nat64_get_ses_num()
6666
6667         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6668                                                 self.nat_addr_n)
6669         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6670         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6671
6672         # in2out
6673         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6674         self.pg0.add_stream(pkts)
6675         self.pg_enable_capture(self.pg_interfaces)
6676         self.pg_start()
6677         capture = self.pg1.get_capture(len(pkts))
6678         self.verify_capture_out(capture, nat_ip=self.nat_addr,
6679                                 dst_ip=self.pg1.remote_ip4)
6680
6681         # out2in
6682         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6683         self.pg1.add_stream(pkts)
6684         self.pg_enable_capture(self.pg_interfaces)
6685         self.pg_start()
6686         capture = self.pg0.get_capture(len(pkts))
6687         ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6688         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6689
6690         # in2out
6691         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6692         self.pg0.add_stream(pkts)
6693         self.pg_enable_capture(self.pg_interfaces)
6694         self.pg_start()
6695         capture = self.pg1.get_capture(len(pkts))
6696         self.verify_capture_out(capture, nat_ip=self.nat_addr,
6697                                 dst_ip=self.pg1.remote_ip4)
6698
6699         # out2in
6700         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6701         self.pg1.add_stream(pkts)
6702         self.pg_enable_capture(self.pg_interfaces)
6703         self.pg_start()
6704         capture = self.pg0.get_capture(len(pkts))
6705         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6706
6707         ses_num_end = self.nat64_get_ses_num()
6708
6709         self.assertEqual(ses_num_end - ses_num_start, 3)
6710
6711         # tenant with specific VRF
6712         self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
6713                                                 self.vrf1_nat_addr_n,
6714                                                 vrf_id=self.vrf1_id)
6715         self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
6716
6717         pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
6718         self.pg2.add_stream(pkts)
6719         self.pg_enable_capture(self.pg_interfaces)
6720         self.pg_start()
6721         capture = self.pg1.get_capture(len(pkts))
6722         self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
6723                                 dst_ip=self.pg1.remote_ip4)
6724
6725         pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
6726         self.pg1.add_stream(pkts)
6727         self.pg_enable_capture(self.pg_interfaces)
6728         self.pg_start()
6729         capture = self.pg2.get_capture(len(pkts))
6730         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
6731
6732     def test_static(self):
6733         """ NAT64 static translation test """
6734         self.tcp_port_in = 60303
6735         self.udp_port_in = 60304
6736         self.icmp_id_in = 60305
6737         self.tcp_port_out = 60303
6738         self.udp_port_out = 60304
6739         self.icmp_id_out = 60305
6740
6741         ses_num_start = self.nat64_get_ses_num()
6742
6743         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6744                                                 self.nat_addr_n)
6745         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6746         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6747
6748         self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6749                                            self.nat_addr_n,
6750                                            self.tcp_port_in,
6751                                            self.tcp_port_out,
6752                                            IP_PROTOS.tcp)
6753         self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6754                                            self.nat_addr_n,
6755                                            self.udp_port_in,
6756                                            self.udp_port_out,
6757                                            IP_PROTOS.udp)
6758         self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
6759                                            self.nat_addr_n,
6760                                            self.icmp_id_in,
6761                                            self.icmp_id_out,
6762                                            IP_PROTOS.icmp)
6763
6764         # in2out
6765         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6766         self.pg0.add_stream(pkts)
6767         self.pg_enable_capture(self.pg_interfaces)
6768         self.pg_start()
6769         capture = self.pg1.get_capture(len(pkts))
6770         self.verify_capture_out(capture, nat_ip=self.nat_addr,
6771                                 dst_ip=self.pg1.remote_ip4, same_port=True)
6772
6773         # out2in
6774         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6775         self.pg1.add_stream(pkts)
6776         self.pg_enable_capture(self.pg_interfaces)
6777         self.pg_start()
6778         capture = self.pg0.get_capture(len(pkts))
6779         ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6780         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
6781
6782         ses_num_end = self.nat64_get_ses_num()
6783
6784         self.assertEqual(ses_num_end - ses_num_start, 3)
6785
6786     @unittest.skipUnless(running_extended_tests(), "part of extended tests")
6787     def test_session_timeout(self):
6788         """ NAT64 session timeout """
6789         self.icmp_id_in = 1234
6790         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6791                                                 self.nat_addr_n)
6792         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6793         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6794         self.vapi.nat_set_timeouts(icmp=5, tcp_transitory=5, tcp_established=5)
6795
6796         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6797         self.pg0.add_stream(pkts)
6798         self.pg_enable_capture(self.pg_interfaces)
6799         self.pg_start()
6800         capture = self.pg1.get_capture(len(pkts))
6801
6802         ses_num_before_timeout = self.nat64_get_ses_num()
6803
6804         sleep(15)
6805
6806         # ICMP and TCP session after timeout
6807         ses_num_after_timeout = self.nat64_get_ses_num()
6808         self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
6809
6810     def test_icmp_error(self):
6811         """ NAT64 ICMP Error message translation """
6812         self.tcp_port_in = 6303
6813         self.udp_port_in = 6304
6814         self.icmp_id_in = 6305
6815
6816         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6817                                                 self.nat_addr_n)
6818         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6819         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6820
6821         # send some packets to create sessions
6822         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
6823         self.pg0.add_stream(pkts)
6824         self.pg_enable_capture(self.pg_interfaces)
6825         self.pg_start()
6826         capture_ip4 = self.pg1.get_capture(len(pkts))
6827         self.verify_capture_out(capture_ip4,
6828                                 nat_ip=self.nat_addr,
6829                                 dst_ip=self.pg1.remote_ip4)
6830
6831         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
6832         self.pg1.add_stream(pkts)
6833         self.pg_enable_capture(self.pg_interfaces)
6834         self.pg_start()
6835         capture_ip6 = self.pg0.get_capture(len(pkts))
6836         ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
6837         self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
6838                                    self.pg0.remote_ip6)
6839
6840         # in2out
6841         pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6842                 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
6843                 ICMPv6DestUnreach(code=1) /
6844                 packet[IPv6] for packet in capture_ip6]
6845         self.pg0.add_stream(pkts)
6846         self.pg_enable_capture(self.pg_interfaces)
6847         self.pg_start()
6848         capture = self.pg1.get_capture(len(pkts))
6849         for packet in capture:
6850             try:
6851                 self.assertEqual(packet[IP].src, self.nat_addr)
6852                 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
6853                 self.assertEqual(packet[ICMP].type, 3)
6854                 self.assertEqual(packet[ICMP].code, 13)
6855                 inner = packet[IPerror]
6856                 self.assertEqual(inner.src, self.pg1.remote_ip4)
6857                 self.assertEqual(inner.dst, self.nat_addr)
6858                 self.assert_packet_checksums_valid(packet)
6859                 if inner.haslayer(TCPerror):
6860                     self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
6861                 elif inner.haslayer(UDPerror):
6862                     self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
6863                 else:
6864                     self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
6865             except:
6866                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6867                 raise
6868
6869         # out2in
6870         pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6871                 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6872                 ICMP(type=3, code=13) /
6873                 packet[IP] for packet in capture_ip4]
6874         self.pg1.add_stream(pkts)
6875         self.pg_enable_capture(self.pg_interfaces)
6876         self.pg_start()
6877         capture = self.pg0.get_capture(len(pkts))
6878         for packet in capture:
6879             try:
6880                 self.assertEqual(packet[IPv6].src, ip.src)
6881                 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
6882                 icmp = packet[ICMPv6DestUnreach]
6883                 self.assertEqual(icmp.code, 1)
6884                 inner = icmp[IPerror6]
6885                 self.assertEqual(inner.src, self.pg0.remote_ip6)
6886                 self.assertEqual(inner.dst, ip.src)
6887                 self.assert_icmpv6_checksum_valid(packet)
6888                 if inner.haslayer(TCPerror):
6889                     self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
6890                 elif inner.haslayer(UDPerror):
6891                     self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
6892                 else:
6893                     self.assertEqual(inner[ICMPv6EchoRequest].id,
6894                                      self.icmp_id_in)
6895             except:
6896                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6897                 raise
6898
6899     def test_hairpinning(self):
6900         """ NAT64 hairpinning """
6901
6902         client = self.pg0.remote_hosts[0]
6903         server = self.pg0.remote_hosts[1]
6904         server_tcp_in_port = 22
6905         server_tcp_out_port = 4022
6906         server_udp_in_port = 23
6907         server_udp_out_port = 4023
6908         client_tcp_in_port = 1234
6909         client_udp_in_port = 1235
6910         client_tcp_out_port = 0
6911         client_udp_out_port = 0
6912         ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
6913         nat_addr_ip6 = ip.src
6914
6915         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
6916                                                 self.nat_addr_n)
6917         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6918         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6919
6920         self.vapi.nat64_add_del_static_bib(server.ip6n,
6921                                            self.nat_addr_n,
6922                                            server_tcp_in_port,
6923                                            server_tcp_out_port,
6924                                            IP_PROTOS.tcp)
6925         self.vapi.nat64_add_del_static_bib(server.ip6n,
6926                                            self.nat_addr_n,
6927                                            server_udp_in_port,
6928                                            server_udp_out_port,
6929                                            IP_PROTOS.udp)
6930
6931         # client to server
6932         pkts = []
6933         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6934              IPv6(src=client.ip6, dst=nat_addr_ip6) /
6935              TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
6936         pkts.append(p)
6937         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6938              IPv6(src=client.ip6, dst=nat_addr_ip6) /
6939              UDP(sport=client_udp_in_port, dport=server_udp_out_port))
6940         pkts.append(p)
6941         self.pg0.add_stream(pkts)
6942         self.pg_enable_capture(self.pg_interfaces)
6943         self.pg_start()
6944         capture = self.pg0.get_capture(len(pkts))
6945         for packet in capture:
6946             try:
6947                 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6948                 self.assertEqual(packet[IPv6].dst, server.ip6)
6949                 self.assert_packet_checksums_valid(packet)
6950                 if packet.haslayer(TCP):
6951                     self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
6952                     self.assertEqual(packet[TCP].dport, server_tcp_in_port)
6953                     client_tcp_out_port = packet[TCP].sport
6954                 else:
6955                     self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
6956                     self.assertEqual(packet[UDP].dport, server_udp_in_port)
6957                     client_udp_out_port = packet[UDP].sport
6958             except:
6959                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6960                 raise
6961
6962         # server to client
6963         pkts = []
6964         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6965              IPv6(src=server.ip6, dst=nat_addr_ip6) /
6966              TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
6967         pkts.append(p)
6968         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6969              IPv6(src=server.ip6, dst=nat_addr_ip6) /
6970              UDP(sport=server_udp_in_port, dport=client_udp_out_port))
6971         pkts.append(p)
6972         self.pg0.add_stream(pkts)
6973         self.pg_enable_capture(self.pg_interfaces)
6974         self.pg_start()
6975         capture = self.pg0.get_capture(len(pkts))
6976         for packet in capture:
6977             try:
6978                 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
6979                 self.assertEqual(packet[IPv6].dst, client.ip6)
6980                 self.assert_packet_checksums_valid(packet)
6981                 if packet.haslayer(TCP):
6982                     self.assertEqual(packet[TCP].sport, server_tcp_out_port)
6983                     self.assertEqual(packet[TCP].dport, client_tcp_in_port)
6984                 else:
6985                     self.assertEqual(packet[UDP].sport, server_udp_out_port)
6986                     self.assertEqual(packet[UDP].dport, client_udp_in_port)
6987             except:
6988                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6989                 raise
6990
6991         # ICMP error
6992         pkts = []
6993         pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6994                 IPv6(src=client.ip6, dst=nat_addr_ip6) /
6995                 ICMPv6DestUnreach(code=1) /
6996                 packet[IPv6] for packet in capture]
6997         self.pg0.add_stream(pkts)
6998         self.pg_enable_capture(self.pg_interfaces)
6999         self.pg_start()
7000         capture = self.pg0.get_capture(len(pkts))
7001         for packet in capture:
7002             try:
7003                 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7004                 self.assertEqual(packet[IPv6].dst, server.ip6)
7005                 icmp = packet[ICMPv6DestUnreach]
7006                 self.assertEqual(icmp.code, 1)
7007                 inner = icmp[IPerror6]
7008                 self.assertEqual(inner.src, server.ip6)
7009                 self.assertEqual(inner.dst, nat_addr_ip6)
7010                 self.assert_packet_checksums_valid(packet)
7011                 if inner.haslayer(TCPerror):
7012                     self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
7013                     self.assertEqual(inner[TCPerror].dport,
7014                                      client_tcp_out_port)
7015                 else:
7016                     self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
7017                     self.assertEqual(inner[UDPerror].dport,
7018                                      client_udp_out_port)
7019             except:
7020                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7021                 raise
7022
7023     def test_prefix(self):
7024         """ NAT64 Network-Specific Prefix """
7025
7026         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7027                                                 self.nat_addr_n)
7028         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7029         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7030         self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
7031                                                 self.vrf1_nat_addr_n,
7032                                                 vrf_id=self.vrf1_id)
7033         self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
7034
7035         # Add global prefix
7036         global_pref64 = "2001:db8::"
7037         global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
7038         global_pref64_len = 32
7039         self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
7040
7041         prefix = self.vapi.nat64_prefix_dump()
7042         self.assertEqual(len(prefix), 1)
7043         self.assertEqual(prefix[0].prefix, global_pref64_n)
7044         self.assertEqual(prefix[0].prefix_len, global_pref64_len)
7045         self.assertEqual(prefix[0].vrf_id, 0)
7046
7047         # Add tenant specific prefix
7048         vrf1_pref64 = "2001:db8:122:300::"
7049         vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
7050         vrf1_pref64_len = 56
7051         self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
7052                                        vrf1_pref64_len,
7053                                        vrf_id=self.vrf1_id)
7054         prefix = self.vapi.nat64_prefix_dump()
7055         self.assertEqual(len(prefix), 2)
7056
7057         # Global prefix
7058         pkts = self.create_stream_in_ip6(self.pg0,
7059                                          self.pg1,
7060                                          pref=global_pref64,
7061                                          plen=global_pref64_len)
7062         self.pg0.add_stream(pkts)
7063         self.pg_enable_capture(self.pg_interfaces)
7064         self.pg_start()
7065         capture = self.pg1.get_capture(len(pkts))
7066         self.verify_capture_out(capture, nat_ip=self.nat_addr,
7067                                 dst_ip=self.pg1.remote_ip4)
7068
7069         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7070         self.pg1.add_stream(pkts)
7071         self.pg_enable_capture(self.pg_interfaces)
7072         self.pg_start()
7073         capture = self.pg0.get_capture(len(pkts))
7074         dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7075                                   global_pref64,
7076                                   global_pref64_len)
7077         self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
7078
7079         # Tenant specific prefix
7080         pkts = self.create_stream_in_ip6(self.pg2,
7081                                          self.pg1,
7082                                          pref=vrf1_pref64,
7083                                          plen=vrf1_pref64_len)
7084         self.pg2.add_stream(pkts)
7085         self.pg_enable_capture(self.pg_interfaces)
7086         self.pg_start()
7087         capture = self.pg1.get_capture(len(pkts))
7088         self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7089                                 dst_ip=self.pg1.remote_ip4)
7090
7091         pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7092         self.pg1.add_stream(pkts)
7093         self.pg_enable_capture(self.pg_interfaces)
7094         self.pg_start()
7095         capture = self.pg2.get_capture(len(pkts))
7096         dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7097                                   vrf1_pref64,
7098                                   vrf1_pref64_len)
7099         self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
7100
7101     def test_unknown_proto(self):
7102         """ NAT64 translate packet with unknown protocol """
7103
7104         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7105                                                 self.nat_addr_n)
7106         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7107         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7108         remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7109
7110         # in2out
7111         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7112              IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
7113              TCP(sport=self.tcp_port_in, dport=20))
7114         self.pg0.add_stream(p)
7115         self.pg_enable_capture(self.pg_interfaces)
7116         self.pg_start()
7117         p = self.pg1.get_capture(1)
7118
7119         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7120              IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
7121              GRE() /
7122              IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7123              TCP(sport=1234, dport=1234))
7124         self.pg0.add_stream(p)
7125         self.pg_enable_capture(self.pg_interfaces)
7126         self.pg_start()
7127         p = self.pg1.get_capture(1)
7128         packet = p[0]
7129         try:
7130             self.assertEqual(packet[IP].src, self.nat_addr)
7131             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
7132             self.assertTrue(packet.haslayer(GRE))
7133             self.assert_packet_checksums_valid(packet)
7134         except:
7135             self.logger.error(ppp("Unexpected or invalid packet:", packet))
7136             raise
7137
7138         # out2in
7139         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7140              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7141              GRE() /
7142              IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7143              TCP(sport=1234, dport=1234))
7144         self.pg1.add_stream(p)
7145         self.pg_enable_capture(self.pg_interfaces)
7146         self.pg_start()
7147         p = self.pg0.get_capture(1)
7148         packet = p[0]
7149         try:
7150             self.assertEqual(packet[IPv6].src, remote_ip6)
7151             self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7152             self.assertEqual(packet[IPv6].nh, 47)
7153         except:
7154             self.logger.error(ppp("Unexpected or invalid packet:", packet))
7155             raise
7156
7157     def test_hairpinning_unknown_proto(self):
7158         """ NAT64 translate packet with unknown protocol - hairpinning """
7159
7160         client = self.pg0.remote_hosts[0]
7161         server = self.pg0.remote_hosts[1]
7162         server_tcp_in_port = 22
7163         server_tcp_out_port = 4022
7164         client_tcp_in_port = 1234
7165         client_tcp_out_port = 1235
7166         server_nat_ip = "10.0.0.100"
7167         client_nat_ip = "10.0.0.110"
7168         server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
7169         client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
7170         server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
7171         client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
7172
7173         self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
7174                                                 client_nat_ip_n)
7175         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7176         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7177
7178         self.vapi.nat64_add_del_static_bib(server.ip6n,
7179                                            server_nat_ip_n,
7180                                            server_tcp_in_port,
7181                                            server_tcp_out_port,
7182                                            IP_PROTOS.tcp)
7183
7184         self.vapi.nat64_add_del_static_bib(server.ip6n,
7185                                            server_nat_ip_n,
7186                                            0,
7187                                            0,
7188                                            IP_PROTOS.gre)
7189
7190         self.vapi.nat64_add_del_static_bib(client.ip6n,
7191                                            client_nat_ip_n,
7192                                            client_tcp_in_port,
7193                                            client_tcp_out_port,
7194                                            IP_PROTOS.tcp)
7195
7196         # client to server
7197         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7198              IPv6(src=client.ip6, dst=server_nat_ip6) /
7199              TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7200         self.pg0.add_stream(p)
7201         self.pg_enable_capture(self.pg_interfaces)
7202         self.pg_start()
7203         p = self.pg0.get_capture(1)
7204
7205         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7206              IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
7207              GRE() /
7208              IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7209              TCP(sport=1234, dport=1234))
7210         self.pg0.add_stream(p)
7211         self.pg_enable_capture(self.pg_interfaces)
7212         self.pg_start()
7213         p = self.pg0.get_capture(1)
7214         packet = p[0]
7215         try:
7216             self.assertEqual(packet[IPv6].src, client_nat_ip6)
7217             self.assertEqual(packet[IPv6].dst, server.ip6)
7218             self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
7219         except:
7220             self.logger.error(ppp("Unexpected or invalid packet:", packet))
7221             raise
7222
7223         # server to client
7224         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7225              IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
7226              GRE() /
7227              IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7228              TCP(sport=1234, dport=1234))
7229         self.pg0.add_stream(p)
7230         self.pg_enable_capture(self.pg_interfaces)
7231         self.pg_start()
7232         p = self.pg0.get_capture(1)
7233         packet = p[0]
7234         try:
7235             self.assertEqual(packet[IPv6].src, server_nat_ip6)
7236             self.assertEqual(packet[IPv6].dst, client.ip6)
7237             self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
7238         except:
7239             self.logger.error(ppp("Unexpected or invalid packet:", packet))
7240             raise
7241
7242     def test_one_armed_nat64(self):
7243         """ One armed NAT64 """
7244         external_port = 0
7245         remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
7246                                            '64:ff9b::',
7247                                            96)
7248
7249         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7250                                                 self.nat_addr_n)
7251         self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
7252         self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
7253
7254         # in2out
7255         p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
7256              IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
7257              TCP(sport=12345, dport=80))
7258         self.pg3.add_stream(p)
7259         self.pg_enable_capture(self.pg_interfaces)
7260         self.pg_start()
7261         capture = self.pg3.get_capture(1)
7262         p = capture[0]
7263         try:
7264             ip = p[IP]
7265             tcp = p[TCP]
7266             self.assertEqual(ip.src, self.nat_addr)
7267             self.assertEqual(ip.dst, self.pg3.remote_ip4)
7268             self.assertNotEqual(tcp.sport, 12345)
7269             external_port = tcp.sport
7270             self.assertEqual(tcp.dport, 80)
7271             self.assert_packet_checksums_valid(p)
7272         except:
7273             self.logger.error(ppp("Unexpected or invalid packet:", p))
7274             raise
7275
7276         # out2in
7277         p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
7278              IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
7279              TCP(sport=80, dport=external_port))
7280         self.pg3.add_stream(p)
7281         self.pg_enable_capture(self.pg_interfaces)
7282         self.pg_start()
7283         capture = self.pg3.get_capture(1)
7284         p = capture[0]
7285         try:
7286             ip = p[IPv6]
7287             tcp = p[TCP]
7288             self.assertEqual(ip.src, remote_host_ip6)
7289             self.assertEqual(ip.dst, self.pg3.remote_ip6)
7290             self.assertEqual(tcp.sport, 80)
7291             self.assertEqual(tcp.dport, 12345)
7292             self.assert_packet_checksums_valid(p)
7293         except:
7294             self.logger.error(ppp("Unexpected or invalid packet:", p))
7295             raise
7296
7297     def test_frag_in_order(self):
7298         """ NAT64 translate fragments arriving in order """
7299         self.tcp_port_in = random.randint(1025, 65535)
7300
7301         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7302                                                 self.nat_addr_n)
7303         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7304         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7305
7306         reass = self.vapi.nat_reass_dump()
7307         reass_n_start = len(reass)
7308
7309         # in2out
7310         data = 'a' * 200
7311         pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
7312                                            self.tcp_port_in, 20, data)
7313         self.pg0.add_stream(pkts)
7314         self.pg_enable_capture(self.pg_interfaces)
7315         self.pg_start()
7316         frags = self.pg1.get_capture(len(pkts))
7317         p = self.reass_frags_and_verify(frags,
7318                                         self.nat_addr,
7319                                         self.pg1.remote_ip4)
7320         self.assertEqual(p[TCP].dport, 20)
7321         self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
7322         self.tcp_port_out = p[TCP].sport
7323         self.assertEqual(data, p[Raw].load)
7324
7325         # out2in
7326         data = "A" * 4 + "b" * 16 + "C" * 3
7327         pkts = self.create_stream_frag(self.pg1,
7328                                        self.nat_addr,
7329                                        20,
7330                                        self.tcp_port_out,
7331                                        data)
7332         self.pg1.add_stream(pkts)
7333         self.pg_enable_capture(self.pg_interfaces)
7334         self.pg_start()
7335         frags = self.pg0.get_capture(len(pkts))
7336         src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7337         p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
7338         self.assertEqual(p[TCP].sport, 20)
7339         self.assertEqual(p[TCP].dport, self.tcp_port_in)
7340         self.assertEqual(data, p[Raw].load)
7341
7342         reass = self.vapi.nat_reass_dump()
7343         reass_n_end = len(reass)
7344
7345         self.assertEqual(reass_n_end - reass_n_start, 2)
7346
7347     def test_reass_hairpinning(self):
7348         """ NAT64 fragments hairpinning """
7349         data = 'a' * 200
7350         server = self.pg0.remote_hosts[1]
7351         server_in_port = random.randint(1025, 65535)
7352         server_out_port = random.randint(1025, 65535)
7353         client_in_port = random.randint(1025, 65535)
7354         ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
7355         nat_addr_ip6 = ip.src
7356
7357         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7358                                                 self.nat_addr_n)
7359         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7360         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7361
7362         # add static BIB entry for server
7363         self.vapi.nat64_add_del_static_bib(server.ip6n,
7364                                            self.nat_addr_n,
7365                                            server_in_port,
7366                                            server_out_port,
7367                                            IP_PROTOS.tcp)
7368
7369         # send packet from host to server
7370         pkts = self.create_stream_frag_ip6(self.pg0,
7371                                            self.nat_addr,
7372                                            client_in_port,
7373                                            server_out_port,
7374                                            data)
7375         self.pg0.add_stream(pkts)
7376         self.pg_enable_capture(self.pg_interfaces)
7377         self.pg_start()
7378         frags = self.pg0.get_capture(len(pkts))
7379         p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
7380         self.assertNotEqual(p[TCP].sport, client_in_port)
7381         self.assertEqual(p[TCP].dport, server_in_port)
7382         self.assertEqual(data, p[Raw].load)
7383
7384     def test_frag_out_of_order(self):
7385         """ NAT64 translate fragments arriving out of order """
7386         self.tcp_port_in = random.randint(1025, 65535)
7387
7388         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7389                                                 self.nat_addr_n)
7390         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7391         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7392
7393         # in2out
7394         data = 'a' * 200
7395         pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
7396                                            self.tcp_port_in, 20, data)
7397         pkts.reverse()
7398         self.pg0.add_stream(pkts)
7399         self.pg_enable_capture(self.pg_interfaces)
7400         self.pg_start()
7401         frags = self.pg1.get_capture(len(pkts))
7402         p = self.reass_frags_and_verify(frags,
7403                                         self.nat_addr,
7404                                         self.pg1.remote_ip4)
7405         self.assertEqual(p[TCP].dport, 20)
7406         self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
7407         self.tcp_port_out = p[TCP].sport
7408         self.assertEqual(data, p[Raw].load)
7409
7410         # out2in
7411         data = "A" * 4 + "B" * 16 + "C" * 3
7412         pkts = self.create_stream_frag(self.pg1,
7413                                        self.nat_addr,
7414                                        20,
7415                                        self.tcp_port_out,
7416                                        data)
7417         pkts.reverse()
7418         self.pg1.add_stream(pkts)
7419         self.pg_enable_capture(self.pg_interfaces)
7420         self.pg_start()
7421         frags = self.pg0.get_capture(len(pkts))
7422         src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7423         p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
7424         self.assertEqual(p[TCP].sport, 20)
7425         self.assertEqual(p[TCP].dport, self.tcp_port_in)
7426         self.assertEqual(data, p[Raw].load)
7427
7428     def test_interface_addr(self):
7429         """ Acquire NAT64 pool addresses from interface """
7430         self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
7431
7432         # no address in NAT64 pool
7433         adresses = self.vapi.nat44_address_dump()
7434         self.assertEqual(0, len(adresses))
7435
7436         # configure interface address and check NAT64 address pool
7437         self.pg4.config_ip4()
7438         addresses = self.vapi.nat64_pool_addr_dump()
7439         self.assertEqual(len(addresses), 1)
7440         self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
7441
7442         # remove interface address and check NAT64 address pool
7443         self.pg4.unconfig_ip4()
7444         addresses = self.vapi.nat64_pool_addr_dump()
7445         self.assertEqual(0, len(adresses))
7446
7447     @unittest.skipUnless(running_extended_tests(), "part of extended tests")
7448     def test_ipfix_max_bibs_sessions(self):
7449         """ IPFIX logging maximum session and BIB entries exceeded """
7450         max_bibs = 1280
7451         max_sessions = 2560
7452         remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
7453                                            '64:ff9b::',
7454                                            96)
7455
7456         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7457                                                 self.nat_addr_n)
7458         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7459         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7460
7461         pkts = []
7462         src = ""
7463         for i in range(0, max_bibs):
7464             src = "fd01:aa::%x" % (i)
7465             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7466                  IPv6(src=src, dst=remote_host_ip6) /
7467                  TCP(sport=12345, dport=80))
7468             pkts.append(p)
7469             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7470                  IPv6(src=src, dst=remote_host_ip6) /
7471                  TCP(sport=12345, dport=22))
7472             pkts.append(p)
7473         self.pg0.add_stream(pkts)
7474         self.pg_enable_capture(self.pg_interfaces)
7475         self.pg_start()
7476         self.pg1.get_capture(max_sessions)
7477
7478         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
7479                                      src_address=self.pg3.local_ip4n,
7480                                      path_mtu=512,
7481                                      template_interval=10)
7482         self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
7483                             src_port=self.ipfix_src_port)
7484
7485         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7486              IPv6(src=src, dst=remote_host_ip6) /
7487              TCP(sport=12345, dport=25))
7488         self.pg0.add_stream(p)
7489         self.pg_enable_capture(self.pg_interfaces)
7490         self.pg_start()
7491         self.pg1.assert_nothing_captured()
7492         sleep(1)
7493         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
7494         capture = self.pg3.get_capture(9)
7495         ipfix = IPFIXDecoder()
7496         # first load template
7497         for p in capture:
7498             self.assertTrue(p.haslayer(IPFIX))
7499             self.assertEqual(p[IP].src, self.pg3.local_ip4)
7500             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7501             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7502             self.assertEqual(p[UDP].dport, 4739)
7503             self.assertEqual(p[IPFIX].observationDomainID,
7504                              self.ipfix_domain_id)
7505             if p.haslayer(Template):
7506                 ipfix.add_template(p.getlayer(Template))
7507         # verify events in data set
7508         for p in capture:
7509             if p.haslayer(Data):
7510                 data = ipfix.decode_data_set(p.getlayer(Set))
7511                 self.verify_ipfix_max_sessions(data, max_sessions)
7512
7513         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7514              IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
7515              TCP(sport=12345, dport=80))
7516         self.pg0.add_stream(p)
7517         self.pg_enable_capture(self.pg_interfaces)
7518         self.pg_start()
7519         self.pg1.assert_nothing_captured()
7520         sleep(1)
7521         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
7522         capture = self.pg3.get_capture(1)
7523         # verify events in data set
7524         for p in capture:
7525             self.assertTrue(p.haslayer(IPFIX))
7526             self.assertEqual(p[IP].src, self.pg3.local_ip4)
7527             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7528             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7529             self.assertEqual(p[UDP].dport, 4739)
7530             self.assertEqual(p[IPFIX].observationDomainID,
7531                              self.ipfix_domain_id)
7532             if p.haslayer(Data):
7533                 data = ipfix.decode_data_set(p.getlayer(Set))
7534                 self.verify_ipfix_max_bibs(data, max_bibs)
7535
7536     def test_ipfix_max_frags(self):
7537         """ IPFIX logging maximum fragments pending reassembly exceeded """
7538         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7539                                                 self.nat_addr_n)
7540         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7541         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7542         self.vapi.nat_set_reass(max_frag=1, is_ip6=1)
7543         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
7544                                      src_address=self.pg3.local_ip4n,
7545                                      path_mtu=512,
7546                                      template_interval=10)
7547         self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
7548                             src_port=self.ipfix_src_port)
7549
7550         data = 'a' * 200
7551         pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
7552                                            self.tcp_port_in, 20, data)
7553         pkts.reverse()
7554         self.pg0.add_stream(pkts)
7555         self.pg_enable_capture(self.pg_interfaces)
7556         self.pg_start()
7557         self.pg1.assert_nothing_captured()
7558         sleep(1)
7559         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
7560         capture = self.pg3.get_capture(9)
7561         ipfix = IPFIXDecoder()
7562         # first load template
7563         for p in capture:
7564             self.assertTrue(p.haslayer(IPFIX))
7565             self.assertEqual(p[IP].src, self.pg3.local_ip4)
7566             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7567             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7568             self.assertEqual(p[UDP].dport, 4739)
7569             self.assertEqual(p[IPFIX].observationDomainID,
7570                              self.ipfix_domain_id)
7571             if p.haslayer(Template):
7572                 ipfix.add_template(p.getlayer(Template))
7573         # verify events in data set
7574         for p in capture:
7575             if p.haslayer(Data):
7576                 data = ipfix.decode_data_set(p.getlayer(Set))
7577                 self.verify_ipfix_max_fragments_ip6(data, 1,
7578                                                     self.pg0.remote_ip6n)
7579
7580     def test_ipfix_bib_ses(self):
7581         """ IPFIX logging NAT64 BIB/session create and delete events """
7582         self.tcp_port_in = random.randint(1025, 65535)
7583         remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
7584                                            '64:ff9b::',
7585                                            96)
7586
7587         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7588                                                 self.nat_addr_n)
7589         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7590         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7591         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
7592                                      src_address=self.pg3.local_ip4n,
7593                                      path_mtu=512,
7594                                      template_interval=10)
7595         self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
7596                             src_port=self.ipfix_src_port)
7597
7598         # Create
7599         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7600              IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
7601              TCP(sport=self.tcp_port_in, dport=25))
7602         self.pg0.add_stream(p)
7603         self.pg_enable_capture(self.pg_interfaces)
7604         self.pg_start()
7605         p = self.pg1.get_capture(1)
7606         self.tcp_port_out = p[0][TCP].sport
7607         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
7608         capture = self.pg3.get_capture(10)
7609         ipfix = IPFIXDecoder()
7610         # first load template
7611         for p in capture:
7612             self.assertTrue(p.haslayer(IPFIX))
7613             self.assertEqual(p[IP].src, self.pg3.local_ip4)
7614             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7615             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7616             self.assertEqual(p[UDP].dport, 4739)
7617             self.assertEqual(p[IPFIX].observationDomainID,
7618                              self.ipfix_domain_id)
7619             if p.haslayer(Template):
7620                 ipfix.add_template(p.getlayer(Template))
7621         # verify events in data set
7622         for p in capture:
7623             if p.haslayer(Data):
7624                 data = ipfix.decode_data_set(p.getlayer(Set))
7625                 if ord(data[0][230]) == 10:
7626                     self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
7627                 elif ord(data[0][230]) == 6:
7628                     self.verify_ipfix_nat64_ses(data,
7629                                                 1,
7630                                                 self.pg0.remote_ip6n,
7631                                                 self.pg1.remote_ip4,
7632                                                 25)
7633                 else:
7634                     self.logger.error(ppp("Unexpected or invalid packet: ", p))
7635
7636         # Delete
7637         self.pg_enable_capture(self.pg_interfaces)
7638         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7639                                                 self.nat_addr_n,
7640                                                 is_add=0)
7641         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
7642         capture = self.pg3.get_capture(2)
7643         # verify events in data set
7644         for p in capture:
7645             self.assertTrue(p.haslayer(IPFIX))
7646             self.assertEqual(p[IP].src, self.pg3.local_ip4)
7647             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7648             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7649             self.assertEqual(p[UDP].dport, 4739)
7650             self.assertEqual(p[IPFIX].observationDomainID,
7651                              self.ipfix_domain_id)
7652             if p.haslayer(Data):
7653                 data = ipfix.decode_data_set(p.getlayer(Set))
7654                 if ord(data[0][230]) == 11:
7655                     self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
7656                 elif ord(data[0][230]) == 7:
7657                     self.verify_ipfix_nat64_ses(data,
7658                                                 0,
7659                                                 self.pg0.remote_ip6n,
7660                                                 self.pg1.remote_ip4,
7661                                                 25)
7662                 else:
7663                     self.logger.error(ppp("Unexpected or invalid packet: ", p))
7664
7665     def nat64_get_ses_num(self):
7666         """
7667         Return number of active NAT64 sessions.
7668         """
7669         st = self.vapi.nat64_st_dump()
7670         return len(st)
7671
7672     def clear_nat64(self):
7673         """
7674         Clear NAT64 configuration.
7675         """
7676         self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
7677                             domain_id=self.ipfix_domain_id)
7678         self.ipfix_src_port = 4739
7679         self.ipfix_domain_id = 1
7680
7681         self.vapi.nat_set_timeouts()
7682
7683         interfaces = self.vapi.nat64_interface_dump()
7684         for intf in interfaces:
7685             if intf.is_inside > 1:
7686                 self.vapi.nat64_add_del_interface(intf.sw_if_index,
7687                                                   0,
7688                                                   is_add=0)
7689             self.vapi.nat64_add_del_interface(intf.sw_if_index,
7690                                               intf.is_inside,
7691                                               is_add=0)
7692
7693         bib = self.vapi.nat64_bib_dump(255)
7694         for bibe in bib:
7695             if bibe.is_static:
7696                 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
7697                                                    bibe.o_addr,
7698                                                    bibe.i_port,
7699                                                    bibe.o_port,
7700                                                    bibe.proto,
7701                                                    bibe.vrf_id,
7702                                                    is_add=0)
7703
7704         adresses = self.vapi.nat64_pool_addr_dump()
7705         for addr in adresses:
7706             self.vapi.nat64_add_del_pool_addr_range(addr.address,
7707                                                     addr.address,
7708                                                     vrf_id=addr.vrf_id,
7709                                                     is_add=0)
7710
7711         prefixes = self.vapi.nat64_prefix_dump()
7712         for prefix in prefixes:
7713             self.vapi.nat64_add_del_prefix(prefix.prefix,
7714                                            prefix.prefix_len,
7715                                            vrf_id=prefix.vrf_id,
7716                                            is_add=0)
7717
7718     def tearDown(self):
7719         super(TestNAT64, self).tearDown()
7720         if not self.vpp_dead:
7721             self.logger.info(self.vapi.cli("show nat64 pool"))
7722             self.logger.info(self.vapi.cli("show nat64 interfaces"))
7723             self.logger.info(self.vapi.cli("show nat64 prefix"))
7724             self.logger.info(self.vapi.cli("show nat64 bib all"))
7725             self.logger.info(self.vapi.cli("show nat64 session table all"))
7726             self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
7727             self.clear_nat64()
7728
7729
7730 class TestDSlite(MethodHolder):
7731     """ DS-Lite Test Cases """
7732
7733     @classmethod
7734     def setUpClass(cls):
7735         super(TestDSlite, cls).setUpClass()
7736
7737         try:
7738             cls.nat_addr = '10.0.0.3'
7739             cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
7740
7741             cls.create_pg_interfaces(range(2))
7742             cls.pg0.admin_up()
7743             cls.pg0.config_ip4()
7744             cls.pg0.resolve_arp()
7745             cls.pg1.admin_up()
7746             cls.pg1.config_ip6()
7747             cls.pg1.generate_remote_hosts(2)
7748             cls.pg1.configure_ipv6_neighbors()
7749
7750         except Exception:
7751             super(TestDSlite, cls).tearDownClass()
7752             raise
7753
7754     def test_dslite(self):
7755         """ Test DS-Lite """
7756         nat_config = self.vapi.nat_show_config()
7757         self.assertEqual(0, nat_config.dslite_ce)
7758
7759         self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
7760                                                  self.nat_addr_n)
7761         aftr_ip4 = '192.0.0.1'
7762         aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
7763         aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
7764         aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
7765         self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
7766
7767         # UDP
7768         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7769              IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
7770              IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7771              UDP(sport=20000, dport=10000))
7772         self.pg1.add_stream(p)
7773         self.pg_enable_capture(self.pg_interfaces)
7774         self.pg_start()
7775         capture = self.pg0.get_capture(1)
7776         capture = capture[0]
7777         self.assertFalse(capture.haslayer(IPv6))
7778         self.assertEqual(capture[IP].src, self.nat_addr)
7779         self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7780         self.assertNotEqual(capture[UDP].sport, 20000)
7781         self.assertEqual(capture[UDP].dport, 10000)
7782         self.assert_packet_checksums_valid(capture)
7783         out_port = capture[UDP].sport
7784
7785         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7786              IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7787              UDP(sport=10000, dport=out_port))
7788         self.pg0.add_stream(p)
7789         self.pg_enable_capture(self.pg_interfaces)
7790         self.pg_start()
7791         capture = self.pg1.get_capture(1)
7792         capture = capture[0]
7793         self.assertEqual(capture[IPv6].src, aftr_ip6)
7794         self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
7795         self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7796         self.assertEqual(capture[IP].dst, '192.168.1.1')
7797         self.assertEqual(capture[UDP].sport, 10000)
7798         self.assertEqual(capture[UDP].dport, 20000)
7799         self.assert_packet_checksums_valid(capture)
7800
7801         # TCP
7802         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7803              IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
7804              IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7805              TCP(sport=20001, dport=10001))
7806         self.pg1.add_stream(p)
7807         self.pg_enable_capture(self.pg_interfaces)
7808         self.pg_start()
7809         capture = self.pg0.get_capture(1)
7810         capture = capture[0]
7811         self.assertFalse(capture.haslayer(IPv6))
7812         self.assertEqual(capture[IP].src, self.nat_addr)
7813         self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7814         self.assertNotEqual(capture[TCP].sport, 20001)
7815         self.assertEqual(capture[TCP].dport, 10001)
7816         self.assert_packet_checksums_valid(capture)
7817         out_port = capture[TCP].sport
7818
7819         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7820              IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7821              TCP(sport=10001, dport=out_port))
7822         self.pg0.add_stream(p)
7823         self.pg_enable_capture(self.pg_interfaces)
7824         self.pg_start()
7825         capture = self.pg1.get_capture(1)
7826         capture = capture[0]
7827         self.assertEqual(capture[IPv6].src, aftr_ip6)
7828         self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7829         self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7830         self.assertEqual(capture[IP].dst, '192.168.1.1')
7831         self.assertEqual(capture[TCP].sport, 10001)
7832         self.assertEqual(capture[TCP].dport, 20001)
7833         self.assert_packet_checksums_valid(capture)
7834
7835         # ICMP
7836         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7837              IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
7838              IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
7839              ICMP(id=4000, type='echo-request'))
7840         self.pg1.add_stream(p)
7841         self.pg_enable_capture(self.pg_interfaces)
7842         self.pg_start()
7843         capture = self.pg0.get_capture(1)
7844         capture = capture[0]
7845         self.assertFalse(capture.haslayer(IPv6))
7846         self.assertEqual(capture[IP].src, self.nat_addr)
7847         self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7848         self.assertNotEqual(capture[ICMP].id, 4000)
7849         self.assert_packet_checksums_valid(capture)
7850         out_id = capture[ICMP].id
7851
7852         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7853              IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
7854              ICMP(id=out_id, type='echo-reply'))
7855         self.pg0.add_stream(p)
7856         self.pg_enable_capture(self.pg_interfaces)
7857         self.pg_start()
7858         capture = self.pg1.get_capture(1)
7859         capture = capture[0]
7860         self.assertEqual(capture[IPv6].src, aftr_ip6)
7861         self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7862         self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7863         self.assertEqual(capture[IP].dst, '192.168.1.1')
7864         self.assertEqual(capture[ICMP].id, 4000)
7865         self.assert_packet_checksums_valid(capture)
7866
7867         # ping DS-Lite AFTR tunnel endpoint address
7868         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7869              IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
7870              ICMPv6EchoRequest())
7871         self.pg1.add_stream(p)
7872         self.pg_enable_capture(self.pg_interfaces)
7873         self.pg_start()
7874         capture = self.pg1.get_capture(1)
7875         capture = capture[0]
7876         self.assertEqual(capture[IPv6].src, aftr_ip6)
7877         self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
7878         self.assertTrue(capture.haslayer(ICMPv6EchoReply))
7879
7880     def tearDown(self):
7881         super(TestDSlite, self).tearDown()
7882         if not self.vpp_dead:
7883             self.logger.info(self.vapi.cli("show dslite pool"))
7884             self.logger.info(
7885                 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
7886             self.logger.info(self.vapi.cli("show dslite sessions"))
7887
7888
7889 class TestDSliteCE(MethodHolder):
7890     """ DS-Lite CE Test Cases """
7891
7892     @classmethod
7893     def setUpConstants(cls):
7894         super(TestDSliteCE, cls).setUpConstants()
7895         cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
7896
7897     @classmethod
7898     def setUpClass(cls):
7899         super(TestDSliteCE, cls).setUpClass()
7900
7901         try:
7902             cls.create_pg_interfaces(range(2))
7903             cls.pg0.admin_up()
7904             cls.pg0.config_ip4()
7905             cls.pg0.resolve_arp()
7906             cls.pg1.admin_up()
7907             cls.pg1.config_ip6()
7908             cls.pg1.generate_remote_hosts(1)
7909             cls.pg1.configure_ipv6_neighbors()
7910
7911         except Exception:
7912             super(TestDSliteCE, cls).tearDownClass()
7913             raise
7914
7915     def test_dslite_ce(self):
7916         """ Test DS-Lite CE """
7917
7918         nat_config = self.vapi.nat_show_config()
7919         self.assertEqual(1, nat_config.dslite_ce)
7920
7921         b4_ip4 = '192.0.0.2'
7922         b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
7923         b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
7924         b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
7925         self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
7926
7927         aftr_ip4 = '192.0.0.1'
7928         aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
7929         aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
7930         aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
7931         self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
7932
7933         self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
7934                                    dst_address_length=128,
7935                                    next_hop_address=self.pg1.remote_ip6n,
7936                                    next_hop_sw_if_index=self.pg1.sw_if_index,
7937                                    is_ipv6=1)
7938
7939         # UDP encapsulation
7940         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7941              IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
7942              UDP(sport=10000, dport=20000))
7943         self.pg0.add_stream(p)
7944         self.pg_enable_capture(self.pg_interfaces)
7945         self.pg_start()
7946         capture = self.pg1.get_capture(1)
7947         capture = capture[0]
7948         self.assertEqual(capture[IPv6].src, b4_ip6)
7949         self.assertEqual(capture[IPv6].dst, aftr_ip6)
7950         self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
7951         self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
7952         self.assertEqual(capture[UDP].sport, 10000)
7953         self.assertEqual(capture[UDP].dport, 20000)
7954         self.assert_packet_checksums_valid(capture)
7955
7956         # UDP decapsulation
7957         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7958              IPv6(dst=b4_ip6, src=aftr_ip6) /
7959              IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
7960              UDP(sport=20000, dport=10000))
7961         self.pg1.add_stream(p)
7962         self.pg_enable_capture(self.pg_interfaces)
7963         self.pg_start()
7964         capture = self.pg0.get_capture(1)
7965         capture = capture[0]
7966         self.assertFalse(capture.haslayer(IPv6))
7967         self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
7968         self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
7969         self.assertEqual(capture[UDP].sport, 20000)
7970         self.assertEqual(capture[UDP].dport, 10000)
7971         self.assert_packet_checksums_valid(capture)
7972
7973         # ping DS-Lite B4 tunnel endpoint address
7974         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7975              IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
7976              ICMPv6EchoRequest())
7977         self.pg1.add_stream(p)
7978         self.pg_enable_capture(self.pg_interfaces)
7979         self.pg_start()
7980         capture = self.pg1.get_capture(1)
7981         capture = capture[0]
7982         self.assertEqual(capture[IPv6].src, b4_ip6)
7983         self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
7984         self.assertTrue(capture.haslayer(ICMPv6EchoReply))
7985
7986     def tearDown(self):
7987         super(TestDSliteCE, self).tearDown()
7988         if not self.vpp_dead:
7989             self.logger.info(
7990                 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
7991             self.logger.info(
7992                 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
7993
7994
7995 class TestNAT66(MethodHolder):
7996     """ NAT66 Test Cases """
7997
7998     @classmethod
7999     def setUpClass(cls):
8000         super(TestNAT66, cls).setUpClass()
8001
8002         try:
8003             cls.nat_addr = 'fd01:ff::2'
8004             cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
8005
8006             cls.create_pg_interfaces(range(2))
8007             cls.interfaces = list(cls.pg_interfaces)
8008
8009             for i in cls.interfaces:
8010                 i.admin_up()
8011                 i.config_ip6()
8012                 i.configure_ipv6_neighbors()
8013
8014         except Exception:
8015             super(TestNAT66, cls).tearDownClass()
8016             raise
8017
8018     def test_static(self):
8019         """ 1:1 NAT66 test """
8020         self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8021         self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8022         self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8023                                                self.nat_addr_n)
8024
8025         # in2out
8026         pkts = []
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              TCP())
8030         pkts.append(p)
8031         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8032              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8033              UDP())
8034         pkts.append(p)
8035         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8036              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8037              ICMPv6EchoRequest())
8038         pkts.append(p)
8039         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8040              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8041              GRE() / IP() / TCP())
8042         pkts.append(p)
8043         self.pg0.add_stream(pkts)
8044         self.pg_enable_capture(self.pg_interfaces)
8045         self.pg_start()
8046         capture = self.pg1.get_capture(len(pkts))
8047         for packet in capture:
8048             try:
8049                 self.assertEqual(packet[IPv6].src, self.nat_addr)
8050                 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
8051                 self.assert_packet_checksums_valid(packet)
8052             except:
8053                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8054                 raise
8055
8056         # out2in
8057         pkts = []
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              TCP())
8061         pkts.append(p)
8062         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8063              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8064              UDP())
8065         pkts.append(p)
8066         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8067              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8068              ICMPv6EchoReply())
8069         pkts.append(p)
8070         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8071              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8072              GRE() / IP() / TCP())
8073         pkts.append(p)
8074         self.pg1.add_stream(pkts)
8075         self.pg_enable_capture(self.pg_interfaces)
8076         self.pg_start()
8077         capture = self.pg0.get_capture(len(pkts))
8078         for packet in capture:
8079             try:
8080                 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
8081                 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8082                 self.assert_packet_checksums_valid(packet)
8083             except:
8084                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8085                 raise
8086
8087         sm = self.vapi.nat66_static_mapping_dump()
8088         self.assertEqual(len(sm), 1)
8089         self.assertEqual(sm[0].total_pkts, 8)
8090
8091     def test_check_no_translate(self):
8092         """ NAT66 translate only when egress interface is outside interface """
8093         self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8094         self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
8095         self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8096                                                self.nat_addr_n)
8097
8098         # in2out
8099         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8100              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8101              UDP())
8102         self.pg0.add_stream([p])
8103         self.pg_enable_capture(self.pg_interfaces)
8104         self.pg_start()
8105         capture = self.pg1.get_capture(1)
8106         packet = capture[0]
8107         try:
8108             self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
8109             self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
8110         except:
8111             self.logger.error(ppp("Unexpected or invalid packet:", packet))
8112             raise
8113
8114     def clear_nat66(self):
8115         """
8116         Clear NAT66 configuration.
8117         """
8118         interfaces = self.vapi.nat66_interface_dump()
8119         for intf in interfaces:
8120             self.vapi.nat66_add_del_interface(intf.sw_if_index,
8121                                               intf.is_inside,
8122                                               is_add=0)
8123
8124         static_mappings = self.vapi.nat66_static_mapping_dump()
8125         for sm in static_mappings:
8126             self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
8127                                                    sm.external_ip_address,
8128                                                    sm.vrf_id,
8129                                                    is_add=0)
8130
8131     def tearDown(self):
8132         super(TestNAT66, self).tearDown()
8133         if not self.vpp_dead:
8134             self.logger.info(self.vapi.cli("show nat66 interfaces"))
8135             self.logger.info(self.vapi.cli("show nat66 static mappings"))
8136             self.clear_nat66()
8137
8138
8139 if __name__ == '__main__':
8140     unittest.main(testRunner=VppTestRunner)