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