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