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