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