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