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