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