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