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