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