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