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