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