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