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