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