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