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