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