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