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