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