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