Tests Cleanup: Fix missing calls to setUpClass/tearDownClass.
[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         if not self.vpp_dead:
4165             self.logger.info(self.vapi.cli("show nat44 addresses"))
4166             self.logger.info(self.vapi.cli("show nat44 interfaces"))
4167             self.logger.info(self.vapi.cli("show nat44 static mappings"))
4168             self.logger.info(self.vapi.cli("show nat44 interface address"))
4169             self.logger.info(self.vapi.cli("show nat44 sessions detail"))
4170             self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
4171             self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
4172             self.logger.info(self.vapi.cli("show nat timeouts"))
4173             self.logger.info(
4174                 self.vapi.cli("show nat addr-port-assignment-alg"))
4175             self.logger.info(self.vapi.cli("show nat ha"))
4176             self.clear_nat44()
4177             self.vapi.cli("clear logging")
4178
4179
4180 class TestNAT44EndpointDependent(MethodHolder):
4181     """ Endpoint-Dependent mapping and filtering test cases """
4182
4183     @classmethod
4184     def setUpConstants(cls):
4185         super(TestNAT44EndpointDependent, cls).setUpConstants()
4186         cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4187
4188     @classmethod
4189     def setUpClass(cls):
4190         super(TestNAT44EndpointDependent, cls).setUpClass()
4191         cls.vapi.cli("set log class nat level debug")
4192         try:
4193             cls.tcp_port_in = 6303
4194             cls.tcp_port_out = 6303
4195             cls.udp_port_in = 6304
4196             cls.udp_port_out = 6304
4197             cls.icmp_id_in = 6305
4198             cls.icmp_id_out = 6305
4199             cls.nat_addr = '10.0.0.3'
4200             cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
4201             cls.ipfix_src_port = 4739
4202             cls.ipfix_domain_id = 1
4203             cls.tcp_external_port = 80
4204
4205             cls.create_pg_interfaces(range(7))
4206             cls.interfaces = list(cls.pg_interfaces[0:3])
4207
4208             for i in cls.interfaces:
4209                 i.admin_up()
4210                 i.config_ip4()
4211                 i.resolve_arp()
4212
4213             cls.pg0.generate_remote_hosts(3)
4214             cls.pg0.configure_ipv4_neighbors()
4215
4216             cls.pg3.admin_up()
4217
4218             cls.pg4.generate_remote_hosts(2)
4219             cls.pg4.config_ip4()
4220             ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
4221             cls.vapi.sw_interface_add_del_address(
4222                 sw_if_index=cls.pg4.sw_if_index, address=ip_addr_n,
4223                 address_length=24)
4224             cls.pg4.admin_up()
4225             cls.pg4.resolve_arp()
4226             cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4227             cls.pg4.resolve_arp()
4228
4229             zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
4230             cls.vapi.ip_table_add_del(is_add=1, table_id=1)
4231
4232             cls.pg5._local_ip4 = "10.1.1.1"
4233             cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
4234                                                    cls.pg5.local_ip4)
4235             cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4236             cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
4237                 socket.AF_INET, cls.pg5.remote_ip4)
4238             cls.pg5.set_table_ip4(1)
4239             cls.pg5.config_ip4()
4240             cls.pg5.admin_up()
4241             cls.vapi.ip_add_del_route(dst_address=cls.pg5.remote_ip4n,
4242                                       dst_address_length=32,
4243                                       next_hop_address=zero_ip4n,
4244                                       next_hop_sw_if_index=cls.pg5.sw_if_index,
4245                                       table_id=1)
4246
4247             cls.pg6._local_ip4 = "10.1.2.1"
4248             cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
4249                                                    cls.pg6.local_ip4)
4250             cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4251             cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
4252                 socket.AF_INET, cls.pg6.remote_ip4)
4253             cls.pg6.set_table_ip4(1)
4254             cls.pg6.config_ip4()
4255             cls.pg6.admin_up()
4256             cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4257                                       dst_address_length=32,
4258                                       next_hop_address=zero_ip4n,
4259                                       next_hop_sw_if_index=cls.pg6.sw_if_index,
4260                                       table_id=1)
4261
4262             cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4263                                       dst_address_length=16,
4264                                       next_hop_address=zero_ip4n, table_id=0,
4265                                       next_hop_table_id=1)
4266             cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
4267                                       dst_address_length=0,
4268                                       next_hop_address=zero_ip4n, table_id=1,
4269                                       next_hop_table_id=0)
4270             cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
4271                                       dst_address_length=0,
4272                                       next_hop_address=cls.pg1.local_ip4n,
4273                                       next_hop_sw_if_index=cls.pg1.sw_if_index,
4274                                       table_id=0)
4275
4276             cls.pg5.resolve_arp()
4277             cls.pg6.resolve_arp()
4278
4279         except Exception:
4280             super(TestNAT44EndpointDependent, cls).tearDownClass()
4281             raise
4282
4283     @classmethod
4284     def tearDownClass(cls):
4285         super(TestNAT44EndpointDependent, cls).tearDownClass()
4286
4287     def test_frag_in_order(self):
4288         """ NAT44 translate fragments arriving in order """
4289         self.nat44_add_address(self.nat_addr)
4290         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4291         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4292                                                   is_inside=0)
4293         self.frag_in_order(proto=IP_PROTOS.tcp)
4294         self.frag_in_order(proto=IP_PROTOS.udp)
4295         self.frag_in_order(proto=IP_PROTOS.icmp)
4296
4297     def test_frag_in_order_dont_translate(self):
4298         """ NAT44 don't translate fragments arriving in order """
4299         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4300         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4301                                                   is_inside=0)
4302         self.vapi.nat44_forwarding_enable_disable(enable=True)
4303         self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4304
4305     def test_frag_out_of_order(self):
4306         """ NAT44 translate fragments arriving out of order """
4307         self.nat44_add_address(self.nat_addr)
4308         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4309         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4310                                                   is_inside=0)
4311         self.frag_out_of_order(proto=IP_PROTOS.tcp)
4312         self.frag_out_of_order(proto=IP_PROTOS.udp)
4313         self.frag_out_of_order(proto=IP_PROTOS.icmp)
4314
4315     def test_frag_out_of_order_dont_translate(self):
4316         """ NAT44 don't translate fragments arriving out of order """
4317         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4318         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4319                                                   is_inside=0)
4320         self.vapi.nat44_forwarding_enable_disable(enable=True)
4321         self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4322
4323     def test_frag_in_order_in_plus_out(self):
4324         """ in+out interface fragments in order """
4325         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4326         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4327                                                   is_inside=0)
4328         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4329         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4330                                                   is_inside=0)
4331
4332         self.server = self.pg1.remote_hosts[0]
4333
4334         self.server_in_addr = self.server.ip4
4335         self.server_out_addr = '11.11.11.11'
4336         self.server_in_port = random.randint(1025, 65535)
4337         self.server_out_port = random.randint(1025, 65535)
4338
4339         self.nat44_add_address(self.server_out_addr)
4340
4341         # add static mappings for server
4342         self.nat44_add_static_mapping(self.server_in_addr,
4343                                       self.server_out_addr,
4344                                       self.server_in_port,
4345                                       self.server_out_port,
4346                                       proto=IP_PROTOS.tcp)
4347         self.nat44_add_static_mapping(self.server_in_addr,
4348                                       self.server_out_addr,
4349                                       self.server_in_port,
4350                                       self.server_out_port,
4351                                       proto=IP_PROTOS.udp)
4352         self.nat44_add_static_mapping(self.server_in_addr,
4353                                       self.server_out_addr,
4354                                       proto=IP_PROTOS.icmp)
4355
4356         self.vapi.nat_set_reass(timeout=10)
4357
4358         self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4359         self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4360         self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4361
4362     def test_frag_out_of_order_in_plus_out(self):
4363         """ in+out interface fragments out of order """
4364         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4365         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4366                                                   is_inside=0)
4367         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4368         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4369                                                   is_inside=0)
4370
4371         self.server = self.pg1.remote_hosts[0]
4372
4373         self.server_in_addr = self.server.ip4
4374         self.server_out_addr = '11.11.11.11'
4375         self.server_in_port = random.randint(1025, 65535)
4376         self.server_out_port = random.randint(1025, 65535)
4377
4378         self.nat44_add_address(self.server_out_addr)
4379
4380         # add static mappings for server
4381         self.nat44_add_static_mapping(self.server_in_addr,
4382                                       self.server_out_addr,
4383                                       self.server_in_port,
4384                                       self.server_out_port,
4385                                       proto=IP_PROTOS.tcp)
4386         self.nat44_add_static_mapping(self.server_in_addr,
4387                                       self.server_out_addr,
4388                                       self.server_in_port,
4389                                       self.server_out_port,
4390                                       proto=IP_PROTOS.udp)
4391         self.nat44_add_static_mapping(self.server_in_addr,
4392                                       self.server_out_addr,
4393                                       proto=IP_PROTOS.icmp)
4394
4395         self.vapi.nat_set_reass(timeout=10)
4396
4397         self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4398         self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4399         self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4400
4401     def test_reass_hairpinning(self):
4402         """ NAT44 fragments hairpinning """
4403         self.server = self.pg0.remote_hosts[1]
4404         self.host_in_port = random.randint(1025, 65535)
4405         self.server_in_port = random.randint(1025, 65535)
4406         self.server_out_port = random.randint(1025, 65535)
4407
4408         self.nat44_add_address(self.nat_addr)
4409         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4410         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4411                                                   is_inside=0)
4412         # add static mapping for server
4413         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4414                                       self.server_in_port,
4415                                       self.server_out_port,
4416                                       proto=IP_PROTOS.tcp)
4417         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4418                                       self.server_in_port,
4419                                       self.server_out_port,
4420                                       proto=IP_PROTOS.udp)
4421         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
4422
4423         self.reass_hairpinning(proto=IP_PROTOS.tcp)
4424         self.reass_hairpinning(proto=IP_PROTOS.udp)
4425         self.reass_hairpinning(proto=IP_PROTOS.icmp)
4426
4427     def test_dynamic(self):
4428         """ NAT44 dynamic translation test """
4429
4430         self.nat44_add_address(self.nat_addr)
4431         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4432         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4433                                                   is_inside=0)
4434
4435         nat_config = self.vapi.nat_show_config()
4436         self.assertEqual(1, nat_config.endpoint_dependent)
4437
4438         # in2out
4439         tcpn = self.statistics.get_counter(
4440             '/err/nat44-ed-in2out-slowpath/TCP packets')
4441         udpn = self.statistics.get_counter(
4442             '/err/nat44-ed-in2out-slowpath/UDP packets')
4443         icmpn = self.statistics.get_counter(
4444             '/err/nat44-ed-in2out-slowpath/ICMP packets')
4445         totaln = self.statistics.get_counter(
4446             '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4447
4448         pkts = self.create_stream_in(self.pg0, self.pg1)
4449         self.pg0.add_stream(pkts)
4450         self.pg_enable_capture(self.pg_interfaces)
4451         self.pg_start()
4452         capture = self.pg1.get_capture(len(pkts))
4453         self.verify_capture_out(capture)
4454
4455         err = self.statistics.get_counter(
4456             '/err/nat44-ed-in2out-slowpath/TCP packets')
4457         self.assertEqual(err - tcpn, 1)
4458         err = self.statistics.get_counter(
4459             '/err/nat44-ed-in2out-slowpath/UDP packets')
4460         self.assertEqual(err - udpn, 1)
4461         err = self.statistics.get_counter(
4462             '/err/nat44-ed-in2out-slowpath/ICMP packets')
4463         self.assertEqual(err - icmpn, 1)
4464         err = self.statistics.get_counter(
4465             '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4466         self.assertEqual(err - totaln, 3)
4467
4468         # out2in
4469         tcpn = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4470         udpn = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4471         icmpn = self.statistics.get_counter(
4472             '/err/nat44-ed-out2in-slowpath/ICMP packets')
4473         totaln = self.statistics.get_counter(
4474             '/err/nat44-ed-out2in/good out2in packets processed')
4475
4476         pkts = self.create_stream_out(self.pg1)
4477         self.pg1.add_stream(pkts)
4478         self.pg_enable_capture(self.pg_interfaces)
4479         self.pg_start()
4480         capture = self.pg0.get_capture(len(pkts))
4481         self.verify_capture_in(capture, self.pg0)
4482
4483         err = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4484         self.assertEqual(err - tcpn, 1)
4485         err = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4486         self.assertEqual(err - udpn, 1)
4487         err = self.statistics.get_counter(
4488             '/err/nat44-ed-out2in-slowpath/ICMP packets')
4489         self.assertEqual(err - icmpn, 1)
4490         err = self.statistics.get_counter(
4491             '/err/nat44-ed-out2in/good out2in packets processed')
4492         self.assertEqual(err - totaln, 2)
4493
4494         users = self.statistics.get_counter('/nat44/total-users')
4495         self.assertEqual(users[0][0], 1)
4496         sessions = self.statistics.get_counter('/nat44/total-sessions')
4497         self.assertEqual(sessions[0][0], 3)
4498
4499     def test_forwarding(self):
4500         """ NAT44 forwarding test """
4501
4502         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4503         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4504                                                   is_inside=0)
4505         self.vapi.nat44_forwarding_enable_disable(1)
4506
4507         real_ip = self.pg0.remote_ip4n
4508         alias_ip = self.nat_addr_n
4509         self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4510                                                external_ip=alias_ip)
4511
4512         try:
4513             # in2out - static mapping match
4514
4515             pkts = self.create_stream_out(self.pg1)
4516             self.pg1.add_stream(pkts)
4517             self.pg_enable_capture(self.pg_interfaces)
4518             self.pg_start()
4519             capture = self.pg0.get_capture(len(pkts))
4520             self.verify_capture_in(capture, self.pg0)
4521
4522             pkts = self.create_stream_in(self.pg0, self.pg1)
4523             self.pg0.add_stream(pkts)
4524             self.pg_enable_capture(self.pg_interfaces)
4525             self.pg_start()
4526             capture = self.pg1.get_capture(len(pkts))
4527             self.verify_capture_out(capture, same_port=True)
4528
4529             # in2out - no static mapping match
4530
4531             host0 = self.pg0.remote_hosts[0]
4532             self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4533             try:
4534                 pkts = self.create_stream_out(self.pg1,
4535                                               dst_ip=self.pg0.remote_ip4,
4536                                               use_inside_ports=True)
4537                 self.pg1.add_stream(pkts)
4538                 self.pg_enable_capture(self.pg_interfaces)
4539                 self.pg_start()
4540                 capture = self.pg0.get_capture(len(pkts))
4541                 self.verify_capture_in(capture, self.pg0)
4542
4543                 pkts = self.create_stream_in(self.pg0, self.pg1)
4544                 self.pg0.add_stream(pkts)
4545                 self.pg_enable_capture(self.pg_interfaces)
4546                 self.pg_start()
4547                 capture = self.pg1.get_capture(len(pkts))
4548                 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4549                                         same_port=True)
4550             finally:
4551                 self.pg0.remote_hosts[0] = host0
4552
4553             user = self.pg0.remote_hosts[1]
4554             sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4555             self.assertEqual(len(sessions), 3)
4556             self.assertTrue(sessions[0].ext_host_valid)
4557             self.vapi.nat44_del_session(
4558                 sessions[0].inside_ip_address,
4559                 sessions[0].inside_port,
4560                 sessions[0].protocol,
4561                 ext_host_address=sessions[0].ext_host_address,
4562                 ext_host_port=sessions[0].ext_host_port)
4563             sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4564             self.assertEqual(len(sessions), 2)
4565
4566         finally:
4567             self.vapi.nat44_forwarding_enable_disable(0)
4568             self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4569                                                    external_ip=alias_ip,
4570                                                    is_add=0)
4571
4572     def test_static_lb(self):
4573         """ NAT44 local service load balancing """
4574         external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4575         external_port = 80
4576         local_port = 8080
4577         server1 = self.pg0.remote_hosts[0]
4578         server2 = self.pg0.remote_hosts[1]
4579
4580         locals = [{'addr': server1.ip4n,
4581                    'port': local_port,
4582                    'probability': 70,
4583                    'vrf_id': 0},
4584                   {'addr': server2.ip4n,
4585                    'port': local_port,
4586                    'probability': 30,
4587                    'vrf_id': 0}]
4588
4589         self.nat44_add_address(self.nat_addr)
4590         self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4591                                                   external_port,
4592                                                   IP_PROTOS.tcp,
4593                                                   local_num=len(locals),
4594                                                   locals=locals)
4595         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4596         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4597                                                   is_inside=0)
4598
4599         # from client to service
4600         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4601              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4602              TCP(sport=12345, dport=external_port))
4603         self.pg1.add_stream(p)
4604         self.pg_enable_capture(self.pg_interfaces)
4605         self.pg_start()
4606         capture = self.pg0.get_capture(1)
4607         p = capture[0]
4608         server = None
4609         try:
4610             ip = p[IP]
4611             tcp = p[TCP]
4612             self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4613             if ip.dst == server1.ip4:
4614                 server = server1
4615             else:
4616                 server = server2
4617             self.assertEqual(tcp.dport, local_port)
4618             self.assert_packet_checksums_valid(p)
4619         except:
4620             self.logger.error(ppp("Unexpected or invalid packet:", p))
4621             raise
4622
4623         # from service back to client
4624         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4625              IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4626              TCP(sport=local_port, dport=12345))
4627         self.pg0.add_stream(p)
4628         self.pg_enable_capture(self.pg_interfaces)
4629         self.pg_start()
4630         capture = self.pg1.get_capture(1)
4631         p = capture[0]
4632         try:
4633             ip = p[IP]
4634             tcp = p[TCP]
4635             self.assertEqual(ip.src, self.nat_addr)
4636             self.assertEqual(tcp.sport, external_port)
4637             self.assert_packet_checksums_valid(p)
4638         except:
4639             self.logger.error(ppp("Unexpected or invalid packet:", p))
4640             raise
4641
4642         sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4643         self.assertEqual(len(sessions), 1)
4644         self.assertTrue(sessions[0].ext_host_valid)
4645         self.vapi.nat44_del_session(
4646             sessions[0].inside_ip_address,
4647             sessions[0].inside_port,
4648             sessions[0].protocol,
4649             ext_host_address=sessions[0].ext_host_address,
4650             ext_host_port=sessions[0].ext_host_port)
4651         sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4652         self.assertEqual(len(sessions), 0)
4653
4654     @unittest.skipUnless(running_extended_tests, "part of extended tests")
4655     def test_static_lb_multi_clients(self):
4656         """ NAT44 local service load balancing - multiple clients"""
4657
4658         external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4659         external_port = 80
4660         local_port = 8080
4661         server1 = self.pg0.remote_hosts[0]
4662         server2 = self.pg0.remote_hosts[1]
4663         server3 = self.pg0.remote_hosts[2]
4664
4665         locals = [{'addr': server1.ip4n,
4666                    'port': local_port,
4667                    'probability': 90,
4668                    'vrf_id': 0},
4669                   {'addr': server2.ip4n,
4670                    'port': local_port,
4671                    'probability': 10,
4672                    'vrf_id': 0}]
4673
4674         self.nat44_add_address(self.nat_addr)
4675         self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4676                                                   external_port,
4677                                                   IP_PROTOS.tcp,
4678                                                   local_num=len(locals),
4679                                                   locals=locals)
4680         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4681         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4682                                                   is_inside=0)
4683
4684         server1_n = 0
4685         server2_n = 0
4686         clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4687         pkts = []
4688         for client in clients:
4689             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4690                  IP(src=client, dst=self.nat_addr) /
4691                  TCP(sport=12345, dport=external_port))
4692             pkts.append(p)
4693         self.pg1.add_stream(pkts)
4694         self.pg_enable_capture(self.pg_interfaces)
4695         self.pg_start()
4696         capture = self.pg0.get_capture(len(pkts))
4697         for p in capture:
4698             if p[IP].dst == server1.ip4:
4699                 server1_n += 1
4700             else:
4701                 server2_n += 1
4702         self.assertGreater(server1_n, server2_n)
4703
4704         # add new back-end
4705         self.vapi.nat44_lb_static_mapping_add_del_local(external_addr_n,
4706                                                         external_port,
4707                                                         server3.ip4n,
4708                                                         local_port,
4709                                                         IP_PROTOS.tcp,
4710                                                         20)
4711         server1_n = 0
4712         server2_n = 0
4713         server3_n = 0
4714         clients = ip4_range(self.pg1.remote_ip4, 60, 110)
4715         pkts = []
4716         for client in clients:
4717             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4718                  IP(src=client, dst=self.nat_addr) /
4719                  TCP(sport=12346, dport=external_port))
4720             pkts.append(p)
4721         self.assertGreater(len(pkts), 0)
4722         self.pg1.add_stream(pkts)
4723         self.pg_enable_capture(self.pg_interfaces)
4724         self.pg_start()
4725         capture = self.pg0.get_capture(len(pkts))
4726         for p in capture:
4727             if p[IP].dst == server1.ip4:
4728                 server1_n += 1
4729             elif p[IP].dst == server2.ip4:
4730                 server2_n += 1
4731             else:
4732                 server3_n += 1
4733         self.assertGreater(server1_n, 0)
4734         self.assertGreater(server2_n, 0)
4735         self.assertGreater(server3_n, 0)
4736
4737         # remove one back-end
4738         self.vapi.nat44_lb_static_mapping_add_del_local(external_addr_n,
4739                                                         external_port,
4740                                                         server2.ip4n,
4741                                                         local_port,
4742                                                         IP_PROTOS.tcp,
4743                                                         10,
4744                                                         is_add=0)
4745         server1_n = 0
4746         server2_n = 0
4747         server3_n = 0
4748         self.pg1.add_stream(pkts)
4749         self.pg_enable_capture(self.pg_interfaces)
4750         self.pg_start()
4751         capture = self.pg0.get_capture(len(pkts))
4752         for p in capture:
4753             if p[IP].dst == server1.ip4:
4754                 server1_n += 1
4755             elif p[IP].dst == server2.ip4:
4756                 server2_n += 1
4757             else:
4758                 server3_n += 1
4759         self.assertGreater(server1_n, 0)
4760         self.assertEqual(server2_n, 0)
4761         self.assertGreater(server3_n, 0)
4762
4763     def test_static_lb_2(self):
4764         """ NAT44 local service load balancing (asymmetrical rule) """
4765         external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4766         external_port = 80
4767         local_port = 8080
4768         server1 = self.pg0.remote_hosts[0]
4769         server2 = self.pg0.remote_hosts[1]
4770
4771         locals = [{'addr': server1.ip4n,
4772                    'port': local_port,
4773                    'probability': 70,
4774                    'vrf_id': 0},
4775                   {'addr': server2.ip4n,
4776                    'port': local_port,
4777                    'probability': 30,
4778                    'vrf_id': 0}]
4779
4780         self.vapi.nat44_forwarding_enable_disable(1)
4781         self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4782                                                   external_port,
4783                                                   IP_PROTOS.tcp,
4784                                                   out2in_only=1,
4785                                                   local_num=len(locals),
4786                                                   locals=locals)
4787         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4788         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4789                                                   is_inside=0)
4790
4791         # from client to service
4792         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4793              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4794              TCP(sport=12345, dport=external_port))
4795         self.pg1.add_stream(p)
4796         self.pg_enable_capture(self.pg_interfaces)
4797         self.pg_start()
4798         capture = self.pg0.get_capture(1)
4799         p = capture[0]
4800         server = None
4801         try:
4802             ip = p[IP]
4803             tcp = p[TCP]
4804             self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4805             if ip.dst == server1.ip4:
4806                 server = server1
4807             else:
4808                 server = server2
4809             self.assertEqual(tcp.dport, local_port)
4810             self.assert_packet_checksums_valid(p)
4811         except:
4812             self.logger.error(ppp("Unexpected or invalid packet:", p))
4813             raise
4814
4815         # from service back to client
4816         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4817              IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4818              TCP(sport=local_port, dport=12345))
4819         self.pg0.add_stream(p)
4820         self.pg_enable_capture(self.pg_interfaces)
4821         self.pg_start()
4822         capture = self.pg1.get_capture(1)
4823         p = capture[0]
4824         try:
4825             ip = p[IP]
4826             tcp = p[TCP]
4827             self.assertEqual(ip.src, self.nat_addr)
4828             self.assertEqual(tcp.sport, external_port)
4829             self.assert_packet_checksums_valid(p)
4830         except:
4831             self.logger.error(ppp("Unexpected or invalid packet:", p))
4832             raise
4833
4834         # from client to server (no translation)
4835         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4836              IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
4837              TCP(sport=12346, dport=local_port))
4838         self.pg1.add_stream(p)
4839         self.pg_enable_capture(self.pg_interfaces)
4840         self.pg_start()
4841         capture = self.pg0.get_capture(1)
4842         p = capture[0]
4843         server = None
4844         try:
4845             ip = p[IP]
4846             tcp = p[TCP]
4847             self.assertEqual(ip.dst, server1.ip4)
4848             self.assertEqual(tcp.dport, local_port)
4849             self.assert_packet_checksums_valid(p)
4850         except:
4851             self.logger.error(ppp("Unexpected or invalid packet:", p))
4852             raise
4853
4854         # from service back to client (no translation)
4855         p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
4856              IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
4857              TCP(sport=local_port, dport=12346))
4858         self.pg0.add_stream(p)
4859         self.pg_enable_capture(self.pg_interfaces)
4860         self.pg_start()
4861         capture = self.pg1.get_capture(1)
4862         p = capture[0]
4863         try:
4864             ip = p[IP]
4865             tcp = p[TCP]
4866             self.assertEqual(ip.src, server1.ip4)
4867             self.assertEqual(tcp.sport, local_port)
4868             self.assert_packet_checksums_valid(p)
4869         except:
4870             self.logger.error(ppp("Unexpected or invalid packet:", p))
4871             raise
4872
4873     def test_lb_affinity(self):
4874         """ NAT44 local service load balancing affinity """
4875         external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4876         external_port = 80
4877         local_port = 8080
4878         server1 = self.pg0.remote_hosts[0]
4879         server2 = self.pg0.remote_hosts[1]
4880
4881         locals = [{'addr': server1.ip4n,
4882                    'port': local_port,
4883                    'probability': 50,
4884                    'vrf_id': 0},
4885                   {'addr': server2.ip4n,
4886                    'port': local_port,
4887                    'probability': 50,
4888                    'vrf_id': 0}]
4889
4890         self.nat44_add_address(self.nat_addr)
4891         self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4892                                                   external_port,
4893                                                   IP_PROTOS.tcp,
4894                                                   affinity=10800,
4895                                                   local_num=len(locals),
4896                                                   locals=locals)
4897         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4898         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4899                                                   is_inside=0)
4900
4901         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4902              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4903              TCP(sport=1025, dport=external_port))
4904         self.pg1.add_stream(p)
4905         self.pg_enable_capture(self.pg_interfaces)
4906         self.pg_start()
4907         capture = self.pg0.get_capture(1)
4908         backend = capture[0][IP].dst
4909
4910         sessions = self.vapi.nat44_user_session_dump(
4911             socket.inet_pton(socket.AF_INET, backend), 0)
4912         self.assertEqual(len(sessions), 1)
4913         self.assertTrue(sessions[0].ext_host_valid)
4914         self.vapi.nat44_del_session(
4915             sessions[0].inside_ip_address,
4916             sessions[0].inside_port,
4917             sessions[0].protocol,
4918             ext_host_address=sessions[0].ext_host_address,
4919             ext_host_port=sessions[0].ext_host_port)
4920
4921         pkts = []
4922         for port in range(1030, 1100):
4923             p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4924                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4925                  TCP(sport=port, dport=external_port))
4926             pkts.append(p)
4927         self.pg1.add_stream(pkts)
4928         self.pg_enable_capture(self.pg_interfaces)
4929         self.pg_start()
4930         capture = self.pg0.get_capture(len(pkts))
4931         for p in capture:
4932             self.assertEqual(p[IP].dst, backend)
4933
4934     def test_unknown_proto(self):
4935         """ NAT44 translate packet with unknown protocol """
4936         self.nat44_add_address(self.nat_addr)
4937         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4938         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4939                                                   is_inside=0)
4940
4941         # in2out
4942         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4943              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4944              TCP(sport=self.tcp_port_in, dport=20))
4945         self.pg0.add_stream(p)
4946         self.pg_enable_capture(self.pg_interfaces)
4947         self.pg_start()
4948         p = self.pg1.get_capture(1)
4949
4950         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4951              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4952              GRE() /
4953              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4954              TCP(sport=1234, dport=1234))
4955         self.pg0.add_stream(p)
4956         self.pg_enable_capture(self.pg_interfaces)
4957         self.pg_start()
4958         p = self.pg1.get_capture(1)
4959         packet = p[0]
4960         try:
4961             self.assertEqual(packet[IP].src, self.nat_addr)
4962             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
4963             self.assertEqual(packet.haslayer(GRE), 1)
4964             self.assert_packet_checksums_valid(packet)
4965         except:
4966             self.logger.error(ppp("Unexpected or invalid packet:", packet))
4967             raise
4968
4969         # out2in
4970         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4971              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4972              GRE() /
4973              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4974              TCP(sport=1234, dport=1234))
4975         self.pg1.add_stream(p)
4976         self.pg_enable_capture(self.pg_interfaces)
4977         self.pg_start()
4978         p = self.pg0.get_capture(1)
4979         packet = p[0]
4980         try:
4981             self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
4982             self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
4983             self.assertEqual(packet.haslayer(GRE), 1)
4984             self.assert_packet_checksums_valid(packet)
4985         except:
4986             self.logger.error(ppp("Unexpected or invalid packet:", packet))
4987             raise
4988
4989     def test_hairpinning_unknown_proto(self):
4990         """ NAT44 translate packet with unknown protocol - hairpinning """
4991         host = self.pg0.remote_hosts[0]
4992         server = self.pg0.remote_hosts[1]
4993         host_in_port = 1234
4994         server_out_port = 8765
4995         server_nat_ip = "10.0.0.11"
4996
4997         self.nat44_add_address(self.nat_addr)
4998         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4999         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5000                                                   is_inside=0)
5001
5002         # add static mapping for server
5003         self.nat44_add_static_mapping(server.ip4, server_nat_ip)
5004
5005         # host to server
5006         p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
5007              IP(src=host.ip4, dst=server_nat_ip) /
5008              TCP(sport=host_in_port, dport=server_out_port))
5009         self.pg0.add_stream(p)
5010         self.pg_enable_capture(self.pg_interfaces)
5011         self.pg_start()
5012         self.pg0.get_capture(1)
5013
5014         p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5015              IP(src=host.ip4, dst=server_nat_ip) /
5016              GRE() /
5017              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5018              TCP(sport=1234, dport=1234))
5019         self.pg0.add_stream(p)
5020         self.pg_enable_capture(self.pg_interfaces)
5021         self.pg_start()
5022         p = self.pg0.get_capture(1)
5023         packet = p[0]
5024         try:
5025             self.assertEqual(packet[IP].src, self.nat_addr)
5026             self.assertEqual(packet[IP].dst, server.ip4)
5027             self.assertEqual(packet.haslayer(GRE), 1)
5028             self.assert_packet_checksums_valid(packet)
5029         except:
5030             self.logger.error(ppp("Unexpected or invalid packet:", packet))
5031             raise
5032
5033         # server to host
5034         p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5035              IP(src=server.ip4, dst=self.nat_addr) /
5036              GRE() /
5037              IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5038              TCP(sport=1234, dport=1234))
5039         self.pg0.add_stream(p)
5040         self.pg_enable_capture(self.pg_interfaces)
5041         self.pg_start()
5042         p = self.pg0.get_capture(1)
5043         packet = p[0]
5044         try:
5045             self.assertEqual(packet[IP].src, server_nat_ip)
5046             self.assertEqual(packet[IP].dst, host.ip4)
5047             self.assertEqual(packet.haslayer(GRE), 1)
5048             self.assert_packet_checksums_valid(packet)
5049         except:
5050             self.logger.error(ppp("Unexpected or invalid packet:", packet))
5051             raise
5052
5053     def test_output_feature_and_service(self):
5054         """ NAT44 interface output feature and services """
5055         external_addr = '1.2.3.4'
5056         external_port = 80
5057         local_port = 8080
5058
5059         self.vapi.nat44_forwarding_enable_disable(1)
5060         self.nat44_add_address(self.nat_addr)
5061         self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
5062         self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5063                                       local_port, external_port,
5064                                       proto=IP_PROTOS.tcp, out2in_only=1)
5065         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5066         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5067                                                   is_inside=0)
5068         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5069                                                          is_inside=0)
5070
5071         # from client to service
5072         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5073              IP(src=self.pg1.remote_ip4, dst=external_addr) /
5074              TCP(sport=12345, dport=external_port))
5075         self.pg1.add_stream(p)
5076         self.pg_enable_capture(self.pg_interfaces)
5077         self.pg_start()
5078         capture = self.pg0.get_capture(1)
5079         p = capture[0]
5080         try:
5081             ip = p[IP]
5082             tcp = p[TCP]
5083             self.assertEqual(ip.dst, self.pg0.remote_ip4)
5084             self.assertEqual(tcp.dport, local_port)
5085             self.assert_packet_checksums_valid(p)
5086         except:
5087             self.logger.error(ppp("Unexpected or invalid packet:", p))
5088             raise
5089
5090         # from service back to client
5091         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5092              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5093              TCP(sport=local_port, dport=12345))
5094         self.pg0.add_stream(p)
5095         self.pg_enable_capture(self.pg_interfaces)
5096         self.pg_start()
5097         capture = self.pg1.get_capture(1)
5098         p = capture[0]
5099         try:
5100             ip = p[IP]
5101             tcp = p[TCP]
5102             self.assertEqual(ip.src, external_addr)
5103             self.assertEqual(tcp.sport, external_port)
5104             self.assert_packet_checksums_valid(p)
5105         except:
5106             self.logger.error(ppp("Unexpected or invalid packet:", p))
5107             raise
5108
5109         # from local network host to external network
5110         pkts = self.create_stream_in(self.pg0, self.pg1)
5111         self.pg0.add_stream(pkts)
5112         self.pg_enable_capture(self.pg_interfaces)
5113         self.pg_start()
5114         capture = self.pg1.get_capture(len(pkts))
5115         self.verify_capture_out(capture)
5116         pkts = self.create_stream_in(self.pg0, self.pg1)
5117         self.pg0.add_stream(pkts)
5118         self.pg_enable_capture(self.pg_interfaces)
5119         self.pg_start()
5120         capture = self.pg1.get_capture(len(pkts))
5121         self.verify_capture_out(capture)
5122
5123         # from external network back to local network host
5124         pkts = self.create_stream_out(self.pg1)
5125         self.pg1.add_stream(pkts)
5126         self.pg_enable_capture(self.pg_interfaces)
5127         self.pg_start()
5128         capture = self.pg0.get_capture(len(pkts))
5129         self.verify_capture_in(capture, self.pg0)
5130
5131     def test_output_feature_and_service2(self):
5132         """ NAT44 interface output feature and service host direct access """
5133         self.vapi.nat44_forwarding_enable_disable(1)
5134         self.nat44_add_address(self.nat_addr)
5135         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5136                                                          is_inside=0)
5137
5138         # session initiated from service host - translate
5139         pkts = self.create_stream_in(self.pg0, self.pg1)
5140         self.pg0.add_stream(pkts)
5141         self.pg_enable_capture(self.pg_interfaces)
5142         self.pg_start()
5143         capture = self.pg1.get_capture(len(pkts))
5144         self.verify_capture_out(capture)
5145
5146         pkts = self.create_stream_out(self.pg1)
5147         self.pg1.add_stream(pkts)
5148         self.pg_enable_capture(self.pg_interfaces)
5149         self.pg_start()
5150         capture = self.pg0.get_capture(len(pkts))
5151         self.verify_capture_in(capture, self.pg0)
5152
5153         # session initiated from remote host - do not translate
5154         self.tcp_port_in = 60303
5155         self.udp_port_in = 60304
5156         self.icmp_id_in = 60305
5157         pkts = self.create_stream_out(self.pg1,
5158                                       self.pg0.remote_ip4,
5159                                       use_inside_ports=True)
5160         self.pg1.add_stream(pkts)
5161         self.pg_enable_capture(self.pg_interfaces)
5162         self.pg_start()
5163         capture = self.pg0.get_capture(len(pkts))
5164         self.verify_capture_in(capture, self.pg0)
5165
5166         pkts = self.create_stream_in(self.pg0, self.pg1)
5167         self.pg0.add_stream(pkts)
5168         self.pg_enable_capture(self.pg_interfaces)
5169         self.pg_start()
5170         capture = self.pg1.get_capture(len(pkts))
5171         self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5172                                 same_port=True)
5173
5174     def test_output_feature_and_service3(self):
5175         """ NAT44 interface output feature and DST NAT """
5176         external_addr = '1.2.3.4'
5177         external_port = 80
5178         local_port = 8080
5179
5180         self.vapi.nat44_forwarding_enable_disable(1)
5181         self.nat44_add_address(self.nat_addr)
5182         self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5183                                       local_port, external_port,
5184                                       proto=IP_PROTOS.tcp, out2in_only=1)
5185         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5186         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5187                                                   is_inside=0)
5188         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5189                                                          is_inside=0)
5190
5191         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5192              IP(src=self.pg0.remote_ip4, dst=external_addr) /
5193              TCP(sport=12345, dport=external_port))
5194         self.pg0.add_stream(p)
5195         self.pg_enable_capture(self.pg_interfaces)
5196         self.pg_start()
5197         capture = self.pg1.get_capture(1)
5198         p = capture[0]
5199         try:
5200             ip = p[IP]
5201             tcp = p[TCP]
5202             self.assertEqual(ip.src, self.pg0.remote_ip4)
5203             self.assertEqual(tcp.sport, 12345)
5204             self.assertEqual(ip.dst, self.pg1.remote_ip4)
5205             self.assertEqual(tcp.dport, local_port)
5206             self.assert_packet_checksums_valid(p)
5207         except:
5208             self.logger.error(ppp("Unexpected or invalid packet:", p))
5209             raise
5210
5211         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5212              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5213              TCP(sport=local_port, dport=12345))
5214         self.pg1.add_stream(p)
5215         self.pg_enable_capture(self.pg_interfaces)
5216         self.pg_start()
5217         capture = self.pg0.get_capture(1)
5218         p = capture[0]
5219         try:
5220             ip = p[IP]
5221             tcp = p[TCP]
5222             self.assertEqual(ip.src, external_addr)
5223             self.assertEqual(tcp.sport, external_port)
5224             self.assertEqual(ip.dst, self.pg0.remote_ip4)
5225             self.assertEqual(tcp.dport, 12345)
5226             self.assert_packet_checksums_valid(p)
5227         except:
5228             self.logger.error(ppp("Unexpected or invalid packet:", p))
5229             raise
5230
5231     def test_next_src_nat(self):
5232         """ On way back forward packet to nat44-in2out node. """
5233         twice_nat_addr = '10.0.1.3'
5234         external_port = 80
5235         local_port = 8080
5236         post_twice_nat_port = 0
5237
5238         self.vapi.nat44_forwarding_enable_disable(1)
5239         self.nat44_add_address(twice_nat_addr, twice_nat=1)
5240         self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5241                                       local_port, external_port,
5242                                       proto=IP_PROTOS.tcp, out2in_only=1,
5243                                       self_twice_nat=1, vrf_id=1)
5244         self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
5245                                                   is_inside=0)
5246
5247         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5248              IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5249              TCP(sport=12345, dport=external_port))
5250         self.pg6.add_stream(p)
5251         self.pg_enable_capture(self.pg_interfaces)
5252         self.pg_start()
5253         capture = self.pg6.get_capture(1)
5254         p = capture[0]
5255         try:
5256             ip = p[IP]
5257             tcp = p[TCP]
5258             self.assertEqual(ip.src, twice_nat_addr)
5259             self.assertNotEqual(tcp.sport, 12345)
5260             post_twice_nat_port = tcp.sport
5261             self.assertEqual(ip.dst, self.pg6.remote_ip4)
5262             self.assertEqual(tcp.dport, local_port)
5263             self.assert_packet_checksums_valid(p)
5264         except:
5265             self.logger.error(ppp("Unexpected or invalid packet:", p))
5266             raise
5267
5268         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5269              IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5270              TCP(sport=local_port, dport=post_twice_nat_port))
5271         self.pg6.add_stream(p)
5272         self.pg_enable_capture(self.pg_interfaces)
5273         self.pg_start()
5274         capture = self.pg6.get_capture(1)
5275         p = capture[0]
5276         try:
5277             ip = p[IP]
5278             tcp = p[TCP]
5279             self.assertEqual(ip.src, self.pg1.remote_ip4)
5280             self.assertEqual(tcp.sport, external_port)
5281             self.assertEqual(ip.dst, self.pg6.remote_ip4)
5282             self.assertEqual(tcp.dport, 12345)
5283             self.assert_packet_checksums_valid(p)
5284         except:
5285             self.logger.error(ppp("Unexpected or invalid packet:", p))
5286             raise
5287
5288     def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5289                          client_id=None):
5290         twice_nat_addr = '10.0.1.3'
5291
5292         port_in = 8080
5293         if lb:
5294             if not same_pg:
5295                 port_in1 = port_in
5296                 port_in2 = port_in
5297             else:
5298                 port_in1 = port_in + 1
5299                 port_in2 = port_in + 2
5300
5301         port_out = 80
5302         eh_port_out = 4567
5303
5304         server1 = self.pg0.remote_hosts[0]
5305         server2 = self.pg0.remote_hosts[1]
5306         if lb and same_pg:
5307             server2 = server1
5308         if not lb:
5309             server = server1
5310
5311         pg0 = self.pg0
5312         if same_pg:
5313             pg1 = self.pg0
5314         else:
5315             pg1 = self.pg1
5316
5317         eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5318                         client_id == 1)
5319
5320         self.nat44_add_address(self.nat_addr)
5321         self.nat44_add_address(twice_nat_addr, twice_nat=1)
5322         if not lb:
5323             self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5324                                           port_in, port_out,
5325                                           proto=IP_PROTOS.tcp,
5326                                           twice_nat=int(not self_twice_nat),
5327                                           self_twice_nat=int(self_twice_nat))
5328         else:
5329             locals = [{'addr': server1.ip4n,
5330                        'port': port_in1,
5331                        'probability': 50,
5332                        'vrf_id': 0},
5333                       {'addr': server2.ip4n,
5334                        'port': port_in2,
5335                        'probability': 50,
5336                        'vrf_id': 0}]
5337             out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
5338             self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
5339                                                       port_out,
5340                                                       IP_PROTOS.tcp,
5341                                                       twice_nat=int(
5342                                                           not self_twice_nat),
5343                                                       self_twice_nat=int(
5344                                                           self_twice_nat),
5345                                                       local_num=len(locals),
5346                                                       locals=locals)
5347         self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
5348         self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
5349                                                   is_inside=0)
5350
5351         if same_pg:
5352             if not lb:
5353                 client = server
5354             else:
5355                 assert client_id is not None
5356                 if client_id == 1:
5357                     client = self.pg0.remote_hosts[0]
5358                 elif client_id == 2:
5359                     client = self.pg0.remote_hosts[1]
5360         else:
5361             client = pg1.remote_hosts[0]
5362         p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5363              IP(src=client.ip4, dst=self.nat_addr) /
5364              TCP(sport=eh_port_out, dport=port_out))
5365         pg1.add_stream(p)
5366         self.pg_enable_capture(self.pg_interfaces)
5367         self.pg_start()
5368         capture = pg0.get_capture(1)
5369         p = capture[0]
5370         try:
5371             ip = p[IP]
5372             tcp = p[TCP]
5373             if lb:
5374                 if ip.dst == server1.ip4:
5375                     server = server1
5376                     port_in = port_in1
5377                 else:
5378                     server = server2
5379                     port_in = port_in2
5380             self.assertEqual(ip.dst, server.ip4)
5381             if lb and same_pg:
5382                 self.assertIn(tcp.dport, [port_in1, port_in2])
5383             else:
5384                 self.assertEqual(tcp.dport, port_in)
5385             if eh_translate:
5386                 self.assertEqual(ip.src, twice_nat_addr)
5387                 self.assertNotEqual(tcp.sport, eh_port_out)
5388             else:
5389                 self.assertEqual(ip.src, client.ip4)
5390                 self.assertEqual(tcp.sport, eh_port_out)
5391             eh_addr_in = ip.src
5392             eh_port_in = tcp.sport
5393             saved_port_in = tcp.dport
5394             self.assert_packet_checksums_valid(p)
5395         except:
5396             self.logger.error(ppp("Unexpected or invalid packet:", p))
5397             raise
5398
5399         p = (Ether(src=server.mac, dst=pg0.local_mac) /
5400              IP(src=server.ip4, dst=eh_addr_in) /
5401              TCP(sport=saved_port_in, dport=eh_port_in))
5402         pg0.add_stream(p)
5403         self.pg_enable_capture(self.pg_interfaces)
5404         self.pg_start()
5405         capture = pg1.get_capture(1)
5406         p = capture[0]
5407         try:
5408             ip = p[IP]
5409             tcp = p[TCP]
5410             self.assertEqual(ip.dst, client.ip4)
5411             self.assertEqual(ip.src, self.nat_addr)
5412             self.assertEqual(tcp.dport, eh_port_out)
5413             self.assertEqual(tcp.sport, port_out)
5414             self.assert_packet_checksums_valid(p)
5415         except:
5416             self.logger.error(ppp("Unexpected or invalid packet:", p))
5417             raise
5418
5419         if eh_translate:
5420             sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5421             self.assertEqual(len(sessions), 1)
5422             self.assertTrue(sessions[0].ext_host_valid)
5423             self.assertTrue(sessions[0].is_twicenat)
5424             self.vapi.nat44_del_session(
5425                 sessions[0].inside_ip_address,
5426                 sessions[0].inside_port,
5427                 sessions[0].protocol,
5428                 ext_host_address=sessions[0].ext_host_nat_address,
5429                 ext_host_port=sessions[0].ext_host_nat_port)
5430             sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5431             self.assertEqual(len(sessions), 0)
5432
5433     def test_twice_nat(self):
5434         """ Twice NAT44 """
5435         self.twice_nat_common()
5436
5437     def test_self_twice_nat_positive(self):
5438         """ Self Twice NAT44 (positive test) """
5439         self.twice_nat_common(self_twice_nat=True, same_pg=True)
5440
5441     def test_self_twice_nat_negative(self):
5442         """ Self Twice NAT44 (negative test) """
5443         self.twice_nat_common(self_twice_nat=True)
5444
5445     def test_twice_nat_lb(self):
5446         """ Twice NAT44 local service load balancing """
5447         self.twice_nat_common(lb=True)
5448
5449     def test_self_twice_nat_lb_positive(self):
5450         """ Self Twice NAT44 local service load balancing (positive test) """
5451         self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5452                               client_id=1)
5453
5454     def test_self_twice_nat_lb_negative(self):
5455         """ Self Twice NAT44 local service load balancing (negative test) """
5456         self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5457                               client_id=2)
5458
5459     def test_twice_nat_interface_addr(self):
5460         """ Acquire twice NAT44 addresses from interface """
5461         self.vapi.nat44_add_del_interface_addr(self.pg3.sw_if_index,
5462                                                twice_nat=1)
5463
5464         # no address in NAT pool
5465         adresses = self.vapi.nat44_address_dump()
5466         self.assertEqual(0, len(adresses))
5467
5468         # configure interface address and check NAT address pool
5469         self.pg3.config_ip4()
5470         adresses = self.vapi.nat44_address_dump()
5471         self.assertEqual(1, len(adresses))
5472         self.assertEqual(adresses[0].ip_address[0:4], self.pg3.local_ip4n)
5473         self.assertEqual(adresses[0].twice_nat, 1)
5474
5475         # remove interface address and check NAT address pool
5476         self.pg3.unconfig_ip4()
5477         adresses = self.vapi.nat44_address_dump()
5478         self.assertEqual(0, len(adresses))
5479
5480     def test_tcp_close(self):
5481         """ Close TCP session from inside network - output feature """
5482         self.vapi.nat44_forwarding_enable_disable(1)
5483         self.nat44_add_address(self.pg1.local_ip4)
5484         twice_nat_addr = '10.0.1.3'
5485         service_ip = '192.168.16.150'
5486         self.nat44_add_address(twice_nat_addr, twice_nat=1)
5487         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5488         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5489                                                   is_inside=0)
5490         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5491                                                          is_inside=0)
5492         self.nat44_add_static_mapping(self.pg0.remote_ip4,
5493                                       service_ip,
5494                                       80,
5495                                       80,
5496                                       proto=IP_PROTOS.tcp,
5497                                       out2in_only=1,
5498                                       twice_nat=1)
5499         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5500         start_sessnum = len(sessions)
5501
5502         # SYN packet out->in
5503         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5504              IP(src=self.pg1.remote_ip4, dst=service_ip) /
5505              TCP(sport=33898, dport=80, flags="S"))
5506         self.pg1.add_stream(p)
5507         self.pg_enable_capture(self.pg_interfaces)
5508         self.pg_start()
5509         capture = self.pg0.get_capture(1)
5510         p = capture[0]
5511         tcp_port = p[TCP].sport
5512
5513         # SYN + ACK packet in->out
5514         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5515              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5516              TCP(sport=80, dport=tcp_port, flags="SA"))
5517         self.pg0.add_stream(p)
5518         self.pg_enable_capture(self.pg_interfaces)
5519         self.pg_start()
5520         self.pg1.get_capture(1)
5521
5522         # ACK packet out->in
5523         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5524              IP(src=self.pg1.remote_ip4, dst=service_ip) /
5525              TCP(sport=33898, dport=80, flags="A"))
5526         self.pg1.add_stream(p)
5527         self.pg_enable_capture(self.pg_interfaces)
5528         self.pg_start()
5529         self.pg0.get_capture(1)
5530
5531         # FIN packet in -> out
5532         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5533              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5534              TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5535         self.pg0.add_stream(p)
5536         self.pg_enable_capture(self.pg_interfaces)
5537         self.pg_start()
5538         self.pg1.get_capture(1)
5539
5540         # FIN+ACK packet out -> in
5541         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5542              IP(src=self.pg1.remote_ip4, dst=service_ip) /
5543              TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5544         self.pg1.add_stream(p)
5545         self.pg_enable_capture(self.pg_interfaces)
5546         self.pg_start()
5547         self.pg0.get_capture(1)
5548
5549         # ACK packet in -> out
5550         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5551              IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5552              TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5553         self.pg0.add_stream(p)
5554         self.pg_enable_capture(self.pg_interfaces)
5555         self.pg_start()
5556         self.pg1.get_capture(1)
5557
5558         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5559                                                      0)
5560         self.assertEqual(len(sessions) - start_sessnum, 0)
5561
5562     def test_tcp_session_close_in(self):
5563         """ Close TCP session from inside network """
5564         self.tcp_port_out = 10505
5565         self.nat44_add_address(self.nat_addr)
5566         self.nat44_add_static_mapping(self.pg0.remote_ip4,
5567                                       self.nat_addr,
5568                                       self.tcp_port_in,
5569                                       self.tcp_port_out,
5570                                       proto=IP_PROTOS.tcp,
5571                                       twice_nat=1)
5572         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5573         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5574                                                   is_inside=0)
5575
5576         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5577         start_sessnum = len(sessions)
5578
5579         self.initiate_tcp_session(self.pg0, self.pg1)
5580
5581         # FIN packet in -> out
5582         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5583              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5584              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5585                  flags="FA", seq=100, ack=300))
5586         self.pg0.add_stream(p)
5587         self.pg_enable_capture(self.pg_interfaces)
5588         self.pg_start()
5589         self.pg1.get_capture(1)
5590
5591         pkts = []
5592
5593         # ACK packet out -> in
5594         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5595              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5596              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5597                  flags="A", seq=300, ack=101))
5598         pkts.append(p)
5599
5600         # FIN packet out -> in
5601         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5602              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5603              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5604                  flags="FA", seq=300, ack=101))
5605         pkts.append(p)
5606
5607         self.pg1.add_stream(pkts)
5608         self.pg_enable_capture(self.pg_interfaces)
5609         self.pg_start()
5610         self.pg0.get_capture(2)
5611
5612         # ACK packet in -> out
5613         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5614              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5615              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5616                  flags="A", seq=101, ack=301))
5617         self.pg0.add_stream(p)
5618         self.pg_enable_capture(self.pg_interfaces)
5619         self.pg_start()
5620         self.pg1.get_capture(1)
5621
5622         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5623                                                      0)
5624         self.assertEqual(len(sessions) - start_sessnum, 0)
5625
5626     def test_tcp_session_close_out(self):
5627         """ Close TCP session from outside network """
5628         self.tcp_port_out = 10505
5629         self.nat44_add_address(self.nat_addr)
5630         self.nat44_add_static_mapping(self.pg0.remote_ip4,
5631                                       self.nat_addr,
5632                                       self.tcp_port_in,
5633                                       self.tcp_port_out,
5634                                       proto=IP_PROTOS.tcp,
5635                                       twice_nat=1)
5636         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5637         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5638                                                   is_inside=0)
5639
5640         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5641         start_sessnum = len(sessions)
5642
5643         self.initiate_tcp_session(self.pg0, self.pg1)
5644
5645         # FIN packet out -> in
5646         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5647              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5648              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5649                  flags="FA", seq=100, ack=300))
5650         self.pg1.add_stream(p)
5651         self.pg_enable_capture(self.pg_interfaces)
5652         self.pg_start()
5653         self.pg0.get_capture(1)
5654
5655         # FIN+ACK packet in -> out
5656         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5657              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5658              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5659                  flags="FA", seq=300, ack=101))
5660
5661         self.pg0.add_stream(p)
5662         self.pg_enable_capture(self.pg_interfaces)
5663         self.pg_start()
5664         self.pg1.get_capture(1)
5665
5666         # ACK packet out -> in
5667         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5668              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5669              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5670                  flags="A", seq=101, ack=301))
5671         self.pg1.add_stream(p)
5672         self.pg_enable_capture(self.pg_interfaces)
5673         self.pg_start()
5674         self.pg0.get_capture(1)
5675
5676         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5677                                                      0)
5678         self.assertEqual(len(sessions) - start_sessnum, 0)
5679
5680     def test_tcp_session_close_simultaneous(self):
5681         """ Close TCP session from inside network """
5682         self.tcp_port_out = 10505
5683         self.nat44_add_address(self.nat_addr)
5684         self.nat44_add_static_mapping(self.pg0.remote_ip4,
5685                                       self.nat_addr,
5686                                       self.tcp_port_in,
5687                                       self.tcp_port_out,
5688                                       proto=IP_PROTOS.tcp,
5689                                       twice_nat=1)
5690         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5691         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5692                                                   is_inside=0)
5693
5694         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5695         start_sessnum = len(sessions)
5696
5697         self.initiate_tcp_session(self.pg0, self.pg1)
5698
5699         # FIN packet in -> out
5700         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5701              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5702              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5703                  flags="FA", seq=100, ack=300))
5704         self.pg0.add_stream(p)
5705         self.pg_enable_capture(self.pg_interfaces)
5706         self.pg_start()
5707         self.pg1.get_capture(1)
5708
5709         # FIN packet out -> in
5710         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5711              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5712              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5713                  flags="FA", seq=300, ack=100))
5714         self.pg1.add_stream(p)
5715         self.pg_enable_capture(self.pg_interfaces)
5716         self.pg_start()
5717         self.pg0.get_capture(1)
5718
5719         # ACK packet in -> out
5720         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5721              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5722              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5723                  flags="A", seq=101, ack=301))
5724         self.pg0.add_stream(p)
5725         self.pg_enable_capture(self.pg_interfaces)
5726         self.pg_start()
5727         self.pg1.get_capture(1)
5728
5729         # ACK packet out -> in
5730         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5731              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5732              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5733                  flags="A", seq=301, ack=101))
5734         self.pg1.add_stream(p)
5735         self.pg_enable_capture(self.pg_interfaces)
5736         self.pg_start()
5737         self.pg0.get_capture(1)
5738
5739         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5740                                                      0)
5741         self.assertEqual(len(sessions) - start_sessnum, 0)
5742
5743     def test_one_armed_nat44_static(self):
5744         """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
5745         remote_host = self.pg4.remote_hosts[0]
5746         local_host = self.pg4.remote_hosts[1]
5747         external_port = 80
5748         local_port = 8080
5749         eh_port_in = 0
5750
5751         self.vapi.nat44_forwarding_enable_disable(1)
5752         self.nat44_add_address(self.nat_addr, twice_nat=1)
5753         self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
5754                                       local_port, external_port,
5755                                       proto=IP_PROTOS.tcp, out2in_only=1,
5756                                       twice_nat=1)
5757         self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
5758         self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
5759                                                   is_inside=0)
5760
5761         # from client to service
5762         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5763              IP(src=remote_host.ip4, dst=self.nat_addr) /
5764              TCP(sport=12345, dport=external_port))
5765         self.pg4.add_stream(p)
5766         self.pg_enable_capture(self.pg_interfaces)
5767         self.pg_start()
5768         capture = self.pg4.get_capture(1)
5769         p = capture[0]
5770         try:
5771             ip = p[IP]
5772             tcp = p[TCP]
5773             self.assertEqual(ip.dst, local_host.ip4)
5774             self.assertEqual(ip.src, self.nat_addr)
5775             self.assertEqual(tcp.dport, local_port)
5776             self.assertNotEqual(tcp.sport, 12345)
5777             eh_port_in = tcp.sport
5778             self.assert_packet_checksums_valid(p)
5779         except:
5780             self.logger.error(ppp("Unexpected or invalid packet:", p))
5781             raise
5782
5783         # from service back to client
5784         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5785              IP(src=local_host.ip4, dst=self.nat_addr) /
5786              TCP(sport=local_port, dport=eh_port_in))
5787         self.pg4.add_stream(p)
5788         self.pg_enable_capture(self.pg_interfaces)
5789         self.pg_start()
5790         capture = self.pg4.get_capture(1)
5791         p = capture[0]
5792         try:
5793             ip = p[IP]
5794             tcp = p[TCP]
5795             self.assertEqual(ip.src, self.nat_addr)
5796             self.assertEqual(ip.dst, remote_host.ip4)
5797             self.assertEqual(tcp.sport, external_port)
5798             self.assertEqual(tcp.dport, 12345)
5799             self.assert_packet_checksums_valid(p)
5800         except:
5801             self.logger.error(ppp("Unexpected or invalid packet:", p))
5802             raise
5803
5804     def test_static_with_port_out2(self):
5805         """ 1:1 NAPT asymmetrical rule """
5806
5807         external_port = 80
5808         local_port = 8080
5809
5810         self.vapi.nat44_forwarding_enable_disable(1)
5811         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
5812                                       local_port, external_port,
5813                                       proto=IP_PROTOS.tcp, out2in_only=1)
5814         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5815         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5816                                                   is_inside=0)
5817
5818         # from client to service
5819         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5820              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5821              TCP(sport=12345, dport=external_port))
5822         self.pg1.add_stream(p)
5823         self.pg_enable_capture(self.pg_interfaces)
5824         self.pg_start()
5825         capture = self.pg0.get_capture(1)
5826         p = capture[0]
5827         try:
5828             ip = p[IP]
5829             tcp = p[TCP]
5830             self.assertEqual(ip.dst, self.pg0.remote_ip4)
5831             self.assertEqual(tcp.dport, local_port)
5832             self.assert_packet_checksums_valid(p)
5833         except:
5834             self.logger.error(ppp("Unexpected or invalid packet:", p))
5835             raise
5836
5837         # ICMP error
5838         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5839              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5840              ICMP(type=11) / capture[0][IP])
5841         self.pg0.add_stream(p)
5842         self.pg_enable_capture(self.pg_interfaces)
5843         self.pg_start()
5844         capture = self.pg1.get_capture(1)
5845         p = capture[0]
5846         try:
5847             self.assertEqual(p[IP].src, self.nat_addr)
5848             inner = p[IPerror]
5849             self.assertEqual(inner.dst, self.nat_addr)
5850             self.assertEqual(inner[TCPerror].dport, external_port)
5851         except:
5852             self.logger.error(ppp("Unexpected or invalid packet:", p))
5853             raise
5854
5855         # from service back to client
5856         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5857              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5858              TCP(sport=local_port, dport=12345))
5859         self.pg0.add_stream(p)
5860         self.pg_enable_capture(self.pg_interfaces)
5861         self.pg_start()
5862         capture = self.pg1.get_capture(1)
5863         p = capture[0]
5864         try:
5865             ip = p[IP]
5866             tcp = p[TCP]
5867             self.assertEqual(ip.src, self.nat_addr)
5868             self.assertEqual(tcp.sport, external_port)
5869             self.assert_packet_checksums_valid(p)
5870         except:
5871             self.logger.error(ppp("Unexpected or invalid packet:", p))
5872             raise
5873
5874         # ICMP error
5875         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5876              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5877              ICMP(type=11) / capture[0][IP])
5878         self.pg1.add_stream(p)
5879         self.pg_enable_capture(self.pg_interfaces)
5880         self.pg_start()
5881         capture = self.pg0.get_capture(1)
5882         p = capture[0]
5883         try:
5884             self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
5885             inner = p[IPerror]
5886             self.assertEqual(inner.src, self.pg0.remote_ip4)
5887             self.assertEqual(inner[TCPerror].sport, local_port)
5888         except:
5889             self.logger.error(ppp("Unexpected or invalid packet:", p))
5890             raise
5891
5892         # from client to server (no translation)
5893         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5894              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5895              TCP(sport=12346, dport=local_port))
5896         self.pg1.add_stream(p)
5897         self.pg_enable_capture(self.pg_interfaces)
5898         self.pg_start()
5899         capture = self.pg0.get_capture(1)
5900         p = capture[0]
5901         try:
5902             ip = p[IP]
5903             tcp = p[TCP]
5904             self.assertEqual(ip.dst, self.pg0.remote_ip4)
5905             self.assertEqual(tcp.dport, local_port)
5906             self.assert_packet_checksums_valid(p)
5907         except:
5908             self.logger.error(ppp("Unexpected or invalid packet:", p))
5909             raise
5910
5911         # from service back to client (no translation)
5912         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5913              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5914              TCP(sport=local_port, dport=12346))
5915         self.pg0.add_stream(p)
5916         self.pg_enable_capture(self.pg_interfaces)
5917         self.pg_start()
5918         capture = self.pg1.get_capture(1)
5919         p = capture[0]
5920         try:
5921             ip = p[IP]
5922             tcp = p[TCP]
5923             self.assertEqual(ip.src, self.pg0.remote_ip4)
5924             self.assertEqual(tcp.sport, local_port)
5925             self.assert_packet_checksums_valid(p)
5926         except:
5927             self.logger.error(ppp("Unexpected or invalid packet:", p))
5928             raise
5929
5930     def test_output_feature(self):
5931         """ NAT44 interface output feature (in2out postrouting) """
5932         self.vapi.nat44_forwarding_enable_disable(1)
5933         self.nat44_add_address(self.nat_addr)
5934         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5935                                                   is_inside=0)
5936         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5937                                                          is_inside=0)
5938
5939         # in2out
5940         pkts = self.create_stream_in(self.pg0, self.pg1)
5941         self.pg0.add_stream(pkts)
5942         self.pg_enable_capture(self.pg_interfaces)
5943         self.pg_start()
5944         capture = self.pg1.get_capture(len(pkts))
5945         self.verify_capture_out(capture)
5946
5947         # out2in
5948         pkts = self.create_stream_out(self.pg1)
5949         self.pg1.add_stream(pkts)
5950         self.pg_enable_capture(self.pg_interfaces)
5951         self.pg_start()
5952         capture = self.pg0.get_capture(len(pkts))
5953         self.verify_capture_in(capture, self.pg0)
5954
5955     def test_multiple_vrf(self):
5956         """ Multiple VRF setup """
5957         external_addr = '1.2.3.4'
5958         external_port = 80
5959         local_port = 8080
5960         port = 0
5961
5962         self.vapi.nat44_forwarding_enable_disable(1)
5963         self.nat44_add_address(self.nat_addr)
5964         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5965         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5966                                                   is_inside=0)
5967         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5968                                                          is_inside=0)
5969         self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
5970         self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index,
5971                                                   is_inside=0)
5972         self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
5973                                                   is_inside=0)
5974         self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
5975                                       local_port, external_port, vrf_id=1,
5976                                       proto=IP_PROTOS.tcp, out2in_only=1)
5977         self.nat44_add_static_mapping(
5978             self.pg0.remote_ip4, external_sw_if_index=self.pg0.sw_if_index,
5979             local_port=local_port, vrf_id=0, external_port=external_port,
5980             proto=IP_PROTOS.tcp, out2in_only=1)
5981
5982         # from client to service (both VRF1)
5983         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5984              IP(src=self.pg6.remote_ip4, dst=external_addr) /
5985              TCP(sport=12345, dport=external_port))
5986         self.pg6.add_stream(p)
5987         self.pg_enable_capture(self.pg_interfaces)
5988         self.pg_start()
5989         capture = self.pg5.get_capture(1)
5990         p = capture[0]
5991         try:
5992             ip = p[IP]
5993             tcp = p[TCP]
5994             self.assertEqual(ip.dst, self.pg5.remote_ip4)
5995             self.assertEqual(tcp.dport, local_port)
5996             self.assert_packet_checksums_valid(p)
5997         except:
5998             self.logger.error(ppp("Unexpected or invalid packet:", p))
5999             raise
6000
6001         # from service back to client (both VRF1)
6002         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6003              IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6004              TCP(sport=local_port, dport=12345))
6005         self.pg5.add_stream(p)
6006         self.pg_enable_capture(self.pg_interfaces)
6007         self.pg_start()
6008         capture = self.pg6.get_capture(1)
6009         p = capture[0]
6010         try:
6011             ip = p[IP]
6012             tcp = p[TCP]
6013             self.assertEqual(ip.src, external_addr)
6014             self.assertEqual(tcp.sport, external_port)
6015             self.assert_packet_checksums_valid(p)
6016         except:
6017             self.logger.error(ppp("Unexpected or invalid packet:", p))
6018             raise
6019
6020         # dynamic NAT from VRF1 to VRF0 (output-feature)
6021         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6022              IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6023              TCP(sport=2345, dport=22))
6024         self.pg5.add_stream(p)
6025         self.pg_enable_capture(self.pg_interfaces)
6026         self.pg_start()
6027         capture = self.pg1.get_capture(1)
6028         p = capture[0]
6029         try:
6030             ip = p[IP]
6031             tcp = p[TCP]
6032             self.assertEqual(ip.src, self.nat_addr)
6033             self.assertNotEqual(tcp.sport, 2345)
6034             self.assert_packet_checksums_valid(p)
6035             port = tcp.sport
6036         except:
6037             self.logger.error(ppp("Unexpected or invalid packet:", p))
6038             raise
6039
6040         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6041              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6042              TCP(sport=22, dport=port))
6043         self.pg1.add_stream(p)
6044         self.pg_enable_capture(self.pg_interfaces)
6045         self.pg_start()
6046         capture = self.pg5.get_capture(1)
6047         p = capture[0]
6048         try:
6049             ip = p[IP]
6050             tcp = p[TCP]
6051             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6052             self.assertEqual(tcp.dport, 2345)
6053             self.assert_packet_checksums_valid(p)
6054         except:
6055             self.logger.error(ppp("Unexpected or invalid packet:", p))
6056             raise
6057
6058         # from client VRF1 to service VRF0
6059         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6060              IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6061              TCP(sport=12346, dport=external_port))
6062         self.pg6.add_stream(p)
6063         self.pg_enable_capture(self.pg_interfaces)
6064         self.pg_start()
6065         capture = self.pg0.get_capture(1)
6066         p = capture[0]
6067         try:
6068             ip = p[IP]
6069             tcp = p[TCP]
6070             self.assertEqual(ip.dst, self.pg0.remote_ip4)
6071             self.assertEqual(tcp.dport, local_port)
6072             self.assert_packet_checksums_valid(p)
6073         except:
6074             self.logger.error(ppp("Unexpected or invalid packet:", p))
6075             raise
6076
6077         # from service VRF0 back to client VRF1
6078         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6079              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6080              TCP(sport=local_port, dport=12346))
6081         self.pg0.add_stream(p)
6082         self.pg_enable_capture(self.pg_interfaces)
6083         self.pg_start()
6084         capture = self.pg6.get_capture(1)
6085         p = capture[0]
6086         try:
6087             ip = p[IP]
6088             tcp = p[TCP]
6089             self.assertEqual(ip.src, self.pg0.local_ip4)
6090             self.assertEqual(tcp.sport, external_port)
6091             self.assert_packet_checksums_valid(p)
6092         except:
6093             self.logger.error(ppp("Unexpected or invalid packet:", p))
6094             raise
6095
6096         # from client VRF0 to service VRF1
6097         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6098              IP(src=self.pg0.remote_ip4, dst=external_addr) /
6099              TCP(sport=12347, dport=external_port))
6100         self.pg0.add_stream(p)
6101         self.pg_enable_capture(self.pg_interfaces)
6102         self.pg_start()
6103         capture = self.pg5.get_capture(1)
6104         p = capture[0]
6105         try:
6106             ip = p[IP]
6107             tcp = p[TCP]
6108             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6109             self.assertEqual(tcp.dport, local_port)
6110             self.assert_packet_checksums_valid(p)
6111         except:
6112             self.logger.error(ppp("Unexpected or invalid packet:", p))
6113             raise
6114
6115         # from service VRF1 back to client VRF0
6116         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6117              IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6118              TCP(sport=local_port, dport=12347))
6119         self.pg5.add_stream(p)
6120         self.pg_enable_capture(self.pg_interfaces)
6121         self.pg_start()
6122         capture = self.pg0.get_capture(1)
6123         p = capture[0]
6124         try:
6125             ip = p[IP]
6126             tcp = p[TCP]
6127             self.assertEqual(ip.src, external_addr)
6128             self.assertEqual(tcp.sport, external_port)
6129             self.assert_packet_checksums_valid(p)
6130         except:
6131             self.logger.error(ppp("Unexpected or invalid packet:", p))
6132             raise
6133
6134         # from client to server (both VRF1, no translation)
6135         p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6136              IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6137              TCP(sport=12348, dport=local_port))
6138         self.pg6.add_stream(p)
6139         self.pg_enable_capture(self.pg_interfaces)
6140         self.pg_start()
6141         capture = self.pg5.get_capture(1)
6142         p = capture[0]
6143         try:
6144             ip = p[IP]
6145             tcp = p[TCP]
6146             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6147             self.assertEqual(tcp.dport, local_port)
6148             self.assert_packet_checksums_valid(p)
6149         except:
6150             self.logger.error(ppp("Unexpected or invalid packet:", p))
6151             raise
6152
6153         # from server back to client (both VRF1, no translation)
6154         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6155              IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6156              TCP(sport=local_port, dport=12348))
6157         self.pg5.add_stream(p)
6158         self.pg_enable_capture(self.pg_interfaces)
6159         self.pg_start()
6160         capture = self.pg6.get_capture(1)
6161         p = capture[0]
6162         try:
6163             ip = p[IP]
6164             tcp = p[TCP]
6165             self.assertEqual(ip.src, self.pg5.remote_ip4)
6166             self.assertEqual(tcp.sport, local_port)
6167             self.assert_packet_checksums_valid(p)
6168         except:
6169             self.logger.error(ppp("Unexpected or invalid packet:", p))
6170             raise
6171
6172         # from client VRF1 to server VRF0 (no translation)
6173         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6174              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6175              TCP(sport=local_port, dport=12349))
6176         self.pg0.add_stream(p)
6177         self.pg_enable_capture(self.pg_interfaces)
6178         self.pg_start()
6179         capture = self.pg6.get_capture(1)
6180         p = capture[0]
6181         try:
6182             ip = p[IP]
6183             tcp = p[TCP]
6184             self.assertEqual(ip.src, self.pg0.remote_ip4)
6185             self.assertEqual(tcp.sport, local_port)
6186             self.assert_packet_checksums_valid(p)
6187         except:
6188             self.logger.error(ppp("Unexpected or invalid packet:", p))
6189             raise
6190
6191         # from server VRF0 back to client VRF1 (no translation)
6192         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6193              IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6194              TCP(sport=local_port, dport=12349))
6195         self.pg0.add_stream(p)
6196         self.pg_enable_capture(self.pg_interfaces)
6197         self.pg_start()
6198         capture = self.pg6.get_capture(1)
6199         p = capture[0]
6200         try:
6201             ip = p[IP]
6202             tcp = p[TCP]
6203             self.assertEqual(ip.src, self.pg0.remote_ip4)
6204             self.assertEqual(tcp.sport, local_port)
6205             self.assert_packet_checksums_valid(p)
6206         except:
6207             self.logger.error(ppp("Unexpected or invalid packet:", p))
6208             raise
6209
6210         # from client VRF0 to server VRF1 (no translation)
6211         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6212              IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6213              TCP(sport=12344, dport=local_port))
6214         self.pg0.add_stream(p)
6215         self.pg_enable_capture(self.pg_interfaces)
6216         self.pg_start()
6217         capture = self.pg5.get_capture(1)
6218         p = capture[0]
6219         try:
6220             ip = p[IP]
6221             tcp = p[TCP]
6222             self.assertEqual(ip.dst, self.pg5.remote_ip4)
6223             self.assertEqual(tcp.dport, local_port)
6224             self.assert_packet_checksums_valid(p)
6225         except:
6226             self.logger.error(ppp("Unexpected or invalid packet:", p))
6227             raise
6228
6229         # from server VRF1 back to client VRF0 (no translation)
6230         p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6231              IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6232              TCP(sport=local_port, dport=12344))
6233         self.pg5.add_stream(p)
6234         self.pg_enable_capture(self.pg_interfaces)
6235         self.pg_start()
6236         capture = self.pg0.get_capture(1)
6237         p = capture[0]
6238         try:
6239             ip = p[IP]
6240             tcp = p[TCP]
6241             self.assertEqual(ip.src, self.pg5.remote_ip4)
6242             self.assertEqual(tcp.sport, local_port)
6243             self.assert_packet_checksums_valid(p)
6244         except:
6245             self.logger.error(ppp("Unexpected or invalid packet:", p))
6246             raise
6247
6248     @unittest.skipUnless(running_extended_tests, "part of extended tests")
6249     def test_session_timeout(self):
6250         """ NAT44 session timeouts """
6251         self.nat44_add_address(self.nat_addr)
6252         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6253         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6254                                                   is_inside=0)
6255         self.vapi.nat_set_timeouts(icmp=5)
6256
6257         max_sessions = 1000
6258         pkts = []
6259         for i in range(0, max_sessions):
6260             src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6261             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6262                  IP(src=src, dst=self.pg1.remote_ip4) /
6263                  ICMP(id=1025, type='echo-request'))
6264             pkts.append(p)
6265         self.pg0.add_stream(pkts)
6266         self.pg_enable_capture(self.pg_interfaces)
6267         self.pg_start()
6268         self.pg1.get_capture(max_sessions)
6269
6270         sleep(10)
6271
6272         pkts = []
6273         for i in range(0, max_sessions):
6274             src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6275             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6276                  IP(src=src, dst=self.pg1.remote_ip4) /
6277                  ICMP(id=1026, type='echo-request'))
6278             pkts.append(p)
6279         self.pg0.add_stream(pkts)
6280         self.pg_enable_capture(self.pg_interfaces)
6281         self.pg_start()
6282         self.pg1.get_capture(max_sessions)
6283
6284         nsessions = 0
6285         users = self.vapi.nat44_user_dump()
6286         for user in users:
6287             nsessions = nsessions + user.nsessions
6288         self.assertLess(nsessions, 2 * max_sessions)
6289
6290     @unittest.skipUnless(running_extended_tests, "part of extended tests")
6291     def test_session_rst_timeout(self):
6292         """ NAT44 session RST timeouts """
6293         self.nat44_add_address(self.nat_addr)
6294         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6295         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6296                                                   is_inside=0)
6297         self.vapi.nat_set_timeouts(tcp_transitory=5)
6298
6299         self.initiate_tcp_session(self.pg0, self.pg1)
6300         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6301              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6302              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6303                  flags="R"))
6304         self.pg0.add_stream(p)
6305         self.pg_enable_capture(self.pg_interfaces)
6306         self.pg_start()
6307         self.pg1.get_capture(1)
6308
6309         sleep(6)
6310
6311         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6312              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6313              TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6314                  flags="S"))
6315         self.pg0.add_stream(p)
6316         self.pg_enable_capture(self.pg_interfaces)
6317         self.pg_start()
6318         self.pg1.get_capture(1)
6319
6320         nsessions = 0
6321         users = self.vapi.nat44_user_dump()
6322         self.assertEqual(len(users), 1)
6323         self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
6324         self.assertEqual(users[0].nsessions, 1)
6325
6326     @unittest.skipUnless(running_extended_tests, "part of extended tests")
6327     def test_session_limit_per_user(self):
6328         """ Maximum sessions per user limit """
6329         self.nat44_add_address(self.nat_addr)
6330         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6331         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6332                                                   is_inside=0)
6333         self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
6334                                      src_address=self.pg2.local_ip4n,
6335                                      path_mtu=512,
6336                                      template_interval=10)
6337         self.vapi.nat_set_timeouts(udp=5)
6338
6339         # get maximum number of translations per user
6340         nat44_config = self.vapi.nat_show_config()
6341
6342         pkts = []
6343         for port in range(0, nat44_config.max_translations_per_user):
6344             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6345                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6346                  UDP(sport=1025 + port, dport=1025 + port))
6347             pkts.append(p)
6348
6349         self.pg0.add_stream(pkts)
6350         self.pg_enable_capture(self.pg_interfaces)
6351         self.pg_start()
6352         capture = self.pg1.get_capture(len(pkts))
6353
6354         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
6355                                            src_port=self.ipfix_src_port)
6356
6357         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6358              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6359              UDP(sport=3001, dport=3002))
6360         self.pg0.add_stream(p)
6361         self.pg_enable_capture(self.pg_interfaces)
6362         self.pg_start()
6363         capture = self.pg1.assert_nothing_captured()
6364
6365         # verify IPFIX logging
6366         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
6367         sleep(1)
6368         capture = self.pg2.get_capture(10)
6369         ipfix = IPFIXDecoder()
6370         # first load template
6371         for p in capture:
6372             self.assertTrue(p.haslayer(IPFIX))
6373             if p.haslayer(Template):
6374                 ipfix.add_template(p.getlayer(Template))
6375         # verify events in data set
6376         for p in capture:
6377             if p.haslayer(Data):
6378                 data = ipfix.decode_data_set(p.getlayer(Set))
6379                 self.verify_ipfix_max_entries_per_user(
6380                     data,
6381                     nat44_config.max_translations_per_user,
6382                     self.pg0.remote_ip4n)
6383
6384         sleep(6)
6385         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6386              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6387              UDP(sport=3001, dport=3002))
6388         self.pg0.add_stream(p)
6389         self.pg_enable_capture(self.pg_interfaces)
6390         self.pg_start()
6391         self.pg1.get_capture(1)
6392
6393     def test_syslog_sess(self):
6394         """ Test syslog session creation and deletion """
6395         self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
6396         self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
6397         self.nat44_add_address(self.nat_addr)
6398         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6399         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6400                                                   is_inside=0)
6401
6402         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6403              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6404              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6405         self.pg0.add_stream(p)
6406         self.pg_enable_capture(self.pg_interfaces)
6407         self.pg_start()
6408         capture = self.pg1.get_capture(1)
6409         self.tcp_port_out = capture[0][TCP].sport
6410         capture = self.pg2.get_capture(1)
6411         self.verify_syslog_sess(capture[0][Raw].load)
6412
6413         self.pg_enable_capture(self.pg_interfaces)
6414         self.pg_start()
6415         self.nat44_add_address(self.nat_addr, is_add=0)
6416         capture = self.pg2.get_capture(1)
6417         self.verify_syslog_sess(capture[0][Raw].load, False)
6418
6419     def tearDown(self):
6420         super(TestNAT44EndpointDependent, self).tearDown()
6421         if not self.vpp_dead:
6422             self.logger.info(self.vapi.cli("show nat44 addresses"))
6423             self.logger.info(self.vapi.cli("show nat44 interfaces"))
6424             self.logger.info(self.vapi.cli("show nat44 static mappings"))
6425             self.logger.info(self.vapi.cli("show nat44 interface address"))
6426             self.logger.info(self.vapi.cli("show nat44 sessions detail"))
6427             self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
6428             self.logger.info(self.vapi.cli("show nat timeouts"))
6429             self.clear_nat44()
6430             self.vapi.cli("clear logging")
6431
6432
6433 class TestNAT44Out2InDPO(MethodHolder):
6434     """ NAT44 Test Cases using out2in DPO """
6435
6436     @classmethod
6437     def setUpConstants(cls):
6438         super(TestNAT44Out2InDPO, cls).setUpConstants()
6439         cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
6440
6441     @classmethod
6442     def setUpClass(cls):
6443         super(TestNAT44Out2InDPO, cls).setUpClass()
6444         cls.vapi.cli("set log class nat level debug")
6445
6446         try:
6447             cls.tcp_port_in = 6303
6448             cls.tcp_port_out = 6303
6449             cls.udp_port_in = 6304
6450             cls.udp_port_out = 6304
6451             cls.icmp_id_in = 6305
6452             cls.icmp_id_out = 6305
6453             cls.nat_addr = '10.0.0.3'
6454             cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
6455             cls.dst_ip4 = '192.168.70.1'
6456
6457             cls.create_pg_interfaces(range(2))
6458
6459             cls.pg0.admin_up()
6460             cls.pg0.config_ip4()
6461             cls.pg0.resolve_arp()
6462
6463             cls.pg1.admin_up()
6464             cls.pg1.config_ip6()
6465             cls.pg1.resolve_ndp()
6466
6467             cls.vapi.ip_add_del_route(dst_address=b'\x00' * 16,
6468                                       dst_address_length=0,
6469                                       next_hop_address=cls.pg1.remote_ip6n,
6470                                       next_hop_sw_if_index=cls.pg1.sw_if_index,
6471                                       is_ipv6=True)
6472
6473         except Exception:
6474             super(TestNAT44Out2InDPO, cls).tearDownClass()
6475             raise
6476
6477     @classmethod
6478     def tearDownClass(cls):
6479         super(TestNAT44Out2InDPO, cls).tearDownClass()
6480
6481     def configure_xlat(self):
6482         self.dst_ip6_pfx = '1:2:3::'
6483         self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6484                                               self.dst_ip6_pfx)
6485         self.dst_ip6_pfx_len = 96
6486         self.src_ip6_pfx = '4:5:6::'
6487         self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6488                                               self.src_ip6_pfx)
6489         self.src_ip6_pfx_len = 96
6490         self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
6491                                  self.src_ip6_pfx_n, self.src_ip6_pfx_len,
6492                                  '\x00\x00\x00\x00', 0)
6493
6494     @unittest.skip('Temporary disabled')
6495     def test_464xlat_ce(self):
6496         """ Test 464XLAT CE with NAT44 """
6497
6498         nat_config = self.vapi.nat_show_config()
6499         self.assertEqual(1, nat_config.out2in_dpo)
6500
6501         self.configure_xlat()
6502
6503         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6504         self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
6505
6506         out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6507                                        self.dst_ip6_pfx_len)
6508         out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
6509                                        self.src_ip6_pfx_len)
6510
6511         try:
6512             pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6513             self.pg0.add_stream(pkts)
6514             self.pg_enable_capture(self.pg_interfaces)
6515             self.pg_start()
6516             capture = self.pg1.get_capture(len(pkts))
6517             self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
6518                                         dst_ip=out_src_ip6)
6519
6520             pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
6521                                               out_dst_ip6)
6522             self.pg1.add_stream(pkts)
6523             self.pg_enable_capture(self.pg_interfaces)
6524             self.pg_start()
6525             capture = self.pg0.get_capture(len(pkts))
6526             self.verify_capture_in(capture, self.pg0)
6527         finally:
6528             self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6529                                                       is_add=0)
6530             self.vapi.nat44_add_del_address_range(self.nat_addr_n,
6531                                                   self.nat_addr_n, is_add=0)
6532
6533     @unittest.skip('Temporary disabled')
6534     def test_464xlat_ce_no_nat(self):
6535         """ Test 464XLAT CE without NAT44 """
6536
6537         self.configure_xlat()
6538
6539         out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6540                                        self.dst_ip6_pfx_len)
6541         out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
6542                                        self.src_ip6_pfx_len)
6543
6544         pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6545         self.pg0.add_stream(pkts)
6546         self.pg_enable_capture(self.pg_interfaces)
6547         self.pg_start()
6548         capture = self.pg1.get_capture(len(pkts))
6549         self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
6550                                     nat_ip=out_dst_ip6, same_port=True)
6551
6552         pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
6553         self.pg1.add_stream(pkts)
6554         self.pg_enable_capture(self.pg_interfaces)
6555         self.pg_start()
6556         capture = self.pg0.get_capture(len(pkts))
6557         self.verify_capture_in(capture, self.pg0)
6558
6559
6560 class TestDeterministicNAT(MethodHolder):
6561     """ Deterministic NAT Test Cases """
6562
6563     @classmethod
6564     def setUpConstants(cls):
6565         super(TestDeterministicNAT, cls).setUpConstants()
6566         cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
6567
6568     @classmethod
6569     def setUpClass(cls):
6570         super(TestDeterministicNAT, cls).setUpClass()
6571         cls.vapi.cli("set log class nat level debug")
6572
6573         try:
6574             cls.tcp_port_in = 6303
6575             cls.tcp_external_port = 6303
6576             cls.udp_port_in = 6304
6577             cls.udp_external_port = 6304
6578             cls.icmp_id_in = 6305
6579             cls.nat_addr = '10.0.0.3'
6580
6581             cls.create_pg_interfaces(range(3))
6582             cls.interfaces = list(cls.pg_interfaces)
6583
6584             for i in cls.interfaces:
6585                 i.admin_up()
6586                 i.config_ip4()
6587                 i.resolve_arp()
6588
6589             cls.pg0.generate_remote_hosts(2)
6590             cls.pg0.configure_ipv4_neighbors()
6591
6592         except Exception:
6593             super(TestDeterministicNAT, cls).tearDownClass()
6594             raise
6595
6596     @classmethod
6597     def tearDownClass(cls):
6598         super(TestDeterministicNAT, cls).tearDownClass()
6599
6600     def create_stream_in(self, in_if, out_if, ttl=64):
6601         """
6602         Create packet stream for inside network
6603
6604         :param in_if: Inside interface
6605         :param out_if: Outside interface
6606         :param ttl: TTL of generated packets
6607         """
6608         pkts = []
6609         # TCP
6610         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6611              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
6612              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6613         pkts.append(p)
6614
6615         # UDP
6616         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6617              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
6618              UDP(sport=self.udp_port_in, dport=self.udp_external_port))
6619         pkts.append(p)
6620
6621         # ICMP
6622         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6623              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
6624              ICMP(id=self.icmp_id_in, type='echo-request'))
6625         pkts.append(p)
6626
6627         return pkts
6628
6629     def create_stream_out(self, out_if, dst_ip=None, ttl=64):
6630         """
6631         Create packet stream for outside network
6632
6633         :param out_if: Outside interface
6634         :param dst_ip: Destination IP address (Default use global NAT address)
6635         :param ttl: TTL of generated packets
6636         """
6637         if dst_ip is None:
6638             dst_ip = self.nat_addr
6639         pkts = []
6640         # TCP
6641         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6642              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
6643              TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
6644         pkts.append(p)
6645
6646         # UDP
6647         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6648              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
6649              UDP(dport=self.udp_port_out, sport=self.udp_external_port))
6650         pkts.append(p)
6651
6652         # ICMP
6653         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6654              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
6655              ICMP(id=self.icmp_external_id, type='echo-reply'))
6656         pkts.append(p)
6657
6658         return pkts
6659
6660     def verify_capture_out(self, capture, nat_ip=None):
6661         """
6662         Verify captured packets on outside network
6663
6664         :param capture: Captured packets
6665         :param nat_ip: Translated IP address (Default use global NAT address)
6666         :param same_port: Source port number is not translated (Default False)
6667         """
6668         if nat_ip is None:
6669             nat_ip = self.nat_addr
6670         for packet in capture:
6671             try:
6672                 self.assertEqual(packet[IP].src, nat_ip)
6673                 if packet.haslayer(TCP):
6674                     self.tcp_port_out = packet[TCP].sport
6675                 elif packet.haslayer(UDP):
6676                     self.udp_port_out = packet[UDP].sport
6677                 else:
6678                     self.icmp_external_id = packet[ICMP].id
6679             except:
6680                 self.logger.error(ppp("Unexpected or invalid packet "
6681                                       "(outside network):", packet))
6682                 raise
6683
6684     def test_deterministic_mode(self):
6685         """ NAT plugin run deterministic mode """
6686         in_addr = '172.16.255.0'
6687         out_addr = '172.17.255.50'
6688         in_addr_t = '172.16.255.20'
6689         in_addr_n = socket.inet_aton(in_addr)
6690         out_addr_n = socket.inet_aton(out_addr)
6691         in_addr_t_n = socket.inet_aton(in_addr_t)
6692         in_plen = 24
6693         out_plen = 32
6694
6695         nat_config = self.vapi.nat_show_config()
6696         self.assertEqual(1, nat_config.deterministic)
6697
6698         self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
6699
6700         rep1 = self.vapi.nat_det_forward(in_addr_t_n)
6701         self.assertEqual(rep1.out_addr[:4], out_addr_n)
6702         rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
6703         self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
6704
6705         deterministic_mappings = self.vapi.nat_det_map_dump()
6706         self.assertEqual(len(deterministic_mappings), 1)
6707         dsm = deterministic_mappings[0]
6708         self.assertEqual(in_addr_n, dsm.in_addr[:4])
6709         self.assertEqual(in_plen, dsm.in_plen)
6710         self.assertEqual(out_addr_n, dsm.out_addr[:4])
6711         self.assertEqual(out_plen, dsm.out_plen)
6712
6713         self.clear_nat_det()
6714         deterministic_mappings = self.vapi.nat_det_map_dump()
6715         self.assertEqual(len(deterministic_mappings), 0)
6716
6717     def test_set_timeouts(self):
6718         """ Set deterministic NAT timeouts """
6719         timeouts_before = self.vapi.nat_get_timeouts()
6720
6721         self.vapi.nat_set_timeouts(timeouts_before.udp + 10,
6722                                    timeouts_before.tcp_established + 10,
6723                                    timeouts_before.tcp_transitory + 10,
6724                                    timeouts_before.icmp + 10)
6725
6726         timeouts_after = self.vapi.nat_get_timeouts()
6727
6728         self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
6729         self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
6730         self.assertNotEqual(timeouts_before.tcp_established,
6731                             timeouts_after.tcp_established)
6732         self.assertNotEqual(timeouts_before.tcp_transitory,
6733                             timeouts_after.tcp_transitory)
6734
6735     def test_det_in(self):
6736         """ Deterministic NAT translation test (TCP, UDP, ICMP) """
6737
6738         nat_ip = "10.0.0.10"
6739
6740         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6741                                       32,
6742                                       socket.inet_aton(nat_ip),
6743                                       32)
6744         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6745         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6746                                                   is_inside=0)
6747
6748         # in2out
6749         pkts = self.create_stream_in(self.pg0, self.pg1)
6750         self.pg0.add_stream(pkts)
6751         self.pg_enable_capture(self.pg_interfaces)
6752         self.pg_start()
6753         capture = self.pg1.get_capture(len(pkts))
6754         self.verify_capture_out(capture, nat_ip)
6755
6756         # out2in
6757         pkts = self.create_stream_out(self.pg1, nat_ip)
6758         self.pg1.add_stream(pkts)
6759         self.pg_enable_capture(self.pg_interfaces)
6760         self.pg_start()
6761         capture = self.pg0.get_capture(len(pkts))
6762         self.verify_capture_in(capture, self.pg0)
6763
6764         # session dump test
6765         sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
6766         self.assertEqual(len(sessions), 3)
6767
6768         # TCP session
6769         s = sessions[0]
6770         self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6771         self.assertEqual(s.in_port, self.tcp_port_in)
6772         self.assertEqual(s.out_port, self.tcp_port_out)
6773         self.assertEqual(s.ext_port, self.tcp_external_port)
6774
6775         # UDP session
6776         s = sessions[1]
6777         self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6778         self.assertEqual(s.in_port, self.udp_port_in)
6779         self.assertEqual(s.out_port, self.udp_port_out)
6780         self.assertEqual(s.ext_port, self.udp_external_port)
6781
6782         # ICMP session
6783         s = sessions[2]
6784         self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6785         self.assertEqual(s.in_port, self.icmp_id_in)
6786         self.assertEqual(s.out_port, self.icmp_external_id)
6787
6788     def test_multiple_users(self):
6789         """ Deterministic NAT multiple users """
6790
6791         nat_ip = "10.0.0.10"
6792         port_in = 80
6793         external_port = 6303
6794
6795         host0 = self.pg0.remote_hosts[0]
6796         host1 = self.pg0.remote_hosts[1]
6797
6798         self.vapi.nat_det_add_del_map(host0.ip4n,
6799                                       24,
6800                                       socket.inet_aton(nat_ip),
6801                                       32)
6802         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6803         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6804                                                   is_inside=0)
6805
6806         # host0 to out
6807         p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
6808              IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
6809              TCP(sport=port_in, dport=external_port))
6810         self.pg0.add_stream(p)
6811         self.pg_enable_capture(self.pg_interfaces)
6812         self.pg_start()
6813         capture = self.pg1.get_capture(1)
6814         p = capture[0]
6815         try:
6816             ip = p[IP]
6817             tcp = p[TCP]
6818             self.assertEqual(ip.src, nat_ip)
6819             self.assertEqual(ip.dst, self.pg1.remote_ip4)
6820             self.assertEqual(tcp.dport, external_port)
6821             port_out0 = tcp.sport
6822         except:
6823             self.logger.error(ppp("Unexpected or invalid packet:", p))
6824             raise
6825
6826         # host1 to out
6827         p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
6828              IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
6829              TCP(sport=port_in, dport=external_port))
6830         self.pg0.add_stream(p)
6831         self.pg_enable_capture(self.pg_interfaces)
6832         self.pg_start()
6833         capture = self.pg1.get_capture(1)
6834         p = capture[0]
6835         try:
6836             ip = p[IP]
6837             tcp = p[TCP]
6838             self.assertEqual(ip.src, nat_ip)
6839             self.assertEqual(ip.dst, self.pg1.remote_ip4)
6840             self.assertEqual(tcp.dport, external_port)
6841             port_out1 = tcp.sport
6842         except:
6843             self.logger.error(ppp("Unexpected or invalid packet:", p))
6844             raise
6845
6846         dms = self.vapi.nat_det_map_dump()
6847         self.assertEqual(1, len(dms))
6848         self.assertEqual(2, dms[0].ses_num)
6849
6850         # out to host0
6851         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6852              IP(src=self.pg1.remote_ip4, dst=nat_ip) /
6853              TCP(sport=external_port, dport=port_out0))
6854         self.pg1.add_stream(p)
6855         self.pg_enable_capture(self.pg_interfaces)
6856         self.pg_start()
6857         capture = self.pg0.get_capture(1)
6858         p = capture[0]
6859         try:
6860             ip = p[IP]
6861             tcp = p[TCP]
6862             self.assertEqual(ip.src, self.pg1.remote_ip4)
6863             self.assertEqual(ip.dst, host0.ip4)
6864             self.assertEqual(tcp.dport, port_in)
6865             self.assertEqual(tcp.sport, external_port)
6866         except:
6867             self.logger.error(ppp("Unexpected or invalid packet:", p))
6868             raise
6869
6870         # out to host1
6871         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6872              IP(src=self.pg1.remote_ip4, dst=nat_ip) /
6873              TCP(sport=external_port, dport=port_out1))
6874         self.pg1.add_stream(p)
6875         self.pg_enable_capture(self.pg_interfaces)
6876         self.pg_start()
6877         capture = self.pg0.get_capture(1)
6878         p = capture[0]
6879         try:
6880             ip = p[IP]
6881             tcp = p[TCP]
6882             self.assertEqual(ip.src, self.pg1.remote_ip4)
6883             self.assertEqual(ip.dst, host1.ip4)
6884             self.assertEqual(tcp.dport, port_in)
6885             self.assertEqual(tcp.sport, external_port)
6886         except:
6887             self.logger.error(ppp("Unexpected or invalid packet", p))
6888             raise
6889
6890         # session close api test
6891         self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
6892                                             port_out1,
6893                                             self.pg1.remote_ip4n,
6894                                             external_port)
6895         dms = self.vapi.nat_det_map_dump()
6896         self.assertEqual(dms[0].ses_num, 1)
6897
6898         self.vapi.nat_det_close_session_in(host0.ip4n,
6899                                            port_in,
6900                                            self.pg1.remote_ip4n,
6901                                            external_port)
6902         dms = self.vapi.nat_det_map_dump()
6903         self.assertEqual(dms[0].ses_num, 0)
6904
6905     def test_tcp_session_close_detection_in(self):
6906         """ Deterministic NAT TCP session close from inside network """
6907         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6908                                       32,
6909                                       socket.inet_aton(self.nat_addr),
6910                                       32)
6911         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6912         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6913                                                   is_inside=0)
6914
6915         self.initiate_tcp_session(self.pg0, self.pg1)
6916
6917         # close the session from inside
6918         try:
6919             # FIN packet in -> out
6920             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6921                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6922                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6923                      flags="F"))
6924             self.pg0.add_stream(p)
6925             self.pg_enable_capture(self.pg_interfaces)
6926             self.pg_start()
6927             self.pg1.get_capture(1)
6928
6929             pkts = []
6930
6931             # ACK packet out -> in
6932             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6933                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6934                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6935                      flags="A"))
6936             pkts.append(p)
6937
6938             # FIN packet out -> in
6939             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6940                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6941                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6942                      flags="F"))
6943             pkts.append(p)
6944
6945             self.pg1.add_stream(pkts)
6946             self.pg_enable_capture(self.pg_interfaces)
6947             self.pg_start()
6948             self.pg0.get_capture(2)
6949
6950             # ACK packet in -> out
6951             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6952                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6953                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6954                      flags="A"))
6955             self.pg0.add_stream(p)
6956             self.pg_enable_capture(self.pg_interfaces)
6957             self.pg_start()
6958             self.pg1.get_capture(1)
6959
6960             # Check if deterministic NAT44 closed the session
6961             dms = self.vapi.nat_det_map_dump()
6962             self.assertEqual(0, dms[0].ses_num)
6963         except:
6964             self.logger.error("TCP session termination failed")
6965             raise
6966
6967     def test_tcp_session_close_detection_out(self):
6968         """ Deterministic NAT TCP session close from outside network """
6969         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6970                                       32,
6971                                       socket.inet_aton(self.nat_addr),
6972                                       32)
6973         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6974         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6975                                                   is_inside=0)
6976
6977         self.initiate_tcp_session(self.pg0, self.pg1)
6978
6979         # close the session from outside
6980         try:
6981             # FIN packet out -> in
6982             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6983                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6984                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6985                      flags="F"))
6986             self.pg1.add_stream(p)
6987             self.pg_enable_capture(self.pg_interfaces)
6988             self.pg_start()
6989             self.pg0.get_capture(1)
6990
6991             pkts = []
6992
6993             # ACK packet in -> out
6994             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6995                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6996                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6997                      flags="A"))
6998             pkts.append(p)
6999
7000             # ACK packet in -> out
7001             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7002                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7003                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7004                      flags="F"))
7005             pkts.append(p)
7006
7007             self.pg0.add_stream(pkts)
7008             self.pg_enable_capture(self.pg_interfaces)
7009             self.pg_start()
7010             self.pg1.get_capture(2)
7011
7012             # ACK packet out -> in
7013             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7014                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7015                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7016                      flags="A"))
7017             self.pg1.add_stream(p)
7018             self.pg_enable_capture(self.pg_interfaces)
7019             self.pg_start()
7020             self.pg0.get_capture(1)
7021
7022             # Check if deterministic NAT44 closed the session
7023             dms = self.vapi.nat_det_map_dump()
7024             self.assertEqual(0, dms[0].ses_num)
7025         except:
7026             self.logger.error("TCP session termination failed")
7027             raise
7028
7029     @unittest.skipUnless(running_extended_tests, "part of extended tests")
7030     def test_session_timeout(self):
7031         """ Deterministic NAT session timeouts """
7032         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
7033                                       32,
7034                                       socket.inet_aton(self.nat_addr),
7035                                       32)
7036         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
7037         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
7038                                                   is_inside=0)
7039
7040         self.initiate_tcp_session(self.pg0, self.pg1)
7041         self.vapi.nat_set_timeouts(5, 5, 5, 5)
7042         pkts = self.create_stream_in(self.pg0, self.pg1)
7043         self.pg0.add_stream(pkts)
7044         self.pg_enable_capture(self.pg_interfaces)
7045         self.pg_start()
7046         capture = self.pg1.get_capture(len(pkts))
7047         sleep(15)
7048
7049         dms = self.vapi.nat_det_map_dump()
7050         self.assertEqual(0, dms[0].ses_num)
7051
7052     @unittest.skipUnless(running_extended_tests, "part of extended tests")
7053     def test_session_limit_per_user(self):
7054         """ Deterministic NAT maximum sessions per user limit """
7055         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
7056                                       32,
7057                                       socket.inet_aton(self.nat_addr),
7058                                       32)
7059         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
7060         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
7061                                                   is_inside=0)
7062         self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
7063                                      src_address=self.pg2.local_ip4n,
7064                                      path_mtu=512,
7065                                      template_interval=10)
7066         self.vapi.nat_ipfix_enable_disable()
7067
7068         pkts = []
7069         for port in range(1025, 2025):
7070             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7071                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7072                  UDP(sport=port, dport=port))
7073             pkts.append(p)
7074
7075         self.pg0.add_stream(pkts)
7076         self.pg_enable_capture(self.pg_interfaces)
7077         self.pg_start()
7078         capture = self.pg1.get_capture(len(pkts))
7079
7080         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7081              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7082              UDP(sport=3001, dport=3002))
7083         self.pg0.add_stream(p)
7084         self.pg_enable_capture(self.pg_interfaces)
7085         self.pg_start()
7086         capture = self.pg1.assert_nothing_captured()
7087
7088         # verify ICMP error packet
7089         capture = self.pg0.get_capture(1)
7090         p = capture[0]
7091         self.assertTrue(p.haslayer(ICMP))
7092         icmp = p[ICMP]
7093         self.assertEqual(icmp.type, 3)
7094         self.assertEqual(icmp.code, 1)
7095         self.assertTrue(icmp.haslayer(IPerror))
7096         inner_ip = icmp[IPerror]
7097         self.assertEqual(inner_ip[UDPerror].sport, 3001)
7098         self.assertEqual(inner_ip[UDPerror].dport, 3002)
7099
7100         dms = self.vapi.nat_det_map_dump()
7101
7102         self.assertEqual(1000, dms[0].ses_num)
7103
7104         # verify IPFIX logging
7105         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
7106         sleep(1)
7107         capture = self.pg2.get_capture(2)
7108         ipfix = IPFIXDecoder()
7109         # first load template
7110         for p in capture:
7111             self.assertTrue(p.haslayer(IPFIX))
7112             if p.haslayer(Template):
7113                 ipfix.add_template(p.getlayer(Template))
7114         # verify events in data set
7115         for p in capture:
7116             if p.haslayer(Data):
7117                 data = ipfix.decode_data_set(p.getlayer(Set))
7118                 self.verify_ipfix_max_entries_per_user(data,
7119                                                        1000,
7120                                                        self.pg0.remote_ip4n)
7121
7122     def clear_nat_det(self):
7123         """
7124         Clear deterministic NAT configuration.
7125         """
7126         self.vapi.nat_ipfix_enable_disable(enable=0)
7127         self.vapi.nat_set_timeouts()
7128         deterministic_mappings = self.vapi.nat_det_map_dump()
7129         for dsm in deterministic_mappings:
7130             self.vapi.nat_det_add_del_map(dsm.in_addr,
7131                                           dsm.in_plen,
7132                                           dsm.out_addr,
7133                                           dsm.out_plen,
7134                                           is_add=0)
7135
7136         interfaces = self.vapi.nat44_interface_dump()
7137         for intf in interfaces:
7138             self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
7139                                                       intf.is_inside,
7140                                                       is_add=0)
7141
7142     def tearDown(self):
7143         super(TestDeterministicNAT, self).tearDown()
7144         if not self.vpp_dead:
7145             self.logger.info(self.vapi.cli("show nat44 interfaces"))
7146             self.logger.info(self.vapi.cli("show nat timeouts"))
7147             self.logger.info(
7148                 self.vapi.cli("show nat44 deterministic mappings"))
7149             self.logger.info(
7150                 self.vapi.cli("show nat44 deterministic sessions"))
7151             self.clear_nat_det()
7152
7153
7154 class TestNAT64(MethodHolder):
7155     """ NAT64 Test Cases """
7156
7157     @classmethod
7158     def setUpConstants(cls):
7159         super(TestNAT64, cls).setUpConstants()
7160         cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
7161                                 "nat64 st hash buckets 256", "}"])
7162
7163     @classmethod
7164     def setUpClass(cls):
7165         super(TestNAT64, cls).setUpClass()
7166
7167         try:
7168             cls.tcp_port_in = 6303
7169             cls.tcp_port_out = 6303
7170             cls.udp_port_in = 6304
7171             cls.udp_port_out = 6304
7172             cls.icmp_id_in = 6305
7173             cls.icmp_id_out = 6305
7174             cls.tcp_external_port = 80
7175             cls.nat_addr = '10.0.0.3'
7176             cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
7177             cls.vrf1_id = 10
7178             cls.vrf1_nat_addr = '10.0.10.3'
7179             cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
7180                                                    cls.vrf1_nat_addr)
7181             cls.ipfix_src_port = 4739
7182             cls.ipfix_domain_id = 1
7183
7184             cls.create_pg_interfaces(range(6))
7185             cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
7186             cls.ip6_interfaces.append(cls.pg_interfaces[2])
7187             cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
7188
7189             cls.vapi.ip_table_add_del(is_ipv6=1, is_add=1,
7190                                       table_id=cls.vrf1_id)
7191
7192             cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
7193
7194             cls.pg0.generate_remote_hosts(2)
7195
7196             for i in cls.ip6_interfaces:
7197                 i.admin_up()
7198                 i.config_ip6()
7199                 i.configure_ipv6_neighbors()
7200
7201             for i in cls.ip4_interfaces:
7202                 i.admin_up()
7203                 i.config_ip4()
7204                 i.resolve_arp()
7205
7206             cls.pg3.admin_up()
7207             cls.pg3.config_ip4()
7208             cls.pg3.resolve_arp()
7209             cls.pg3.config_ip6()
7210             cls.pg3.configure_ipv6_neighbors()
7211
7212             cls.pg5.admin_up()
7213             cls.pg5.config_ip6()
7214
7215         except Exception:
7216             super(TestNAT64, cls).tearDownClass()
7217             raise
7218
7219     @classmethod
7220     def tearDownClass(cls):
7221         super(TestNAT64, cls).tearDownClass()
7222
7223     def test_nat64_inside_interface_handles_neighbor_advertisement(self):
7224         """ NAT64 inside interface handles Neighbor Advertisement """
7225
7226         self.vapi.nat64_add_del_interface(self.pg5.sw_if_index)
7227
7228         # Try to send ping
7229         ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7230                 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7231                 ICMPv6EchoRequest())
7232         pkts = [ping]
7233         self.pg5.add_stream(pkts)
7234         self.pg_enable_capture(self.pg_interfaces)
7235         self.pg_start()
7236
7237         # Wait for Neighbor Solicitation
7238         capture = self.pg5.get_capture(len(pkts))
7239         packet = capture[0]
7240         try:
7241             self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7242             self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
7243             tgt = packet[ICMPv6ND_NS].tgt
7244         except:
7245             self.logger.error(ppp("Unexpected or invalid packet:", packet))
7246             raise
7247
7248         # Send Neighbor Advertisement
7249         p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7250              IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7251              ICMPv6ND_NA(tgt=tgt) /
7252              ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
7253         pkts = [p]
7254         self.pg5.add_stream(pkts)
7255         self.pg_enable_capture(self.pg_interfaces)
7256         self.pg_start()
7257
7258         # Try to send ping again
7259         pkts = [ping]
7260         self.pg5.add_stream(pkts)
7261         self.pg_enable_capture(self.pg_interfaces)
7262         self.pg_start()
7263
7264         # Wait for ping reply
7265         capture = self.pg5.get_capture(len(pkts))
7266         packet = capture[0]
7267         try:
7268             self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7269             self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
7270             self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
7271         except:
7272             self.logger.error(ppp("Unexpected or invalid packet:", packet))
7273             raise
7274
7275     def test_pool(self):
7276         """ Add/delete address to NAT64 pool """
7277         nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
7278
7279         self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
7280
7281         addresses = self.vapi.nat64_pool_addr_dump()
7282         self.assertEqual(len(addresses), 1)
7283         self.assertEqual(addresses[0].address, nat_addr)
7284
7285         self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
7286
7287         addresses = self.vapi.nat64_pool_addr_dump()
7288         self.assertEqual(len(addresses), 0)
7289
7290     def test_interface(self):
7291         """ Enable/disable NAT64 feature on the interface """
7292         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7293         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7294
7295         interfaces = self.vapi.nat64_interface_dump()
7296         self.assertEqual(len(interfaces), 2)
7297         pg0_found = False
7298         pg1_found = False
7299         for intf in interfaces:
7300             if intf.sw_if_index == self.pg0.sw_if_index:
7301                 self.assertEqual(intf.is_inside, 1)
7302                 pg0_found = True
7303             elif intf.sw_if_index == self.pg1.sw_if_index:
7304                 self.assertEqual(intf.is_inside, 0)
7305                 pg1_found = True
7306         self.assertTrue(pg0_found)
7307         self.assertTrue(pg1_found)
7308
7309         features = self.vapi.cli("show interface features pg0")
7310         self.assertIn('nat64-in2out', features)
7311         features = self.vapi.cli("show interface features pg1")
7312         self.assertIn('nat64-out2in', features)
7313
7314         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
7315         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
7316
7317         interfaces = self.vapi.nat64_interface_dump()
7318         self.assertEqual(len(interfaces), 0)
7319
7320     def test_static_bib(self):
7321         """ Add/delete static BIB entry """
7322         in_addr = socket.inet_pton(socket.AF_INET6,
7323                                    '2001:db8:85a3::8a2e:370:7334')
7324         out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
7325         in_port = 1234
7326         out_port = 5678
7327         proto = IP_PROTOS.tcp
7328
7329         self.vapi.nat64_add_del_static_bib(in_addr,
7330                                            out_addr,
7331                                            in_port,
7332                                            out_port,
7333                                            proto)
7334         bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
7335         static_bib_num = 0
7336         for bibe in bib:
7337             if bibe.is_static:
7338                 static_bib_num += 1
7339                 self.assertEqual(bibe.i_addr, in_addr)
7340                 self.assertEqual(bibe.o_addr, out_addr)
7341                 self.assertEqual(bibe.i_port, in_port)
7342                 self.assertEqual(bibe.o_port, out_port)
7343         self.assertEqual(static_bib_num, 1)
7344         bibs = self.statistics.get_counter('/nat64/total-bibs')
7345         self.assertEqual(bibs[0][0], 1)
7346
7347         self.vapi.nat64_add_del_static_bib(in_addr,
7348                                            out_addr,
7349                                            in_port,
7350                                            out_port,
7351                                            proto,
7352                                            is_add=0)
7353         bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
7354         static_bib_num = 0
7355         for bibe in bib:
7356             if bibe.is_static:
7357                 static_bib_num += 1
7358         self.assertEqual(static_bib_num, 0)
7359         bibs = self.statistics.get_counter('/nat64/total-bibs')
7360         self.assertEqual(bibs[0][0], 0)
7361
7362     def test_set_timeouts(self):
7363         """ Set NAT64 timeouts """
7364         # verify default values
7365         timeouts = self.vapi.nat_get_timeouts()
7366         self.assertEqual(timeouts.udp, 300)
7367         self.assertEqual(timeouts.icmp, 60)
7368         self.assertEqual(timeouts.tcp_transitory, 240)
7369         self.assertEqual(timeouts.tcp_established, 7440)
7370
7371         # set and verify custom values
7372         self.vapi.nat_set_timeouts(udp=200, icmp=30, tcp_transitory=250,
7373                                    tcp_established=7450)
7374         timeouts = self.vapi.nat_get_timeouts()
7375         self.assertEqual(timeouts.udp, 200)
7376         self.assertEqual(timeouts.icmp, 30)
7377         self.assertEqual(timeouts.tcp_transitory, 250)
7378         self.assertEqual(timeouts.tcp_established, 7450)
7379
7380     def test_dynamic(self):
7381         """ NAT64 dynamic translation test """
7382         self.tcp_port_in = 6303
7383         self.udp_port_in = 6304
7384         self.icmp_id_in = 6305
7385
7386         ses_num_start = self.nat64_get_ses_num()
7387
7388         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7389                                                 self.nat_addr_n)
7390         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7391         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7392
7393         # in2out
7394         tcpn = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7395         udpn = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7396         icmpn = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7397         totaln = self.statistics.get_counter(
7398             '/err/nat64-in2out/good in2out packets processed')
7399
7400         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7401         self.pg0.add_stream(pkts)
7402         self.pg_enable_capture(self.pg_interfaces)
7403         self.pg_start()
7404         capture = self.pg1.get_capture(len(pkts))
7405         self.verify_capture_out(capture, nat_ip=self.nat_addr,
7406                                 dst_ip=self.pg1.remote_ip4)
7407
7408         err = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7409         self.assertEqual(err - tcpn, 1)
7410         err = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7411         self.assertEqual(err - udpn, 1)
7412         err = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7413         self.assertEqual(err - icmpn, 1)
7414         err = self.statistics.get_counter(
7415             '/err/nat64-in2out/good in2out packets processed')
7416         self.assertEqual(err - totaln, 3)
7417
7418         # out2in
7419         tcpn = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7420         udpn = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7421         icmpn = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7422         totaln = self.statistics.get_counter(
7423             '/err/nat64-out2in/good out2in packets processed')
7424
7425         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7426         self.pg1.add_stream(pkts)
7427         self.pg_enable_capture(self.pg_interfaces)
7428         self.pg_start()
7429         capture = self.pg0.get_capture(len(pkts))
7430         ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7431         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7432
7433         err = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7434         self.assertEqual(err - tcpn, 1)
7435         err = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7436         self.assertEqual(err - udpn, 1)
7437         err = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7438         self.assertEqual(err - icmpn, 1)
7439         err = self.statistics.get_counter(
7440             '/err/nat64-out2in/good out2in packets processed')
7441         self.assertEqual(err - totaln, 3)
7442
7443         bibs = self.statistics.get_counter('/nat64/total-bibs')
7444         self.assertEqual(bibs[0][0], 3)
7445         sessions = self.statistics.get_counter('/nat64/total-sessions')
7446         self.assertEqual(sessions[0][0], 3)
7447
7448         # in2out
7449         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7450         self.pg0.add_stream(pkts)
7451         self.pg_enable_capture(self.pg_interfaces)
7452         self.pg_start()
7453         capture = self.pg1.get_capture(len(pkts))
7454         self.verify_capture_out(capture, nat_ip=self.nat_addr,
7455                                 dst_ip=self.pg1.remote_ip4)
7456
7457         # out2in
7458         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7459         self.pg1.add_stream(pkts)
7460         self.pg_enable_capture(self.pg_interfaces)
7461         self.pg_start()
7462         capture = self.pg0.get_capture(len(pkts))
7463         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7464
7465         ses_num_end = self.nat64_get_ses_num()
7466
7467         self.assertEqual(ses_num_end - ses_num_start, 3)
7468
7469         # tenant with specific VRF
7470         self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
7471                                                 self.vrf1_nat_addr_n,
7472                                                 vrf_id=self.vrf1_id)
7473         self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
7474
7475         pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
7476         self.pg2.add_stream(pkts)
7477         self.pg_enable_capture(self.pg_interfaces)
7478         self.pg_start()
7479         capture = self.pg1.get_capture(len(pkts))
7480         self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7481                                 dst_ip=self.pg1.remote_ip4)
7482
7483         pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7484         self.pg1.add_stream(pkts)
7485         self.pg_enable_capture(self.pg_interfaces)
7486         self.pg_start()
7487         capture = self.pg2.get_capture(len(pkts))
7488         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
7489
7490     def test_static(self):
7491         """ NAT64 static translation test """
7492         self.tcp_port_in = 60303
7493         self.udp_port_in = 60304
7494         self.icmp_id_in = 60305
7495         self.tcp_port_out = 60303
7496         self.udp_port_out = 60304
7497         self.icmp_id_out = 60305
7498
7499         ses_num_start = self.nat64_get_ses_num()
7500
7501         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7502                                                 self.nat_addr_n)
7503         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7504         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7505
7506         self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7507                                            self.nat_addr_n,
7508                                            self.tcp_port_in,
7509                                            self.tcp_port_out,
7510                                            IP_PROTOS.tcp)
7511         self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7512                                            self.nat_addr_n,
7513                                            self.udp_port_in,
7514                                            self.udp_port_out,
7515                                            IP_PROTOS.udp)
7516         self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7517                                            self.nat_addr_n,
7518                                            self.icmp_id_in,
7519                                            self.icmp_id_out,
7520                                            IP_PROTOS.icmp)
7521
7522         # in2out
7523         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7524         self.pg0.add_stream(pkts)
7525         self.pg_enable_capture(self.pg_interfaces)
7526         self.pg_start()
7527         capture = self.pg1.get_capture(len(pkts))
7528         self.verify_capture_out(capture, nat_ip=self.nat_addr,
7529                                 dst_ip=self.pg1.remote_ip4, same_port=True)
7530
7531         # out2in
7532         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7533         self.pg1.add_stream(pkts)
7534         self.pg_enable_capture(self.pg_interfaces)
7535         self.pg_start()
7536         capture = self.pg0.get_capture(len(pkts))
7537         ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7538         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7539
7540         ses_num_end = self.nat64_get_ses_num()
7541
7542         self.assertEqual(ses_num_end - ses_num_start, 3)
7543
7544     @unittest.skipUnless(running_extended_tests, "part of extended tests")
7545     def test_session_timeout(self):
7546         """ NAT64 session timeout """
7547         self.icmp_id_in = 1234
7548         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7549                                                 self.nat_addr_n)
7550         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7551         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7552         self.vapi.nat_set_timeouts(icmp=5, tcp_transitory=5, tcp_established=5)
7553
7554         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7555         self.pg0.add_stream(pkts)
7556         self.pg_enable_capture(self.pg_interfaces)
7557         self.pg_start()
7558         capture = self.pg1.get_capture(len(pkts))
7559
7560         ses_num_before_timeout = self.nat64_get_ses_num()
7561
7562         sleep(15)
7563
7564         # ICMP and TCP session after timeout
7565         ses_num_after_timeout = self.nat64_get_ses_num()
7566         self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
7567
7568     def test_icmp_error(self):
7569         """ NAT64 ICMP Error message translation """
7570         self.tcp_port_in = 6303
7571         self.udp_port_in = 6304
7572         self.icmp_id_in = 6305
7573
7574         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7575                                                 self.nat_addr_n)
7576         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7577         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7578
7579         # send some packets to create sessions
7580         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7581         self.pg0.add_stream(pkts)
7582         self.pg_enable_capture(self.pg_interfaces)
7583         self.pg_start()
7584         capture_ip4 = self.pg1.get_capture(len(pkts))
7585         self.verify_capture_out(capture_ip4,
7586                                 nat_ip=self.nat_addr,
7587                                 dst_ip=self.pg1.remote_ip4)
7588
7589         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7590         self.pg1.add_stream(pkts)
7591         self.pg_enable_capture(self.pg_interfaces)
7592         self.pg_start()
7593         capture_ip6 = self.pg0.get_capture(len(pkts))
7594         ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7595         self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
7596                                    self.pg0.remote_ip6)
7597
7598         # in2out
7599         pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7600                 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
7601                 ICMPv6DestUnreach(code=1) /
7602                 packet[IPv6] for packet in capture_ip6]
7603         self.pg0.add_stream(pkts)
7604         self.pg_enable_capture(self.pg_interfaces)
7605         self.pg_start()
7606         capture = self.pg1.get_capture(len(pkts))
7607         for packet in capture:
7608             try:
7609                 self.assertEqual(packet[IP].src, self.nat_addr)
7610                 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
7611                 self.assertEqual(packet[ICMP].type, 3)
7612                 self.assertEqual(packet[ICMP].code, 13)
7613                 inner = packet[IPerror]
7614                 self.assertEqual(inner.src, self.pg1.remote_ip4)
7615                 self.assertEqual(inner.dst, self.nat_addr)
7616                 self.assert_packet_checksums_valid(packet)
7617                 if inner.haslayer(TCPerror):
7618                     self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
7619                 elif inner.haslayer(UDPerror):
7620                     self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
7621                 else:
7622                     self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
7623             except:
7624                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7625                 raise
7626
7627         # out2in
7628         pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7629                 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7630                 ICMP(type=3, code=13) /
7631                 packet[IP] for packet in capture_ip4]
7632         self.pg1.add_stream(pkts)
7633         self.pg_enable_capture(self.pg_interfaces)
7634         self.pg_start()
7635         capture = self.pg0.get_capture(len(pkts))
7636         for packet in capture:
7637             try:
7638                 self.assertEqual(packet[IPv6].src, ip.src)
7639                 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7640                 icmp = packet[ICMPv6DestUnreach]
7641                 self.assertEqual(icmp.code, 1)
7642                 inner = icmp[IPerror6]
7643                 self.assertEqual(inner.src, self.pg0.remote_ip6)
7644                 self.assertEqual(inner.dst, ip.src)
7645                 self.assert_icmpv6_checksum_valid(packet)
7646                 if inner.haslayer(TCPerror):
7647                     self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
7648                 elif inner.haslayer(UDPerror):
7649                     self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
7650                 else:
7651                     self.assertEqual(inner[ICMPv6EchoRequest].id,
7652                                      self.icmp_id_in)
7653             except:
7654                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7655                 raise
7656
7657     def test_hairpinning(self):
7658         """ NAT64 hairpinning """
7659
7660         client = self.pg0.remote_hosts[0]
7661         server = self.pg0.remote_hosts[1]
7662         server_tcp_in_port = 22
7663         server_tcp_out_port = 4022
7664         server_udp_in_port = 23
7665         server_udp_out_port = 4023
7666         client_tcp_in_port = 1234
7667         client_udp_in_port = 1235
7668         client_tcp_out_port = 0
7669         client_udp_out_port = 0
7670         ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
7671         nat_addr_ip6 = ip.src
7672
7673         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7674                                                 self.nat_addr_n)
7675         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7676         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7677
7678         self.vapi.nat64_add_del_static_bib(server.ip6n,
7679                                            self.nat_addr_n,
7680                                            server_tcp_in_port,
7681                                            server_tcp_out_port,
7682                                            IP_PROTOS.tcp)
7683         self.vapi.nat64_add_del_static_bib(server.ip6n,
7684                                            self.nat_addr_n,
7685                                            server_udp_in_port,
7686                                            server_udp_out_port,
7687                                            IP_PROTOS.udp)
7688
7689         # client to server
7690         pkts = []
7691         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7692              IPv6(src=client.ip6, dst=nat_addr_ip6) /
7693              TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7694         pkts.append(p)
7695         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7696              IPv6(src=client.ip6, dst=nat_addr_ip6) /
7697              UDP(sport=client_udp_in_port, dport=server_udp_out_port))
7698         pkts.append(p)
7699         self.pg0.add_stream(pkts)
7700         self.pg_enable_capture(self.pg_interfaces)
7701         self.pg_start()
7702         capture = self.pg0.get_capture(len(pkts))
7703         for packet in capture:
7704             try:
7705                 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7706                 self.assertEqual(packet[IPv6].dst, server.ip6)
7707                 self.assert_packet_checksums_valid(packet)
7708                 if packet.haslayer(TCP):
7709                     self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
7710                     self.assertEqual(packet[TCP].dport, server_tcp_in_port)
7711                     client_tcp_out_port = packet[TCP].sport
7712                 else:
7713                     self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
7714                     self.assertEqual(packet[UDP].dport, server_udp_in_port)
7715                     client_udp_out_port = packet[UDP].sport
7716             except:
7717                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7718                 raise
7719
7720         # server to client
7721         pkts = []
7722         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7723              IPv6(src=server.ip6, dst=nat_addr_ip6) /
7724              TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
7725         pkts.append(p)
7726         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7727              IPv6(src=server.ip6, dst=nat_addr_ip6) /
7728              UDP(sport=server_udp_in_port, dport=client_udp_out_port))
7729         pkts.append(p)
7730         self.pg0.add_stream(pkts)
7731         self.pg_enable_capture(self.pg_interfaces)
7732         self.pg_start()
7733         capture = self.pg0.get_capture(len(pkts))
7734         for packet in capture:
7735             try:
7736                 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7737                 self.assertEqual(packet[IPv6].dst, client.ip6)
7738                 self.assert_packet_checksums_valid(packet)
7739                 if packet.haslayer(TCP):
7740                     self.assertEqual(packet[TCP].sport, server_tcp_out_port)
7741                     self.assertEqual(packet[TCP].dport, client_tcp_in_port)
7742                 else:
7743                     self.assertEqual(packet[UDP].sport, server_udp_out_port)
7744                     self.assertEqual(packet[UDP].dport, client_udp_in_port)
7745             except:
7746                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7747                 raise
7748
7749         # ICMP error
7750         pkts = []
7751         pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7752                 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7753                 ICMPv6DestUnreach(code=1) /
7754                 packet[IPv6] for packet in capture]
7755         self.pg0.add_stream(pkts)
7756         self.pg_enable_capture(self.pg_interfaces)
7757         self.pg_start()
7758         capture = self.pg0.get_capture(len(pkts))
7759         for packet in capture:
7760             try:
7761                 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7762                 self.assertEqual(packet[IPv6].dst, server.ip6)
7763                 icmp = packet[ICMPv6DestUnreach]
7764                 self.assertEqual(icmp.code, 1)
7765                 inner = icmp[IPerror6]
7766                 self.assertEqual(inner.src, server.ip6)
7767                 self.assertEqual(inner.dst, nat_addr_ip6)
7768                 self.assert_packet_checksums_valid(packet)
7769                 if inner.haslayer(TCPerror):
7770                     self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
7771                     self.assertEqual(inner[TCPerror].dport,
7772                                      client_tcp_out_port)
7773                 else:
7774                     self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
7775                     self.assertEqual(inner[UDPerror].dport,
7776                                      client_udp_out_port)
7777             except:
7778                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7779                 raise
7780
7781     def test_prefix(self):
7782         """ NAT64 Network-Specific Prefix """
7783
7784         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7785                                                 self.nat_addr_n)
7786         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7787         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7788         self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
7789                                                 self.vrf1_nat_addr_n,
7790                                                 vrf_id=self.vrf1_id)
7791         self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
7792
7793         # Add global prefix
7794         global_pref64 = "2001:db8::"
7795         global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
7796         global_pref64_len = 32
7797         self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
7798
7799         prefix = self.vapi.nat64_prefix_dump()
7800         self.assertEqual(len(prefix), 1)
7801         self.assertEqual(prefix[0].prefix, global_pref64_n)
7802         self.assertEqual(prefix[0].prefix_len, global_pref64_len)
7803         self.assertEqual(prefix[0].vrf_id, 0)
7804
7805         # Add tenant specific prefix
7806         vrf1_pref64 = "2001:db8:122:300::"
7807         vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
7808         vrf1_pref64_len = 56
7809         self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
7810                                        vrf1_pref64_len,
7811                                        vrf_id=self.vrf1_id)
7812         prefix = self.vapi.nat64_prefix_dump()
7813         self.assertEqual(len(prefix), 2)
7814
7815         # Global prefix
7816         pkts = self.create_stream_in_ip6(self.pg0,
7817                                          self.pg1,
7818                                          pref=global_pref64,
7819                                          plen=global_pref64_len)
7820         self.pg0.add_stream(pkts)
7821         self.pg_enable_capture(self.pg_interfaces)
7822         self.pg_start()
7823         capture = self.pg1.get_capture(len(pkts))
7824         self.verify_capture_out(capture, nat_ip=self.nat_addr,
7825                                 dst_ip=self.pg1.remote_ip4)
7826
7827         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7828         self.pg1.add_stream(pkts)
7829         self.pg_enable_capture(self.pg_interfaces)
7830         self.pg_start()
7831         capture = self.pg0.get_capture(len(pkts))
7832         dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7833                                   global_pref64,
7834                                   global_pref64_len)
7835         self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
7836
7837         # Tenant specific prefix
7838         pkts = self.create_stream_in_ip6(self.pg2,
7839                                          self.pg1,
7840                                          pref=vrf1_pref64,
7841                                          plen=vrf1_pref64_len)
7842         self.pg2.add_stream(pkts)
7843         self.pg_enable_capture(self.pg_interfaces)
7844         self.pg_start()
7845         capture = self.pg1.get_capture(len(pkts))
7846         self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7847                                 dst_ip=self.pg1.remote_ip4)
7848
7849         pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7850         self.pg1.add_stream(pkts)
7851         self.pg_enable_capture(self.pg_interfaces)
7852         self.pg_start()
7853         capture = self.pg2.get_capture(len(pkts))
7854         dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7855                                   vrf1_pref64,
7856                                   vrf1_pref64_len)
7857         self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
7858
7859     def test_unknown_proto(self):
7860         """ NAT64 translate packet with unknown protocol """
7861
7862         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7863                                                 self.nat_addr_n)
7864         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7865         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7866         remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7867
7868         # in2out
7869         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7870              IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
7871              TCP(sport=self.tcp_port_in, dport=20))
7872         self.pg0.add_stream(p)
7873         self.pg_enable_capture(self.pg_interfaces)
7874         self.pg_start()
7875         p = self.pg1.get_capture(1)
7876
7877         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7878              IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
7879              GRE() /
7880              IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7881              TCP(sport=1234, dport=1234))
7882         self.pg0.add_stream(p)
7883         self.pg_enable_capture(self.pg_interfaces)
7884         self.pg_start()
7885         p = self.pg1.get_capture(1)
7886         packet = p[0]
7887         try:
7888             self.assertEqual(packet[IP].src, self.nat_addr)
7889             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
7890             self.assertEqual(packet.haslayer(GRE), 1)
7891             self.assert_packet_checksums_valid(packet)
7892         except:
7893             self.logger.error(ppp("Unexpected or invalid packet:", packet))
7894             raise
7895
7896         # out2in
7897         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7898              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7899              GRE() /
7900              IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7901              TCP(sport=1234, dport=1234))
7902         self.pg1.add_stream(p)
7903         self.pg_enable_capture(self.pg_interfaces)
7904         self.pg_start()
7905         p = self.pg0.get_capture(1)
7906         packet = p[0]
7907         try:
7908             self.assertEqual(packet[IPv6].src, remote_ip6)
7909             self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7910             self.assertEqual(packet[IPv6].nh, 47)
7911         except:
7912             self.logger.error(ppp("Unexpected or invalid packet:", packet))
7913             raise
7914
7915     def test_hairpinning_unknown_proto(self):
7916         """ NAT64 translate packet with unknown protocol - hairpinning """
7917
7918         client = self.pg0.remote_hosts[0]
7919         server = self.pg0.remote_hosts[1]
7920         server_tcp_in_port = 22
7921         server_tcp_out_port = 4022
7922         client_tcp_in_port = 1234
7923         client_tcp_out_port = 1235
7924         server_nat_ip = "10.0.0.100"
7925         client_nat_ip = "10.0.0.110"
7926         server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
7927         client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
7928         server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
7929         client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
7930
7931         self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
7932                                                 client_nat_ip_n)
7933         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7934         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7935
7936         self.vapi.nat64_add_del_static_bib(server.ip6n,
7937                                            server_nat_ip_n,
7938                                            server_tcp_in_port,
7939                                            server_tcp_out_port,
7940                                            IP_PROTOS.tcp)
7941
7942         self.vapi.nat64_add_del_static_bib(server.ip6n,
7943                                            server_nat_ip_n,
7944                                            0,
7945                                            0,
7946                                            IP_PROTOS.gre)
7947
7948         self.vapi.nat64_add_del_static_bib(client.ip6n,
7949                                            client_nat_ip_n,
7950                                            client_tcp_in_port,
7951                                            client_tcp_out_port,
7952                                            IP_PROTOS.tcp)
7953
7954         # client to server
7955         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7956              IPv6(src=client.ip6, dst=server_nat_ip6) /
7957              TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7958         self.pg0.add_stream(p)
7959         self.pg_enable_capture(self.pg_interfaces)
7960         self.pg_start()
7961         p = self.pg0.get_capture(1)
7962
7963         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7964              IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
7965              GRE() /
7966              IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7967              TCP(sport=1234, dport=1234))
7968         self.pg0.add_stream(p)
7969         self.pg_enable_capture(self.pg_interfaces)
7970         self.pg_start()
7971         p = self.pg0.get_capture(1)
7972         packet = p[0]
7973         try:
7974             self.assertEqual(packet[IPv6].src, client_nat_ip6)
7975             self.assertEqual(packet[IPv6].dst, server.ip6)
7976             self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
7977         except:
7978             self.logger.error(ppp("Unexpected or invalid packet:", packet))
7979             raise
7980
7981         # server to client
7982         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7983              IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
7984              GRE() /
7985              IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7986              TCP(sport=1234, dport=1234))
7987         self.pg0.add_stream(p)
7988         self.pg_enable_capture(self.pg_interfaces)
7989         self.pg_start()
7990         p = self.pg0.get_capture(1)
7991         packet = p[0]
7992         try:
7993             self.assertEqual(packet[IPv6].src, server_nat_ip6)
7994             self.assertEqual(packet[IPv6].dst, client.ip6)
7995             self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
7996         except:
7997             self.logger.error(ppp("Unexpected or invalid packet:", packet))
7998             raise
7999
8000     def test_one_armed_nat64(self):
8001         """ One armed NAT64 """
8002         external_port = 0
8003         remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
8004                                            '64:ff9b::',
8005                                            96)
8006
8007         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8008                                                 self.nat_addr_n)
8009         self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
8010         self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
8011
8012         # in2out
8013         p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8014              IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
8015              TCP(sport=12345, dport=80))
8016         self.pg3.add_stream(p)
8017         self.pg_enable_capture(self.pg_interfaces)
8018         self.pg_start()
8019         capture = self.pg3.get_capture(1)
8020         p = capture[0]
8021         try:
8022             ip = p[IP]
8023             tcp = p[TCP]
8024             self.assertEqual(ip.src, self.nat_addr)
8025             self.assertEqual(ip.dst, self.pg3.remote_ip4)
8026             self.assertNotEqual(tcp.sport, 12345)
8027             external_port = tcp.sport
8028             self.assertEqual(tcp.dport, 80)
8029             self.assert_packet_checksums_valid(p)
8030         except:
8031             self.logger.error(ppp("Unexpected or invalid packet:", p))
8032             raise
8033
8034         # out2in
8035         p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8036              IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
8037              TCP(sport=80, dport=external_port))
8038         self.pg3.add_stream(p)
8039         self.pg_enable_capture(self.pg_interfaces)
8040         self.pg_start()
8041         capture = self.pg3.get_capture(1)
8042         p = capture[0]
8043         try:
8044             ip = p[IPv6]
8045             tcp = p[TCP]
8046             self.assertEqual(ip.src, remote_host_ip6)
8047             self.assertEqual(ip.dst, self.pg3.remote_ip6)
8048             self.assertEqual(tcp.sport, 80)
8049             self.assertEqual(tcp.dport, 12345)
8050             self.assert_packet_checksums_valid(p)
8051         except:
8052             self.logger.error(ppp("Unexpected or invalid packet:", p))
8053             raise
8054
8055     def test_frag_in_order(self):
8056         """ NAT64 translate fragments arriving in order """
8057         self.tcp_port_in = random.randint(1025, 65535)
8058
8059         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8060                                                 self.nat_addr_n)
8061         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8062         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8063
8064         reass = self.vapi.nat_reass_dump()
8065         reass_n_start = len(reass)
8066
8067         # in2out
8068         data = b'a' * 200
8069         pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8070                                            self.tcp_port_in, 20, data)
8071         self.pg0.add_stream(pkts)
8072         self.pg_enable_capture(self.pg_interfaces)
8073         self.pg_start()
8074         frags = self.pg1.get_capture(len(pkts))
8075         p = self.reass_frags_and_verify(frags,
8076                                         self.nat_addr,
8077                                         self.pg1.remote_ip4)
8078         self.assertEqual(p[TCP].dport, 20)
8079         self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8080         self.tcp_port_out = p[TCP].sport
8081         self.assertEqual(data, p[Raw].load)
8082
8083         # out2in
8084         data = b"A" * 4 + b"b" * 16 + b"C" * 3
8085         pkts = self.create_stream_frag(self.pg1,
8086                                        self.nat_addr,
8087                                        20,
8088                                        self.tcp_port_out,
8089                                        data)
8090         self.pg1.add_stream(pkts)
8091         self.pg_enable_capture(self.pg_interfaces)
8092         self.pg_start()
8093         frags = self.pg0.get_capture(len(pkts))
8094         src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8095         p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8096         self.assertEqual(p[TCP].sport, 20)
8097         self.assertEqual(p[TCP].dport, self.tcp_port_in)
8098         self.assertEqual(data, p[Raw].load)
8099
8100         reass = self.vapi.nat_reass_dump()
8101         reass_n_end = len(reass)
8102
8103         self.assertEqual(reass_n_end - reass_n_start, 2)
8104
8105     def test_reass_hairpinning(self):
8106         """ NAT64 fragments hairpinning """
8107         data = 'a' * 200
8108         server = self.pg0.remote_hosts[1]
8109         server_in_port = random.randint(1025, 65535)
8110         server_out_port = random.randint(1025, 65535)
8111         client_in_port = random.randint(1025, 65535)
8112         ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8113         nat_addr_ip6 = ip.src
8114
8115         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8116                                                 self.nat_addr_n)
8117         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8118         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8119
8120         # add static BIB entry for server
8121         self.vapi.nat64_add_del_static_bib(server.ip6n,
8122                                            self.nat_addr_n,
8123                                            server_in_port,
8124                                            server_out_port,
8125                                            IP_PROTOS.tcp)
8126
8127         # send packet from host to server
8128         pkts = self.create_stream_frag_ip6(self.pg0,
8129                                            self.nat_addr,
8130                                            client_in_port,
8131                                            server_out_port,
8132                                            data)
8133         self.pg0.add_stream(pkts)
8134         self.pg_enable_capture(self.pg_interfaces)
8135         self.pg_start()
8136         frags = self.pg0.get_capture(len(pkts))
8137         p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
8138         self.assertNotEqual(p[TCP].sport, client_in_port)
8139         self.assertEqual(p[TCP].dport, server_in_port)
8140         self.assertEqual(data, p[Raw].load)
8141
8142     def test_frag_out_of_order(self):
8143         """ NAT64 translate fragments arriving out of order """
8144         self.tcp_port_in = random.randint(1025, 65535)
8145
8146         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8147                                                 self.nat_addr_n)
8148         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8149         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8150
8151         # in2out
8152         data = b'a' * 200
8153         pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8154                                            self.tcp_port_in, 20, data)
8155         pkts.reverse()
8156         self.pg0.add_stream(pkts)
8157         self.pg_enable_capture(self.pg_interfaces)
8158         self.pg_start()
8159         frags = self.pg1.get_capture(len(pkts))
8160         p = self.reass_frags_and_verify(frags,
8161                                         self.nat_addr,
8162                                         self.pg1.remote_ip4)
8163         self.assertEqual(p[TCP].dport, 20)
8164         self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8165         self.tcp_port_out = p[TCP].sport
8166         self.assertEqual(data, p[Raw].load)
8167
8168         # out2in
8169         data = b"A" * 4 + b"B" * 16 + b"C" * 3
8170         pkts = self.create_stream_frag(self.pg1,
8171                                        self.nat_addr,
8172                                        20,
8173                                        self.tcp_port_out,
8174                                        data)
8175         pkts.reverse()
8176         self.pg1.add_stream(pkts)
8177         self.pg_enable_capture(self.pg_interfaces)
8178         self.pg_start()
8179         frags = self.pg0.get_capture(len(pkts))
8180         src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8181         p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8182         self.assertEqual(p[TCP].sport, 20)
8183         self.assertEqual(p[TCP].dport, self.tcp_port_in)
8184         self.assertEqual(data, p[Raw].load)
8185
8186     def test_interface_addr(self):
8187         """ Acquire NAT64 pool addresses from interface """
8188         self.vapi.nat64_add_del_interface_addr(self.pg4.sw_if_index)
8189
8190         # no address in NAT64 pool
8191         addresses = self.vapi.nat44_address_dump()
8192         self.assertEqual(0, len(addresses))
8193
8194         # configure interface address and check NAT64 address pool
8195         self.pg4.config_ip4()
8196         addresses = self.vapi.nat64_pool_addr_dump()
8197         self.assertEqual(len(addresses), 1)
8198         self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
8199
8200         # remove interface address and check NAT64 address pool
8201         self.pg4.unconfig_ip4()
8202         addresses = self.vapi.nat64_pool_addr_dump()
8203         self.assertEqual(0, len(addresses))
8204
8205     @unittest.skipUnless(running_extended_tests, "part of extended tests")
8206     def test_ipfix_max_bibs_sessions(self):
8207         """ IPFIX logging maximum session and BIB entries exceeded """
8208         max_bibs = 1280
8209         max_sessions = 2560
8210         remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8211                                            '64:ff9b::',
8212                                            96)
8213
8214         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8215                                                 self.nat_addr_n)
8216         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8217         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8218
8219         pkts = []
8220         src = ""
8221         for i in range(0, max_bibs):
8222             src = "fd01:aa::%x" % (i)
8223             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8224                  IPv6(src=src, dst=remote_host_ip6) /
8225                  TCP(sport=12345, dport=80))
8226             pkts.append(p)
8227             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8228                  IPv6(src=src, dst=remote_host_ip6) /
8229                  TCP(sport=12345, dport=22))
8230             pkts.append(p)
8231         self.pg0.add_stream(pkts)
8232         self.pg_enable_capture(self.pg_interfaces)
8233         self.pg_start()
8234         self.pg1.get_capture(max_sessions)
8235
8236         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8237                                      src_address=self.pg3.local_ip4n,
8238                                      path_mtu=512,
8239                                      template_interval=10)
8240         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8241                                            src_port=self.ipfix_src_port)
8242
8243         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8244              IPv6(src=src, dst=remote_host_ip6) /
8245              TCP(sport=12345, dport=25))
8246         self.pg0.add_stream(p)
8247         self.pg_enable_capture(self.pg_interfaces)
8248         self.pg_start()
8249         self.pg1.assert_nothing_captured()
8250         sleep(1)
8251         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
8252         capture = self.pg3.get_capture(9)
8253         ipfix = IPFIXDecoder()
8254         # first load template
8255         for p in capture:
8256             self.assertTrue(p.haslayer(IPFIX))
8257             self.assertEqual(p[IP].src, self.pg3.local_ip4)
8258             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8259             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8260             self.assertEqual(p[UDP].dport, 4739)
8261             self.assertEqual(p[IPFIX].observationDomainID,
8262                              self.ipfix_domain_id)
8263             if p.haslayer(Template):
8264                 ipfix.add_template(p.getlayer(Template))
8265         # verify events in data set
8266         for p in capture:
8267             if p.haslayer(Data):
8268                 data = ipfix.decode_data_set(p.getlayer(Set))
8269                 self.verify_ipfix_max_sessions(data, max_sessions)
8270
8271         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8272              IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8273              TCP(sport=12345, dport=80))
8274         self.pg0.add_stream(p)
8275         self.pg_enable_capture(self.pg_interfaces)
8276         self.pg_start()
8277         self.pg1.assert_nothing_captured()
8278         sleep(1)
8279         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
8280         capture = self.pg3.get_capture(1)
8281         # verify events in data set
8282         for p in capture:
8283             self.assertTrue(p.haslayer(IPFIX))
8284             self.assertEqual(p[IP].src, self.pg3.local_ip4)
8285             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8286             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8287             self.assertEqual(p[UDP].dport, 4739)
8288             self.assertEqual(p[IPFIX].observationDomainID,
8289                              self.ipfix_domain_id)
8290             if p.haslayer(Data):
8291                 data = ipfix.decode_data_set(p.getlayer(Set))
8292                 self.verify_ipfix_max_bibs(data, max_bibs)
8293
8294     def test_ipfix_max_frags(self):
8295         """ IPFIX logging maximum fragments pending reassembly exceeded """
8296         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8297                                                 self.nat_addr_n)
8298         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8299         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8300         self.vapi.nat_set_reass(max_frag=1, is_ip6=1)
8301         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8302                                      src_address=self.pg3.local_ip4n,
8303                                      path_mtu=512,
8304                                      template_interval=10)
8305         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8306                                            src_port=self.ipfix_src_port)
8307
8308         data = b'a' * 200
8309         pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8310                                            self.tcp_port_in, 20, data)
8311         pkts.reverse()
8312         self.pg0.add_stream(pkts)
8313         self.pg_enable_capture(self.pg_interfaces)
8314         self.pg_start()
8315         self.pg1.assert_nothing_captured()
8316         sleep(1)
8317         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
8318         capture = self.pg3.get_capture(9)
8319         ipfix = IPFIXDecoder()
8320         # first load template
8321         for p in capture:
8322             self.assertTrue(p.haslayer(IPFIX))
8323             self.assertEqual(p[IP].src, self.pg3.local_ip4)
8324             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8325             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8326             self.assertEqual(p[UDP].dport, 4739)
8327             self.assertEqual(p[IPFIX].observationDomainID,
8328                              self.ipfix_domain_id)
8329             if p.haslayer(Template):
8330                 ipfix.add_template(p.getlayer(Template))
8331         # verify events in data set
8332         for p in capture:
8333             if p.haslayer(Data):
8334                 data = ipfix.decode_data_set(p.getlayer(Set))
8335                 self.verify_ipfix_max_fragments_ip6(data, 1,
8336                                                     self.pg0.remote_ip6n)
8337
8338     def test_ipfix_bib_ses(self):
8339         """ IPFIX logging NAT64 BIB/session create and delete events """
8340         self.tcp_port_in = random.randint(1025, 65535)
8341         remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8342                                            '64:ff9b::',
8343                                            96)
8344
8345         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8346                                                 self.nat_addr_n)
8347         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8348         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8349         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8350                                      src_address=self.pg3.local_ip4n,
8351                                      path_mtu=512,
8352                                      template_interval=10)
8353         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8354                                            src_port=self.ipfix_src_port)
8355
8356         # Create
8357         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8358              IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8359              TCP(sport=self.tcp_port_in, dport=25))
8360         self.pg0.add_stream(p)
8361         self.pg_enable_capture(self.pg_interfaces)
8362         self.pg_start()
8363         p = self.pg1.get_capture(1)
8364         self.tcp_port_out = p[0][TCP].sport
8365         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
8366         capture = self.pg3.get_capture(10)
8367         ipfix = IPFIXDecoder()
8368         # first load template
8369         for p in capture:
8370             self.assertTrue(p.haslayer(IPFIX))
8371             self.assertEqual(p[IP].src, self.pg3.local_ip4)
8372             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8373             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8374             self.assertEqual(p[UDP].dport, 4739)
8375             self.assertEqual(p[IPFIX].observationDomainID,
8376                              self.ipfix_domain_id)
8377             if p.haslayer(Template):
8378                 ipfix.add_template(p.getlayer(Template))
8379         # verify events in data set
8380         for p in capture:
8381             if p.haslayer(Data):
8382                 data = ipfix.decode_data_set(p.getlayer(Set))
8383                 if scapy.compat.orb(data[0][230]) == 10:
8384                     self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
8385                 elif scapy.compat.orb(data[0][230]) == 6:
8386                     self.verify_ipfix_nat64_ses(data,
8387                                                 1,
8388                                                 self.pg0.remote_ip6n,
8389                                                 self.pg1.remote_ip4,
8390                                                 25)
8391                 else:
8392                     self.logger.error(ppp("Unexpected or invalid packet: ", p))
8393
8394         # Delete
8395         self.pg_enable_capture(self.pg_interfaces)
8396         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8397                                                 self.nat_addr_n,
8398                                                 is_add=0)
8399         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
8400         capture = self.pg3.get_capture(2)
8401         # verify events in data set
8402         for p in capture:
8403             self.assertTrue(p.haslayer(IPFIX))
8404             self.assertEqual(p[IP].src, self.pg3.local_ip4)
8405             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8406             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8407             self.assertEqual(p[UDP].dport, 4739)
8408             self.assertEqual(p[IPFIX].observationDomainID,
8409                              self.ipfix_domain_id)
8410             if p.haslayer(Data):
8411                 data = ipfix.decode_data_set(p.getlayer(Set))
8412                 if scapy.compat.orb(data[0][230]) == 11:
8413                     self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
8414                 elif scapy.compat.orb(data[0][230]) == 7:
8415                     self.verify_ipfix_nat64_ses(data,
8416                                                 0,
8417                                                 self.pg0.remote_ip6n,
8418                                                 self.pg1.remote_ip4,
8419                                                 25)
8420                 else:
8421                     self.logger.error(ppp("Unexpected or invalid packet: ", p))
8422
8423     def test_syslog_sess(self):
8424         """ Test syslog session creation and deletion """
8425         self.tcp_port_in = random.randint(1025, 65535)
8426         remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8427                                            '64:ff9b::',
8428                                            96)
8429
8430         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8431                                                 self.nat_addr_n)
8432         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8433         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8434         self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
8435         self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
8436
8437         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8438              IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8439              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
8440         self.pg0.add_stream(p)
8441         self.pg_enable_capture(self.pg_interfaces)
8442         self.pg_start()
8443         p = self.pg1.get_capture(1)
8444         self.tcp_port_out = p[0][TCP].sport
8445         capture = self.pg3.get_capture(1)
8446         self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
8447
8448         self.pg_enable_capture(self.pg_interfaces)
8449         self.pg_start()
8450         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8451                                                 self.nat_addr_n,
8452                                                 is_add=0)
8453         capture = self.pg3.get_capture(1)
8454         self.verify_syslog_sess(capture[0][Raw].load, False, True)
8455
8456     def nat64_get_ses_num(self):
8457         """
8458         Return number of active NAT64 sessions.
8459         """
8460         st = self.vapi.nat64_st_dump()
8461         return len(st)
8462
8463     def clear_nat64(self):
8464         """
8465         Clear NAT64 configuration.
8466         """
8467         self.vapi.nat_ipfix_enable_disable(enable=0,
8468                                            src_port=self.ipfix_src_port,
8469                                            domain_id=self.ipfix_domain_id)
8470         self.ipfix_src_port = 4739
8471         self.ipfix_domain_id = 1
8472
8473         self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
8474
8475         self.vapi.nat_set_timeouts()
8476
8477         interfaces = self.vapi.nat64_interface_dump()
8478         for intf in interfaces:
8479             if intf.is_inside > 1:
8480                 self.vapi.nat64_add_del_interface(intf.sw_if_index,
8481                                                   0,
8482                                                   is_add=0)
8483             self.vapi.nat64_add_del_interface(intf.sw_if_index,
8484                                               intf.is_inside,
8485                                               is_add=0)
8486
8487         bib = self.vapi.nat64_bib_dump(255)
8488         for bibe in bib:
8489             if bibe.is_static:
8490                 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
8491                                                    bibe.o_addr,
8492                                                    bibe.i_port,
8493                                                    bibe.o_port,
8494                                                    bibe.proto,
8495                                                    bibe.vrf_id,
8496                                                    is_add=0)
8497
8498         adresses = self.vapi.nat64_pool_addr_dump()
8499         for addr in adresses:
8500             self.vapi.nat64_add_del_pool_addr_range(addr.address,
8501                                                     addr.address,
8502                                                     vrf_id=addr.vrf_id,
8503                                                     is_add=0)
8504
8505         prefixes = self.vapi.nat64_prefix_dump()
8506         for prefix in prefixes:
8507             self.vapi.nat64_add_del_prefix(prefix.prefix,
8508                                            prefix.prefix_len,
8509                                            vrf_id=prefix.vrf_id,
8510                                            is_add=0)
8511
8512         bibs = self.statistics.get_counter('/nat64/total-bibs')
8513         self.assertEqual(bibs[0][0], 0)
8514         sessions = self.statistics.get_counter('/nat64/total-sessions')
8515         self.assertEqual(sessions[0][0], 0)
8516
8517     def tearDown(self):
8518         super(TestNAT64, self).tearDown()
8519         if not self.vpp_dead:
8520             self.logger.info(self.vapi.cli("show nat64 pool"))
8521             self.logger.info(self.vapi.cli("show nat64 interfaces"))
8522             self.logger.info(self.vapi.cli("show nat64 prefix"))
8523             self.logger.info(self.vapi.cli("show nat64 bib all"))
8524             self.logger.info(self.vapi.cli("show nat64 session table all"))
8525             self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
8526             self.clear_nat64()
8527
8528
8529 class TestDSlite(MethodHolder):
8530     """ DS-Lite Test Cases """
8531
8532     @classmethod
8533     def setUpClass(cls):
8534         super(TestDSlite, cls).setUpClass()
8535
8536         try:
8537             cls.nat_addr = '10.0.0.3'
8538             cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
8539
8540             cls.create_pg_interfaces(range(3))
8541             cls.pg0.admin_up()
8542             cls.pg0.config_ip4()
8543             cls.pg0.resolve_arp()
8544             cls.pg1.admin_up()
8545             cls.pg1.config_ip6()
8546             cls.pg1.generate_remote_hosts(2)
8547             cls.pg1.configure_ipv6_neighbors()
8548             cls.pg2.admin_up()
8549             cls.pg2.config_ip4()
8550             cls.pg2.resolve_arp()
8551
8552         except Exception:
8553             super(TestDSlite, cls).tearDownClass()
8554             raise
8555
8556     @classmethod
8557     def tearDownClass(cls):
8558         super(TestDSlite, cls).tearDownClass()
8559
8560     def verify_syslog_apmadd(self, data, isaddr, isport, xsaddr, xsport,
8561                              sv6enc, proto):
8562         message = data.decode('utf-8')
8563         try:
8564             message = SyslogMessage.parse(message)
8565         except ParseError as e:
8566             self.logger.error(e)
8567         else:
8568             self.assertEqual(message.severity, SyslogSeverity.info)
8569             self.assertEqual(message.appname, 'NAT')
8570             self.assertEqual(message.msgid, 'APMADD')
8571             sd_params = message.sd.get('napmap')
8572             self.assertTrue(sd_params is not None)
8573             self.assertEqual(sd_params.get('IATYP'), 'IPv4')
8574             self.assertEqual(sd_params.get('ISADDR'), isaddr)
8575             self.assertEqual(sd_params.get('ISPORT'), "%d" % isport)
8576             self.assertEqual(sd_params.get('XATYP'), 'IPv4')
8577             self.assertEqual(sd_params.get('XSADDR'), xsaddr)
8578             self.assertEqual(sd_params.get('XSPORT'), "%d" % xsport)
8579             self.assertEqual(sd_params.get('PROTO'), "%d" % proto)
8580             self.assertTrue(sd_params.get('SSUBIX') is not None)
8581             self.assertEqual(sd_params.get('SV6ENC'), sv6enc)
8582
8583     def test_dslite(self):
8584         """ Test DS-Lite """
8585         nat_config = self.vapi.nat_show_config()
8586         self.assertEqual(0, nat_config.dslite_ce)
8587
8588         self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
8589                                                  self.nat_addr_n)
8590         aftr_ip4 = '192.0.0.1'
8591         aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
8592         aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
8593         aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
8594         self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
8595         self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
8596
8597         # UDP
8598         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8599              IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
8600              IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8601              UDP(sport=20000, dport=10000))
8602         self.pg1.add_stream(p)
8603         self.pg_enable_capture(self.pg_interfaces)
8604         self.pg_start()
8605         capture = self.pg0.get_capture(1)
8606         capture = capture[0]
8607         self.assertFalse(capture.haslayer(IPv6))
8608         self.assertEqual(capture[IP].src, self.nat_addr)
8609         self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8610         self.assertNotEqual(capture[UDP].sport, 20000)
8611         self.assertEqual(capture[UDP].dport, 10000)
8612         self.assert_packet_checksums_valid(capture)
8613         out_port = capture[UDP].sport
8614         capture = self.pg2.get_capture(1)
8615         self.verify_syslog_apmadd(capture[0][Raw].load, '192.168.1.1',
8616                                   20000, self.nat_addr, out_port,
8617                                   self.pg1.remote_hosts[0].ip6, IP_PROTOS.udp)
8618
8619         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8620              IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8621              UDP(sport=10000, dport=out_port))
8622         self.pg0.add_stream(p)
8623         self.pg_enable_capture(self.pg_interfaces)
8624         self.pg_start()
8625         capture = self.pg1.get_capture(1)
8626         capture = capture[0]
8627         self.assertEqual(capture[IPv6].src, aftr_ip6)
8628         self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8629         self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8630         self.assertEqual(capture[IP].dst, '192.168.1.1')
8631         self.assertEqual(capture[UDP].sport, 10000)
8632         self.assertEqual(capture[UDP].dport, 20000)
8633         self.assert_packet_checksums_valid(capture)
8634
8635         # TCP
8636         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8637              IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8638              IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8639              TCP(sport=20001, dport=10001))
8640         self.pg1.add_stream(p)
8641         self.pg_enable_capture(self.pg_interfaces)
8642         self.pg_start()
8643         capture = self.pg0.get_capture(1)
8644         capture = capture[0]
8645         self.assertFalse(capture.haslayer(IPv6))
8646         self.assertEqual(capture[IP].src, self.nat_addr)
8647         self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8648         self.assertNotEqual(capture[TCP].sport, 20001)
8649         self.assertEqual(capture[TCP].dport, 10001)
8650         self.assert_packet_checksums_valid(capture)
8651         out_port = capture[TCP].sport
8652
8653         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8654              IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8655              TCP(sport=10001, dport=out_port))
8656         self.pg0.add_stream(p)
8657         self.pg_enable_capture(self.pg_interfaces)
8658         self.pg_start()
8659         capture = self.pg1.get_capture(1)
8660         capture = capture[0]
8661         self.assertEqual(capture[IPv6].src, aftr_ip6)
8662         self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8663         self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8664         self.assertEqual(capture[IP].dst, '192.168.1.1')
8665         self.assertEqual(capture[TCP].sport, 10001)
8666         self.assertEqual(capture[TCP].dport, 20001)
8667         self.assert_packet_checksums_valid(capture)
8668
8669         # ICMP
8670         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8671              IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8672              IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8673              ICMP(id=4000, type='echo-request'))
8674         self.pg1.add_stream(p)
8675         self.pg_enable_capture(self.pg_interfaces)
8676         self.pg_start()
8677         capture = self.pg0.get_capture(1)
8678         capture = capture[0]
8679         self.assertFalse(capture.haslayer(IPv6))
8680         self.assertEqual(capture[IP].src, self.nat_addr)
8681         self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8682         self.assertNotEqual(capture[ICMP].id, 4000)
8683         self.assert_packet_checksums_valid(capture)
8684         out_id = capture[ICMP].id
8685
8686         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8687              IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8688              ICMP(id=out_id, type='echo-reply'))
8689         self.pg0.add_stream(p)
8690         self.pg_enable_capture(self.pg_interfaces)
8691         self.pg_start()
8692         capture = self.pg1.get_capture(1)
8693         capture = capture[0]
8694         self.assertEqual(capture[IPv6].src, aftr_ip6)
8695         self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8696         self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8697         self.assertEqual(capture[IP].dst, '192.168.1.1')
8698         self.assertEqual(capture[ICMP].id, 4000)
8699         self.assert_packet_checksums_valid(capture)
8700
8701         # ping DS-Lite AFTR tunnel endpoint address
8702         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8703              IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
8704              ICMPv6EchoRequest())
8705         self.pg1.add_stream(p)
8706         self.pg_enable_capture(self.pg_interfaces)
8707         self.pg_start()
8708         capture = self.pg1.get_capture(1)
8709         capture = capture[0]
8710         self.assertEqual(capture[IPv6].src, aftr_ip6)
8711         self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8712         self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8713
8714         b4s = self.statistics.get_counter('/dslite/total-b4s')
8715         self.assertEqual(b4s[0][0], 2)
8716         sessions = self.statistics.get_counter('/dslite/total-sessions')
8717         self.assertEqual(sessions[0][0], 3)
8718
8719     def tearDown(self):
8720         super(TestDSlite, self).tearDown()
8721         if not self.vpp_dead:
8722             self.logger.info(self.vapi.cli("show dslite pool"))
8723             self.logger.info(
8724                 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8725             self.logger.info(self.vapi.cli("show dslite sessions"))
8726
8727
8728 class TestDSliteCE(MethodHolder):
8729     """ DS-Lite CE Test Cases """
8730
8731     @classmethod
8732     def setUpConstants(cls):
8733         super(TestDSliteCE, cls).setUpConstants()
8734         cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
8735
8736     @classmethod
8737     def setUpClass(cls):
8738         super(TestDSliteCE, cls).setUpClass()
8739
8740         try:
8741             cls.create_pg_interfaces(range(2))
8742             cls.pg0.admin_up()
8743             cls.pg0.config_ip4()
8744             cls.pg0.resolve_arp()
8745             cls.pg1.admin_up()
8746             cls.pg1.config_ip6()
8747             cls.pg1.generate_remote_hosts(1)
8748             cls.pg1.configure_ipv6_neighbors()
8749
8750         except Exception:
8751             super(TestDSliteCE, cls).tearDownClass()
8752             raise
8753
8754     @classmethod
8755     def tearDownClass(cls):
8756         super(TestDSliteCE, cls).tearDownClass()
8757
8758     def test_dslite_ce(self):
8759         """ Test DS-Lite CE """
8760
8761         nat_config = self.vapi.nat_show_config()
8762         self.assertEqual(1, nat_config.dslite_ce)
8763
8764         b4_ip4 = '192.0.0.2'
8765         b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
8766         b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
8767         b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
8768         self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
8769
8770         aftr_ip4 = '192.0.0.1'
8771         aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
8772         aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
8773         aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
8774         self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
8775
8776         self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
8777                                    dst_address_length=128,
8778                                    next_hop_address=self.pg1.remote_ip6n,
8779                                    next_hop_sw_if_index=self.pg1.sw_if_index,
8780                                    is_ipv6=1)
8781
8782         # UDP encapsulation
8783         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8784              IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
8785              UDP(sport=10000, dport=20000))
8786         self.pg0.add_stream(p)
8787         self.pg_enable_capture(self.pg_interfaces)
8788         self.pg_start()
8789         capture = self.pg1.get_capture(1)
8790         capture = capture[0]
8791         self.assertEqual(capture[IPv6].src, b4_ip6)
8792         self.assertEqual(capture[IPv6].dst, aftr_ip6)
8793         self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8794         self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
8795         self.assertEqual(capture[UDP].sport, 10000)
8796         self.assertEqual(capture[UDP].dport, 20000)
8797         self.assert_packet_checksums_valid(capture)
8798
8799         # UDP decapsulation
8800         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8801              IPv6(dst=b4_ip6, src=aftr_ip6) /
8802              IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
8803              UDP(sport=20000, dport=10000))
8804         self.pg1.add_stream(p)
8805         self.pg_enable_capture(self.pg_interfaces)
8806         self.pg_start()
8807         capture = self.pg0.get_capture(1)
8808         capture = capture[0]
8809         self.assertFalse(capture.haslayer(IPv6))
8810         self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
8811         self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8812         self.assertEqual(capture[UDP].sport, 20000)
8813         self.assertEqual(capture[UDP].dport, 10000)
8814         self.assert_packet_checksums_valid(capture)
8815
8816         # ping DS-Lite B4 tunnel endpoint address
8817         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8818              IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
8819              ICMPv6EchoRequest())
8820         self.pg1.add_stream(p)
8821         self.pg_enable_capture(self.pg_interfaces)
8822         self.pg_start()
8823         capture = self.pg1.get_capture(1)
8824         capture = capture[0]
8825         self.assertEqual(capture[IPv6].src, b4_ip6)
8826         self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8827         self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8828
8829     def tearDown(self):
8830         super(TestDSliteCE, self).tearDown()
8831         if not self.vpp_dead:
8832             self.logger.info(
8833                 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8834             self.logger.info(
8835                 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
8836
8837
8838 class TestNAT66(MethodHolder):
8839     """ NAT66 Test Cases """
8840
8841     @classmethod
8842     def setUpClass(cls):
8843         super(TestNAT66, cls).setUpClass()
8844
8845         try:
8846             cls.nat_addr = 'fd01:ff::2'
8847             cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
8848
8849             cls.create_pg_interfaces(range(2))
8850             cls.interfaces = list(cls.pg_interfaces)
8851
8852             for i in cls.interfaces:
8853                 i.admin_up()
8854                 i.config_ip6()
8855                 i.configure_ipv6_neighbors()
8856
8857         except Exception:
8858             super(TestNAT66, cls).tearDownClass()
8859             raise
8860
8861     @classmethod
8862     def tearDownClass(cls):
8863         super(TestNAT66, cls).tearDownClass()
8864
8865     def test_static(self):
8866         """ 1:1 NAT66 test """
8867         self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8868         self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8869         self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8870                                                self.nat_addr_n)
8871
8872         # in2out
8873         pkts = []
8874         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8875              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8876              TCP())
8877         pkts.append(p)
8878         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8879              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8880              UDP())
8881         pkts.append(p)
8882         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8883              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8884              ICMPv6EchoRequest())
8885         pkts.append(p)
8886         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8887              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8888              GRE() / IP() / TCP())
8889         pkts.append(p)
8890         self.pg0.add_stream(pkts)
8891         self.pg_enable_capture(self.pg_interfaces)
8892         self.pg_start()
8893         capture = self.pg1.get_capture(len(pkts))
8894         for packet in capture:
8895             try:
8896                 self.assertEqual(packet[IPv6].src, self.nat_addr)
8897                 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
8898                 self.assert_packet_checksums_valid(packet)
8899             except:
8900                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8901                 raise
8902
8903         # out2in
8904         pkts = []
8905         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8906              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8907              TCP())
8908         pkts.append(p)
8909         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8910              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8911              UDP())
8912         pkts.append(p)
8913         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8914              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8915              ICMPv6EchoReply())
8916         pkts.append(p)
8917         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8918              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8919              GRE() / IP() / TCP())
8920         pkts.append(p)
8921         self.pg1.add_stream(pkts)
8922         self.pg_enable_capture(self.pg_interfaces)
8923         self.pg_start()
8924         capture = self.pg0.get_capture(len(pkts))
8925         for packet in capture:
8926             try:
8927                 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
8928                 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8929                 self.assert_packet_checksums_valid(packet)
8930             except:
8931                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8932                 raise
8933
8934         sm = self.vapi.nat66_static_mapping_dump()
8935         self.assertEqual(len(sm), 1)
8936         self.assertEqual(sm[0].total_pkts, 8)
8937
8938     def test_check_no_translate(self):
8939         """ NAT66 translate only when egress interface is outside interface """
8940         self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8941         self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
8942         self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8943                                                self.nat_addr_n)
8944
8945         # in2out
8946         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8947              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8948              UDP())
8949         self.pg0.add_stream([p])
8950         self.pg_enable_capture(self.pg_interfaces)
8951         self.pg_start()
8952         capture = self.pg1.get_capture(1)
8953         packet = capture[0]
8954         try:
8955             self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
8956             self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
8957         except:
8958             self.logger.error(ppp("Unexpected or invalid packet:", packet))
8959             raise
8960
8961     def clear_nat66(self):
8962         """
8963         Clear NAT66 configuration.
8964         """
8965         interfaces = self.vapi.nat66_interface_dump()
8966         for intf in interfaces:
8967             self.vapi.nat66_add_del_interface(intf.sw_if_index,
8968                                               intf.is_inside,
8969                                               is_add=0)
8970
8971         static_mappings = self.vapi.nat66_static_mapping_dump()
8972         for sm in static_mappings:
8973             self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
8974                                                    sm.external_ip_address,
8975                                                    sm.vrf_id,
8976                                                    is_add=0)
8977
8978     def tearDown(self):
8979         super(TestNAT66, self).tearDown()
8980         if not self.vpp_dead:
8981             self.logger.info(self.vapi.cli("show nat66 interfaces"))
8982             self.logger.info(self.vapi.cli("show nat66 static mappings"))
8983             self.clear_nat66()
8984
8985
8986 if __name__ == '__main__':
8987     unittest.main(testRunner=VppTestRunner)