Tests: use self.assertNotIn().
[vpp.git] / test / test_nat.py
1 #!/usr/bin/env python
2
3 import socket
4 import unittest
5 import struct
6 import random
7
8 from framework import VppTestCase, VppTestRunner, running_extended_tests
9 from scapy.layers.inet import IP, TCP, UDP, ICMP
10 from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
11 from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply, \
12     ICMPv6ND_NS, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr, fragment6
13 from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
14 from scapy.layers.l2 import Ether, ARP, GRE
15 from scapy.data import IP_PROTOS
16 from scapy.packet import bind_layers, Raw
17 from util import ppp
18 from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
19 from time import sleep
20 from util import ip4_range
21 from vpp_papi import mac_pton
22 from syslog_rfc5424_parser import SyslogMessage, ParseError
23 from syslog_rfc5424_parser.constants import SyslogFacility, SyslogSeverity
24 from vpp_papi_provider import SYSLOG_SEVERITY
25 from io import BytesIO
26 from vpp_papi import VppEnum
27 from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \
28     IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \
29     PacketListField
30
31
32 # NAT HA protocol event data
33 class Event(Packet):
34     name = "Event"
35     fields_desc = [ByteEnumField("event_type", None,
36                                  {1: "add", 2: "del", 3: "refresh"}),
37                    ByteEnumField("protocol", None,
38                                  {0: "udp", 1: "tcp", 2: "icmp"}),
39                    ShortField("flags", 0),
40                    IPField("in_addr", None),
41                    IPField("out_addr", None),
42                    ShortField("in_port", None),
43                    ShortField("out_port", None),
44                    IPField("eh_addr", None),
45                    IPField("ehn_addr", None),
46                    ShortField("eh_port", None),
47                    ShortField("ehn_port", None),
48                    IntField("fib_index", None),
49                    IntField("total_pkts", 0),
50                    LongField("total_bytes", 0)]
51
52     def extract_padding(self, s):
53         return "", s
54
55
56 # NAT HA protocol header
57 class HANATStateSync(Packet):
58     name = "HA NAT state sync"
59     fields_desc = [XByteField("version", 1),
60                    FlagsField("flags", 0, 8, ['ACK']),
61                    FieldLenField("count", None, count_of="events"),
62                    IntField("sequence_number", 1),
63                    IntField("thread_index", 0),
64                    PacketListField("events", [], Event,
65                                    count_from=lambda pkt: pkt.count)]
66
67
68 class MethodHolder(VppTestCase):
69     """ NAT create capture and verify method holder """
70
71     def clear_nat44(self):
72         """
73         Clear NAT44 configuration.
74         """
75         if hasattr(self, 'pg7') and hasattr(self, 'pg8'):
76             # I found no elegant way to do this
77             self.vapi.ip_add_del_route(
78                 dst_address=self.pg7.remote_ip4n,
79                 dst_address_length=32,
80                 next_hop_address=self.pg7.remote_ip4n,
81                 next_hop_sw_if_index=self.pg7.sw_if_index,
82                 is_add=0)
83             self.vapi.ip_add_del_route(
84                 dst_address=self.pg8.remote_ip4n,
85                 dst_address_length=32,
86                 next_hop_address=self.pg8.remote_ip4n,
87                 next_hop_sw_if_index=self.pg8.sw_if_index,
88                 is_add=0)
89
90             for intf in [self.pg7, self.pg8]:
91                 self.vapi.ip_neighbor_add_del(
92                     intf.sw_if_index,
93                     intf.remote_mac,
94                     intf.remote_ip4,
95                     flags=(VppEnum.vl_api_ip_neighbor_flags_t.
96                            IP_API_NEIGHBOR_FLAG_STATIC),
97                     is_add=0)
98
99             if self.pg7.has_ip4_config:
100                 self.pg7.unconfig_ip4()
101
102         self.vapi.nat44_forwarding_enable_disable(0)
103
104         interfaces = self.vapi.nat44_interface_addr_dump()
105         for intf in interfaces:
106             self.vapi.nat44_add_del_interface_addr(intf.sw_if_index,
107                                                    twice_nat=intf.twice_nat,
108                                                    is_add=0)
109
110         self.vapi.nat_ipfix_enable_disable(enable=0,
111                                            src_port=self.ipfix_src_port,
112                                            domain_id=self.ipfix_domain_id)
113         self.ipfix_src_port = 4739
114         self.ipfix_domain_id = 1
115
116         self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
117
118         self.vapi.nat_ha_set_listener('0.0.0.0', 0)
119         self.vapi.nat_ha_set_failover('0.0.0.0', 0)
120
121         interfaces = self.vapi.nat44_interface_dump()
122         for intf in interfaces:
123             if intf.is_inside > 1:
124                 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
125                                                           0,
126                                                           is_add=0)
127             self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
128                                                       intf.is_inside,
129                                                       is_add=0)
130
131         interfaces = self.vapi.nat44_interface_output_feature_dump()
132         for intf in interfaces:
133             self.vapi.nat44_interface_add_del_output_feature(intf.sw_if_index,
134                                                              intf.is_inside,
135                                                              is_add=0)
136
137         static_mappings = self.vapi.nat44_static_mapping_dump()
138         for sm in static_mappings:
139             self.vapi.nat44_add_del_static_mapping(
140                 sm.local_ip_address,
141                 sm.external_ip_address,
142                 local_port=sm.local_port,
143                 external_port=sm.external_port,
144                 addr_only=sm.addr_only,
145                 vrf_id=sm.vrf_id,
146                 protocol=sm.protocol,
147                 twice_nat=sm.twice_nat,
148                 self_twice_nat=sm.self_twice_nat,
149                 out2in_only=sm.out2in_only,
150                 tag=sm.tag,
151                 external_sw_if_index=sm.external_sw_if_index,
152                 is_add=0)
153
154         lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
155         for lb_sm in lb_static_mappings:
156             self.vapi.nat44_add_del_lb_static_mapping(
157                 lb_sm.external_addr,
158                 lb_sm.external_port,
159                 lb_sm.protocol,
160                 twice_nat=lb_sm.twice_nat,
161                 self_twice_nat=lb_sm.self_twice_nat,
162                 out2in_only=lb_sm.out2in_only,
163                 tag=lb_sm.tag,
164                 is_add=0,
165                 local_num=0,
166                 locals=[])
167
168         identity_mappings = self.vapi.nat44_identity_mapping_dump()
169         for id_m in identity_mappings:
170             self.vapi.nat44_add_del_identity_mapping(
171                 addr_only=id_m.addr_only,
172                 ip=id_m.ip_address,
173                 port=id_m.port,
174                 sw_if_index=id_m.sw_if_index,
175                 vrf_id=id_m.vrf_id,
176                 protocol=id_m.protocol,
177                 is_add=0)
178
179         adresses = self.vapi.nat44_address_dump()
180         for addr in adresses:
181             self.vapi.nat44_add_del_address_range(addr.ip_address,
182                                                   addr.ip_address,
183                                                   twice_nat=addr.twice_nat,
184                                                   is_add=0)
185
186         self.vapi.nat_set_reass()
187         self.vapi.nat_set_reass(is_ip6=1)
188         self.verify_no_nat44_user()
189         self.vapi.nat_set_timeouts()
190         self.vapi.nat_set_addr_and_port_alloc_alg()
191         self.vapi.nat_set_mss_clamping()
192
193     def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
194                                  local_port=0, external_port=0, vrf_id=0,
195                                  is_add=1, external_sw_if_index=0xFFFFFFFF,
196                                  proto=0, twice_nat=0, self_twice_nat=0,
197                                  out2in_only=0, tag=""):
198         """
199         Add/delete NAT44 static mapping
200
201         :param local_ip: Local IP address
202         :param external_ip: External IP address
203         :param local_port: Local port number (Optional)
204         :param external_port: External port number (Optional)
205         :param vrf_id: VRF ID (Default 0)
206         :param is_add: 1 if add, 0 if delete (Default add)
207         :param external_sw_if_index: External interface instead of IP address
208         :param proto: IP protocol (Mandatory if port specified)
209         :param twice_nat: 1 if translate external host address and port
210         :param self_twice_nat: 1 if translate external host address and port
211                                whenever external host address equals
212                                local address of internal host
213         :param out2in_only: if 1 rule is matching only out2in direction
214         :param tag: Opaque string tag
215         """
216         addr_only = 1
217         if local_port and external_port:
218             addr_only = 0
219         l_ip = socket.inet_pton(socket.AF_INET, local_ip)
220         e_ip = socket.inet_pton(socket.AF_INET, external_ip)
221         self.vapi.nat44_add_del_static_mapping(
222             l_ip,
223             e_ip,
224             external_sw_if_index,
225             local_port,
226             external_port,
227             addr_only,
228             vrf_id,
229             proto,
230             twice_nat,
231             self_twice_nat,
232             out2in_only,
233             tag,
234             is_add)
235
236     def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
237         """
238         Add/delete NAT44 address
239
240         :param ip: IP address
241         :param is_add: 1 if add, 0 if delete (Default add)
242         :param twice_nat: twice NAT address for extenal hosts
243         """
244         nat_addr = socket.inet_pton(socket.AF_INET, ip)
245         self.vapi.nat44_add_del_address_range(nat_addr, nat_addr, is_add,
246                                               vrf_id=vrf_id,
247                                               twice_nat=twice_nat)
248
249     def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
250         """
251         Create packet stream for inside network
252
253         :param in_if: Inside interface
254         :param out_if: Outside interface
255         :param dst_ip: Destination address
256         :param ttl: TTL of generated packets
257         """
258         if dst_ip is None:
259             dst_ip = out_if.remote_ip4
260
261         pkts = []
262         # TCP
263         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
264              IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
265              TCP(sport=self.tcp_port_in, dport=20))
266         pkts.append(p)
267
268         # UDP
269         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
270              IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
271              UDP(sport=self.udp_port_in, dport=20))
272         pkts.append(p)
273
274         # ICMP
275         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
276              IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
277              ICMP(id=self.icmp_id_in, type='echo-request'))
278         pkts.append(p)
279
280         return pkts
281
282     def compose_ip6(self, ip4, pref, plen):
283         """
284         Compose IPv4-embedded IPv6 addresses
285
286         :param ip4: IPv4 address
287         :param pref: IPv6 prefix
288         :param plen: IPv6 prefix length
289         :returns: IPv4-embedded IPv6 addresses
290         """
291         pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
292         ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
293         if plen == 32:
294             pref_n[4] = ip4_n[0]
295             pref_n[5] = ip4_n[1]
296             pref_n[6] = ip4_n[2]
297             pref_n[7] = ip4_n[3]
298         elif plen == 40:
299             pref_n[5] = ip4_n[0]
300             pref_n[6] = ip4_n[1]
301             pref_n[7] = ip4_n[2]
302             pref_n[9] = ip4_n[3]
303         elif plen == 48:
304             pref_n[6] = ip4_n[0]
305             pref_n[7] = ip4_n[1]
306             pref_n[9] = ip4_n[2]
307             pref_n[10] = ip4_n[3]
308         elif plen == 56:
309             pref_n[7] = ip4_n[0]
310             pref_n[9] = ip4_n[1]
311             pref_n[10] = ip4_n[2]
312             pref_n[11] = ip4_n[3]
313         elif plen == 64:
314             pref_n[9] = ip4_n[0]
315             pref_n[10] = ip4_n[1]
316             pref_n[11] = ip4_n[2]
317             pref_n[12] = ip4_n[3]
318         elif plen == 96:
319             pref_n[12] = ip4_n[0]
320             pref_n[13] = ip4_n[1]
321             pref_n[14] = ip4_n[2]
322             pref_n[15] = ip4_n[3]
323         return socket.inet_ntop(socket.AF_INET6, ''.join(pref_n))
324
325     def extract_ip4(self, ip6, plen):
326         """
327         Extract IPv4 address embedded in IPv6 addresses
328
329         :param ip6: IPv6 address
330         :param plen: IPv6 prefix length
331         :returns: extracted IPv4 address
332         """
333         ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
334         ip4_n = [None] * 4
335         if plen == 32:
336             ip4_n[0] = ip6_n[4]
337             ip4_n[1] = ip6_n[5]
338             ip4_n[2] = ip6_n[6]
339             ip4_n[3] = ip6_n[7]
340         elif plen == 40:
341             ip4_n[0] = ip6_n[5]
342             ip4_n[1] = ip6_n[6]
343             ip4_n[2] = ip6_n[7]
344             ip4_n[3] = ip6_n[9]
345         elif plen == 48:
346             ip4_n[0] = ip6_n[6]
347             ip4_n[1] = ip6_n[7]
348             ip4_n[2] = ip6_n[9]
349             ip4_n[3] = ip6_n[10]
350         elif plen == 56:
351             ip4_n[0] = ip6_n[7]
352             ip4_n[1] = ip6_n[9]
353             ip4_n[2] = ip6_n[10]
354             ip4_n[3] = ip6_n[11]
355         elif plen == 64:
356             ip4_n[0] = ip6_n[9]
357             ip4_n[1] = ip6_n[10]
358             ip4_n[2] = ip6_n[11]
359             ip4_n[3] = ip6_n[12]
360         elif plen == 96:
361             ip4_n[0] = ip6_n[12]
362             ip4_n[1] = ip6_n[13]
363             ip4_n[2] = ip6_n[14]
364             ip4_n[3] = ip6_n[15]
365         return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
366
367     def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
368         """
369         Create IPv6 packet stream for inside network
370
371         :param in_if: Inside interface
372         :param out_if: Outside interface
373         :param ttl: Hop Limit of generated packets
374         :param pref: NAT64 prefix
375         :param plen: NAT64 prefix length
376         """
377         pkts = []
378         if pref is None:
379             dst = ''.join(['64:ff9b::', out_if.remote_ip4])
380         else:
381             dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
382
383         # TCP
384         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
385              IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
386              TCP(sport=self.tcp_port_in, dport=20))
387         pkts.append(p)
388
389         # UDP
390         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
391              IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
392              UDP(sport=self.udp_port_in, dport=20))
393         pkts.append(p)
394
395         # ICMP
396         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
397              IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
398              ICMPv6EchoRequest(id=self.icmp_id_in))
399         pkts.append(p)
400
401         return pkts
402
403     def create_stream_out(self, out_if, dst_ip=None, ttl=64,
404                           use_inside_ports=False):
405         """
406         Create packet stream for outside network
407
408         :param out_if: Outside interface
409         :param dst_ip: Destination IP address (Default use global NAT address)
410         :param ttl: TTL of generated packets
411         :param use_inside_ports: Use inside NAT ports as destination ports
412                instead of outside ports
413         """
414         if dst_ip is None:
415             dst_ip = self.nat_addr
416         if not use_inside_ports:
417             tcp_port = self.tcp_port_out
418             udp_port = self.udp_port_out
419             icmp_id = self.icmp_id_out
420         else:
421             tcp_port = self.tcp_port_in
422             udp_port = self.udp_port_in
423             icmp_id = self.icmp_id_in
424         pkts = []
425         # TCP
426         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
427              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
428              TCP(dport=tcp_port, sport=20))
429         pkts.append(p)
430
431         # UDP
432         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
433              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
434              UDP(dport=udp_port, sport=20))
435         pkts.append(p)
436
437         # ICMP
438         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
439              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
440              ICMP(id=icmp_id, type='echo-reply'))
441         pkts.append(p)
442
443         return pkts
444
445     def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
446         """
447         Create packet stream for outside network
448
449         :param out_if: Outside interface
450         :param dst_ip: Destination IP address (Default use global NAT address)
451         :param hl: HL of generated packets
452         """
453         pkts = []
454         # TCP
455         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
456              IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
457              TCP(dport=self.tcp_port_out, sport=20))
458         pkts.append(p)
459
460         # UDP
461         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
462              IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
463              UDP(dport=self.udp_port_out, sport=20))
464         pkts.append(p)
465
466         # ICMP
467         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
468              IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
469              ICMPv6EchoReply(id=self.icmp_id_out))
470         pkts.append(p)
471
472         return pkts
473
474     def verify_capture_out(self, capture, nat_ip=None, same_port=False,
475                            dst_ip=None, is_ip6=False):
476         """
477         Verify captured packets on outside network
478
479         :param capture: Captured packets
480         :param nat_ip: Translated IP address (Default use global NAT address)
481         :param same_port: Sorce port number is not translated (Default False)
482         :param dst_ip: Destination IP address (Default do not verify)
483         :param is_ip6: If L3 protocol is IPv6 (Default False)
484         """
485         if is_ip6:
486             IP46 = IPv6
487             ICMP46 = ICMPv6EchoRequest
488         else:
489             IP46 = IP
490             ICMP46 = ICMP
491         if nat_ip is None:
492             nat_ip = self.nat_addr
493         for packet in capture:
494             try:
495                 if not is_ip6:
496                     self.assert_packet_checksums_valid(packet)
497                 self.assertEqual(packet[IP46].src, nat_ip)
498                 if dst_ip is not None:
499                     self.assertEqual(packet[IP46].dst, dst_ip)
500                 if packet.haslayer(TCP):
501                     if same_port:
502                         self.assertEqual(packet[TCP].sport, self.tcp_port_in)
503                     else:
504                         self.assertNotEqual(
505                             packet[TCP].sport, self.tcp_port_in)
506                     self.tcp_port_out = packet[TCP].sport
507                     self.assert_packet_checksums_valid(packet)
508                 elif packet.haslayer(UDP):
509                     if same_port:
510                         self.assertEqual(packet[UDP].sport, self.udp_port_in)
511                     else:
512                         self.assertNotEqual(
513                             packet[UDP].sport, self.udp_port_in)
514                     self.udp_port_out = packet[UDP].sport
515                 else:
516                     if same_port:
517                         self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
518                     else:
519                         self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
520                     self.icmp_id_out = packet[ICMP46].id
521                     self.assert_packet_checksums_valid(packet)
522             except:
523                 self.logger.error(ppp("Unexpected or invalid packet "
524                                       "(outside network):", packet))
525                 raise
526
527     def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
528                                dst_ip=None):
529         """
530         Verify captured packets on outside network
531
532         :param capture: Captured packets
533         :param nat_ip: Translated IP address
534         :param same_port: Sorce port number is not translated (Default False)
535         :param dst_ip: Destination IP address (Default do not verify)
536         """
537         return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
538                                        True)
539
540     def verify_capture_in(self, capture, in_if):
541         """
542         Verify captured packets on inside network
543
544         :param capture: Captured packets
545         :param in_if: Inside interface
546         """
547         for packet in capture:
548             try:
549                 self.assert_packet_checksums_valid(packet)
550                 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
551                 if packet.haslayer(TCP):
552                     self.assertEqual(packet[TCP].dport, self.tcp_port_in)
553                 elif packet.haslayer(UDP):
554                     self.assertEqual(packet[UDP].dport, self.udp_port_in)
555                 else:
556                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
557             except:
558                 self.logger.error(ppp("Unexpected or invalid packet "
559                                       "(inside network):", packet))
560                 raise
561
562     def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
563         """
564         Verify captured IPv6 packets on inside network
565
566         :param capture: Captured packets
567         :param src_ip: Source IP
568         :param dst_ip: Destination IP address
569         """
570         for packet in capture:
571             try:
572                 self.assertEqual(packet[IPv6].src, src_ip)
573                 self.assertEqual(packet[IPv6].dst, dst_ip)
574                 self.assert_packet_checksums_valid(packet)
575                 if packet.haslayer(TCP):
576                     self.assertEqual(packet[TCP].dport, self.tcp_port_in)
577                 elif packet.haslayer(UDP):
578                     self.assertEqual(packet[UDP].dport, self.udp_port_in)
579                 else:
580                     self.assertEqual(packet[ICMPv6EchoReply].id,
581                                      self.icmp_id_in)
582             except:
583                 self.logger.error(ppp("Unexpected or invalid packet "
584                                       "(inside network):", packet))
585                 raise
586
587     def verify_capture_no_translation(self, capture, ingress_if, egress_if):
588         """
589         Verify captured packet that don't have to be translated
590
591         :param capture: Captured packets
592         :param ingress_if: Ingress interface
593         :param egress_if: Egress interface
594         """
595         for packet in capture:
596             try:
597                 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
598                 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
599                 if packet.haslayer(TCP):
600                     self.assertEqual(packet[TCP].sport, self.tcp_port_in)
601                 elif packet.haslayer(UDP):
602                     self.assertEqual(packet[UDP].sport, self.udp_port_in)
603                 else:
604                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
605             except:
606                 self.logger.error(ppp("Unexpected or invalid packet "
607                                       "(inside network):", packet))
608                 raise
609
610     def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
611                                             icmp_type=11):
612         """
613         Verify captured packets with ICMP errors on outside network
614
615         :param capture: Captured packets
616         :param src_ip: Translated IP address or IP address of VPP
617                        (Default use global NAT address)
618         :param icmp_type: Type of error ICMP packet
619                           we are expecting (Default 11)
620         """
621         if src_ip is None:
622             src_ip = self.nat_addr
623         for packet in capture:
624             try:
625                 self.assertEqual(packet[IP].src, src_ip)
626                 self.assertEqual(packet.haslayer(ICMP), 1)
627                 icmp = packet[ICMP]
628                 self.assertEqual(icmp.type, icmp_type)
629                 self.assertTrue(icmp.haslayer(IPerror))
630                 inner_ip = icmp[IPerror]
631                 if inner_ip.haslayer(TCPerror):
632                     self.assertEqual(inner_ip[TCPerror].dport,
633                                      self.tcp_port_out)
634                 elif inner_ip.haslayer(UDPerror):
635                     self.assertEqual(inner_ip[UDPerror].dport,
636                                      self.udp_port_out)
637                 else:
638                     self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
639             except:
640                 self.logger.error(ppp("Unexpected or invalid packet "
641                                       "(outside network):", packet))
642                 raise
643
644     def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
645         """
646         Verify captured packets with ICMP errors on inside network
647
648         :param capture: Captured packets
649         :param in_if: Inside interface
650         :param icmp_type: Type of error ICMP packet
651                           we are expecting (Default 11)
652         """
653         for packet in capture:
654             try:
655                 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
656                 self.assertEqual(packet.haslayer(ICMP), 1)
657                 icmp = packet[ICMP]
658                 self.assertEqual(icmp.type, icmp_type)
659                 self.assertTrue(icmp.haslayer(IPerror))
660                 inner_ip = icmp[IPerror]
661                 if inner_ip.haslayer(TCPerror):
662                     self.assertEqual(inner_ip[TCPerror].sport,
663                                      self.tcp_port_in)
664                 elif inner_ip.haslayer(UDPerror):
665                     self.assertEqual(inner_ip[UDPerror].sport,
666                                      self.udp_port_in)
667                 else:
668                     self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
669             except:
670                 self.logger.error(ppp("Unexpected or invalid packet "
671                                       "(inside network):", packet))
672                 raise
673
674     def create_stream_frag(self, src_if, dst, sport, dport, data,
675                            proto=IP_PROTOS.tcp, echo_reply=False):
676         """
677         Create fragmented packet stream
678
679         :param src_if: Source interface
680         :param dst: Destination IPv4 address
681         :param sport: Source port
682         :param dport: Destination port
683         :param data: Payload data
684         :param proto: protocol (TCP, UDP, ICMP)
685         :param echo_reply: use echo_reply if protocol is ICMP
686         :returns: Fragmets
687         """
688         if proto == IP_PROTOS.tcp:
689             p = (IP(src=src_if.remote_ip4, dst=dst) /
690                  TCP(sport=sport, dport=dport) /
691                  Raw(data))
692             p = p.__class__(str(p))
693             chksum = p['TCP'].chksum
694             proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
695         elif proto == IP_PROTOS.udp:
696             proto_header = UDP(sport=sport, dport=dport)
697         elif proto == IP_PROTOS.icmp:
698             if not echo_reply:
699                 proto_header = ICMP(id=sport, type='echo-request')
700             else:
701                 proto_header = ICMP(id=sport, type='echo-reply')
702         else:
703             raise Exception("Unsupported protocol")
704         id = random.randint(0, 65535)
705         pkts = []
706         if proto == IP_PROTOS.tcp:
707             raw = Raw(data[0:4])
708         else:
709             raw = Raw(data[0:16])
710         p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
711              IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
712              proto_header /
713              raw)
714         pkts.append(p)
715         if proto == IP_PROTOS.tcp:
716             raw = Raw(data[4:20])
717         else:
718             raw = Raw(data[16:32])
719         p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
720              IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
721                 proto=proto) /
722              raw)
723         pkts.append(p)
724         if proto == IP_PROTOS.tcp:
725             raw = Raw(data[20:])
726         else:
727             raw = Raw(data[32:])
728         p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
729              IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
730                 id=id) /
731              raw)
732         pkts.append(p)
733         return pkts
734
735     def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
736                                pref=None, plen=0, frag_size=128):
737         """
738         Create fragmented packet stream
739
740         :param src_if: Source interface
741         :param dst: Destination IPv4 address
742         :param sport: Source TCP port
743         :param dport: Destination TCP port
744         :param data: Payload data
745         :param pref: NAT64 prefix
746         :param plen: NAT64 prefix length
747         :param fragsize: size of fragments
748         :returns: Fragmets
749         """
750         if pref is None:
751             dst_ip6 = ''.join(['64:ff9b::', dst])
752         else:
753             dst_ip6 = self.compose_ip6(dst, pref, plen)
754
755         p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
756              IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
757              IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
758              TCP(sport=sport, dport=dport) /
759              Raw(data))
760
761         return fragment6(p, frag_size)
762
763     def reass_frags_and_verify(self, frags, src, dst):
764         """
765         Reassemble and verify fragmented packet
766
767         :param frags: Captured fragments
768         :param src: Source IPv4 address to verify
769         :param dst: Destination IPv4 address to verify
770
771         :returns: Reassembled IPv4 packet
772         """
773         buffer = BytesIO()
774         for p in frags:
775             self.assertEqual(p[IP].src, src)
776             self.assertEqual(p[IP].dst, dst)
777             self.assert_ip_checksum_valid(p)
778             buffer.seek(p[IP].frag * 8)
779             buffer.write(bytes(p[IP].payload))
780         ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
781                 proto=frags[0][IP].proto)
782         if ip.proto == IP_PROTOS.tcp:
783             p = (ip / TCP(buffer.getvalue()))
784             self.assert_tcp_checksum_valid(p)
785         elif ip.proto == IP_PROTOS.udp:
786             p = (ip / UDP(buffer.getvalue()[:8]) /
787                  Raw(buffer.getvalue()[8:]))
788         elif ip.proto == IP_PROTOS.icmp:
789             p = (ip / ICMP(buffer.getvalue()))
790         return p
791
792     def reass_frags_and_verify_ip6(self, frags, src, dst):
793         """
794         Reassemble and verify fragmented packet
795
796         :param frags: Captured fragments
797         :param src: Source IPv6 address to verify
798         :param dst: Destination IPv6 address to verify
799
800         :returns: Reassembled IPv6 packet
801         """
802         buffer = BytesIO()
803         for p in frags:
804             self.assertEqual(p[IPv6].src, src)
805             self.assertEqual(p[IPv6].dst, dst)
806             buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
807             buffer.write(bytes(p[IPv6ExtHdrFragment].payload))
808         ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
809                   nh=frags[0][IPv6ExtHdrFragment].nh)
810         if ip.nh == IP_PROTOS.tcp:
811             p = (ip / TCP(buffer.getvalue()))
812         elif ip.nh == IP_PROTOS.udp:
813             p = (ip / UDP(buffer.getvalue()))
814         self.assert_packet_checksums_valid(p)
815         return p
816
817     def initiate_tcp_session(self, in_if, out_if):
818         """
819         Initiates TCP session
820
821         :param in_if: Inside interface
822         :param out_if: Outside interface
823         """
824         try:
825             # SYN packet in->out
826             p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
827                  IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
828                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
829                      flags="S"))
830             in_if.add_stream(p)
831             self.pg_enable_capture(self.pg_interfaces)
832             self.pg_start()
833             capture = out_if.get_capture(1)
834             p = capture[0]
835             self.tcp_port_out = p[TCP].sport
836
837             # SYN + ACK packet out->in
838             p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
839                  IP(src=out_if.remote_ip4, dst=self.nat_addr) /
840                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
841                      flags="SA"))
842             out_if.add_stream(p)
843             self.pg_enable_capture(self.pg_interfaces)
844             self.pg_start()
845             in_if.get_capture(1)
846
847             # ACK packet in->out
848             p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
849                  IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
850                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
851                      flags="A"))
852             in_if.add_stream(p)
853             self.pg_enable_capture(self.pg_interfaces)
854             self.pg_start()
855             out_if.get_capture(1)
856
857         except:
858             self.logger.error("TCP 3 way handshake failed")
859             raise
860
861     def verify_ipfix_nat44_ses(self, data):
862         """
863         Verify IPFIX NAT44 session create/delete event
864
865         :param data: Decoded IPFIX data records
866         """
867         nat44_ses_create_num = 0
868         nat44_ses_delete_num = 0
869         self.assertEqual(6, len(data))
870         for record in data:
871             # natEvent
872             self.assertIn(ord(record[230]), [4, 5])
873             if ord(record[230]) == 4:
874                 nat44_ses_create_num += 1
875             else:
876                 nat44_ses_delete_num += 1
877             # sourceIPv4Address
878             self.assertEqual(self.pg0.remote_ip4n, record[8])
879             # postNATSourceIPv4Address
880             self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
881                              record[225])
882             # ingressVRFID
883             self.assertEqual(struct.pack("!I", 0), record[234])
884             # protocolIdentifier/sourceTransportPort/postNAPTSourceTransportPort
885             if IP_PROTOS.icmp == ord(record[4]):
886                 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
887                 self.assertEqual(struct.pack("!H", self.icmp_id_out),
888                                  record[227])
889             elif IP_PROTOS.tcp == ord(record[4]):
890                 self.assertEqual(struct.pack("!H", self.tcp_port_in),
891                                  record[7])
892                 self.assertEqual(struct.pack("!H", self.tcp_port_out),
893                                  record[227])
894             elif IP_PROTOS.udp == ord(record[4]):
895                 self.assertEqual(struct.pack("!H", self.udp_port_in),
896                                  record[7])
897                 self.assertEqual(struct.pack("!H", self.udp_port_out),
898                                  record[227])
899             else:
900                 self.fail("Invalid protocol")
901         self.assertEqual(3, nat44_ses_create_num)
902         self.assertEqual(3, nat44_ses_delete_num)
903
904     def verify_ipfix_addr_exhausted(self, data):
905         """
906         Verify IPFIX NAT addresses event
907
908         :param data: Decoded IPFIX data records
909         """
910         self.assertEqual(1, len(data))
911         record = data[0]
912         # natEvent
913         self.assertEqual(ord(record[230]), 3)
914         # natPoolID
915         self.assertEqual(struct.pack("!I", 0), record[283])
916
917     def verify_ipfix_max_sessions(self, data, limit):
918         """
919         Verify IPFIX maximum session entries exceeded event
920
921         :param data: Decoded IPFIX data records
922         :param limit: Number of maximum session entries that can be created.
923         """
924         self.assertEqual(1, len(data))
925         record = data[0]
926         # natEvent
927         self.assertEqual(ord(record[230]), 13)
928         # natQuotaExceededEvent
929         self.assertEqual(struct.pack("I", 1), record[466])
930         # maxSessionEntries
931         self.assertEqual(struct.pack("I", limit), record[471])
932
933     def verify_ipfix_max_bibs(self, data, limit):
934         """
935         Verify IPFIX maximum BIB entries exceeded event
936
937         :param data: Decoded IPFIX data records
938         :param limit: Number of maximum BIB entries that can be created.
939         """
940         self.assertEqual(1, len(data))
941         record = data[0]
942         # natEvent
943         self.assertEqual(ord(record[230]), 13)
944         # natQuotaExceededEvent
945         self.assertEqual(struct.pack("I", 2), record[466])
946         # maxBIBEntries
947         self.assertEqual(struct.pack("I", limit), record[472])
948
949     def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
950         """
951         Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
952
953         :param data: Decoded IPFIX data records
954         :param limit: Number of maximum fragments pending reassembly
955         :param src_addr: IPv6 source address
956         """
957         self.assertEqual(1, len(data))
958         record = data[0]
959         # natEvent
960         self.assertEqual(ord(record[230]), 13)
961         # natQuotaExceededEvent
962         self.assertEqual(struct.pack("I", 5), record[466])
963         # maxFragmentsPendingReassembly
964         self.assertEqual(struct.pack("I", limit), record[475])
965         # sourceIPv6Address
966         self.assertEqual(src_addr, record[27])
967
968     def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
969         """
970         Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
971
972         :param data: Decoded IPFIX data records
973         :param limit: Number of maximum fragments pending reassembly
974         :param src_addr: IPv4 source address
975         """
976         self.assertEqual(1, len(data))
977         record = data[0]
978         # natEvent
979         self.assertEqual(ord(record[230]), 13)
980         # natQuotaExceededEvent
981         self.assertEqual(struct.pack("I", 5), record[466])
982         # maxFragmentsPendingReassembly
983         self.assertEqual(struct.pack("I", limit), record[475])
984         # sourceIPv4Address
985         self.assertEqual(src_addr, record[8])
986
987     def verify_ipfix_bib(self, data, is_create, src_addr):
988         """
989         Verify IPFIX NAT64 BIB create and delete events
990
991         :param data: Decoded IPFIX data records
992         :param is_create: Create event if nonzero value otherwise delete event
993         :param src_addr: IPv6 source address
994         """
995         self.assertEqual(1, len(data))
996         record = data[0]
997         # natEvent
998         if is_create:
999             self.assertEqual(ord(record[230]), 10)
1000         else:
1001             self.assertEqual(ord(record[230]), 11)
1002         # sourceIPv6Address
1003         self.assertEqual(src_addr, record[27])
1004         # postNATSourceIPv4Address
1005         self.assertEqual(self.nat_addr_n, record[225])
1006         # protocolIdentifier
1007         self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
1008         # ingressVRFID
1009         self.assertEqual(struct.pack("!I", 0), record[234])
1010         # sourceTransportPort
1011         self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1012         # postNAPTSourceTransportPort
1013         self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1014
1015     def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
1016                                dst_port):
1017         """
1018         Verify IPFIX NAT64 session create and delete events
1019
1020         :param data: Decoded IPFIX data records
1021         :param is_create: Create event if nonzero value otherwise delete event
1022         :param src_addr: IPv6 source address
1023         :param dst_addr: IPv4 destination address
1024         :param dst_port: destination TCP port
1025         """
1026         self.assertEqual(1, len(data))
1027         record = data[0]
1028         # natEvent
1029         if is_create:
1030             self.assertEqual(ord(record[230]), 6)
1031         else:
1032             self.assertEqual(ord(record[230]), 7)
1033         # sourceIPv6Address
1034         self.assertEqual(src_addr, record[27])
1035         # destinationIPv6Address
1036         self.assertEqual(socket.inet_pton(socket.AF_INET6,
1037                                           self.compose_ip6(dst_addr,
1038                                                            '64:ff9b::',
1039                                                            96)),
1040                          record[28])
1041         # postNATSourceIPv4Address
1042         self.assertEqual(self.nat_addr_n, record[225])
1043         # postNATDestinationIPv4Address
1044         self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
1045                          record[226])
1046         # protocolIdentifier
1047         self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
1048         # ingressVRFID
1049         self.assertEqual(struct.pack("!I", 0), record[234])
1050         # sourceTransportPort
1051         self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1052         # postNAPTSourceTransportPort
1053         self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1054         # destinationTransportPort
1055         self.assertEqual(struct.pack("!H", dst_port), record[11])
1056         # postNAPTDestinationTransportPort
1057         self.assertEqual(struct.pack("!H", dst_port), record[228])
1058
1059     def verify_no_nat44_user(self):
1060         """ Verify that there is no NAT44 user """
1061         users = self.vapi.nat44_user_dump()
1062         self.assertEqual(len(users), 0)
1063         users = self.statistics.get_counter('/nat44/total-users')
1064         self.assertEqual(users[0][0], 0)
1065         sessions = self.statistics.get_counter('/nat44/total-sessions')
1066         self.assertEqual(sessions[0][0], 0)
1067
1068     def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
1069         """
1070         Verify IPFIX maximum entries per user exceeded event
1071
1072         :param data: Decoded IPFIX data records
1073         :param limit: Number of maximum entries per user
1074         :param src_addr: IPv4 source address
1075         """
1076         self.assertEqual(1, len(data))
1077         record = data[0]
1078         # natEvent
1079         self.assertEqual(ord(record[230]), 13)
1080         # natQuotaExceededEvent
1081         self.assertEqual(struct.pack("I", 3), record[466])
1082         # maxEntriesPerUser
1083         self.assertEqual(struct.pack("I", limit), record[473])
1084         # sourceIPv4Address
1085         self.assertEqual(src_addr, record[8])
1086
1087     def verify_syslog_apmap(self, data, is_add=True):
1088         message = data.decode('utf-8')
1089         try:
1090             message = SyslogMessage.parse(message)
1091         except ParseError as e:
1092             self.logger.error(e)
1093             raise
1094         else:
1095             self.assertEqual(message.severity, SyslogSeverity.info)
1096             self.assertEqual(message.appname, 'NAT')
1097             self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
1098             sd_params = message.sd.get('napmap')
1099             self.assertTrue(sd_params is not None)
1100             self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1101             self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1102             self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1103             self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1104             self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1105             self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1106             self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1107             self.assertTrue(sd_params.get('SSUBIX') is not None)
1108             self.assertEqual(sd_params.get('SVLAN'), '0')
1109
1110     def verify_syslog_sess(self, data, is_add=True, is_ip6=False):
1111         message = data.decode('utf-8')
1112         try:
1113             message = SyslogMessage.parse(message)
1114         except ParseError as e:
1115             self.logger.error(e)
1116             raise
1117         else:
1118             self.assertEqual(message.severity, SyslogSeverity.info)
1119             self.assertEqual(message.appname, 'NAT')
1120             self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL')
1121             sd_params = message.sd.get('nsess')
1122             self.assertTrue(sd_params is not None)
1123             if is_ip6:
1124                 self.assertEqual(sd_params.get('IATYP'), 'IPv6')
1125                 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
1126             else:
1127                 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1128                 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1129                 self.assertTrue(sd_params.get('SSUBIX') is not None)
1130             self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1131             self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1132             self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1133             self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1134             self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1135             self.assertEqual(sd_params.get('SVLAN'), '0')
1136             self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
1137             self.assertEqual(sd_params.get('XDPORT'),
1138                              "%d" % self.tcp_external_port)
1139
1140     def verify_mss_value(self, pkt, mss):
1141         """
1142         Verify TCP MSS value
1143
1144         :param pkt:
1145         :param mss:
1146         """
1147         if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
1148             raise TypeError("Not a TCP/IP packet")
1149
1150         for option in pkt[TCP].options:
1151             if option[0] == 'MSS':
1152                 self.assertEqual(option[1], mss)
1153                 self.assert_tcp_checksum_valid(pkt)
1154
1155     @staticmethod
1156     def proto2layer(proto):
1157         if proto == IP_PROTOS.tcp:
1158             return TCP
1159         elif proto == IP_PROTOS.udp:
1160             return UDP
1161         elif proto == IP_PROTOS.icmp:
1162             return ICMP
1163         else:
1164             raise Exception("Unsupported protocol")
1165
1166     def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1167         layer = self.proto2layer(proto)
1168
1169         if proto == IP_PROTOS.tcp:
1170             data = "A" * 4 + "B" * 16 + "C" * 3
1171         else:
1172             data = "A" * 16 + "B" * 16 + "C" * 3
1173         self.port_in = random.randint(1025, 65535)
1174
1175         reass = self.vapi.nat_reass_dump()
1176         reass_n_start = len(reass)
1177
1178         # in2out
1179         pkts = self.create_stream_frag(self.pg0,
1180                                        self.pg1.remote_ip4,
1181                                        self.port_in,
1182                                        20,
1183                                        data,
1184                                        proto)
1185         self.pg0.add_stream(pkts)
1186         self.pg_enable_capture(self.pg_interfaces)
1187         self.pg_start()
1188         frags = self.pg1.get_capture(len(pkts))
1189         if not dont_translate:
1190             p = self.reass_frags_and_verify(frags,
1191                                             self.nat_addr,
1192                                             self.pg1.remote_ip4)
1193         else:
1194             p = self.reass_frags_and_verify(frags,
1195                                             self.pg0.remote_ip4,
1196                                             self.pg1.remote_ip4)
1197         if proto != IP_PROTOS.icmp:
1198             if not dont_translate:
1199                 self.assertEqual(p[layer].dport, 20)
1200                 self.assertNotEqual(p[layer].sport, self.port_in)
1201             else:
1202                 self.assertEqual(p[layer].sport, self.port_in)
1203         else:
1204             if not dont_translate:
1205                 self.assertNotEqual(p[layer].id, self.port_in)
1206             else:
1207                 self.assertEqual(p[layer].id, self.port_in)
1208         self.assertEqual(data, p[Raw].load)
1209
1210         # out2in
1211         if not dont_translate:
1212             dst_addr = self.nat_addr
1213         else:
1214             dst_addr = self.pg0.remote_ip4
1215         if proto != IP_PROTOS.icmp:
1216             sport = 20
1217             dport = p[layer].sport
1218         else:
1219             sport = p[layer].id
1220             dport = 0
1221         pkts = self.create_stream_frag(self.pg1,
1222                                        dst_addr,
1223                                        sport,
1224                                        dport,
1225                                        data,
1226                                        proto,
1227                                        echo_reply=True)
1228         self.pg1.add_stream(pkts)
1229         self.pg_enable_capture(self.pg_interfaces)
1230         self.pg_start()
1231         frags = self.pg0.get_capture(len(pkts))
1232         p = self.reass_frags_and_verify(frags,
1233                                         self.pg1.remote_ip4,
1234                                         self.pg0.remote_ip4)
1235         if proto != IP_PROTOS.icmp:
1236             self.assertEqual(p[layer].sport, 20)
1237             self.assertEqual(p[layer].dport, self.port_in)
1238         else:
1239             self.assertEqual(p[layer].id, self.port_in)
1240         self.assertEqual(data, p[Raw].load)
1241
1242         reass = self.vapi.nat_reass_dump()
1243         reass_n_end = len(reass)
1244
1245         self.assertEqual(reass_n_end - reass_n_start, 2)
1246
1247     def frag_in_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1248         layer = self.proto2layer(proto)
1249
1250         if proto == IP_PROTOS.tcp:
1251             data = "A" * 4 + "B" * 16 + "C" * 3
1252         else:
1253             data = "A" * 16 + "B" * 16 + "C" * 3
1254         self.port_in = random.randint(1025, 65535)
1255
1256         for i in range(2):
1257             reass = self.vapi.nat_reass_dump()
1258             reass_n_start = len(reass)
1259
1260             # out2in
1261             pkts = self.create_stream_frag(self.pg0,
1262                                            self.server_out_addr,
1263                                            self.port_in,
1264                                            self.server_out_port,
1265                                            data,
1266                                            proto)
1267             self.pg0.add_stream(pkts)
1268             self.pg_enable_capture(self.pg_interfaces)
1269             self.pg_start()
1270             frags = self.pg1.get_capture(len(pkts))
1271             p = self.reass_frags_and_verify(frags,
1272                                             self.pg0.remote_ip4,
1273                                             self.server_in_addr)
1274             if proto != IP_PROTOS.icmp:
1275                 self.assertEqual(p[layer].sport, self.port_in)
1276                 self.assertEqual(p[layer].dport, self.server_in_port)
1277             else:
1278                 self.assertEqual(p[layer].id, self.port_in)
1279             self.assertEqual(data, p[Raw].load)
1280
1281             # in2out
1282             if proto != IP_PROTOS.icmp:
1283                 pkts = self.create_stream_frag(self.pg1,
1284                                                self.pg0.remote_ip4,
1285                                                self.server_in_port,
1286                                                p[layer].sport,
1287                                                data,
1288                                                proto)
1289             else:
1290                 pkts = self.create_stream_frag(self.pg1,
1291                                                self.pg0.remote_ip4,
1292                                                p[layer].id,
1293                                                0,
1294                                                data,
1295                                                proto,
1296                                                echo_reply=True)
1297             self.pg1.add_stream(pkts)
1298             self.pg_enable_capture(self.pg_interfaces)
1299             self.pg_start()
1300             frags = self.pg0.get_capture(len(pkts))
1301             p = self.reass_frags_and_verify(frags,
1302                                             self.server_out_addr,
1303                                             self.pg0.remote_ip4)
1304             if proto != IP_PROTOS.icmp:
1305                 self.assertEqual(p[layer].sport, self.server_out_port)
1306                 self.assertEqual(p[layer].dport, self.port_in)
1307             else:
1308                 self.assertEqual(p[layer].id, self.port_in)
1309             self.assertEqual(data, p[Raw].load)
1310
1311             reass = self.vapi.nat_reass_dump()
1312             reass_n_end = len(reass)
1313
1314             self.assertEqual(reass_n_end - reass_n_start, 2)
1315
1316     def reass_hairpinning(self, proto=IP_PROTOS.tcp):
1317         layer = self.proto2layer(proto)
1318
1319         if proto == IP_PROTOS.tcp:
1320             data = "A" * 4 + "B" * 16 + "C" * 3
1321         else:
1322             data = "A" * 16 + "B" * 16 + "C" * 3
1323
1324         # send packet from host to server
1325         pkts = self.create_stream_frag(self.pg0,
1326                                        self.nat_addr,
1327                                        self.host_in_port,
1328                                        self.server_out_port,
1329                                        data,
1330                                        proto)
1331         self.pg0.add_stream(pkts)
1332         self.pg_enable_capture(self.pg_interfaces)
1333         self.pg_start()
1334         frags = self.pg0.get_capture(len(pkts))
1335         p = self.reass_frags_and_verify(frags,
1336                                         self.nat_addr,
1337                                         self.server.ip4)
1338         if proto != IP_PROTOS.icmp:
1339             self.assertNotEqual(p[layer].sport, self.host_in_port)
1340             self.assertEqual(p[layer].dport, self.server_in_port)
1341         else:
1342             self.assertNotEqual(p[layer].id, self.host_in_port)
1343         self.assertEqual(data, p[Raw].load)
1344
1345     def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1346         layer = self.proto2layer(proto)
1347
1348         if proto == IP_PROTOS.tcp:
1349             data = "A" * 4 + "B" * 16 + "C" * 3
1350         else:
1351             data = "A" * 16 + "B" * 16 + "C" * 3
1352         self.port_in = random.randint(1025, 65535)
1353
1354         for i in range(2):
1355             # in2out
1356             pkts = self.create_stream_frag(self.pg0,
1357                                            self.pg1.remote_ip4,
1358                                            self.port_in,
1359                                            20,
1360                                            data,
1361                                            proto)
1362             pkts.reverse()
1363             self.pg0.add_stream(pkts)
1364             self.pg_enable_capture(self.pg_interfaces)
1365             self.pg_start()
1366             frags = self.pg1.get_capture(len(pkts))
1367             if not dont_translate:
1368                 p = self.reass_frags_and_verify(frags,
1369                                                 self.nat_addr,
1370                                                 self.pg1.remote_ip4)
1371             else:
1372                 p = self.reass_frags_and_verify(frags,
1373                                                 self.pg0.remote_ip4,
1374                                                 self.pg1.remote_ip4)
1375             if proto != IP_PROTOS.icmp:
1376                 if not dont_translate:
1377                     self.assertEqual(p[layer].dport, 20)
1378                     self.assertNotEqual(p[layer].sport, self.port_in)
1379                 else:
1380                     self.assertEqual(p[layer].sport, self.port_in)
1381             else:
1382                 if not dont_translate:
1383                     self.assertNotEqual(p[layer].id, self.port_in)
1384                 else:
1385                     self.assertEqual(p[layer].id, self.port_in)
1386             self.assertEqual(data, p[Raw].load)
1387
1388             # out2in
1389             if not dont_translate:
1390                 dst_addr = self.nat_addr
1391             else:
1392                 dst_addr = self.pg0.remote_ip4
1393             if proto != IP_PROTOS.icmp:
1394                 sport = 20
1395                 dport = p[layer].sport
1396             else:
1397                 sport = p[layer].id
1398                 dport = 0
1399             pkts = self.create_stream_frag(self.pg1,
1400                                            dst_addr,
1401                                            sport,
1402                                            dport,
1403                                            data,
1404                                            proto,
1405                                            echo_reply=True)
1406             pkts.reverse()
1407             self.pg1.add_stream(pkts)
1408             self.pg_enable_capture(self.pg_interfaces)
1409             self.pg_start()
1410             frags = self.pg0.get_capture(len(pkts))
1411             p = self.reass_frags_and_verify(frags,
1412                                             self.pg1.remote_ip4,
1413                                             self.pg0.remote_ip4)
1414             if proto != IP_PROTOS.icmp:
1415                 self.assertEqual(p[layer].sport, 20)
1416                 self.assertEqual(p[layer].dport, self.port_in)
1417             else:
1418                 self.assertEqual(p[layer].id, self.port_in)
1419             self.assertEqual(data, p[Raw].load)
1420
1421     def frag_out_of_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1422         layer = self.proto2layer(proto)
1423
1424         if proto == IP_PROTOS.tcp:
1425             data = "A" * 4 + "B" * 16 + "C" * 3
1426         else:
1427             data = "A" * 16 + "B" * 16 + "C" * 3
1428         self.port_in = random.randint(1025, 65535)
1429
1430         for i in range(2):
1431             # out2in
1432             pkts = self.create_stream_frag(self.pg0,
1433                                            self.server_out_addr,
1434                                            self.port_in,
1435                                            self.server_out_port,
1436                                            data,
1437                                            proto)
1438             pkts.reverse()
1439             self.pg0.add_stream(pkts)
1440             self.pg_enable_capture(self.pg_interfaces)
1441             self.pg_start()
1442             frags = self.pg1.get_capture(len(pkts))
1443             p = self.reass_frags_and_verify(frags,
1444                                             self.pg0.remote_ip4,
1445                                             self.server_in_addr)
1446             if proto != IP_PROTOS.icmp:
1447                 self.assertEqual(p[layer].dport, self.server_in_port)
1448                 self.assertEqual(p[layer].sport, self.port_in)
1449                 self.assertEqual(p[layer].dport, self.server_in_port)
1450             else:
1451                 self.assertEqual(p[layer].id, self.port_in)
1452             self.assertEqual(data, p[Raw].load)
1453
1454             # in2out
1455             if proto != IP_PROTOS.icmp:
1456                 pkts = self.create_stream_frag(self.pg1,
1457                                                self.pg0.remote_ip4,
1458                                                self.server_in_port,
1459                                                p[layer].sport,
1460                                                data,
1461                                                proto)
1462             else:
1463                 pkts = self.create_stream_frag(self.pg1,
1464                                                self.pg0.remote_ip4,
1465                                                p[layer].id,
1466                                                0,
1467                                                data,
1468                                                proto,
1469                                                echo_reply=True)
1470             pkts.reverse()
1471             self.pg1.add_stream(pkts)
1472             self.pg_enable_capture(self.pg_interfaces)
1473             self.pg_start()
1474             frags = self.pg0.get_capture(len(pkts))
1475             p = self.reass_frags_and_verify(frags,
1476                                             self.server_out_addr,
1477                                             self.pg0.remote_ip4)
1478             if proto != IP_PROTOS.icmp:
1479                 self.assertEqual(p[layer].sport, self.server_out_port)
1480                 self.assertEqual(p[layer].dport, self.port_in)
1481             else:
1482                 self.assertEqual(p[layer].id, self.port_in)
1483             self.assertEqual(data, p[Raw].load)
1484
1485
1486 class TestNAT44(MethodHolder):
1487     """ NAT44 Test Cases """
1488
1489     @classmethod
1490     def setUpClass(cls):
1491         super(TestNAT44, cls).setUpClass()
1492         cls.vapi.cli("set log class nat level debug")
1493
1494         try:
1495             cls.tcp_port_in = 6303
1496             cls.tcp_port_out = 6303
1497             cls.udp_port_in = 6304
1498             cls.udp_port_out = 6304
1499             cls.icmp_id_in = 6305
1500             cls.icmp_id_out = 6305
1501             cls.nat_addr = '10.0.0.3'
1502             cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
1503             cls.ipfix_src_port = 4739
1504             cls.ipfix_domain_id = 1
1505             cls.tcp_external_port = 80
1506             cls.udp_external_port = 69
1507
1508             cls.create_pg_interfaces(range(10))
1509             cls.interfaces = list(cls.pg_interfaces[0:4])
1510
1511             for i in cls.interfaces:
1512                 i.admin_up()
1513                 i.config_ip4()
1514                 i.resolve_arp()
1515
1516             cls.pg0.generate_remote_hosts(3)
1517             cls.pg0.configure_ipv4_neighbors()
1518
1519             cls.pg1.generate_remote_hosts(1)
1520             cls.pg1.configure_ipv4_neighbors()
1521
1522             cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
1523             cls.vapi.ip_table_add_del(is_add=1, table_id=10)
1524             cls.vapi.ip_table_add_del(is_add=1, table_id=20)
1525
1526             cls.pg4._local_ip4 = "172.16.255.1"
1527             cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1528             cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1529             cls.pg4.set_table_ip4(10)
1530             cls.pg5._local_ip4 = "172.17.255.3"
1531             cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1532             cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
1533             cls.pg5.set_table_ip4(10)
1534             cls.pg6._local_ip4 = "172.16.255.1"
1535             cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1536             cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1537             cls.pg6.set_table_ip4(20)
1538             for i in cls.overlapping_interfaces:
1539                 i.config_ip4()
1540                 i.admin_up()
1541                 i.resolve_arp()
1542
1543             cls.pg7.admin_up()
1544             cls.pg8.admin_up()
1545
1546             cls.pg9.generate_remote_hosts(2)
1547             cls.pg9.config_ip4()
1548             ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
1549             cls.vapi.sw_interface_add_del_address(
1550                 sw_if_index=cls.pg9.sw_if_index, address=ip_addr_n,
1551                 address_length=24)
1552             cls.pg9.admin_up()
1553             cls.pg9.resolve_arp()
1554             cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1555             cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1556             cls.pg9.resolve_arp()
1557
1558         except Exception:
1559             super(TestNAT44, cls).tearDownClass()
1560             raise
1561
1562     def test_dynamic(self):
1563         """ NAT44 dynamic translation test """
1564         self.nat44_add_address(self.nat_addr)
1565         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1566         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1567                                                   is_inside=0)
1568
1569         # in2out
1570         tcpn = self.statistics.get_counter(
1571             '/err/nat44-in2out-slowpath/TCP packets')
1572         udpn = self.statistics.get_counter(
1573             '/err/nat44-in2out-slowpath/UDP packets')
1574         icmpn = self.statistics.get_counter(
1575             '/err/nat44-in2out-slowpath/ICMP packets')
1576         totaln = self.statistics.get_counter(
1577             '/err/nat44-in2out-slowpath/good in2out packets processed')
1578
1579         pkts = self.create_stream_in(self.pg0, self.pg1)
1580         self.pg0.add_stream(pkts)
1581         self.pg_enable_capture(self.pg_interfaces)
1582         self.pg_start()
1583         capture = self.pg1.get_capture(len(pkts))
1584         self.verify_capture_out(capture)
1585
1586         err = self.statistics.get_counter(
1587             '/err/nat44-in2out-slowpath/TCP packets')
1588         self.assertEqual(err - tcpn, 1)
1589         err = self.statistics.get_counter(
1590             '/err/nat44-in2out-slowpath/UDP packets')
1591         self.assertEqual(err - udpn, 1)
1592         err = self.statistics.get_counter(
1593             '/err/nat44-in2out-slowpath/ICMP packets')
1594         self.assertEqual(err - icmpn, 1)
1595         err = self.statistics.get_counter(
1596             '/err/nat44-in2out-slowpath/good in2out packets processed')
1597         self.assertEqual(err - totaln, 3)
1598
1599         # out2in
1600         tcpn = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
1601         udpn = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
1602         icmpn = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
1603         totaln = self.statistics.get_counter(
1604             '/err/nat44-out2in/good out2in packets processed')
1605
1606         pkts = self.create_stream_out(self.pg1)
1607         self.pg1.add_stream(pkts)
1608         self.pg_enable_capture(self.pg_interfaces)
1609         self.pg_start()
1610         capture = self.pg0.get_capture(len(pkts))
1611         self.verify_capture_in(capture, self.pg0)
1612
1613         err = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
1614         self.assertEqual(err - tcpn, 1)
1615         err = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
1616         self.assertEqual(err - udpn, 1)
1617         err = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
1618         self.assertEqual(err - icmpn, 1)
1619         err = self.statistics.get_counter(
1620             '/err/nat44-out2in/good out2in packets processed')
1621         self.assertEqual(err - totaln, 3)
1622
1623         users = self.statistics.get_counter('/nat44/total-users')
1624         self.assertEqual(users[0][0], 1)
1625         sessions = self.statistics.get_counter('/nat44/total-sessions')
1626         self.assertEqual(sessions[0][0], 3)
1627
1628     def test_dynamic_icmp_errors_in2out_ttl_1(self):
1629         """ NAT44 handling of client packets with TTL=1 """
1630
1631         self.nat44_add_address(self.nat_addr)
1632         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1633         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1634                                                   is_inside=0)
1635
1636         # Client side - generate traffic
1637         pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1638         self.pg0.add_stream(pkts)
1639         self.pg_enable_capture(self.pg_interfaces)
1640         self.pg_start()
1641
1642         # Client side - verify ICMP type 11 packets
1643         capture = self.pg0.get_capture(len(pkts))
1644         self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1645
1646     def test_dynamic_icmp_errors_out2in_ttl_1(self):
1647         """ NAT44 handling of server packets with TTL=1 """
1648
1649         self.nat44_add_address(self.nat_addr)
1650         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1651         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1652                                                   is_inside=0)
1653
1654         # Client side - create sessions
1655         pkts = self.create_stream_in(self.pg0, self.pg1)
1656         self.pg0.add_stream(pkts)
1657         self.pg_enable_capture(self.pg_interfaces)
1658         self.pg_start()
1659
1660         # Server side - generate traffic
1661         capture = self.pg1.get_capture(len(pkts))
1662         self.verify_capture_out(capture)
1663         pkts = self.create_stream_out(self.pg1, ttl=1)
1664         self.pg1.add_stream(pkts)
1665         self.pg_enable_capture(self.pg_interfaces)
1666         self.pg_start()
1667
1668         # Server side - verify ICMP type 11 packets
1669         capture = self.pg1.get_capture(len(pkts))
1670         self.verify_capture_out_with_icmp_errors(capture,
1671                                                  src_ip=self.pg1.local_ip4)
1672
1673     def test_dynamic_icmp_errors_in2out_ttl_2(self):
1674         """ NAT44 handling of error responses to client packets with TTL=2 """
1675
1676         self.nat44_add_address(self.nat_addr)
1677         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1678         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1679                                                   is_inside=0)
1680
1681         # Client side - generate traffic
1682         pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1683         self.pg0.add_stream(pkts)
1684         self.pg_enable_capture(self.pg_interfaces)
1685         self.pg_start()
1686
1687         # Server side - simulate ICMP type 11 response
1688         capture = self.pg1.get_capture(len(pkts))
1689         pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1690                 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1691                 ICMP(type=11) / packet[IP] for packet in capture]
1692         self.pg1.add_stream(pkts)
1693         self.pg_enable_capture(self.pg_interfaces)
1694         self.pg_start()
1695
1696         # Client side - verify ICMP type 11 packets
1697         capture = self.pg0.get_capture(len(pkts))
1698         self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1699
1700     def test_dynamic_icmp_errors_out2in_ttl_2(self):
1701         """ NAT44 handling of error responses to server packets with TTL=2 """
1702
1703         self.nat44_add_address(self.nat_addr)
1704         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1705         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1706                                                   is_inside=0)
1707
1708         # Client side - create sessions
1709         pkts = self.create_stream_in(self.pg0, self.pg1)
1710         self.pg0.add_stream(pkts)
1711         self.pg_enable_capture(self.pg_interfaces)
1712         self.pg_start()
1713
1714         # Server side - generate traffic
1715         capture = self.pg1.get_capture(len(pkts))
1716         self.verify_capture_out(capture)
1717         pkts = self.create_stream_out(self.pg1, ttl=2)
1718         self.pg1.add_stream(pkts)
1719         self.pg_enable_capture(self.pg_interfaces)
1720         self.pg_start()
1721
1722         # Client side - simulate ICMP type 11 response
1723         capture = self.pg0.get_capture(len(pkts))
1724         pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1725                 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1726                 ICMP(type=11) / packet[IP] for packet in capture]
1727         self.pg0.add_stream(pkts)
1728         self.pg_enable_capture(self.pg_interfaces)
1729         self.pg_start()
1730
1731         # Server side - verify ICMP type 11 packets
1732         capture = self.pg1.get_capture(len(pkts))
1733         self.verify_capture_out_with_icmp_errors(capture)
1734
1735     def test_ping_out_interface_from_outside(self):
1736         """ Ping NAT44 out interface from outside network """
1737
1738         self.nat44_add_address(self.nat_addr)
1739         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1740         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1741                                                   is_inside=0)
1742
1743         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1744              IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1745              ICMP(id=self.icmp_id_out, type='echo-request'))
1746         pkts = [p]
1747         self.pg1.add_stream(pkts)
1748         self.pg_enable_capture(self.pg_interfaces)
1749         self.pg_start()
1750         capture = self.pg1.get_capture(len(pkts))
1751         packet = capture[0]
1752         try:
1753             self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1754             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1755             self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1756             self.assertEqual(packet[ICMP].type, 0)  # echo reply
1757         except:
1758             self.logger.error(ppp("Unexpected or invalid packet "
1759                                   "(outside network):", packet))
1760             raise
1761
1762     def test_ping_internal_host_from_outside(self):
1763         """ Ping internal host from outside network """
1764
1765         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1766         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1767         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1768                                                   is_inside=0)
1769
1770         # out2in
1771         pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1772                IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
1773                ICMP(id=self.icmp_id_out, type='echo-request'))
1774         self.pg1.add_stream(pkt)
1775         self.pg_enable_capture(self.pg_interfaces)
1776         self.pg_start()
1777         capture = self.pg0.get_capture(1)
1778         self.verify_capture_in(capture, self.pg0)
1779         self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1780
1781         # in2out
1782         pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1783                IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1784                ICMP(id=self.icmp_id_in, type='echo-reply'))
1785         self.pg0.add_stream(pkt)
1786         self.pg_enable_capture(self.pg_interfaces)
1787         self.pg_start()
1788         capture = self.pg1.get_capture(1)
1789         self.verify_capture_out(capture, same_port=True)
1790         self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1791
1792     def test_forwarding(self):
1793         """ NAT44 forwarding test """
1794
1795         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1796         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1797                                                   is_inside=0)
1798         self.vapi.nat44_forwarding_enable_disable(1)
1799
1800         real_ip = self.pg0.remote_ip4n
1801         alias_ip = self.nat_addr_n
1802         self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1803                                                external_ip=alias_ip)
1804
1805         try:
1806             # static mapping match
1807
1808             pkts = self.create_stream_out(self.pg1)
1809             self.pg1.add_stream(pkts)
1810             self.pg_enable_capture(self.pg_interfaces)
1811             self.pg_start()
1812             capture = self.pg0.get_capture(len(pkts))
1813             self.verify_capture_in(capture, self.pg0)
1814
1815             pkts = self.create_stream_in(self.pg0, self.pg1)
1816             self.pg0.add_stream(pkts)
1817             self.pg_enable_capture(self.pg_interfaces)
1818             self.pg_start()
1819             capture = self.pg1.get_capture(len(pkts))
1820             self.verify_capture_out(capture, same_port=True)
1821
1822             # no static mapping match
1823
1824             host0 = self.pg0.remote_hosts[0]
1825             self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1826             try:
1827                 pkts = self.create_stream_out(self.pg1,
1828                                               dst_ip=self.pg0.remote_ip4,
1829                                               use_inside_ports=True)
1830                 self.pg1.add_stream(pkts)
1831                 self.pg_enable_capture(self.pg_interfaces)
1832                 self.pg_start()
1833                 capture = self.pg0.get_capture(len(pkts))
1834                 self.verify_capture_in(capture, self.pg0)
1835
1836                 pkts = self.create_stream_in(self.pg0, self.pg1)
1837                 self.pg0.add_stream(pkts)
1838                 self.pg_enable_capture(self.pg_interfaces)
1839                 self.pg_start()
1840                 capture = self.pg1.get_capture(len(pkts))
1841                 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1842                                         same_port=True)
1843             finally:
1844                 self.pg0.remote_hosts[0] = host0
1845
1846         finally:
1847             self.vapi.nat44_forwarding_enable_disable(0)
1848             self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1849                                                    external_ip=alias_ip,
1850                                                    is_add=0)
1851
1852     def test_static_in(self):
1853         """ 1:1 NAT initialized from inside network """
1854
1855         nat_ip = "10.0.0.10"
1856         self.tcp_port_out = 6303
1857         self.udp_port_out = 6304
1858         self.icmp_id_out = 6305
1859
1860         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1861         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1862         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1863                                                   is_inside=0)
1864         sm = self.vapi.nat44_static_mapping_dump()
1865         self.assertEqual(len(sm), 1)
1866         self.assertEqual((sm[0].tag).split('\0', 1)[0], '')
1867         self.assertEqual(sm[0].protocol, 0)
1868         self.assertEqual(sm[0].local_port, 0)
1869         self.assertEqual(sm[0].external_port, 0)
1870
1871         # in2out
1872         pkts = self.create_stream_in(self.pg0, self.pg1)
1873         self.pg0.add_stream(pkts)
1874         self.pg_enable_capture(self.pg_interfaces)
1875         self.pg_start()
1876         capture = self.pg1.get_capture(len(pkts))
1877         self.verify_capture_out(capture, nat_ip, True)
1878
1879         # out2in
1880         pkts = self.create_stream_out(self.pg1, nat_ip)
1881         self.pg1.add_stream(pkts)
1882         self.pg_enable_capture(self.pg_interfaces)
1883         self.pg_start()
1884         capture = self.pg0.get_capture(len(pkts))
1885         self.verify_capture_in(capture, self.pg0)
1886
1887     def test_static_out(self):
1888         """ 1:1 NAT initialized from outside network """
1889
1890         nat_ip = "10.0.0.20"
1891         self.tcp_port_out = 6303
1892         self.udp_port_out = 6304
1893         self.icmp_id_out = 6305
1894         tag = "testTAG"
1895
1896         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
1897         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1898         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1899                                                   is_inside=0)
1900         sm = self.vapi.nat44_static_mapping_dump()
1901         self.assertEqual(len(sm), 1)
1902         self.assertEqual((sm[0].tag).split('\0', 1)[0], tag)
1903
1904         # out2in
1905         pkts = self.create_stream_out(self.pg1, nat_ip)
1906         self.pg1.add_stream(pkts)
1907         self.pg_enable_capture(self.pg_interfaces)
1908         self.pg_start()
1909         capture = self.pg0.get_capture(len(pkts))
1910         self.verify_capture_in(capture, self.pg0)
1911
1912         # in2out
1913         pkts = self.create_stream_in(self.pg0, self.pg1)
1914         self.pg0.add_stream(pkts)
1915         self.pg_enable_capture(self.pg_interfaces)
1916         self.pg_start()
1917         capture = self.pg1.get_capture(len(pkts))
1918         self.verify_capture_out(capture, nat_ip, True)
1919
1920     def test_static_with_port_in(self):
1921         """ 1:1 NAPT initialized from inside network """
1922
1923         self.tcp_port_out = 3606
1924         self.udp_port_out = 3607
1925         self.icmp_id_out = 3608
1926
1927         self.nat44_add_address(self.nat_addr)
1928         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1929                                       self.tcp_port_in, self.tcp_port_out,
1930                                       proto=IP_PROTOS.tcp)
1931         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1932                                       self.udp_port_in, self.udp_port_out,
1933                                       proto=IP_PROTOS.udp)
1934         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1935                                       self.icmp_id_in, self.icmp_id_out,
1936                                       proto=IP_PROTOS.icmp)
1937         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1938         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1939                                                   is_inside=0)
1940
1941         # in2out
1942         pkts = self.create_stream_in(self.pg0, self.pg1)
1943         self.pg0.add_stream(pkts)
1944         self.pg_enable_capture(self.pg_interfaces)
1945         self.pg_start()
1946         capture = self.pg1.get_capture(len(pkts))
1947         self.verify_capture_out(capture)
1948
1949         # out2in
1950         pkts = self.create_stream_out(self.pg1)
1951         self.pg1.add_stream(pkts)
1952         self.pg_enable_capture(self.pg_interfaces)
1953         self.pg_start()
1954         capture = self.pg0.get_capture(len(pkts))
1955         self.verify_capture_in(capture, self.pg0)
1956
1957     def test_static_with_port_out(self):
1958         """ 1:1 NAPT initialized from outside network """
1959
1960         self.tcp_port_out = 30606
1961         self.udp_port_out = 30607
1962         self.icmp_id_out = 30608
1963
1964         self.nat44_add_address(self.nat_addr)
1965         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1966                                       self.tcp_port_in, self.tcp_port_out,
1967                                       proto=IP_PROTOS.tcp)
1968         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1969                                       self.udp_port_in, self.udp_port_out,
1970                                       proto=IP_PROTOS.udp)
1971         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1972                                       self.icmp_id_in, self.icmp_id_out,
1973                                       proto=IP_PROTOS.icmp)
1974         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1975         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1976                                                   is_inside=0)
1977
1978         # out2in
1979         pkts = self.create_stream_out(self.pg1)
1980         self.pg1.add_stream(pkts)
1981         self.pg_enable_capture(self.pg_interfaces)
1982         self.pg_start()
1983         capture = self.pg0.get_capture(len(pkts))
1984         self.verify_capture_in(capture, self.pg0)
1985
1986         # in2out
1987         pkts = self.create_stream_in(self.pg0, self.pg1)
1988         self.pg0.add_stream(pkts)
1989         self.pg_enable_capture(self.pg_interfaces)
1990         self.pg_start()
1991         capture = self.pg1.get_capture(len(pkts))
1992         self.verify_capture_out(capture)
1993
1994     def test_static_vrf_aware(self):
1995         """ 1:1 NAT VRF awareness """
1996
1997         nat_ip1 = "10.0.0.30"
1998         nat_ip2 = "10.0.0.40"
1999         self.tcp_port_out = 6303
2000         self.udp_port_out = 6304
2001         self.icmp_id_out = 6305
2002
2003         self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
2004                                       vrf_id=10)
2005         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
2006                                       vrf_id=10)
2007         self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2008                                                   is_inside=0)
2009         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2010         self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
2011
2012         # inside interface VRF match NAT44 static mapping VRF
2013         pkts = self.create_stream_in(self.pg4, self.pg3)
2014         self.pg4.add_stream(pkts)
2015         self.pg_enable_capture(self.pg_interfaces)
2016         self.pg_start()
2017         capture = self.pg3.get_capture(len(pkts))
2018         self.verify_capture_out(capture, nat_ip1, True)
2019
2020         # inside interface VRF don't match NAT44 static mapping VRF (packets
2021         # are dropped)
2022         pkts = self.create_stream_in(self.pg0, self.pg3)
2023         self.pg0.add_stream(pkts)
2024         self.pg_enable_capture(self.pg_interfaces)
2025         self.pg_start()
2026         self.pg3.assert_nothing_captured()
2027
2028     def test_dynamic_to_static(self):
2029         """ Switch from dynamic translation to 1:1NAT """
2030         nat_ip = "10.0.0.10"
2031         self.tcp_port_out = 6303
2032         self.udp_port_out = 6304
2033         self.icmp_id_out = 6305
2034
2035         self.nat44_add_address(self.nat_addr)
2036         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2037         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2038                                                   is_inside=0)
2039
2040         # dynamic
2041         pkts = self.create_stream_in(self.pg0, self.pg1)
2042         self.pg0.add_stream(pkts)
2043         self.pg_enable_capture(self.pg_interfaces)
2044         self.pg_start()
2045         capture = self.pg1.get_capture(len(pkts))
2046         self.verify_capture_out(capture)
2047
2048         # 1:1NAT
2049         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2050         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2051         self.assertEqual(len(sessions), 0)
2052         pkts = self.create_stream_in(self.pg0, self.pg1)
2053         self.pg0.add_stream(pkts)
2054         self.pg_enable_capture(self.pg_interfaces)
2055         self.pg_start()
2056         capture = self.pg1.get_capture(len(pkts))
2057         self.verify_capture_out(capture, nat_ip, True)
2058
2059     def test_identity_nat(self):
2060         """ Identity NAT """
2061
2062         self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n)
2063         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2064         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2065                                                   is_inside=0)
2066
2067         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2068              IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2069              TCP(sport=12345, dport=56789))
2070         self.pg1.add_stream(p)
2071         self.pg_enable_capture(self.pg_interfaces)
2072         self.pg_start()
2073         capture = self.pg0.get_capture(1)
2074         p = capture[0]
2075         try:
2076             ip = p[IP]
2077             tcp = p[TCP]
2078             self.assertEqual(ip.dst, self.pg0.remote_ip4)
2079             self.assertEqual(ip.src, self.pg1.remote_ip4)
2080             self.assertEqual(tcp.dport, 56789)
2081             self.assertEqual(tcp.sport, 12345)
2082             self.assert_packet_checksums_valid(p)
2083         except:
2084             self.logger.error(ppp("Unexpected or invalid packet:", p))
2085             raise
2086
2087         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2088         self.assertEqual(len(sessions), 0)
2089         self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n,
2090                                                  vrf_id=1)
2091         identity_mappings = self.vapi.nat44_identity_mapping_dump()
2092         self.assertEqual(len(identity_mappings), 2)
2093
2094     def test_multiple_inside_interfaces(self):
2095         """ NAT44 multiple non-overlapping address space inside interfaces """
2096
2097         self.nat44_add_address(self.nat_addr)
2098         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2099         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2100         self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2101                                                   is_inside=0)
2102
2103         # between two NAT44 inside interfaces (no translation)
2104         pkts = self.create_stream_in(self.pg0, self.pg1)
2105         self.pg0.add_stream(pkts)
2106         self.pg_enable_capture(self.pg_interfaces)
2107         self.pg_start()
2108         capture = self.pg1.get_capture(len(pkts))
2109         self.verify_capture_no_translation(capture, self.pg0, self.pg1)
2110
2111         # from NAT44 inside to interface without NAT44 feature (no translation)
2112         pkts = self.create_stream_in(self.pg0, self.pg2)
2113         self.pg0.add_stream(pkts)
2114         self.pg_enable_capture(self.pg_interfaces)
2115         self.pg_start()
2116         capture = self.pg2.get_capture(len(pkts))
2117         self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2118
2119         # in2out 1st interface
2120         pkts = self.create_stream_in(self.pg0, self.pg3)
2121         self.pg0.add_stream(pkts)
2122         self.pg_enable_capture(self.pg_interfaces)
2123         self.pg_start()
2124         capture = self.pg3.get_capture(len(pkts))
2125         self.verify_capture_out(capture)
2126
2127         # out2in 1st interface
2128         pkts = self.create_stream_out(self.pg3)
2129         self.pg3.add_stream(pkts)
2130         self.pg_enable_capture(self.pg_interfaces)
2131         self.pg_start()
2132         capture = self.pg0.get_capture(len(pkts))
2133         self.verify_capture_in(capture, self.pg0)
2134
2135         # in2out 2nd interface
2136         pkts = self.create_stream_in(self.pg1, self.pg3)
2137         self.pg1.add_stream(pkts)
2138         self.pg_enable_capture(self.pg_interfaces)
2139         self.pg_start()
2140         capture = self.pg3.get_capture(len(pkts))
2141         self.verify_capture_out(capture)
2142
2143         # out2in 2nd interface
2144         pkts = self.create_stream_out(self.pg3)
2145         self.pg3.add_stream(pkts)
2146         self.pg_enable_capture(self.pg_interfaces)
2147         self.pg_start()
2148         capture = self.pg1.get_capture(len(pkts))
2149         self.verify_capture_in(capture, self.pg1)
2150
2151     def test_inside_overlapping_interfaces(self):
2152         """ NAT44 multiple inside interfaces with overlapping address space """
2153
2154         static_nat_ip = "10.0.0.10"
2155         self.nat44_add_address(self.nat_addr)
2156         self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2157                                                   is_inside=0)
2158         self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
2159         self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
2160         self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
2161         self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2162                                       vrf_id=20)
2163
2164         # between NAT44 inside interfaces with same VRF (no translation)
2165         pkts = self.create_stream_in(self.pg4, self.pg5)
2166         self.pg4.add_stream(pkts)
2167         self.pg_enable_capture(self.pg_interfaces)
2168         self.pg_start()
2169         capture = self.pg5.get_capture(len(pkts))
2170         self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2171
2172         # between NAT44 inside interfaces with different VRF (hairpinning)
2173         p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2174              IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2175              TCP(sport=1234, dport=5678))
2176         self.pg4.add_stream(p)
2177         self.pg_enable_capture(self.pg_interfaces)
2178         self.pg_start()
2179         capture = self.pg6.get_capture(1)
2180         p = capture[0]
2181         try:
2182             ip = p[IP]
2183             tcp = p[TCP]
2184             self.assertEqual(ip.src, self.nat_addr)
2185             self.assertEqual(ip.dst, self.pg6.remote_ip4)
2186             self.assertNotEqual(tcp.sport, 1234)
2187             self.assertEqual(tcp.dport, 5678)
2188         except:
2189             self.logger.error(ppp("Unexpected or invalid packet:", p))
2190             raise
2191
2192         # in2out 1st interface
2193         pkts = self.create_stream_in(self.pg4, self.pg3)
2194         self.pg4.add_stream(pkts)
2195         self.pg_enable_capture(self.pg_interfaces)
2196         self.pg_start()
2197         capture = self.pg3.get_capture(len(pkts))
2198         self.verify_capture_out(capture)
2199
2200         # out2in 1st interface
2201         pkts = self.create_stream_out(self.pg3)
2202         self.pg3.add_stream(pkts)
2203         self.pg_enable_capture(self.pg_interfaces)
2204         self.pg_start()
2205         capture = self.pg4.get_capture(len(pkts))
2206         self.verify_capture_in(capture, self.pg4)
2207
2208         # in2out 2nd interface
2209         pkts = self.create_stream_in(self.pg5, self.pg3)
2210         self.pg5.add_stream(pkts)
2211         self.pg_enable_capture(self.pg_interfaces)
2212         self.pg_start()
2213         capture = self.pg3.get_capture(len(pkts))
2214         self.verify_capture_out(capture)
2215
2216         # out2in 2nd interface
2217         pkts = self.create_stream_out(self.pg3)
2218         self.pg3.add_stream(pkts)
2219         self.pg_enable_capture(self.pg_interfaces)
2220         self.pg_start()
2221         capture = self.pg5.get_capture(len(pkts))
2222         self.verify_capture_in(capture, self.pg5)
2223
2224         # pg5 session dump
2225         addresses = self.vapi.nat44_address_dump()
2226         self.assertEqual(len(addresses), 1)
2227         sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
2228         self.assertEqual(len(sessions), 3)
2229         for session in sessions:
2230             self.assertFalse(session.is_static)
2231             self.assertEqual(session.inside_ip_address[0:4],
2232                              self.pg5.remote_ip4n)
2233             self.assertEqual(session.outside_ip_address,
2234                              addresses[0].ip_address)
2235         self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2236         self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2237         self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2238         self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2239         self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2240         self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2241         self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2242         self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2243         self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2244
2245         # in2out 3rd interface
2246         pkts = self.create_stream_in(self.pg6, self.pg3)
2247         self.pg6.add_stream(pkts)
2248         self.pg_enable_capture(self.pg_interfaces)
2249         self.pg_start()
2250         capture = self.pg3.get_capture(len(pkts))
2251         self.verify_capture_out(capture, static_nat_ip, True)
2252
2253         # out2in 3rd interface
2254         pkts = self.create_stream_out(self.pg3, static_nat_ip)
2255         self.pg3.add_stream(pkts)
2256         self.pg_enable_capture(self.pg_interfaces)
2257         self.pg_start()
2258         capture = self.pg6.get_capture(len(pkts))
2259         self.verify_capture_in(capture, self.pg6)
2260
2261         # general user and session dump verifications
2262         users = self.vapi.nat44_user_dump()
2263         self.assertGreaterEqual(len(users), 3)
2264         addresses = self.vapi.nat44_address_dump()
2265         self.assertEqual(len(addresses), 1)
2266         for user in users:
2267             sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2268                                                          user.vrf_id)
2269             for session in sessions:
2270                 self.assertEqual(user.ip_address, session.inside_ip_address)
2271                 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2272                 self.assertTrue(session.protocol in
2273                                 [IP_PROTOS.tcp, IP_PROTOS.udp,
2274                                  IP_PROTOS.icmp])
2275                 self.assertFalse(session.ext_host_valid)
2276
2277         # pg4 session dump
2278         sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
2279         self.assertGreaterEqual(len(sessions), 4)
2280         for session in sessions:
2281             self.assertFalse(session.is_static)
2282             self.assertEqual(session.inside_ip_address[0:4],
2283                              self.pg4.remote_ip4n)
2284             self.assertEqual(session.outside_ip_address,
2285                              addresses[0].ip_address)
2286
2287         # pg6 session dump
2288         sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
2289         self.assertGreaterEqual(len(sessions), 3)
2290         for session in sessions:
2291             self.assertTrue(session.is_static)
2292             self.assertEqual(session.inside_ip_address[0:4],
2293                              self.pg6.remote_ip4n)
2294             self.assertEqual(session.outside_ip_address,
2295                              socket.inet_pton(socket.AF_INET, static_nat_ip))
2296             self.assertTrue(session.inside_port in
2297                             [self.tcp_port_in, self.udp_port_in,
2298                              self.icmp_id_in])
2299
2300     def test_hairpinning(self):
2301         """ NAT44 hairpinning - 1:1 NAPT """
2302
2303         host = self.pg0.remote_hosts[0]
2304         server = self.pg0.remote_hosts[1]
2305         host_in_port = 1234
2306         host_out_port = 0
2307         server_in_port = 5678
2308         server_out_port = 8765
2309
2310         self.nat44_add_address(self.nat_addr)
2311         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2312         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2313                                                   is_inside=0)
2314         # add static mapping for server
2315         self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2316                                       server_in_port, server_out_port,
2317                                       proto=IP_PROTOS.tcp)
2318
2319         # send packet from host to server
2320         p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2321              IP(src=host.ip4, dst=self.nat_addr) /
2322              TCP(sport=host_in_port, dport=server_out_port))
2323         self.pg0.add_stream(p)
2324         self.pg_enable_capture(self.pg_interfaces)
2325         self.pg_start()
2326         capture = self.pg0.get_capture(1)
2327         p = capture[0]
2328         try:
2329             ip = p[IP]
2330             tcp = p[TCP]
2331             self.assertEqual(ip.src, self.nat_addr)
2332             self.assertEqual(ip.dst, server.ip4)
2333             self.assertNotEqual(tcp.sport, host_in_port)
2334             self.assertEqual(tcp.dport, server_in_port)
2335             self.assert_packet_checksums_valid(p)
2336             host_out_port = tcp.sport
2337         except:
2338             self.logger.error(ppp("Unexpected or invalid packet:", p))
2339             raise
2340
2341         # send reply from server to host
2342         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2343              IP(src=server.ip4, dst=self.nat_addr) /
2344              TCP(sport=server_in_port, dport=host_out_port))
2345         self.pg0.add_stream(p)
2346         self.pg_enable_capture(self.pg_interfaces)
2347         self.pg_start()
2348         capture = self.pg0.get_capture(1)
2349         p = capture[0]
2350         try:
2351             ip = p[IP]
2352             tcp = p[TCP]
2353             self.assertEqual(ip.src, self.nat_addr)
2354             self.assertEqual(ip.dst, host.ip4)
2355             self.assertEqual(tcp.sport, server_out_port)
2356             self.assertEqual(tcp.dport, host_in_port)
2357             self.assert_packet_checksums_valid(p)
2358         except:
2359             self.logger.error(ppp("Unexpected or invalid packet:", p))
2360             raise
2361
2362     def test_hairpinning2(self):
2363         """ NAT44 hairpinning - 1:1 NAT"""
2364
2365         server1_nat_ip = "10.0.0.10"
2366         server2_nat_ip = "10.0.0.11"
2367         host = self.pg0.remote_hosts[0]
2368         server1 = self.pg0.remote_hosts[1]
2369         server2 = self.pg0.remote_hosts[2]
2370         server_tcp_port = 22
2371         server_udp_port = 20
2372
2373         self.nat44_add_address(self.nat_addr)
2374         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2375         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2376                                                   is_inside=0)
2377
2378         # add static mapping for servers
2379         self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2380         self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
2381
2382         # host to server1
2383         pkts = []
2384         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2385              IP(src=host.ip4, dst=server1_nat_ip) /
2386              TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2387         pkts.append(p)
2388         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2389              IP(src=host.ip4, dst=server1_nat_ip) /
2390              UDP(sport=self.udp_port_in, dport=server_udp_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              ICMP(id=self.icmp_id_in, type='echo-request'))
2395         pkts.append(p)
2396         self.pg0.add_stream(pkts)
2397         self.pg_enable_capture(self.pg_interfaces)
2398         self.pg_start()
2399         capture = self.pg0.get_capture(len(pkts))
2400         for packet in capture:
2401             try:
2402                 self.assertEqual(packet[IP].src, self.nat_addr)
2403                 self.assertEqual(packet[IP].dst, server1.ip4)
2404                 if packet.haslayer(TCP):
2405                     self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2406                     self.assertEqual(packet[TCP].dport, server_tcp_port)
2407                     self.tcp_port_out = packet[TCP].sport
2408                     self.assert_packet_checksums_valid(packet)
2409                 elif packet.haslayer(UDP):
2410                     self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2411                     self.assertEqual(packet[UDP].dport, server_udp_port)
2412                     self.udp_port_out = packet[UDP].sport
2413                 else:
2414                     self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2415                     self.icmp_id_out = packet[ICMP].id
2416             except:
2417                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2418                 raise
2419
2420         # server1 to host
2421         pkts = []
2422         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2423              IP(src=server1.ip4, dst=self.nat_addr) /
2424              TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2425         pkts.append(p)
2426         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2427              IP(src=server1.ip4, dst=self.nat_addr) /
2428              UDP(sport=server_udp_port, dport=self.udp_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              ICMP(id=self.icmp_id_out, type='echo-reply'))
2433         pkts.append(p)
2434         self.pg0.add_stream(pkts)
2435         self.pg_enable_capture(self.pg_interfaces)
2436         self.pg_start()
2437         capture = self.pg0.get_capture(len(pkts))
2438         for packet in capture:
2439             try:
2440                 self.assertEqual(packet[IP].src, server1_nat_ip)
2441                 self.assertEqual(packet[IP].dst, host.ip4)
2442                 if packet.haslayer(TCP):
2443                     self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2444                     self.assertEqual(packet[TCP].sport, server_tcp_port)
2445                     self.assert_packet_checksums_valid(packet)
2446                 elif packet.haslayer(UDP):
2447                     self.assertEqual(packet[UDP].dport, self.udp_port_in)
2448                     self.assertEqual(packet[UDP].sport, server_udp_port)
2449                 else:
2450                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2451             except:
2452                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2453                 raise
2454
2455         # server2 to server1
2456         pkts = []
2457         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2458              IP(src=server2.ip4, dst=server1_nat_ip) /
2459              TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2460         pkts.append(p)
2461         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2462              IP(src=server2.ip4, dst=server1_nat_ip) /
2463              UDP(sport=self.udp_port_in, dport=server_udp_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              ICMP(id=self.icmp_id_in, type='echo-request'))
2468         pkts.append(p)
2469         self.pg0.add_stream(pkts)
2470         self.pg_enable_capture(self.pg_interfaces)
2471         self.pg_start()
2472         capture = self.pg0.get_capture(len(pkts))
2473         for packet in capture:
2474             try:
2475                 self.assertEqual(packet[IP].src, server2_nat_ip)
2476                 self.assertEqual(packet[IP].dst, server1.ip4)
2477                 if packet.haslayer(TCP):
2478                     self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2479                     self.assertEqual(packet[TCP].dport, server_tcp_port)
2480                     self.tcp_port_out = packet[TCP].sport
2481                     self.assert_packet_checksums_valid(packet)
2482                 elif packet.haslayer(UDP):
2483                     self.assertEqual(packet[UDP].sport, self.udp_port_in)
2484                     self.assertEqual(packet[UDP].dport, server_udp_port)
2485                     self.udp_port_out = packet[UDP].sport
2486                 else:
2487                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2488                     self.icmp_id_out = packet[ICMP].id
2489             except:
2490                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2491                 raise
2492
2493         # server1 to server2
2494         pkts = []
2495         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2496              IP(src=server1.ip4, dst=server2_nat_ip) /
2497              TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2498         pkts.append(p)
2499         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2500              IP(src=server1.ip4, dst=server2_nat_ip) /
2501              UDP(sport=server_udp_port, dport=self.udp_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              ICMP(id=self.icmp_id_out, type='echo-reply'))
2506         pkts.append(p)
2507         self.pg0.add_stream(pkts)
2508         self.pg_enable_capture(self.pg_interfaces)
2509         self.pg_start()
2510         capture = self.pg0.get_capture(len(pkts))
2511         for packet in capture:
2512             try:
2513                 self.assertEqual(packet[IP].src, server1_nat_ip)
2514                 self.assertEqual(packet[IP].dst, server2.ip4)
2515                 if packet.haslayer(TCP):
2516                     self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2517                     self.assertEqual(packet[TCP].sport, server_tcp_port)
2518                     self.assert_packet_checksums_valid(packet)
2519                 elif packet.haslayer(UDP):
2520                     self.assertEqual(packet[UDP].dport, self.udp_port_in)
2521                     self.assertEqual(packet[UDP].sport, server_udp_port)
2522                 else:
2523                     self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2524             except:
2525                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2526                 raise
2527
2528     def test_max_translations_per_user(self):
2529         """ MAX translations per user - recycle the least recently used """
2530
2531         self.nat44_add_address(self.nat_addr)
2532         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2533         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2534                                                   is_inside=0)
2535
2536         # get maximum number of translations per user
2537         nat44_config = self.vapi.nat_show_config()
2538
2539         # send more than maximum number of translations per user packets
2540         pkts_num = nat44_config.max_translations_per_user + 5
2541         pkts = []
2542         for port in range(0, pkts_num):
2543             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2544                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2545                  TCP(sport=1025 + port))
2546             pkts.append(p)
2547         self.pg0.add_stream(pkts)
2548         self.pg_enable_capture(self.pg_interfaces)
2549         self.pg_start()
2550
2551         # verify number of translated packet
2552         self.pg1.get_capture(pkts_num)
2553
2554         users = self.vapi.nat44_user_dump()
2555         for user in users:
2556             if user.ip_address == self.pg0.remote_ip4n:
2557                 self.assertEqual(user.nsessions,
2558                                  nat44_config.max_translations_per_user)
2559                 self.assertEqual(user.nstaticsessions, 0)
2560
2561         tcp_port = 22
2562         self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2563                                       tcp_port, tcp_port,
2564                                       proto=IP_PROTOS.tcp)
2565         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2566              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2567              TCP(sport=tcp_port))
2568         self.pg0.add_stream(p)
2569         self.pg_enable_capture(self.pg_interfaces)
2570         self.pg_start()
2571         self.pg1.get_capture(1)
2572         users = self.vapi.nat44_user_dump()
2573         for user in users:
2574             if user.ip_address == self.pg0.remote_ip4n:
2575                 self.assertEqual(user.nsessions,
2576                                  nat44_config.max_translations_per_user - 1)
2577                 self.assertEqual(user.nstaticsessions, 1)
2578
2579     def test_interface_addr(self):
2580         """ Acquire NAT44 addresses from interface """
2581         self.vapi.nat44_add_del_interface_addr(self.pg7.sw_if_index)
2582
2583         # no address in NAT pool
2584         adresses = self.vapi.nat44_address_dump()
2585         self.assertEqual(0, len(adresses))
2586
2587         # configure interface address and check NAT address pool
2588         self.pg7.config_ip4()
2589         adresses = self.vapi.nat44_address_dump()
2590         self.assertEqual(1, len(adresses))
2591         self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
2592
2593         # remove interface address and check NAT address pool
2594         self.pg7.unconfig_ip4()
2595         adresses = self.vapi.nat44_address_dump()
2596         self.assertEqual(0, len(adresses))
2597
2598     def test_interface_addr_static_mapping(self):
2599         """ Static mapping with addresses from interface """
2600         tag = "testTAG"
2601
2602         self.vapi.nat44_add_del_interface_addr(self.pg7.sw_if_index)
2603         self.nat44_add_static_mapping(
2604             '1.2.3.4',
2605             external_sw_if_index=self.pg7.sw_if_index,
2606             tag=tag)
2607
2608         # static mappings with external interface
2609         static_mappings = self.vapi.nat44_static_mapping_dump()
2610         self.assertEqual(1, len(static_mappings))
2611         self.assertEqual(self.pg7.sw_if_index,
2612                          static_mappings[0].external_sw_if_index)
2613         self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2614
2615         # configure interface address and check static mappings
2616         self.pg7.config_ip4()
2617         static_mappings = self.vapi.nat44_static_mapping_dump()
2618         self.assertEqual(2, len(static_mappings))
2619         resolved = False
2620         for sm in static_mappings:
2621             if sm.external_sw_if_index == 0xFFFFFFFF:
2622                 self.assertEqual(sm.external_ip_address[0:4],
2623                                  self.pg7.local_ip4n)
2624                 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2625                 resolved = True
2626         self.assertTrue(resolved)
2627
2628         # remove interface address and check static mappings
2629         self.pg7.unconfig_ip4()
2630         static_mappings = self.vapi.nat44_static_mapping_dump()
2631         self.assertEqual(1, len(static_mappings))
2632         self.assertEqual(self.pg7.sw_if_index,
2633                          static_mappings[0].external_sw_if_index)
2634         self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2635
2636         # configure interface address again and check static mappings
2637         self.pg7.config_ip4()
2638         static_mappings = self.vapi.nat44_static_mapping_dump()
2639         self.assertEqual(2, len(static_mappings))
2640         resolved = False
2641         for sm in static_mappings:
2642             if sm.external_sw_if_index == 0xFFFFFFFF:
2643                 self.assertEqual(sm.external_ip_address[0:4],
2644                                  self.pg7.local_ip4n)
2645                 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2646                 resolved = True
2647         self.assertTrue(resolved)
2648
2649         # remove static mapping
2650         self.nat44_add_static_mapping(
2651             '1.2.3.4',
2652             external_sw_if_index=self.pg7.sw_if_index,
2653             tag=tag,
2654             is_add=0)
2655         static_mappings = self.vapi.nat44_static_mapping_dump()
2656         self.assertEqual(0, len(static_mappings))
2657
2658     def test_interface_addr_identity_nat(self):
2659         """ Identity NAT with addresses from interface """
2660
2661         port = 53053
2662         self.vapi.nat44_add_del_interface_addr(self.pg7.sw_if_index)
2663         self.vapi.nat44_add_del_identity_mapping(
2664             sw_if_index=self.pg7.sw_if_index,
2665             port=port,
2666             protocol=IP_PROTOS.tcp,
2667             addr_only=0)
2668
2669         # identity mappings with external interface
2670         identity_mappings = self.vapi.nat44_identity_mapping_dump()
2671         self.assertEqual(1, len(identity_mappings))
2672         self.assertEqual(self.pg7.sw_if_index,
2673                          identity_mappings[0].sw_if_index)
2674
2675         # configure interface address and check identity mappings
2676         self.pg7.config_ip4()
2677         identity_mappings = self.vapi.nat44_identity_mapping_dump()
2678         resolved = False
2679         self.assertEqual(2, len(identity_mappings))
2680         for sm in identity_mappings:
2681             if sm.sw_if_index == 0xFFFFFFFF:
2682                 self.assertEqual(identity_mappings[0].ip_address,
2683                                  self.pg7.local_ip4n)
2684                 self.assertEqual(port, identity_mappings[0].port)
2685                 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2686                 resolved = True
2687         self.assertTrue(resolved)
2688
2689         # remove interface address and check identity mappings
2690         self.pg7.unconfig_ip4()
2691         identity_mappings = self.vapi.nat44_identity_mapping_dump()
2692         self.assertEqual(1, len(identity_mappings))
2693         self.assertEqual(self.pg7.sw_if_index,
2694                          identity_mappings[0].sw_if_index)
2695
2696     def test_ipfix_nat44_sess(self):
2697         """ IPFIX logging NAT44 session created/delted """
2698         self.ipfix_domain_id = 10
2699         self.ipfix_src_port = 20202
2700         colector_port = 30303
2701         bind_layers(UDP, IPFIX, dport=30303)
2702         self.nat44_add_address(self.nat_addr)
2703         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2704         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2705                                                   is_inside=0)
2706         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2707                                      src_address=self.pg3.local_ip4n,
2708                                      path_mtu=512,
2709                                      template_interval=10,
2710                                      collector_port=colector_port)
2711         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2712                                            src_port=self.ipfix_src_port)
2713
2714         pkts = self.create_stream_in(self.pg0, self.pg1)
2715         self.pg0.add_stream(pkts)
2716         self.pg_enable_capture(self.pg_interfaces)
2717         self.pg_start()
2718         capture = self.pg1.get_capture(len(pkts))
2719         self.verify_capture_out(capture)
2720         self.nat44_add_address(self.nat_addr, is_add=0)
2721         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
2722         capture = self.pg3.get_capture(9)
2723         ipfix = IPFIXDecoder()
2724         # first load template
2725         for p in capture:
2726             self.assertTrue(p.haslayer(IPFIX))
2727             self.assertEqual(p[IP].src, self.pg3.local_ip4)
2728             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2729             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2730             self.assertEqual(p[UDP].dport, colector_port)
2731             self.assertEqual(p[IPFIX].observationDomainID,
2732                              self.ipfix_domain_id)
2733             if p.haslayer(Template):
2734                 ipfix.add_template(p.getlayer(Template))
2735         # verify events in data set
2736         for p in capture:
2737             if p.haslayer(Data):
2738                 data = ipfix.decode_data_set(p.getlayer(Set))
2739                 self.verify_ipfix_nat44_ses(data)
2740
2741     def test_ipfix_addr_exhausted(self):
2742         """ IPFIX logging NAT addresses exhausted """
2743         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2744         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2745                                                   is_inside=0)
2746         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2747                                      src_address=self.pg3.local_ip4n,
2748                                      path_mtu=512,
2749                                      template_interval=10)
2750         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2751                                            src_port=self.ipfix_src_port)
2752
2753         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2754              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2755              TCP(sport=3025))
2756         self.pg0.add_stream(p)
2757         self.pg_enable_capture(self.pg_interfaces)
2758         self.pg_start()
2759         self.pg1.assert_nothing_captured()
2760         sleep(1)
2761         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
2762         capture = self.pg3.get_capture(9)
2763         ipfix = IPFIXDecoder()
2764         # first load template
2765         for p in capture:
2766             self.assertTrue(p.haslayer(IPFIX))
2767             self.assertEqual(p[IP].src, self.pg3.local_ip4)
2768             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2769             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2770             self.assertEqual(p[UDP].dport, 4739)
2771             self.assertEqual(p[IPFIX].observationDomainID,
2772                              self.ipfix_domain_id)
2773             if p.haslayer(Template):
2774                 ipfix.add_template(p.getlayer(Template))
2775         # verify events in data set
2776         for p in capture:
2777             if p.haslayer(Data):
2778                 data = ipfix.decode_data_set(p.getlayer(Set))
2779                 self.verify_ipfix_addr_exhausted(data)
2780
2781     @unittest.skipUnless(running_extended_tests, "part of extended tests")
2782     def test_ipfix_max_sessions(self):
2783         """ IPFIX logging maximum session entries exceeded """
2784         self.nat44_add_address(self.nat_addr)
2785         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2786         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2787                                                   is_inside=0)
2788
2789         nat44_config = self.vapi.nat_show_config()
2790         max_sessions = 10 * nat44_config.translation_buckets
2791
2792         pkts = []
2793         for i in range(0, max_sessions):
2794             src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2795             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2796                  IP(src=src, dst=self.pg1.remote_ip4) /
2797                  TCP(sport=1025))
2798             pkts.append(p)
2799         self.pg0.add_stream(pkts)
2800         self.pg_enable_capture(self.pg_interfaces)
2801         self.pg_start()
2802
2803         self.pg1.get_capture(max_sessions)
2804         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2805                                      src_address=self.pg3.local_ip4n,
2806                                      path_mtu=512,
2807                                      template_interval=10)
2808         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2809                                            src_port=self.ipfix_src_port)
2810
2811         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2812              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2813              TCP(sport=1025))
2814         self.pg0.add_stream(p)
2815         self.pg_enable_capture(self.pg_interfaces)
2816         self.pg_start()
2817         self.pg1.assert_nothing_captured()
2818         sleep(1)
2819         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
2820         capture = self.pg3.get_capture(9)
2821         ipfix = IPFIXDecoder()
2822         # first load template
2823         for p in capture:
2824             self.assertTrue(p.haslayer(IPFIX))
2825             self.assertEqual(p[IP].src, self.pg3.local_ip4)
2826             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2827             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2828             self.assertEqual(p[UDP].dport, 4739)
2829             self.assertEqual(p[IPFIX].observationDomainID,
2830                              self.ipfix_domain_id)
2831             if p.haslayer(Template):
2832                 ipfix.add_template(p.getlayer(Template))
2833         # verify events in data set
2834         for p in capture:
2835             if p.haslayer(Data):
2836                 data = ipfix.decode_data_set(p.getlayer(Set))
2837                 self.verify_ipfix_max_sessions(data, max_sessions)
2838
2839     def test_syslog_apmap(self):
2840         """ Test syslog address and port mapping creation and deletion """
2841         self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
2842         self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
2843         self.nat44_add_address(self.nat_addr)
2844         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2845         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2846                                                   is_inside=0)
2847
2848         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2849              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2850              TCP(sport=self.tcp_port_in, dport=20))
2851         self.pg0.add_stream(p)
2852         self.pg_enable_capture(self.pg_interfaces)
2853         self.pg_start()
2854         capture = self.pg1.get_capture(1)
2855         self.tcp_port_out = capture[0][TCP].sport
2856         capture = self.pg3.get_capture(1)
2857         self.verify_syslog_apmap(capture[0][Raw].load)
2858
2859         self.pg_enable_capture(self.pg_interfaces)
2860         self.pg_start()
2861         self.nat44_add_address(self.nat_addr, is_add=0)
2862         capture = self.pg3.get_capture(1)
2863         self.verify_syslog_apmap(capture[0][Raw].load, False)
2864
2865     def test_pool_addr_fib(self):
2866         """ NAT44 add pool addresses to FIB """
2867         static_addr = '10.0.0.10'
2868         self.nat44_add_address(self.nat_addr)
2869         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2870         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2871                                                   is_inside=0)
2872         self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
2873
2874         # NAT44 address
2875         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2876              ARP(op=ARP.who_has, pdst=self.nat_addr,
2877                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2878         self.pg1.add_stream(p)
2879         self.pg_enable_capture(self.pg_interfaces)
2880         self.pg_start()
2881         capture = self.pg1.get_capture(1)
2882         self.assertTrue(capture[0].haslayer(ARP))
2883         self.assertTrue(capture[0][ARP].op, ARP.is_at)
2884
2885         # 1:1 NAT address
2886         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2887              ARP(op=ARP.who_has, pdst=static_addr,
2888                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2889         self.pg1.add_stream(p)
2890         self.pg_enable_capture(self.pg_interfaces)
2891         self.pg_start()
2892         capture = self.pg1.get_capture(1)
2893         self.assertTrue(capture[0].haslayer(ARP))
2894         self.assertTrue(capture[0][ARP].op, ARP.is_at)
2895
2896         # send ARP to non-NAT44 interface
2897         p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2898              ARP(op=ARP.who_has, pdst=self.nat_addr,
2899                  psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2900         self.pg2.add_stream(p)
2901         self.pg_enable_capture(self.pg_interfaces)
2902         self.pg_start()
2903         self.pg1.assert_nothing_captured()
2904
2905         # remove addresses and verify
2906         self.nat44_add_address(self.nat_addr, is_add=0)
2907         self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2908                                       is_add=0)
2909
2910         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2911              ARP(op=ARP.who_has, pdst=self.nat_addr,
2912                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2913         self.pg1.add_stream(p)
2914         self.pg_enable_capture(self.pg_interfaces)
2915         self.pg_start()
2916         self.pg1.assert_nothing_captured()
2917
2918         p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2919              ARP(op=ARP.who_has, pdst=static_addr,
2920                  psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2921         self.pg1.add_stream(p)
2922         self.pg_enable_capture(self.pg_interfaces)
2923         self.pg_start()
2924         self.pg1.assert_nothing_captured()
2925
2926     def test_vrf_mode(self):
2927         """ NAT44 tenant VRF aware address pool mode """
2928
2929         vrf_id1 = 1
2930         vrf_id2 = 2
2931         nat_ip1 = "10.0.0.10"
2932         nat_ip2 = "10.0.0.11"
2933
2934         self.pg0.unconfig_ip4()
2935         self.pg1.unconfig_ip4()
2936         self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
2937         self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
2938         self.pg0.set_table_ip4(vrf_id1)
2939         self.pg1.set_table_ip4(vrf_id2)
2940         self.pg0.config_ip4()
2941         self.pg1.config_ip4()
2942         self.pg0.resolve_arp()
2943         self.pg1.resolve_arp()
2944
2945         self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2946         self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2947         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2948         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2949         self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2950                                                   is_inside=0)
2951
2952         try:
2953             # first VRF
2954             pkts = self.create_stream_in(self.pg0, self.pg2)
2955             self.pg0.add_stream(pkts)
2956             self.pg_enable_capture(self.pg_interfaces)
2957             self.pg_start()
2958             capture = self.pg2.get_capture(len(pkts))
2959             self.verify_capture_out(capture, nat_ip1)
2960
2961             # second VRF
2962             pkts = self.create_stream_in(self.pg1, self.pg2)
2963             self.pg1.add_stream(pkts)
2964             self.pg_enable_capture(self.pg_interfaces)
2965             self.pg_start()
2966             capture = self.pg2.get_capture(len(pkts))
2967             self.verify_capture_out(capture, nat_ip2)
2968
2969         finally:
2970             self.pg0.unconfig_ip4()
2971             self.pg1.unconfig_ip4()
2972             self.pg0.set_table_ip4(0)
2973             self.pg1.set_table_ip4(0)
2974             self.pg0.config_ip4()
2975             self.pg1.config_ip4()
2976             self.pg0.resolve_arp()
2977             self.pg1.resolve_arp()
2978             self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id1)
2979             self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id2)
2980
2981     def test_vrf_feature_independent(self):
2982         """ NAT44 tenant VRF independent address pool mode """
2983
2984         nat_ip1 = "10.0.0.10"
2985         nat_ip2 = "10.0.0.11"
2986
2987         self.nat44_add_address(nat_ip1)
2988         self.nat44_add_address(nat_ip2, vrf_id=99)
2989         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2990         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2991         self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2992                                                   is_inside=0)
2993
2994         # first VRF
2995         pkts = self.create_stream_in(self.pg0, self.pg2)
2996         self.pg0.add_stream(pkts)
2997         self.pg_enable_capture(self.pg_interfaces)
2998         self.pg_start()
2999         capture = self.pg2.get_capture(len(pkts))
3000         self.verify_capture_out(capture, nat_ip1)
3001
3002         # second VRF
3003         pkts = self.create_stream_in(self.pg1, self.pg2)
3004         self.pg1.add_stream(pkts)
3005         self.pg_enable_capture(self.pg_interfaces)
3006         self.pg_start()
3007         capture = self.pg2.get_capture(len(pkts))
3008         self.verify_capture_out(capture, nat_ip1)
3009
3010     def test_dynamic_ipless_interfaces(self):
3011         """ NAT44 interfaces without configured IP address """
3012
3013         self.vapi.ip_neighbor_add_del(
3014             self.pg7.sw_if_index,
3015             self.pg7.remote_mac,
3016             self.pg7.remote_ip4,
3017             flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3018                    IP_API_NEIGHBOR_FLAG_STATIC))
3019         self.vapi.ip_neighbor_add_del(
3020             self.pg8.sw_if_index,
3021             self.pg8.remote_mac,
3022             self.pg8.remote_ip4,
3023             flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3024                    IP_API_NEIGHBOR_FLAG_STATIC))
3025
3026         self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3027                                    dst_address_length=32,
3028                                    next_hop_address=self.pg7.remote_ip4n,
3029                                    next_hop_sw_if_index=self.pg7.sw_if_index)
3030         self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3031                                    dst_address_length=32,
3032                                    next_hop_address=self.pg8.remote_ip4n,
3033                                    next_hop_sw_if_index=self.pg8.sw_if_index)
3034
3035         self.nat44_add_address(self.nat_addr)
3036         self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
3037         self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
3038                                                   is_inside=0)
3039
3040         # in2out
3041         pkts = self.create_stream_in(self.pg7, self.pg8)
3042         self.pg7.add_stream(pkts)
3043         self.pg_enable_capture(self.pg_interfaces)
3044         self.pg_start()
3045         capture = self.pg8.get_capture(len(pkts))
3046         self.verify_capture_out(capture)
3047
3048         # out2in
3049         pkts = self.create_stream_out(self.pg8, self.nat_addr)
3050         self.pg8.add_stream(pkts)
3051         self.pg_enable_capture(self.pg_interfaces)
3052         self.pg_start()
3053         capture = self.pg7.get_capture(len(pkts))
3054         self.verify_capture_in(capture, self.pg7)
3055
3056     def test_static_ipless_interfaces(self):
3057         """ NAT44 interfaces without configured IP address - 1:1 NAT """
3058
3059         self.vapi.ip_neighbor_add_del(
3060             self.pg7.sw_if_index,
3061             self.pg7.remote_mac,
3062             self.pg7.remote_ip4,
3063             flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3064                    IP_API_NEIGHBOR_FLAG_STATIC))
3065         self.vapi.ip_neighbor_add_del(
3066             self.pg8.sw_if_index,
3067             self.pg8.remote_mac,
3068             self.pg8.remote_ip4,
3069             flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3070                    IP_API_NEIGHBOR_FLAG_STATIC))
3071
3072         self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3073                                    dst_address_length=32,
3074                                    next_hop_address=self.pg7.remote_ip4n,
3075                                    next_hop_sw_if_index=self.pg7.sw_if_index)
3076         self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3077                                    dst_address_length=32,
3078                                    next_hop_address=self.pg8.remote_ip4n,
3079                                    next_hop_sw_if_index=self.pg8.sw_if_index)
3080
3081         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
3082         self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
3083         self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
3084                                                   is_inside=0)
3085
3086         # out2in
3087         pkts = self.create_stream_out(self.pg8)
3088         self.pg8.add_stream(pkts)
3089         self.pg_enable_capture(self.pg_interfaces)
3090         self.pg_start()
3091         capture = self.pg7.get_capture(len(pkts))
3092         self.verify_capture_in(capture, self.pg7)
3093
3094         # in2out
3095         pkts = self.create_stream_in(self.pg7, self.pg8)
3096         self.pg7.add_stream(pkts)
3097         self.pg_enable_capture(self.pg_interfaces)
3098         self.pg_start()
3099         capture = self.pg8.get_capture(len(pkts))
3100         self.verify_capture_out(capture, self.nat_addr, True)
3101
3102     def test_static_with_port_ipless_interfaces(self):
3103         """ NAT44 interfaces without configured IP address - 1:1 NAPT """
3104
3105         self.tcp_port_out = 30606
3106         self.udp_port_out = 30607
3107         self.icmp_id_out = 30608
3108
3109         self.vapi.ip_neighbor_add_del(
3110             self.pg7.sw_if_index,
3111             self.pg7.remote_mac,
3112             self.pg7.remote_ip4,
3113             flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3114                    IP_API_NEIGHBOR_FLAG_STATIC))
3115         self.vapi.ip_neighbor_add_del(
3116             self.pg8.sw_if_index,
3117             self.pg8.remote_mac,
3118             self.pg8.remote_ip4,
3119             flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3120                    IP_API_NEIGHBOR_FLAG_STATIC))
3121
3122         self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3123                                    dst_address_length=32,
3124                                    next_hop_address=self.pg7.remote_ip4n,
3125                                    next_hop_sw_if_index=self.pg7.sw_if_index)
3126         self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3127                                    dst_address_length=32,
3128                                    next_hop_address=self.pg8.remote_ip4n,
3129                                    next_hop_sw_if_index=self.pg8.sw_if_index)
3130
3131         self.nat44_add_address(self.nat_addr)
3132         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3133                                       self.tcp_port_in, self.tcp_port_out,
3134                                       proto=IP_PROTOS.tcp)
3135         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3136                                       self.udp_port_in, self.udp_port_out,
3137                                       proto=IP_PROTOS.udp)
3138         self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3139                                       self.icmp_id_in, self.icmp_id_out,
3140                                       proto=IP_PROTOS.icmp)
3141         self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
3142         self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
3143                                                   is_inside=0)
3144
3145         # out2in
3146         pkts = self.create_stream_out(self.pg8)
3147         self.pg8.add_stream(pkts)
3148         self.pg_enable_capture(self.pg_interfaces)
3149         self.pg_start()
3150         capture = self.pg7.get_capture(len(pkts))
3151         self.verify_capture_in(capture, self.pg7)
3152
3153         # in2out
3154         pkts = self.create_stream_in(self.pg7, self.pg8)
3155         self.pg7.add_stream(pkts)
3156         self.pg_enable_capture(self.pg_interfaces)
3157         self.pg_start()
3158         capture = self.pg8.get_capture(len(pkts))
3159         self.verify_capture_out(capture)
3160
3161     def test_static_unknown_proto(self):
3162         """ 1:1 NAT translate packet with unknown protocol """
3163         nat_ip = "10.0.0.10"
3164         self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
3165         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3166         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3167                                                   is_inside=0)
3168
3169         # in2out
3170         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3171              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3172              GRE() /
3173              IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3174              TCP(sport=1234, dport=1234))
3175         self.pg0.add_stream(p)
3176         self.pg_enable_capture(self.pg_interfaces)
3177         self.pg_start()
3178         p = self.pg1.get_capture(1)
3179         packet = p[0]
3180         try:
3181             self.assertEqual(packet[IP].src, nat_ip)
3182             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3183             self.assertEqual(packet.haslayer(GRE), 1)
3184             self.assert_packet_checksums_valid(packet)
3185         except:
3186             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3187             raise
3188
3189         # out2in
3190         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3191              IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3192              GRE() /
3193              IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3194              TCP(sport=1234, dport=1234))
3195         self.pg1.add_stream(p)
3196         self.pg_enable_capture(self.pg_interfaces)
3197         self.pg_start()
3198         p = self.pg0.get_capture(1)
3199         packet = p[0]
3200         try:
3201             self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3202             self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3203             self.assertEqual(packet.haslayer(GRE), 1)
3204             self.assert_packet_checksums_valid(packet)
3205         except:
3206             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3207             raise
3208
3209     def test_hairpinning_static_unknown_proto(self):
3210         """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3211
3212         host = self.pg0.remote_hosts[0]
3213         server = self.pg0.remote_hosts[1]
3214
3215         host_nat_ip = "10.0.0.10"
3216         server_nat_ip = "10.0.0.11"
3217
3218         self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3219         self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3220         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3221         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3222                                                   is_inside=0)
3223
3224         # host to server
3225         p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3226              IP(src=host.ip4, dst=server_nat_ip) /
3227              GRE() /
3228              IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3229              TCP(sport=1234, dport=1234))
3230         self.pg0.add_stream(p)
3231         self.pg_enable_capture(self.pg_interfaces)
3232         self.pg_start()
3233         p = self.pg0.get_capture(1)
3234         packet = p[0]
3235         try:
3236             self.assertEqual(packet[IP].src, host_nat_ip)
3237             self.assertEqual(packet[IP].dst, server.ip4)
3238             self.assertEqual(packet.haslayer(GRE), 1)
3239             self.assert_packet_checksums_valid(packet)
3240         except:
3241             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3242             raise
3243
3244         # server to host
3245         p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3246              IP(src=server.ip4, dst=host_nat_ip) /
3247              GRE() /
3248              IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3249              TCP(sport=1234, dport=1234))
3250         self.pg0.add_stream(p)
3251         self.pg_enable_capture(self.pg_interfaces)
3252         self.pg_start()
3253         p = self.pg0.get_capture(1)
3254         packet = p[0]
3255         try:
3256             self.assertEqual(packet[IP].src, server_nat_ip)
3257             self.assertEqual(packet[IP].dst, host.ip4)
3258             self.assertEqual(packet.haslayer(GRE), 1)
3259             self.assert_packet_checksums_valid(packet)
3260         except:
3261             self.logger.error(ppp("Unexpected or invalid packet:", packet))
3262             raise
3263
3264     def test_output_feature(self):
3265         """ NAT44 interface output feature (in2out postrouting) """
3266         self.nat44_add_address(self.nat_addr)
3267         self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3268         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
3269         self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3270                                                          is_inside=0)
3271
3272         # in2out
3273         pkts = self.create_stream_in(self.pg0, self.pg3)
3274         self.pg0.add_stream(pkts)
3275         self.pg_enable_capture(self.pg_interfaces)
3276         self.pg_start()
3277         capture = self.pg3.get_capture(len(pkts))
3278         self.verify_capture_out(capture)
3279
3280         # out2in
3281         pkts = self.create_stream_out(self.pg3)
3282         self.pg3.add_stream(pkts)
3283         self.pg_enable_capture(self.pg_interfaces)
3284         self.pg_start()
3285         capture = self.pg0.get_capture(len(pkts))
3286         self.verify_capture_in(capture, self.pg0)
3287
3288         # from non-NAT interface to NAT inside interface
3289         pkts = self.create_stream_in(self.pg2, self.pg0)
3290         self.pg2.add_stream(pkts)
3291         self.pg_enable_capture(self.pg_interfaces)
3292         self.pg_start()
3293         capture = self.pg0.get_capture(len(pkts))
3294         self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3295
3296     def test_output_feature_vrf_aware(self):
3297         """ NAT44 interface output feature VRF aware (in2out postrouting) """
3298         nat_ip_vrf10 = "10.0.0.10"
3299         nat_ip_vrf20 = "10.0.0.20"
3300
3301         self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3302                                    dst_address_length=32,
3303                                    next_hop_address=self.pg3.remote_ip4n,
3304                                    next_hop_sw_if_index=self.pg3.sw_if_index,
3305                                    table_id=10)
3306         self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3307                                    dst_address_length=32,
3308                                    next_hop_address=self.pg3.remote_ip4n,
3309                                    next_hop_sw_if_index=self.pg3.sw_if_index,
3310                                    table_id=20)
3311
3312         self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3313         self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3314         self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
3315         self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
3316         self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3317                                                          is_inside=0)
3318
3319         # in2out VRF 10
3320         pkts = self.create_stream_in(self.pg4, self.pg3)
3321         self.pg4.add_stream(pkts)
3322         self.pg_enable_capture(self.pg_interfaces)
3323         self.pg_start()
3324         capture = self.pg3.get_capture(len(pkts))
3325         self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3326
3327         # out2in VRF 10
3328         pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3329         self.pg3.add_stream(pkts)
3330         self.pg_enable_capture(self.pg_interfaces)
3331         self.pg_start()
3332         capture = self.pg4.get_capture(len(pkts))
3333         self.verify_capture_in(capture, self.pg4)
3334
3335         # in2out VRF 20
3336         pkts = self.create_stream_in(self.pg6, self.pg3)
3337         self.pg6.add_stream(pkts)
3338         self.pg_enable_capture(self.pg_interfaces)
3339         self.pg_start()
3340         capture = self.pg3.get_capture(len(pkts))
3341         self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3342
3343         # out2in VRF 20
3344         pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3345         self.pg3.add_stream(pkts)
3346         self.pg_enable_capture(self.pg_interfaces)
3347         self.pg_start()
3348         capture = self.pg6.get_capture(len(pkts))
3349         self.verify_capture_in(capture, self.pg6)
3350
3351     def test_output_feature_hairpinning(self):
3352         """ NAT44 interface output feature hairpinning (in2out postrouting) """
3353         host = self.pg0.remote_hosts[0]
3354         server = self.pg0.remote_hosts[1]
3355         host_in_port = 1234
3356         host_out_port = 0
3357         server_in_port = 5678
3358         server_out_port = 8765
3359
3360         self.nat44_add_address(self.nat_addr)
3361         self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3362         self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3363                                                          is_inside=0)
3364
3365         # add static mapping for server
3366         self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3367                                       server_in_port, server_out_port,
3368                                       proto=IP_PROTOS.tcp)
3369
3370         # send packet from host to server
3371         p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3372              IP(src=host.ip4, dst=self.nat_addr) /
3373              TCP(sport=host_in_port, dport=server_out_port))
3374         self.pg0.add_stream(p)
3375         self.pg_enable_capture(self.pg_interfaces)
3376         self.pg_start()
3377         capture = self.pg0.get_capture(1)
3378         p = capture[0]
3379         try:
3380             ip = p[IP]
3381             tcp = p[TCP]
3382             self.assertEqual(ip.src, self.nat_addr)
3383             self.assertEqual(ip.dst, server.ip4)
3384             self.assertNotEqual(tcp.sport, host_in_port)
3385             self.assertEqual(tcp.dport, server_in_port)
3386             self.assert_packet_checksums_valid(p)
3387             host_out_port = tcp.sport
3388         except:
3389             self.logger.error(ppp("Unexpected or invalid packet:", p))
3390             raise
3391
3392         # send reply from server to host
3393         p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3394              IP(src=server.ip4, dst=self.nat_addr) /
3395              TCP(sport=server_in_port, dport=host_out_port))
3396         self.pg0.add_stream(p)
3397         self.pg_enable_capture(self.pg_interfaces)
3398         self.pg_start()
3399         capture = self.pg0.get_capture(1)
3400         p = capture[0]
3401         try:
3402             ip = p[IP]
3403             tcp = p[TCP]
3404             self.assertEqual(ip.src, self.nat_addr)
3405             self.assertEqual(ip.dst, host.ip4)
3406             self.assertEqual(tcp.sport, server_out_port)
3407             self.assertEqual(tcp.dport, host_in_port)
3408             self.assert_packet_checksums_valid(p)
3409         except:
3410             self.logger.error(ppp("Unexpected or invalid packet:", p))
3411             raise
3412
3413     def test_one_armed_nat44(self):
3414         """ One armed NAT44 """
3415         remote_host = self.pg9.remote_hosts[0]
3416         local_host = self.pg9.remote_hosts[1]
3417         external_port = 0
3418
3419         self.nat44_add_address(self.nat_addr)
3420         self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3421         self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3422                                                   is_inside=0)
3423
3424         # in2out
3425         p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3426              IP(src=local_host.ip4, dst=remote_host.ip4) /
3427              TCP(sport=12345, dport=80))
3428         self.pg9.add_stream(p)
3429         self.pg_enable_capture(self.pg_interfaces)
3430         self.pg_start()
3431         capture = self.pg9.get_capture(1)
3432         p = capture[0]
3433         try:
3434             ip = p[IP]
3435             tcp = p[TCP]
3436             self.assertEqual(ip.src, self.nat_addr)
3437             self.assertEqual(ip.dst, remote_host.ip4)
3438             self.assertNotEqual(tcp.sport, 12345)
3439             external_port = tcp.sport
3440             self.assertEqual(tcp.dport, 80)
3441             self.assert_packet_checksums_valid(p)
3442         except:
3443             self.logger.error(ppp("Unexpected or invalid packet:", p))
3444             raise
3445
3446         # out2in
3447         p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3448              IP(src=remote_host.ip4, dst=self.nat_addr) /
3449              TCP(sport=80, dport=external_port))
3450         self.pg9.add_stream(p)
3451         self.pg_enable_capture(self.pg_interfaces)
3452         self.pg_start()
3453         capture = self.pg9.get_capture(1)
3454         p = capture[0]
3455         try:
3456             ip = p[IP]
3457             tcp = p[TCP]
3458             self.assertEqual(ip.src, remote_host.ip4)
3459             self.assertEqual(ip.dst, local_host.ip4)
3460             self.assertEqual(tcp.sport, 80)
3461             self.assertEqual(tcp.dport, 12345)
3462             self.assert_packet_checksums_valid(p)
3463         except:
3464             self.logger.error(ppp("Unexpected or invalid packet:", p))
3465             raise
3466
3467         err = self.statistics.get_counter('/err/nat44-classify/next in2out')
3468         self.assertEqual(err, 1)
3469         err = self.statistics.get_counter('/err/nat44-classify/next out2in')
3470         self.assertEqual(err, 1)
3471
3472     def test_del_session(self):
3473         """ Delete NAT44 session """
3474         self.nat44_add_address(self.nat_addr)
3475         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3476         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3477                                                   is_inside=0)
3478
3479         pkts = self.create_stream_in(self.pg0, self.pg1)
3480         self.pg0.add_stream(pkts)
3481         self.pg_enable_capture(self.pg_interfaces)
3482         self.pg_start()
3483         self.pg1.get_capture(len(pkts))
3484
3485         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3486         nsessions = len(sessions)
3487
3488         self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3489                                     sessions[0].inside_port,
3490                                     sessions[0].protocol)
3491         self.vapi.nat44_del_session(sessions[1].outside_ip_address,
3492                                     sessions[1].outside_port,
3493                                     sessions[1].protocol,
3494                                     is_in=0)
3495
3496         sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3497         self.assertEqual(nsessions - len(sessions), 2)
3498
3499         self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3500                                     sessions[0].inside_port,
3501                                     sessions[0].protocol)
3502
3503         self.verify_no_nat44_user()
3504
3505     def test_set_get_reass(self):
3506         """ NAT44 set/get virtual fragmentation reassembly """
3507         reas_cfg1 = self.vapi.nat_get_reass()
3508
3509         self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3510                                 max_reass=reas_cfg1.ip4_max_reass * 2,
3511                                 max_frag=reas_cfg1.ip4_max_frag * 2)
3512
3513         reas_cfg2 = self.vapi.nat_get_reass()
3514
3515         self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3516         self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3517         self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3518
3519         self.vapi.nat_set_reass(drop_frag=1)
3520         self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3521
3522     def test_frag_in_order(self):
3523         """ NAT44 translate fragments arriving in order """
3524
3525         self.nat44_add_address(self.nat_addr)
3526         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3527         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3528                                                   is_inside=0)
3529
3530         self.frag_in_order(proto=IP_PROTOS.tcp)
3531         self.frag_in_order(proto=IP_PROTOS.udp)
3532         self.frag_in_order(proto=IP_PROTOS.icmp)
3533
3534     def test_frag_forwarding(self):
3535         """ NAT44 forwarding fragment test """
3536         self.vapi.nat44_add_del_interface_addr(self.pg1.sw_if_index)
3537         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3538         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3539                                                   is_inside=0)
3540         self.vapi.nat44_forwarding_enable_disable(1)
3541
3542         data = "A" * 16 + "B" * 16 + "C" * 3
3543         pkts = self.create_stream_frag(self.pg1,
3544                                        self.pg0.remote_ip4,
3545                                        4789,
3546                                        4789,
3547                                        data,
3548                                        proto=IP_PROTOS.udp)
3549         self.pg1.add_stream(pkts)
3550         self.pg_enable_capture(self.pg_interfaces)
3551         self.pg_start()
3552         frags = self.pg0.get_capture(len(pkts))
3553         p = self.reass_frags_and_verify(frags,
3554                                         self.pg1.remote_ip4,
3555                                         self.pg0.remote_ip4)
3556         self.assertEqual(p[UDP].sport, 4789)
3557         self.assertEqual(p[UDP].dport, 4789)
3558         self.assertEqual(data, p[Raw].load)
3559
3560     def test_reass_hairpinning(self):
3561         """ NAT44 fragments hairpinning """
3562
3563         self.server = self.pg0.remote_hosts[1]
3564         self.host_in_port = random.randint(1025, 65535)
3565         self.server_in_port = random.randint(1025, 65535)
3566         self.server_out_port = random.randint(1025, 65535)
3567
3568         self.nat44_add_address(self.nat_addr)
3569         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3570         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3571                                                   is_inside=0)
3572         # add static mapping for server
3573         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3574                                       self.server_in_port,
3575                                       self.server_out_port,
3576                                       proto=IP_PROTOS.tcp)
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.udp)
3581         self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
3582
3583         self.reass_hairpinning(proto=IP_PROTOS.tcp)
3584         self.reass_hairpinning(proto=IP_PROTOS.udp)
3585         self.reass_hairpinning(proto=IP_PROTOS.icmp)
3586
3587     def test_frag_out_of_order(self):
3588         """ NAT44 translate fragments arriving out of order """
3589
3590         self.nat44_add_address(self.nat_addr)
3591         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3592         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3593                                                   is_inside=0)
3594
3595         self.frag_out_of_order(proto=IP_PROTOS.tcp)
3596         self.frag_out_of_order(proto=IP_PROTOS.udp)
3597         self.frag_out_of_order(proto=IP_PROTOS.icmp)
3598
3599     def test_port_restricted(self):
3600         """ Port restricted NAT44 (MAP-E CE) """
3601         self.nat44_add_address(self.nat_addr)
3602         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3603         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3604                                                   is_inside=0)
3605         self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3606                                                   psid_offset=6,
3607                                                   psid_length=6,
3608                                                   psid=10)
3609
3610         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3611              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3612              TCP(sport=4567, dport=22))
3613         self.pg0.add_stream(p)
3614         self.pg_enable_capture(self.pg_interfaces)
3615         self.pg_start()
3616         capture = self.pg1.get_capture(1)
3617         p = capture[0]
3618         try:
3619             ip = p[IP]
3620             tcp = p[TCP]
3621             self.assertEqual(ip.dst, self.pg1.remote_ip4)
3622             self.assertEqual(ip.src, self.nat_addr)
3623             self.assertEqual(tcp.dport, 22)
3624             self.assertNotEqual(tcp.sport, 4567)
3625             self.assertEqual((tcp.sport >> 6) & 63, 10)
3626             self.assert_packet_checksums_valid(p)
3627         except:
3628             self.logger.error(ppp("Unexpected or invalid packet:", p))
3629             raise
3630
3631     def test_port_range(self):
3632         """ External address port range """
3633         self.nat44_add_address(self.nat_addr)
3634         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3635         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3636                                                   is_inside=0)
3637         self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3638                                                   start_port=1025,
3639                                                   end_port=1027)
3640
3641         pkts = []
3642         for port in range(0, 5):
3643             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3644                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3645                  TCP(sport=1125 + port))
3646             pkts.append(p)
3647         self.pg0.add_stream(pkts)
3648         self.pg_enable_capture(self.pg_interfaces)
3649         self.pg_start()
3650         capture = self.pg1.get_capture(3)
3651         for p in capture:
3652             tcp = p[TCP]
3653             self.assertGreaterEqual(tcp.sport, 1025)
3654             self.assertLessEqual(tcp.sport, 1027)
3655
3656     def test_ipfix_max_frags(self):
3657         """ IPFIX logging maximum fragments pending reassembly exceeded """
3658         self.nat44_add_address(self.nat_addr)
3659         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3660         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3661                                                   is_inside=0)
3662         self.vapi.nat_set_reass(max_frag=1)
3663         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
3664                                      src_address=self.pg3.local_ip4n,
3665                                      path_mtu=512,
3666                                      template_interval=10)
3667         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
3668                                            src_port=self.ipfix_src_port)
3669
3670         data = "A" * 4 + "B" * 16 + "C" * 3
3671         self.tcp_port_in = random.randint(1025, 65535)
3672         pkts = self.create_stream_frag(self.pg0,
3673                                        self.pg1.remote_ip4,
3674                                        self.tcp_port_in,
3675                                        20,
3676                                        data)
3677         pkts.reverse()
3678         self.pg0.add_stream(pkts)
3679         self.pg_enable_capture(self.pg_interfaces)
3680         self.pg_start()
3681         self.pg1.assert_nothing_captured()
3682         sleep(1)
3683         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
3684         capture = self.pg3.get_capture(9)
3685         ipfix = IPFIXDecoder()
3686         # first load template
3687         for p in capture:
3688             self.assertTrue(p.haslayer(IPFIX))
3689             self.assertEqual(p[IP].src, self.pg3.local_ip4)
3690             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
3691             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
3692             self.assertEqual(p[UDP].dport, 4739)
3693             self.assertEqual(p[IPFIX].observationDomainID,
3694                              self.ipfix_domain_id)
3695             if p.haslayer(Template):
3696                 ipfix.add_template(p.getlayer(Template))
3697         # verify events in data set
3698         for p in capture:
3699             if p.haslayer(Data):
3700                 data = ipfix.decode_data_set(p.getlayer(Set))
3701                 self.verify_ipfix_max_fragments_ip4(data, 1,
3702                                                     self.pg0.remote_ip4n)
3703
3704     def test_multiple_outside_vrf(self):
3705         """ Multiple outside VRF """
3706         vrf_id1 = 1
3707         vrf_id2 = 2
3708
3709         self.pg1.unconfig_ip4()
3710         self.pg2.unconfig_ip4()
3711         self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
3712         self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
3713         self.pg1.set_table_ip4(vrf_id1)
3714         self.pg2.set_table_ip4(vrf_id2)
3715         self.pg1.config_ip4()
3716         self.pg2.config_ip4()
3717         self.pg1.resolve_arp()
3718         self.pg2.resolve_arp()
3719
3720         self.nat44_add_address(self.nat_addr)
3721         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3722         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3723                                                   is_inside=0)
3724         self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
3725                                                   is_inside=0)
3726
3727         try:
3728             # first VRF
3729             pkts = self.create_stream_in(self.pg0, self.pg1)
3730             self.pg0.add_stream(pkts)
3731             self.pg_enable_capture(self.pg_interfaces)
3732             self.pg_start()
3733             capture = self.pg1.get_capture(len(pkts))
3734             self.verify_capture_out(capture, self.nat_addr)
3735
3736             pkts = self.create_stream_out(self.pg1, self.nat_addr)
3737             self.pg1.add_stream(pkts)
3738             self.pg_enable_capture(self.pg_interfaces)
3739             self.pg_start()
3740             capture = self.pg0.get_capture(len(pkts))
3741             self.verify_capture_in(capture, self.pg0)
3742
3743             self.tcp_port_in = 60303
3744             self.udp_port_in = 60304
3745             self.icmp_id_in = 60305
3746
3747             # second VRF
3748             pkts = self.create_stream_in(self.pg0, self.pg2)
3749             self.pg0.add_stream(pkts)
3750             self.pg_enable_capture(self.pg_interfaces)
3751             self.pg_start()
3752             capture = self.pg2.get_capture(len(pkts))
3753             self.verify_capture_out(capture, self.nat_addr)
3754
3755             pkts = self.create_stream_out(self.pg2, self.nat_addr)
3756             self.pg2.add_stream(pkts)
3757             self.pg_enable_capture(self.pg_interfaces)
3758             self.pg_start()
3759             capture = self.pg0.get_capture(len(pkts))
3760             self.verify_capture_in(capture, self.pg0)
3761
3762         finally:
3763             self.pg1.unconfig_ip4()
3764             self.pg2.unconfig_ip4()
3765             self.pg1.set_table_ip4(0)
3766             self.pg2.set_table_ip4(0)
3767             self.pg1.config_ip4()
3768             self.pg2.config_ip4()
3769             self.pg1.resolve_arp()
3770             self.pg2.resolve_arp()
3771
3772     @unittest.skipUnless(running_extended_tests, "part of extended tests")
3773     def test_session_timeout(self):
3774         """ NAT44 session timeouts """
3775         self.nat44_add_address(self.nat_addr)
3776         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3777         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3778                                                   is_inside=0)
3779         self.vapi.nat_set_timeouts(udp=5)
3780
3781         max_sessions = 1000
3782         pkts = []
3783         for i in range(0, max_sessions):
3784             src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3785             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3786                  IP(src=src, dst=self.pg1.remote_ip4) /
3787                  UDP(sport=1025, dport=53))
3788             pkts.append(p)
3789         self.pg0.add_stream(pkts)
3790         self.pg_enable_capture(self.pg_interfaces)
3791         self.pg_start()
3792         self.pg1.get_capture(max_sessions)
3793
3794         sleep(6)
3795
3796         pkts = []
3797         for i in range(0, max_sessions):
3798             src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3799             p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3800                  IP(src=src, dst=self.pg1.remote_ip4) /
3801                  UDP(sport=1026, dport=53))
3802             pkts.append(p)
3803         self.pg0.add_stream(pkts)
3804         self.pg_enable_capture(self.pg_interfaces)
3805         self.pg_start()
3806         self.pg1.get_capture(max_sessions)
3807
3808         nsessions = 0
3809         users = self.vapi.nat44_user_dump()
3810         for user in users:
3811             nsessions = nsessions + user.nsessions
3812         self.assertLess(nsessions, 2 * max_sessions)
3813
3814     def test_mss_clamping(self):
3815         """ TCP MSS clamping """
3816         self.nat44_add_address(self.nat_addr)
3817         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3818         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3819                                                   is_inside=0)
3820
3821         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3822              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3823              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3824                  flags="S", options=[('MSS', 1400)]))
3825
3826         self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3827         self.pg0.add_stream(p)
3828         self.pg_enable_capture(self.pg_interfaces)
3829         self.pg_start()
3830         capture = self.pg1.get_capture(1)
3831         # Negotiated MSS value greater than configured - changed
3832         self.verify_mss_value(capture[0], 1000)
3833
3834         self.vapi.nat_set_mss_clamping(enable=0)
3835         self.pg0.add_stream(p)
3836         self.pg_enable_capture(self.pg_interfaces)
3837         self.pg_start()
3838         capture = self.pg1.get_capture(1)
3839         # MSS clamping disabled - negotiated MSS unchanged
3840         self.verify_mss_value(capture[0], 1400)
3841
3842         self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3843         self.pg0.add_stream(p)
3844         self.pg_enable_capture(self.pg_interfaces)
3845         self.pg_start()
3846         capture = self.pg1.get_capture(1)
3847         # Negotiated MSS value smaller than configured - unchanged
3848         self.verify_mss_value(capture[0], 1400)
3849
3850     @unittest.skipUnless(running_extended_tests, "part of extended tests")
3851     def test_ha_send(self):
3852         """ Send HA session synchronization events (active) """
3853         self.nat44_add_address(self.nat_addr)
3854         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3855         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3856                                                   is_inside=0)
3857         self.vapi.nat_ha_set_listener(self.pg3.local_ip4, port=12345)
3858         self.vapi.nat_ha_set_failover(self.pg3.remote_ip4, port=12346)
3859         bind_layers(UDP, HANATStateSync, sport=12345)
3860
3861         # create sessions
3862         pkts = self.create_stream_in(self.pg0, self.pg1)
3863         self.pg0.add_stream(pkts)
3864         self.pg_enable_capture(self.pg_interfaces)
3865         self.pg_start()
3866         capture = self.pg1.get_capture(len(pkts))
3867         self.verify_capture_out(capture)
3868         # active send HA events
3869         self.vapi.nat_ha_flush()
3870         stats = self.statistics.get_counter('/nat44/ha/add-event-send')
3871         self.assertEqual(stats[0][0], 3)
3872         capture = self.pg3.get_capture(1)
3873         p = capture[0]
3874         self.assert_packet_checksums_valid(p)
3875         try:
3876             ip = p[IP]
3877             udp = p[UDP]
3878             hanat = p[HANATStateSync]
3879         except IndexError:
3880             self.logger.error(ppp("Invalid packet:", p))
3881             raise
3882         else:
3883             self.assertEqual(ip.src, self.pg3.local_ip4)
3884             self.assertEqual(ip.dst, self.pg3.remote_ip4)
3885             self.assertEqual(udp.sport, 12345)
3886             self.assertEqual(udp.dport, 12346)
3887             self.assertEqual(hanat.version, 1)
3888             self.assertEqual(hanat.thread_index, 0)
3889             self.assertEqual(hanat.count, 3)
3890             seq = hanat.sequence_number
3891             for event in hanat.events:
3892                 self.assertEqual(event.event_type, 1)
3893                 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
3894                 self.assertEqual(event.out_addr, self.nat_addr)
3895                 self.assertEqual(event.fib_index, 0)
3896
3897         # ACK received events
3898         ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3899                IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3900                UDP(sport=12346, dport=12345) /
3901                HANATStateSync(sequence_number=seq, flags='ACK'))
3902         self.pg3.add_stream(ack)
3903         self.pg_start()
3904         stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3905         self.assertEqual(stats[0][0], 1)
3906
3907         # delete one session
3908         self.pg_enable_capture(self.pg_interfaces)
3909         self.vapi.nat44_del_session(self.pg0.remote_ip4n, self.tcp_port_in,
3910                                     IP_PROTOS.tcp)
3911         self.vapi.nat_ha_flush()
3912         stats = self.statistics.get_counter('/nat44/ha/del-event-send')
3913         self.assertEqual(stats[0][0], 1)
3914         capture = self.pg3.get_capture(1)
3915         p = capture[0]
3916         try:
3917             hanat = p[HANATStateSync]
3918         except IndexError:
3919             self.logger.error(ppp("Invalid packet:", p))
3920             raise
3921         else:
3922             self.assertGreater(hanat.sequence_number, seq)
3923
3924         # do not send ACK, active retry send HA event again
3925         self.pg_enable_capture(self.pg_interfaces)
3926         sleep(12)
3927         stats = self.statistics.get_counter('/nat44/ha/retry-count')
3928         self.assertEqual(stats[0][0], 3)
3929         stats = self.statistics.get_counter('/nat44/ha/missed-count')
3930         self.assertEqual(stats[0][0], 1)
3931         capture = self.pg3.get_capture(3)
3932         for packet in capture:
3933             self.assertEqual(packet, p)
3934
3935         # session counters refresh
3936         pkts = self.create_stream_out(self.pg1)
3937         self.pg1.add_stream(pkts)
3938         self.pg_enable_capture(self.pg_interfaces)
3939         self.pg_start()
3940         self.pg0.get_capture(2)
3941         self.vapi.nat_ha_flush()
3942         stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
3943         self.assertEqual(stats[0][0], 2)
3944         capture = self.pg3.get_capture(1)
3945         p = capture[0]
3946         self.assert_packet_checksums_valid(p)
3947         try:
3948             ip = p[IP]
3949             udp = p[UDP]
3950             hanat = p[HANATStateSync]
3951         except IndexError:
3952             self.logger.error(ppp("Invalid packet:", p))
3953             raise
3954         else:
3955             self.assertEqual(ip.src, self.pg3.local_ip4)
3956             self.assertEqual(ip.dst, self.pg3.remote_ip4)
3957             self.assertEqual(udp.sport, 12345)
3958             self.assertEqual(udp.dport, 12346)
3959             self.assertEqual(hanat.version, 1)
3960             self.assertEqual(hanat.count, 2)
3961             seq = hanat.sequence_number
3962             for event in hanat.events:
3963                 self.assertEqual(event.event_type, 3)
3964                 self.assertEqual(event.out_addr, self.nat_addr)
3965                 self.assertEqual(event.fib_index, 0)
3966                 self.assertEqual(event.total_pkts, 2)
3967                 self.assertGreater(event.total_bytes, 0)
3968
3969         ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3970                IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3971                UDP(sport=12346, dport=12345) /
3972                HANATStateSync(sequence_number=seq, flags='ACK'))
3973         self.pg3.add_stream(ack)
3974         self.pg_start()
3975         stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3976         self.assertEqual(stats[0][0], 2)
3977
3978     def test_ha_recv(self):
3979         """ Receive HA session synchronization events (passive) """
3980         self.nat44_add_address(self.nat_addr)
3981         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3982         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3983                                                   is_inside=0)
3984         self.vapi.nat_ha_set_listener(self.pg3.local_ip4, port=12345)
3985         bind_layers(UDP, HANATStateSync, sport=12345)
3986
3987         self.tcp_port_out = random.randint(1025, 65535)
3988         self.udp_port_out = random.randint(1025, 65535)
3989
3990         # send HA session add events to failover/passive
3991         p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3992              IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3993              UDP(sport=12346, dport=12345) /
3994              HANATStateSync(sequence_number=1, events=[
3995                  Event(event_type='add', protocol='tcp',
3996                        in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3997                        in_port=self.tcp_port_in, out_port=self.tcp_port_out,
3998                        eh_addr=self.pg1.remote_ip4,
3999                        ehn_addr=self.pg1.remote_ip4,
4000                        eh_port=self.tcp_external_port,
4001                        ehn_port=self.tcp_external_port, fib_index=0),
4002                  Event(event_type='add', protocol='udp',
4003                        in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4004                        in_port=self.udp_port_in, out_port=self.udp_port_out,
4005                        eh_addr=self.pg1.remote_ip4,
4006                        ehn_addr=self.pg1.remote_ip4,
4007                        eh_port=self.udp_external_port,
4008                        ehn_port=self.udp_external_port, fib_index=0)]))
4009
4010         self.pg3.add_stream(p)
4011         self.pg_enable_capture(self.pg_interfaces)
4012         self.pg_start()
4013         # receive ACK
4014         capture = self.pg3.get_capture(1)
4015         p = capture[0]
4016         try:
4017             hanat = p[HANATStateSync]
4018         except IndexError:
4019             self.logger.error(ppp("Invalid packet:", p))
4020             raise
4021         else:
4022             self.assertEqual(hanat.sequence_number, 1)
4023             self.assertEqual(hanat.flags, 'ACK')
4024             self.assertEqual(hanat.version, 1)
4025             self.assertEqual(hanat.thread_index, 0)
4026         stats = self.statistics.get_counter('/nat44/ha/ack-send')
4027         self.assertEqual(stats[0][0], 1)
4028         stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
4029         self.assertEqual(stats[0][0], 2)
4030         users = self.statistics.get_counter('/nat44/total-users')
4031         self.assertEqual(users[0][0], 1)
4032         sessions = self.statistics.get_counter('/nat44/total-sessions')
4033         self.assertEqual(sessions[0][0], 2)
4034         users = self.vapi.nat44_user_dump()
4035         self.assertEqual(len(users), 1)
4036         self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
4037         # there should be 2 sessions created by HA
4038         sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4039                                                      users[0].vrf_id)
4040         self.assertEqual(len(sessions), 2)
4041         for session in sessions:
4042             self.assertEqual(session.inside_ip_address, self.pg0.remote_ip4n)
4043             self.assertEqual(session.outside_ip_address, self.nat_addr_n)
4044             self.assertIn(session.inside_port,
4045                           [self.tcp_port_in, self.udp_port_in])
4046             self.assertIn(session.outside_port,
4047                           [self.tcp_port_out, self.udp_port_out])
4048             self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
4049
4050         # send HA session delete event to failover/passive
4051         p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4052              IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4053              UDP(sport=12346, dport=12345) /
4054              HANATStateSync(sequence_number=2, events=[
4055                  Event(event_type='del', protocol='udp',
4056                        in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4057                        in_port=self.udp_port_in, out_port=self.udp_port_out,
4058                        eh_addr=self.pg1.remote_ip4,
4059                        ehn_addr=self.pg1.remote_ip4,
4060                        eh_port=self.udp_external_port,
4061                        ehn_port=self.udp_external_port, fib_index=0)]))
4062
4063         self.pg3.add_stream(p)
4064         self.pg_enable_capture(self.pg_interfaces)
4065         self.pg_start()
4066         # receive ACK
4067         capture = self.pg3.get_capture(1)
4068         p = capture[0]
4069         try:
4070             hanat = p[HANATStateSync]
4071         except IndexError:
4072             self.logger.error(ppp("Invalid packet:", p))
4073             raise
4074         else:
4075             self.assertEqual(hanat.sequence_number, 2)
4076             self.assertEqual(hanat.flags, 'ACK')
4077             self.assertEqual(hanat.version, 1)
4078         users = self.vapi.nat44_user_dump()
4079         self.assertEqual(len(users), 1)
4080         self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
4081         # now we should have only 1 session, 1 deleted by HA
4082         sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4083                                                      users[0].vrf_id)
4084         self.assertEqual(len(sessions), 1)
4085         stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
4086         self.assertEqual(stats[0][0], 1)
4087
4088         stats = self.statistics.get_counter('/err/nat-ha/pkts-processed')
4089         self.assertEqual(stats, 2)
4090
4091         # send HA session refresh event to failover/passive
4092         p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4093              IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4094              UDP(sport=12346, dport=12345) /
4095              HANATStateSync(sequence_number=3, events=[
4096                  Event(event_type='refresh', protocol='tcp',
4097                        in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4098                        in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4099                        eh_addr=self.pg1.remote_ip4,
4100                        ehn_addr=self.pg1.remote_ip4,
4101                        eh_port=self.tcp_external_port,
4102                        ehn_port=self.tcp_external_port, fib_index=0,
4103                        total_bytes=1024, total_pkts=2)]))
4104         self.pg3.add_stream(p)
4105         self.pg_enable_capture(self.pg_interfaces)
4106         self.pg_start()
4107         # receive ACK
4108         capture = self.pg3.get_capture(1)
4109         p = capture[0]
4110         try:
4111             hanat = p[HANATStateSync]
4112         except IndexError:
4113             self.logger.error(ppp("Invalid packet:", p))
4114             raise
4115         else:
4116             self.assertEqual(hanat.sequence_number, 3)
4117             self.assertEqual(hanat.flags, 'ACK')
4118             self.assertEqual(hanat.version, 1)
4119         users = self.vapi.nat44_user_dump()
4120         self.assertEqual(len(users), 1)
4121         self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
4122         sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4123                                                      users[0].vrf_id)
4124         self.assertEqual(len(sessions), 1)
4125         session = sessions[0]
4126         self.assertEqual(session.total_bytes, 1024)
4127         self.assertEqual(session.total_pkts, 2)
4128         stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
4129         self.assertEqual(stats[0][0], 1)
4130
4131         stats = self.statistics.get_counter('/err/nat-ha/pkts-processed')
4132         self.assertEqual(stats, 3)
4133
4134         # send packet to test session created by HA
4135         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4136              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4137              TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
4138         self.pg1.add_stream(p)
4139         self.pg_enable_capture(self.pg_interfaces)
4140         self.pg_start()
4141         capture = self.pg0.get_capture(1)
4142         p = capture[0]
4143         try:
4144             ip = p[IP]
4145             tcp = p[TCP]
4146         except IndexError:
4147             self.logger.error(ppp("Invalid packet:", p))
4148             raise
4149         else:
4150             self.assertEqual(ip.src, self.pg1.remote_ip4)
4151             self.assertEqual(ip.dst, self.pg0.remote_ip4)
4152             self.assertEqual(tcp.sport, self.tcp_external_port)
4153             self.assertEqual(tcp.dport, self.tcp_port_in)
4154
4155     def tearDown(self):
4156         super(TestNAT44, self).tearDown()
4157         if not self.vpp_dead:
4158             self.logger.info(self.vapi.cli("show nat44 addresses"))
4159             self.logger.info(self.vapi.cli("show nat44 interfaces"))
4160             self.logger.info(self.vapi.cli("show nat44 static mappings"))
4161             self.logger.info(self.vapi.cli("show nat44 interface address"))
4162             self.logger.info(self.vapi.cli("show nat44 sessions detail"))
4163             self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
4164             self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
4165             self.logger.info(self.vapi.cli("show nat timeouts"))
4166             self.logger.info(
4167                 self.vapi.cli("show nat addr-port-assignment-alg"))
4168             self.logger.info(self.vapi.cli("show nat ha"))
4169             self.clear_nat44()
4170             self.vapi.cli("clear logging")
4171
4172
4173 class TestNAT44EndpointDependent(MethodHolder):
4174     """ Endpoint-Dependent mapping and filtering test cases """
4175
4176     @classmethod
4177     def setUpConstants(cls):
4178         super(TestNAT44EndpointDependent, cls).setUpConstants()
4179         cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4180
4181     @classmethod
4182     def setUpClass(cls):
4183         super(TestNAT44EndpointDependent, cls).setUpClass()
4184         cls.vapi.cli("set log class nat level debug")
4185         try:
4186             cls.tcp_port_in = 6303
4187             cls.tcp_port_out = 6303
4188             cls.udp_port_in = 6304
4189             cls.udp_port_out = 6304
4190             cls.icmp_id_in = 6305
4191             cls.icmp_id_out = 6305
4192             cls.nat_addr = '10.0.0.3'
4193             cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
4194             cls.ipfix_src_port = 4739
4195             cls.ipfix_domain_id = 1
4196             cls.tcp_external_port = 80
4197
4198             cls.create_pg_interfaces(range(7))
4199             cls.interfaces = list(cls.pg_interfaces[0:3])
4200
4201             for i in cls.interfaces:
4202                 i.admin_up()
4203                 i.config_ip4()
4204                 i.resolve_arp()
4205
4206             cls.pg0.generate_remote_hosts(3)
4207             cls.pg0.configure_ipv4_neighbors()
4208
4209             cls.pg3.admin_up()
4210
4211             cls.pg4.generate_remote_hosts(2)
4212             cls.pg4.config_ip4()
4213             ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
4214             cls.vapi.sw_interface_add_del_address(
4215                 sw_if_index=cls.pg4.sw_if_index, address=ip_addr_n,
4216                 address_length=24)
4217             cls.pg4.admin_up()
4218             cls.pg4.resolve_arp()
4219             cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4220             cls.pg4.resolve_arp()
4221
4222             zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
4223             cls.vapi.ip_table_add_del(is_add=1, table_id=1)
4224
4225             cls.pg5._local_ip4 = "10.1.1.1"
4226             cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
4227                                                    cls.pg5.local_ip4)
4228             cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4229             cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
4230                 socket.AF_INET, cls.pg5.remote_ip4)
4231             cls.pg5.set_table_ip4(1)
4232             cls.pg5.config_ip4()
4233             cls.pg5.admin_up()
4234             cls.vapi.ip_add_del_route(dst_address=cls.pg5.remote_ip4n,
4235                                       dst_address_length=32,
4236                                       table_id=1,
4237                                       next_hop_sw_if_index=cls.pg5.sw_if_index,
4238                                       next_hop_address=zero_ip4n)
4239
4240             cls.pg6._local_ip4 = "10.1.2.1"
4241             cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
4242                                                    cls.pg6.local_ip4)
4243             cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4244             cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
4245                 socket.AF_INET, cls.pg6.remote_ip4)
4246             cls.pg6.set_table_ip4(1)
4247             cls.pg6.config_ip4()
4248             cls.pg6.admin_up()
4249             cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4250                                       dst_address_length=32,
4251                                       table_id=1,
4252                                       next_hop_sw_if_index=cls.pg6.sw_if_index,
4253                                       next_hop_address=zero_ip4n)
4254
4255             cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4256                                       dst_address_length=16,
4257                                       next_hop_address=zero_ip4n,
4258                                       table_id=0,
4259                                       next_hop_table_id=1)
4260             cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
4261                                       dst_address_length=0,
4262                                       next_hop_address=zero_ip4n,
4263                                       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                                       table_id=0,
4268                                       next_hop_sw_if_index=cls.pg1.sw_if_index,
4269                                       next_hop_address=cls.pg1.local_ip4n)
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(is_ipv6=True, dst_address='\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
6463         except Exception:
6464             super(TestNAT44Out2InDPO, cls).tearDownClass()
6465             raise
6466
6467     def configure_xlat(self):
6468         self.dst_ip6_pfx = '1:2:3::'
6469         self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6470                                               self.dst_ip6_pfx)
6471         self.dst_ip6_pfx_len = 96
6472         self.src_ip6_pfx = '4:5:6::'
6473         self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6474                                               self.src_ip6_pfx)
6475         self.src_ip6_pfx_len = 96
6476         self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
6477                                  self.src_ip6_pfx_n, self.src_ip6_pfx_len,
6478                                  '\x00\x00\x00\x00', 0)
6479
6480     @unittest.skip('Temporary disabled')
6481     def test_464xlat_ce(self):
6482         """ Test 464XLAT CE with NAT44 """
6483
6484         nat_config = self.vapi.nat_show_config()
6485         self.assertEqual(1, nat_config.out2in_dpo)
6486
6487         self.configure_xlat()
6488
6489         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6490         self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
6491
6492         out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6493                                        self.dst_ip6_pfx_len)
6494         out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
6495                                        self.src_ip6_pfx_len)
6496
6497         try:
6498             pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6499             self.pg0.add_stream(pkts)
6500             self.pg_enable_capture(self.pg_interfaces)
6501             self.pg_start()
6502             capture = self.pg1.get_capture(len(pkts))
6503             self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
6504                                         dst_ip=out_src_ip6)
6505
6506             pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
6507                                               out_dst_ip6)
6508             self.pg1.add_stream(pkts)
6509             self.pg_enable_capture(self.pg_interfaces)
6510             self.pg_start()
6511             capture = self.pg0.get_capture(len(pkts))
6512             self.verify_capture_in(capture, self.pg0)
6513         finally:
6514             self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6515                                                       is_add=0)
6516             self.vapi.nat44_add_del_address_range(self.nat_addr_n,
6517                                                   self.nat_addr_n, is_add=0)
6518
6519     @unittest.skip('Temporary disabled')
6520     def test_464xlat_ce_no_nat(self):
6521         """ Test 464XLAT CE without NAT44 """
6522
6523         self.configure_xlat()
6524
6525         out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6526                                        self.dst_ip6_pfx_len)
6527         out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
6528                                        self.src_ip6_pfx_len)
6529
6530         pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6531         self.pg0.add_stream(pkts)
6532         self.pg_enable_capture(self.pg_interfaces)
6533         self.pg_start()
6534         capture = self.pg1.get_capture(len(pkts))
6535         self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
6536                                     nat_ip=out_dst_ip6, same_port=True)
6537
6538         pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
6539         self.pg1.add_stream(pkts)
6540         self.pg_enable_capture(self.pg_interfaces)
6541         self.pg_start()
6542         capture = self.pg0.get_capture(len(pkts))
6543         self.verify_capture_in(capture, self.pg0)
6544
6545
6546 class TestDeterministicNAT(MethodHolder):
6547     """ Deterministic NAT Test Cases """
6548
6549     @classmethod
6550     def setUpConstants(cls):
6551         super(TestDeterministicNAT, cls).setUpConstants()
6552         cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
6553
6554     @classmethod
6555     def setUpClass(cls):
6556         super(TestDeterministicNAT, cls).setUpClass()
6557         cls.vapi.cli("set log class nat level debug")
6558
6559         try:
6560             cls.tcp_port_in = 6303
6561             cls.tcp_external_port = 6303
6562             cls.udp_port_in = 6304
6563             cls.udp_external_port = 6304
6564             cls.icmp_id_in = 6305
6565             cls.nat_addr = '10.0.0.3'
6566
6567             cls.create_pg_interfaces(range(3))
6568             cls.interfaces = list(cls.pg_interfaces)
6569
6570             for i in cls.interfaces:
6571                 i.admin_up()
6572                 i.config_ip4()
6573                 i.resolve_arp()
6574
6575             cls.pg0.generate_remote_hosts(2)
6576             cls.pg0.configure_ipv4_neighbors()
6577
6578         except Exception:
6579             super(TestDeterministicNAT, cls).tearDownClass()
6580             raise
6581
6582     def create_stream_in(self, in_if, out_if, ttl=64):
6583         """
6584         Create packet stream for inside network
6585
6586         :param in_if: Inside interface
6587         :param out_if: Outside interface
6588         :param ttl: TTL of generated packets
6589         """
6590         pkts = []
6591         # TCP
6592         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6593              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
6594              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6595         pkts.append(p)
6596
6597         # UDP
6598         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6599              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
6600              UDP(sport=self.udp_port_in, dport=self.udp_external_port))
6601         pkts.append(p)
6602
6603         # ICMP
6604         p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6605              IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
6606              ICMP(id=self.icmp_id_in, type='echo-request'))
6607         pkts.append(p)
6608
6609         return pkts
6610
6611     def create_stream_out(self, out_if, dst_ip=None, ttl=64):
6612         """
6613         Create packet stream for outside network
6614
6615         :param out_if: Outside interface
6616         :param dst_ip: Destination IP address (Default use global NAT address)
6617         :param ttl: TTL of generated packets
6618         """
6619         if dst_ip is None:
6620             dst_ip = self.nat_addr
6621         pkts = []
6622         # TCP
6623         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6624              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
6625              TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
6626         pkts.append(p)
6627
6628         # UDP
6629         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6630              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
6631              UDP(dport=self.udp_port_out, sport=self.udp_external_port))
6632         pkts.append(p)
6633
6634         # ICMP
6635         p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6636              IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
6637              ICMP(id=self.icmp_external_id, type='echo-reply'))
6638         pkts.append(p)
6639
6640         return pkts
6641
6642     def verify_capture_out(self, capture, nat_ip=None):
6643         """
6644         Verify captured packets on outside network
6645
6646         :param capture: Captured packets
6647         :param nat_ip: Translated IP address (Default use global NAT address)
6648         :param same_port: Sorce port number is not translated (Default False)
6649         """
6650         if nat_ip is None:
6651             nat_ip = self.nat_addr
6652         for packet in capture:
6653             try:
6654                 self.assertEqual(packet[IP].src, nat_ip)
6655                 if packet.haslayer(TCP):
6656                     self.tcp_port_out = packet[TCP].sport
6657                 elif packet.haslayer(UDP):
6658                     self.udp_port_out = packet[UDP].sport
6659                 else:
6660                     self.icmp_external_id = packet[ICMP].id
6661             except:
6662                 self.logger.error(ppp("Unexpected or invalid packet "
6663                                       "(outside network):", packet))
6664                 raise
6665
6666     def test_deterministic_mode(self):
6667         """ NAT plugin run deterministic mode """
6668         in_addr = '172.16.255.0'
6669         out_addr = '172.17.255.50'
6670         in_addr_t = '172.16.255.20'
6671         in_addr_n = socket.inet_aton(in_addr)
6672         out_addr_n = socket.inet_aton(out_addr)
6673         in_addr_t_n = socket.inet_aton(in_addr_t)
6674         in_plen = 24
6675         out_plen = 32
6676
6677         nat_config = self.vapi.nat_show_config()
6678         self.assertEqual(1, nat_config.deterministic)
6679
6680         self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
6681
6682         rep1 = self.vapi.nat_det_forward(in_addr_t_n)
6683         self.assertEqual(rep1.out_addr[:4], out_addr_n)
6684         rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
6685         self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
6686
6687         deterministic_mappings = self.vapi.nat_det_map_dump()
6688         self.assertEqual(len(deterministic_mappings), 1)
6689         dsm = deterministic_mappings[0]
6690         self.assertEqual(in_addr_n, dsm.in_addr[:4])
6691         self.assertEqual(in_plen, dsm.in_plen)
6692         self.assertEqual(out_addr_n, dsm.out_addr[:4])
6693         self.assertEqual(out_plen, dsm.out_plen)
6694
6695         self.clear_nat_det()
6696         deterministic_mappings = self.vapi.nat_det_map_dump()
6697         self.assertEqual(len(deterministic_mappings), 0)
6698
6699     def test_set_timeouts(self):
6700         """ Set deterministic NAT timeouts """
6701         timeouts_before = self.vapi.nat_get_timeouts()
6702
6703         self.vapi.nat_set_timeouts(timeouts_before.udp + 10,
6704                                    timeouts_before.tcp_established + 10,
6705                                    timeouts_before.tcp_transitory + 10,
6706                                    timeouts_before.icmp + 10)
6707
6708         timeouts_after = self.vapi.nat_get_timeouts()
6709
6710         self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
6711         self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
6712         self.assertNotEqual(timeouts_before.tcp_established,
6713                             timeouts_after.tcp_established)
6714         self.assertNotEqual(timeouts_before.tcp_transitory,
6715                             timeouts_after.tcp_transitory)
6716
6717     def test_det_in(self):
6718         """ Deterministic NAT translation test (TCP, UDP, ICMP) """
6719
6720         nat_ip = "10.0.0.10"
6721
6722         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6723                                       32,
6724                                       socket.inet_aton(nat_ip),
6725                                       32)
6726         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6727         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6728                                                   is_inside=0)
6729
6730         # in2out
6731         pkts = self.create_stream_in(self.pg0, self.pg1)
6732         self.pg0.add_stream(pkts)
6733         self.pg_enable_capture(self.pg_interfaces)
6734         self.pg_start()
6735         capture = self.pg1.get_capture(len(pkts))
6736         self.verify_capture_out(capture, nat_ip)
6737
6738         # out2in
6739         pkts = self.create_stream_out(self.pg1, nat_ip)
6740         self.pg1.add_stream(pkts)
6741         self.pg_enable_capture(self.pg_interfaces)
6742         self.pg_start()
6743         capture = self.pg0.get_capture(len(pkts))
6744         self.verify_capture_in(capture, self.pg0)
6745
6746         # session dump test
6747         sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
6748         self.assertEqual(len(sessions), 3)
6749
6750         # TCP session
6751         s = sessions[0]
6752         self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6753         self.assertEqual(s.in_port, self.tcp_port_in)
6754         self.assertEqual(s.out_port, self.tcp_port_out)
6755         self.assertEqual(s.ext_port, self.tcp_external_port)
6756
6757         # UDP session
6758         s = sessions[1]
6759         self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6760         self.assertEqual(s.in_port, self.udp_port_in)
6761         self.assertEqual(s.out_port, self.udp_port_out)
6762         self.assertEqual(s.ext_port, self.udp_external_port)
6763
6764         # ICMP session
6765         s = sessions[2]
6766         self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6767         self.assertEqual(s.in_port, self.icmp_id_in)
6768         self.assertEqual(s.out_port, self.icmp_external_id)
6769
6770     def test_multiple_users(self):
6771         """ Deterministic NAT multiple users """
6772
6773         nat_ip = "10.0.0.10"
6774         port_in = 80
6775         external_port = 6303
6776
6777         host0 = self.pg0.remote_hosts[0]
6778         host1 = self.pg0.remote_hosts[1]
6779
6780         self.vapi.nat_det_add_del_map(host0.ip4n,
6781                                       24,
6782                                       socket.inet_aton(nat_ip),
6783                                       32)
6784         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6785         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6786                                                   is_inside=0)
6787
6788         # host0 to out
6789         p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
6790              IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
6791              TCP(sport=port_in, dport=external_port))
6792         self.pg0.add_stream(p)
6793         self.pg_enable_capture(self.pg_interfaces)
6794         self.pg_start()
6795         capture = self.pg1.get_capture(1)
6796         p = capture[0]
6797         try:
6798             ip = p[IP]
6799             tcp = p[TCP]
6800             self.assertEqual(ip.src, nat_ip)
6801             self.assertEqual(ip.dst, self.pg1.remote_ip4)
6802             self.assertEqual(tcp.dport, external_port)
6803             port_out0 = tcp.sport
6804         except:
6805             self.logger.error(ppp("Unexpected or invalid packet:", p))
6806             raise
6807
6808         # host1 to out
6809         p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
6810              IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
6811              TCP(sport=port_in, dport=external_port))
6812         self.pg0.add_stream(p)
6813         self.pg_enable_capture(self.pg_interfaces)
6814         self.pg_start()
6815         capture = self.pg1.get_capture(1)
6816         p = capture[0]
6817         try:
6818             ip = p[IP]
6819             tcp = p[TCP]
6820             self.assertEqual(ip.src, nat_ip)
6821             self.assertEqual(ip.dst, self.pg1.remote_ip4)
6822             self.assertEqual(tcp.dport, external_port)
6823             port_out1 = tcp.sport
6824         except:
6825             self.logger.error(ppp("Unexpected or invalid packet:", p))
6826             raise
6827
6828         dms = self.vapi.nat_det_map_dump()
6829         self.assertEqual(1, len(dms))
6830         self.assertEqual(2, dms[0].ses_num)
6831
6832         # out to host0
6833         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6834              IP(src=self.pg1.remote_ip4, dst=nat_ip) /
6835              TCP(sport=external_port, dport=port_out0))
6836         self.pg1.add_stream(p)
6837         self.pg_enable_capture(self.pg_interfaces)
6838         self.pg_start()
6839         capture = self.pg0.get_capture(1)
6840         p = capture[0]
6841         try:
6842             ip = p[IP]
6843             tcp = p[TCP]
6844             self.assertEqual(ip.src, self.pg1.remote_ip4)
6845             self.assertEqual(ip.dst, host0.ip4)
6846             self.assertEqual(tcp.dport, port_in)
6847             self.assertEqual(tcp.sport, external_port)
6848         except:
6849             self.logger.error(ppp("Unexpected or invalid packet:", p))
6850             raise
6851
6852         # out to host1
6853         p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6854              IP(src=self.pg1.remote_ip4, dst=nat_ip) /
6855              TCP(sport=external_port, dport=port_out1))
6856         self.pg1.add_stream(p)
6857         self.pg_enable_capture(self.pg_interfaces)
6858         self.pg_start()
6859         capture = self.pg0.get_capture(1)
6860         p = capture[0]
6861         try:
6862             ip = p[IP]
6863             tcp = p[TCP]
6864             self.assertEqual(ip.src, self.pg1.remote_ip4)
6865             self.assertEqual(ip.dst, host1.ip4)
6866             self.assertEqual(tcp.dport, port_in)
6867             self.assertEqual(tcp.sport, external_port)
6868         except:
6869             self.logger.error(ppp("Unexpected or invalid packet", p))
6870             raise
6871
6872         # session close api test
6873         self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
6874                                             port_out1,
6875                                             self.pg1.remote_ip4n,
6876                                             external_port)
6877         dms = self.vapi.nat_det_map_dump()
6878         self.assertEqual(dms[0].ses_num, 1)
6879
6880         self.vapi.nat_det_close_session_in(host0.ip4n,
6881                                            port_in,
6882                                            self.pg1.remote_ip4n,
6883                                            external_port)
6884         dms = self.vapi.nat_det_map_dump()
6885         self.assertEqual(dms[0].ses_num, 0)
6886
6887     def test_tcp_session_close_detection_in(self):
6888         """ Deterministic NAT TCP session close from inside network """
6889         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6890                                       32,
6891                                       socket.inet_aton(self.nat_addr),
6892                                       32)
6893         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6894         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6895                                                   is_inside=0)
6896
6897         self.initiate_tcp_session(self.pg0, self.pg1)
6898
6899         # close the session from inside
6900         try:
6901             # FIN packet in -> out
6902             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6903                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6904                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6905                      flags="F"))
6906             self.pg0.add_stream(p)
6907             self.pg_enable_capture(self.pg_interfaces)
6908             self.pg_start()
6909             self.pg1.get_capture(1)
6910
6911             pkts = []
6912
6913             # ACK packet out -> in
6914             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6915                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6916                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6917                      flags="A"))
6918             pkts.append(p)
6919
6920             # FIN packet out -> in
6921             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6922                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6923                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6924                      flags="F"))
6925             pkts.append(p)
6926
6927             self.pg1.add_stream(pkts)
6928             self.pg_enable_capture(self.pg_interfaces)
6929             self.pg_start()
6930             self.pg0.get_capture(2)
6931
6932             # ACK packet in -> out
6933             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6934                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6935                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6936                      flags="A"))
6937             self.pg0.add_stream(p)
6938             self.pg_enable_capture(self.pg_interfaces)
6939             self.pg_start()
6940             self.pg1.get_capture(1)
6941
6942             # Check if deterministic NAT44 closed the session
6943             dms = self.vapi.nat_det_map_dump()
6944             self.assertEqual(0, dms[0].ses_num)
6945         except:
6946             self.logger.error("TCP session termination failed")
6947             raise
6948
6949     def test_tcp_session_close_detection_out(self):
6950         """ Deterministic NAT TCP session close from outside network """
6951         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6952                                       32,
6953                                       socket.inet_aton(self.nat_addr),
6954                                       32)
6955         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6956         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6957                                                   is_inside=0)
6958
6959         self.initiate_tcp_session(self.pg0, self.pg1)
6960
6961         # close the session from outside
6962         try:
6963             # FIN packet out -> in
6964             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6965                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6966                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6967                      flags="F"))
6968             self.pg1.add_stream(p)
6969             self.pg_enable_capture(self.pg_interfaces)
6970             self.pg_start()
6971             self.pg0.get_capture(1)
6972
6973             pkts = []
6974
6975             # ACK packet in -> out
6976             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6977                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6978                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6979                      flags="A"))
6980             pkts.append(p)
6981
6982             # ACK packet in -> out
6983             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6984                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6985                  TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6986                      flags="F"))
6987             pkts.append(p)
6988
6989             self.pg0.add_stream(pkts)
6990             self.pg_enable_capture(self.pg_interfaces)
6991             self.pg_start()
6992             self.pg1.get_capture(2)
6993
6994             # ACK packet out -> in
6995             p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6996                  IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6997                  TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6998                      flags="A"))
6999             self.pg1.add_stream(p)
7000             self.pg_enable_capture(self.pg_interfaces)
7001             self.pg_start()
7002             self.pg0.get_capture(1)
7003
7004             # Check if deterministic NAT44 closed the session
7005             dms = self.vapi.nat_det_map_dump()
7006             self.assertEqual(0, dms[0].ses_num)
7007         except:
7008             self.logger.error("TCP session termination failed")
7009             raise
7010
7011     @unittest.skipUnless(running_extended_tests, "part of extended tests")
7012     def test_session_timeout(self):
7013         """ Deterministic NAT session timeouts """
7014         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
7015                                       32,
7016                                       socket.inet_aton(self.nat_addr),
7017                                       32)
7018         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
7019         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
7020                                                   is_inside=0)
7021
7022         self.initiate_tcp_session(self.pg0, self.pg1)
7023         self.vapi.nat_set_timeouts(5, 5, 5, 5)
7024         pkts = self.create_stream_in(self.pg0, self.pg1)
7025         self.pg0.add_stream(pkts)
7026         self.pg_enable_capture(self.pg_interfaces)
7027         self.pg_start()
7028         capture = self.pg1.get_capture(len(pkts))
7029         sleep(15)
7030
7031         dms = self.vapi.nat_det_map_dump()
7032         self.assertEqual(0, dms[0].ses_num)
7033
7034     @unittest.skipUnless(running_extended_tests, "part of extended tests")
7035     def test_session_limit_per_user(self):
7036         """ Deterministic NAT maximum sessions per user limit """
7037         self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
7038                                       32,
7039                                       socket.inet_aton(self.nat_addr),
7040                                       32)
7041         self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
7042         self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
7043                                                   is_inside=0)
7044         self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
7045                                      src_address=self.pg2.local_ip4n,
7046                                      path_mtu=512,
7047                                      template_interval=10)
7048         self.vapi.nat_ipfix_enable_disable()
7049
7050         pkts = []
7051         for port in range(1025, 2025):
7052             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7053                  IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7054                  UDP(sport=port, dport=port))
7055             pkts.append(p)
7056
7057         self.pg0.add_stream(pkts)
7058         self.pg_enable_capture(self.pg_interfaces)
7059         self.pg_start()
7060         capture = self.pg1.get_capture(len(pkts))
7061
7062         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7063              IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7064              UDP(sport=3001, dport=3002))
7065         self.pg0.add_stream(p)
7066         self.pg_enable_capture(self.pg_interfaces)
7067         self.pg_start()
7068         capture = self.pg1.assert_nothing_captured()
7069
7070         # verify ICMP error packet
7071         capture = self.pg0.get_capture(1)
7072         p = capture[0]
7073         self.assertTrue(p.haslayer(ICMP))
7074         icmp = p[ICMP]
7075         self.assertEqual(icmp.type, 3)
7076         self.assertEqual(icmp.code, 1)
7077         self.assertTrue(icmp.haslayer(IPerror))
7078         inner_ip = icmp[IPerror]
7079         self.assertEqual(inner_ip[UDPerror].sport, 3001)
7080         self.assertEqual(inner_ip[UDPerror].dport, 3002)
7081
7082         dms = self.vapi.nat_det_map_dump()
7083
7084         self.assertEqual(1000, dms[0].ses_num)
7085
7086         # verify IPFIX logging
7087         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
7088         sleep(1)
7089         capture = self.pg2.get_capture(2)
7090         ipfix = IPFIXDecoder()
7091         # first load template
7092         for p in capture:
7093             self.assertTrue(p.haslayer(IPFIX))
7094             if p.haslayer(Template):
7095                 ipfix.add_template(p.getlayer(Template))
7096         # verify events in data set
7097         for p in capture:
7098             if p.haslayer(Data):
7099                 data = ipfix.decode_data_set(p.getlayer(Set))
7100                 self.verify_ipfix_max_entries_per_user(data,
7101                                                        1000,
7102                                                        self.pg0.remote_ip4n)
7103
7104     def clear_nat_det(self):
7105         """
7106         Clear deterministic NAT configuration.
7107         """
7108         self.vapi.nat_ipfix_enable_disable(enable=0)
7109         self.vapi.nat_set_timeouts()
7110         deterministic_mappings = self.vapi.nat_det_map_dump()
7111         for dsm in deterministic_mappings:
7112             self.vapi.nat_det_add_del_map(dsm.in_addr,
7113                                           dsm.in_plen,
7114                                           dsm.out_addr,
7115                                           dsm.out_plen,
7116                                           is_add=0)
7117
7118         interfaces = self.vapi.nat44_interface_dump()
7119         for intf in interfaces:
7120             self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
7121                                                       intf.is_inside,
7122                                                       is_add=0)
7123
7124     def tearDown(self):
7125         super(TestDeterministicNAT, self).tearDown()
7126         if not self.vpp_dead:
7127             self.logger.info(self.vapi.cli("show nat44 interfaces"))
7128             self.logger.info(self.vapi.cli("show nat timeouts"))
7129             self.logger.info(
7130                 self.vapi.cli("show nat44 deterministic mappings"))
7131             self.logger.info(
7132                 self.vapi.cli("show nat44 deterministic sessions"))
7133             self.clear_nat_det()
7134
7135
7136 class TestNAT64(MethodHolder):
7137     """ NAT64 Test Cases """
7138
7139     @classmethod
7140     def setUpConstants(cls):
7141         super(TestNAT64, cls).setUpConstants()
7142         cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
7143                                 "nat64 st hash buckets 256", "}"])
7144
7145     @classmethod
7146     def setUpClass(cls):
7147         super(TestNAT64, cls).setUpClass()
7148
7149         try:
7150             cls.tcp_port_in = 6303
7151             cls.tcp_port_out = 6303
7152             cls.udp_port_in = 6304
7153             cls.udp_port_out = 6304
7154             cls.icmp_id_in = 6305
7155             cls.icmp_id_out = 6305
7156             cls.tcp_external_port = 80
7157             cls.nat_addr = '10.0.0.3'
7158             cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
7159             cls.vrf1_id = 10
7160             cls.vrf1_nat_addr = '10.0.10.3'
7161             cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
7162                                                    cls.vrf1_nat_addr)
7163             cls.ipfix_src_port = 4739
7164             cls.ipfix_domain_id = 1
7165
7166             cls.create_pg_interfaces(range(6))
7167             cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
7168             cls.ip6_interfaces.append(cls.pg_interfaces[2])
7169             cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
7170
7171             cls.vapi.ip_table_add_del(is_ipv6=1, is_add=1,
7172                                       table_id=cls.vrf1_id)
7173
7174             cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
7175
7176             cls.pg0.generate_remote_hosts(2)
7177
7178             for i in cls.ip6_interfaces:
7179                 i.admin_up()
7180                 i.config_ip6()
7181                 i.configure_ipv6_neighbors()
7182
7183             for i in cls.ip4_interfaces:
7184                 i.admin_up()
7185                 i.config_ip4()
7186                 i.resolve_arp()
7187
7188             cls.pg3.admin_up()
7189             cls.pg3.config_ip4()
7190             cls.pg3.resolve_arp()
7191             cls.pg3.config_ip6()
7192             cls.pg3.configure_ipv6_neighbors()
7193
7194             cls.pg5.admin_up()
7195             cls.pg5.config_ip6()
7196
7197         except Exception:
7198             super(TestNAT64, cls).tearDownClass()
7199             raise
7200
7201     def test_nat64_inside_interface_handles_neighbor_advertisement(self):
7202         """ NAT64 inside interface handles Neighbor Advertisement """
7203
7204         self.vapi.nat64_add_del_interface(self.pg5.sw_if_index)
7205
7206         # Try to send ping
7207         ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7208                 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7209                 ICMPv6EchoRequest())
7210         pkts = [ping]
7211         self.pg5.add_stream(pkts)
7212         self.pg_enable_capture(self.pg_interfaces)
7213         self.pg_start()
7214
7215         # Wait for Neighbor Solicitation
7216         capture = self.pg5.get_capture(len(pkts))
7217         packet = capture[0]
7218         try:
7219             self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7220             self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
7221             tgt = packet[ICMPv6ND_NS].tgt
7222         except:
7223             self.logger.error(ppp("Unexpected or invalid packet:", packet))
7224             raise
7225
7226         # Send Neighbor Advertisement
7227         p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7228              IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7229              ICMPv6ND_NA(tgt=tgt) /
7230              ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
7231         pkts = [p]
7232         self.pg5.add_stream(pkts)
7233         self.pg_enable_capture(self.pg_interfaces)
7234         self.pg_start()
7235
7236         # Try to send ping again
7237         pkts = [ping]
7238         self.pg5.add_stream(pkts)
7239         self.pg_enable_capture(self.pg_interfaces)
7240         self.pg_start()
7241
7242         # Wait for ping reply
7243         capture = self.pg5.get_capture(len(pkts))
7244         packet = capture[0]
7245         try:
7246             self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7247             self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
7248             self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
7249         except:
7250             self.logger.error(ppp("Unexpected or invalid packet:", packet))
7251             raise
7252
7253     def test_pool(self):
7254         """ Add/delete address to NAT64 pool """
7255         nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
7256
7257         self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
7258
7259         addresses = self.vapi.nat64_pool_addr_dump()
7260         self.assertEqual(len(addresses), 1)
7261         self.assertEqual(addresses[0].address, nat_addr)
7262
7263         self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
7264
7265         addresses = self.vapi.nat64_pool_addr_dump()
7266         self.assertEqual(len(addresses), 0)
7267
7268     def test_interface(self):
7269         """ Enable/disable NAT64 feature on the interface """
7270         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7271         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7272
7273         interfaces = self.vapi.nat64_interface_dump()
7274         self.assertEqual(len(interfaces), 2)
7275         pg0_found = False
7276         pg1_found = False
7277         for intf in interfaces:
7278             if intf.sw_if_index == self.pg0.sw_if_index:
7279                 self.assertEqual(intf.is_inside, 1)
7280                 pg0_found = True
7281             elif intf.sw_if_index == self.pg1.sw_if_index:
7282                 self.assertEqual(intf.is_inside, 0)
7283                 pg1_found = True
7284         self.assertTrue(pg0_found)
7285         self.assertTrue(pg1_found)
7286
7287         features = self.vapi.cli("show interface features pg0")
7288         self.assertIn('nat64-in2out', features)
7289         features = self.vapi.cli("show interface features pg1")
7290         self.assertIn('nat64-out2in', features)
7291
7292         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
7293         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
7294
7295         interfaces = self.vapi.nat64_interface_dump()
7296         self.assertEqual(len(interfaces), 0)
7297
7298     def test_static_bib(self):
7299         """ Add/delete static BIB entry """
7300         in_addr = socket.inet_pton(socket.AF_INET6,
7301                                    '2001:db8:85a3::8a2e:370:7334')
7302         out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
7303         in_port = 1234
7304         out_port = 5678
7305         proto = IP_PROTOS.tcp
7306
7307         self.vapi.nat64_add_del_static_bib(in_addr,
7308                                            out_addr,
7309                                            in_port,
7310                                            out_port,
7311                                            proto)
7312         bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
7313         static_bib_num = 0
7314         for bibe in bib:
7315             if bibe.is_static:
7316                 static_bib_num += 1
7317                 self.assertEqual(bibe.i_addr, in_addr)
7318                 self.assertEqual(bibe.o_addr, out_addr)
7319                 self.assertEqual(bibe.i_port, in_port)
7320                 self.assertEqual(bibe.o_port, out_port)
7321         self.assertEqual(static_bib_num, 1)
7322         bibs = self.statistics.get_counter('/nat64/total-bibs')
7323         self.assertEqual(bibs[0][0], 1)
7324
7325         self.vapi.nat64_add_del_static_bib(in_addr,
7326                                            out_addr,
7327                                            in_port,
7328                                            out_port,
7329                                            proto,
7330                                            is_add=0)
7331         bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
7332         static_bib_num = 0
7333         for bibe in bib:
7334             if bibe.is_static:
7335                 static_bib_num += 1
7336         self.assertEqual(static_bib_num, 0)
7337         bibs = self.statistics.get_counter('/nat64/total-bibs')
7338         self.assertEqual(bibs[0][0], 0)
7339
7340     def test_set_timeouts(self):
7341         """ Set NAT64 timeouts """
7342         # verify default values
7343         timeouts = self.vapi.nat_get_timeouts()
7344         self.assertEqual(timeouts.udp, 300)
7345         self.assertEqual(timeouts.icmp, 60)
7346         self.assertEqual(timeouts.tcp_transitory, 240)
7347         self.assertEqual(timeouts.tcp_established, 7440)
7348
7349         # set and verify custom values
7350         self.vapi.nat_set_timeouts(udp=200, icmp=30, tcp_transitory=250,
7351                                    tcp_established=7450)
7352         timeouts = self.vapi.nat_get_timeouts()
7353         self.assertEqual(timeouts.udp, 200)
7354         self.assertEqual(timeouts.icmp, 30)
7355         self.assertEqual(timeouts.tcp_transitory, 250)
7356         self.assertEqual(timeouts.tcp_established, 7450)
7357
7358     def test_dynamic(self):
7359         """ NAT64 dynamic translation test """
7360         self.tcp_port_in = 6303
7361         self.udp_port_in = 6304
7362         self.icmp_id_in = 6305
7363
7364         ses_num_start = self.nat64_get_ses_num()
7365
7366         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7367                                                 self.nat_addr_n)
7368         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7369         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7370
7371         # in2out
7372         tcpn = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7373         udpn = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7374         icmpn = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7375         totaln = self.statistics.get_counter(
7376             '/err/nat64-in2out/good in2out packets processed')
7377
7378         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7379         self.pg0.add_stream(pkts)
7380         self.pg_enable_capture(self.pg_interfaces)
7381         self.pg_start()
7382         capture = self.pg1.get_capture(len(pkts))
7383         self.verify_capture_out(capture, nat_ip=self.nat_addr,
7384                                 dst_ip=self.pg1.remote_ip4)
7385
7386         err = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7387         self.assertEqual(err - tcpn, 1)
7388         err = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7389         self.assertEqual(err - udpn, 1)
7390         err = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7391         self.assertEqual(err - icmpn, 1)
7392         err = self.statistics.get_counter(
7393             '/err/nat64-in2out/good in2out packets processed')
7394         self.assertEqual(err - totaln, 3)
7395
7396         # out2in
7397         tcpn = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7398         udpn = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7399         icmpn = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7400         totaln = self.statistics.get_counter(
7401             '/err/nat64-out2in/good out2in packets processed')
7402
7403         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7404         self.pg1.add_stream(pkts)
7405         self.pg_enable_capture(self.pg_interfaces)
7406         self.pg_start()
7407         capture = self.pg0.get_capture(len(pkts))
7408         ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7409         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7410
7411         err = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7412         self.assertEqual(err - tcpn, 1)
7413         err = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7414         self.assertEqual(err - udpn, 1)
7415         err = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7416         self.assertEqual(err - icmpn, 1)
7417         err = self.statistics.get_counter(
7418             '/err/nat64-out2in/good out2in packets processed')
7419         self.assertEqual(err - totaln, 3)
7420
7421         bibs = self.statistics.get_counter('/nat64/total-bibs')
7422         self.assertEqual(bibs[0][0], 3)
7423         sessions = self.statistics.get_counter('/nat64/total-sessions')
7424         self.assertEqual(sessions[0][0], 3)
7425
7426         # in2out
7427         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7428         self.pg0.add_stream(pkts)
7429         self.pg_enable_capture(self.pg_interfaces)
7430         self.pg_start()
7431         capture = self.pg1.get_capture(len(pkts))
7432         self.verify_capture_out(capture, nat_ip=self.nat_addr,
7433                                 dst_ip=self.pg1.remote_ip4)
7434
7435         # out2in
7436         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7437         self.pg1.add_stream(pkts)
7438         self.pg_enable_capture(self.pg_interfaces)
7439         self.pg_start()
7440         capture = self.pg0.get_capture(len(pkts))
7441         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7442
7443         ses_num_end = self.nat64_get_ses_num()
7444
7445         self.assertEqual(ses_num_end - ses_num_start, 3)
7446
7447         # tenant with specific VRF
7448         self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
7449                                                 self.vrf1_nat_addr_n,
7450                                                 vrf_id=self.vrf1_id)
7451         self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
7452
7453         pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
7454         self.pg2.add_stream(pkts)
7455         self.pg_enable_capture(self.pg_interfaces)
7456         self.pg_start()
7457         capture = self.pg1.get_capture(len(pkts))
7458         self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7459                                 dst_ip=self.pg1.remote_ip4)
7460
7461         pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7462         self.pg1.add_stream(pkts)
7463         self.pg_enable_capture(self.pg_interfaces)
7464         self.pg_start()
7465         capture = self.pg2.get_capture(len(pkts))
7466         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
7467
7468     def test_static(self):
7469         """ NAT64 static translation test """
7470         self.tcp_port_in = 60303
7471         self.udp_port_in = 60304
7472         self.icmp_id_in = 60305
7473         self.tcp_port_out = 60303
7474         self.udp_port_out = 60304
7475         self.icmp_id_out = 60305
7476
7477         ses_num_start = self.nat64_get_ses_num()
7478
7479         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7480                                                 self.nat_addr_n)
7481         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7482         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7483
7484         self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7485                                            self.nat_addr_n,
7486                                            self.tcp_port_in,
7487                                            self.tcp_port_out,
7488                                            IP_PROTOS.tcp)
7489         self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7490                                            self.nat_addr_n,
7491                                            self.udp_port_in,
7492                                            self.udp_port_out,
7493                                            IP_PROTOS.udp)
7494         self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7495                                            self.nat_addr_n,
7496                                            self.icmp_id_in,
7497                                            self.icmp_id_out,
7498                                            IP_PROTOS.icmp)
7499
7500         # in2out
7501         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7502         self.pg0.add_stream(pkts)
7503         self.pg_enable_capture(self.pg_interfaces)
7504         self.pg_start()
7505         capture = self.pg1.get_capture(len(pkts))
7506         self.verify_capture_out(capture, nat_ip=self.nat_addr,
7507                                 dst_ip=self.pg1.remote_ip4, same_port=True)
7508
7509         # out2in
7510         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7511         self.pg1.add_stream(pkts)
7512         self.pg_enable_capture(self.pg_interfaces)
7513         self.pg_start()
7514         capture = self.pg0.get_capture(len(pkts))
7515         ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7516         self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7517
7518         ses_num_end = self.nat64_get_ses_num()
7519
7520         self.assertEqual(ses_num_end - ses_num_start, 3)
7521
7522     @unittest.skipUnless(running_extended_tests, "part of extended tests")
7523     def test_session_timeout(self):
7524         """ NAT64 session timeout """
7525         self.icmp_id_in = 1234
7526         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7527                                                 self.nat_addr_n)
7528         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7529         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7530         self.vapi.nat_set_timeouts(icmp=5, tcp_transitory=5, tcp_established=5)
7531
7532         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7533         self.pg0.add_stream(pkts)
7534         self.pg_enable_capture(self.pg_interfaces)
7535         self.pg_start()
7536         capture = self.pg1.get_capture(len(pkts))
7537
7538         ses_num_before_timeout = self.nat64_get_ses_num()
7539
7540         sleep(15)
7541
7542         # ICMP and TCP session after timeout
7543         ses_num_after_timeout = self.nat64_get_ses_num()
7544         self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
7545
7546     def test_icmp_error(self):
7547         """ NAT64 ICMP Error message translation """
7548         self.tcp_port_in = 6303
7549         self.udp_port_in = 6304
7550         self.icmp_id_in = 6305
7551
7552         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7553                                                 self.nat_addr_n)
7554         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7555         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7556
7557         # send some packets to create sessions
7558         pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7559         self.pg0.add_stream(pkts)
7560         self.pg_enable_capture(self.pg_interfaces)
7561         self.pg_start()
7562         capture_ip4 = self.pg1.get_capture(len(pkts))
7563         self.verify_capture_out(capture_ip4,
7564                                 nat_ip=self.nat_addr,
7565                                 dst_ip=self.pg1.remote_ip4)
7566
7567         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7568         self.pg1.add_stream(pkts)
7569         self.pg_enable_capture(self.pg_interfaces)
7570         self.pg_start()
7571         capture_ip6 = self.pg0.get_capture(len(pkts))
7572         ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7573         self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
7574                                    self.pg0.remote_ip6)
7575
7576         # in2out
7577         pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7578                 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
7579                 ICMPv6DestUnreach(code=1) /
7580                 packet[IPv6] for packet in capture_ip6]
7581         self.pg0.add_stream(pkts)
7582         self.pg_enable_capture(self.pg_interfaces)
7583         self.pg_start()
7584         capture = self.pg1.get_capture(len(pkts))
7585         for packet in capture:
7586             try:
7587                 self.assertEqual(packet[IP].src, self.nat_addr)
7588                 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
7589                 self.assertEqual(packet[ICMP].type, 3)
7590                 self.assertEqual(packet[ICMP].code, 13)
7591                 inner = packet[IPerror]
7592                 self.assertEqual(inner.src, self.pg1.remote_ip4)
7593                 self.assertEqual(inner.dst, self.nat_addr)
7594                 self.assert_packet_checksums_valid(packet)
7595                 if inner.haslayer(TCPerror):
7596                     self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
7597                 elif inner.haslayer(UDPerror):
7598                     self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
7599                 else:
7600                     self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
7601             except:
7602                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7603                 raise
7604
7605         # out2in
7606         pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7607                 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7608                 ICMP(type=3, code=13) /
7609                 packet[IP] for packet in capture_ip4]
7610         self.pg1.add_stream(pkts)
7611         self.pg_enable_capture(self.pg_interfaces)
7612         self.pg_start()
7613         capture = self.pg0.get_capture(len(pkts))
7614         for packet in capture:
7615             try:
7616                 self.assertEqual(packet[IPv6].src, ip.src)
7617                 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7618                 icmp = packet[ICMPv6DestUnreach]
7619                 self.assertEqual(icmp.code, 1)
7620                 inner = icmp[IPerror6]
7621                 self.assertEqual(inner.src, self.pg0.remote_ip6)
7622                 self.assertEqual(inner.dst, ip.src)
7623                 self.assert_icmpv6_checksum_valid(packet)
7624                 if inner.haslayer(TCPerror):
7625                     self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
7626                 elif inner.haslayer(UDPerror):
7627                     self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
7628                 else:
7629                     self.assertEqual(inner[ICMPv6EchoRequest].id,
7630                                      self.icmp_id_in)
7631             except:
7632                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7633                 raise
7634
7635     def test_hairpinning(self):
7636         """ NAT64 hairpinning """
7637
7638         client = self.pg0.remote_hosts[0]
7639         server = self.pg0.remote_hosts[1]
7640         server_tcp_in_port = 22
7641         server_tcp_out_port = 4022
7642         server_udp_in_port = 23
7643         server_udp_out_port = 4023
7644         client_tcp_in_port = 1234
7645         client_udp_in_port = 1235
7646         client_tcp_out_port = 0
7647         client_udp_out_port = 0
7648         ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
7649         nat_addr_ip6 = ip.src
7650
7651         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7652                                                 self.nat_addr_n)
7653         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7654         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7655
7656         self.vapi.nat64_add_del_static_bib(server.ip6n,
7657                                            self.nat_addr_n,
7658                                            server_tcp_in_port,
7659                                            server_tcp_out_port,
7660                                            IP_PROTOS.tcp)
7661         self.vapi.nat64_add_del_static_bib(server.ip6n,
7662                                            self.nat_addr_n,
7663                                            server_udp_in_port,
7664                                            server_udp_out_port,
7665                                            IP_PROTOS.udp)
7666
7667         # client to server
7668         pkts = []
7669         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7670              IPv6(src=client.ip6, dst=nat_addr_ip6) /
7671              TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7672         pkts.append(p)
7673         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7674              IPv6(src=client.ip6, dst=nat_addr_ip6) /
7675              UDP(sport=client_udp_in_port, dport=server_udp_out_port))
7676         pkts.append(p)
7677         self.pg0.add_stream(pkts)
7678         self.pg_enable_capture(self.pg_interfaces)
7679         self.pg_start()
7680         capture = self.pg0.get_capture(len(pkts))
7681         for packet in capture:
7682             try:
7683                 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7684                 self.assertEqual(packet[IPv6].dst, server.ip6)
7685                 self.assert_packet_checksums_valid(packet)
7686                 if packet.haslayer(TCP):
7687                     self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
7688                     self.assertEqual(packet[TCP].dport, server_tcp_in_port)
7689                     client_tcp_out_port = packet[TCP].sport
7690                 else:
7691                     self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
7692                     self.assertEqual(packet[UDP].dport, server_udp_in_port)
7693                     client_udp_out_port = packet[UDP].sport
7694             except:
7695                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7696                 raise
7697
7698         # server to client
7699         pkts = []
7700         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7701              IPv6(src=server.ip6, dst=nat_addr_ip6) /
7702              TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
7703         pkts.append(p)
7704         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7705              IPv6(src=server.ip6, dst=nat_addr_ip6) /
7706              UDP(sport=server_udp_in_port, dport=client_udp_out_port))
7707         pkts.append(p)
7708         self.pg0.add_stream(pkts)
7709         self.pg_enable_capture(self.pg_interfaces)
7710         self.pg_start()
7711         capture = self.pg0.get_capture(len(pkts))
7712         for packet in capture:
7713             try:
7714                 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7715                 self.assertEqual(packet[IPv6].dst, client.ip6)
7716                 self.assert_packet_checksums_valid(packet)
7717                 if packet.haslayer(TCP):
7718                     self.assertEqual(packet[TCP].sport, server_tcp_out_port)
7719                     self.assertEqual(packet[TCP].dport, client_tcp_in_port)
7720                 else:
7721                     self.assertEqual(packet[UDP].sport, server_udp_out_port)
7722                     self.assertEqual(packet[UDP].dport, client_udp_in_port)
7723             except:
7724                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7725                 raise
7726
7727         # ICMP error
7728         pkts = []
7729         pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7730                 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7731                 ICMPv6DestUnreach(code=1) /
7732                 packet[IPv6] for packet in capture]
7733         self.pg0.add_stream(pkts)
7734         self.pg_enable_capture(self.pg_interfaces)
7735         self.pg_start()
7736         capture = self.pg0.get_capture(len(pkts))
7737         for packet in capture:
7738             try:
7739                 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7740                 self.assertEqual(packet[IPv6].dst, server.ip6)
7741                 icmp = packet[ICMPv6DestUnreach]
7742                 self.assertEqual(icmp.code, 1)
7743                 inner = icmp[IPerror6]
7744                 self.assertEqual(inner.src, server.ip6)
7745                 self.assertEqual(inner.dst, nat_addr_ip6)
7746                 self.assert_packet_checksums_valid(packet)
7747                 if inner.haslayer(TCPerror):
7748                     self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
7749                     self.assertEqual(inner[TCPerror].dport,
7750                                      client_tcp_out_port)
7751                 else:
7752                     self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
7753                     self.assertEqual(inner[UDPerror].dport,
7754                                      client_udp_out_port)
7755             except:
7756                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7757                 raise
7758
7759     def test_prefix(self):
7760         """ NAT64 Network-Specific Prefix """
7761
7762         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7763                                                 self.nat_addr_n)
7764         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7765         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7766         self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
7767                                                 self.vrf1_nat_addr_n,
7768                                                 vrf_id=self.vrf1_id)
7769         self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
7770
7771         # Add global prefix
7772         global_pref64 = "2001:db8::"
7773         global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
7774         global_pref64_len = 32
7775         self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
7776
7777         prefix = self.vapi.nat64_prefix_dump()
7778         self.assertEqual(len(prefix), 1)
7779         self.assertEqual(prefix[0].prefix, global_pref64_n)
7780         self.assertEqual(prefix[0].prefix_len, global_pref64_len)
7781         self.assertEqual(prefix[0].vrf_id, 0)
7782
7783         # Add tenant specific prefix
7784         vrf1_pref64 = "2001:db8:122:300::"
7785         vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
7786         vrf1_pref64_len = 56
7787         self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
7788                                        vrf1_pref64_len,
7789                                        vrf_id=self.vrf1_id)
7790         prefix = self.vapi.nat64_prefix_dump()
7791         self.assertEqual(len(prefix), 2)
7792
7793         # Global prefix
7794         pkts = self.create_stream_in_ip6(self.pg0,
7795                                          self.pg1,
7796                                          pref=global_pref64,
7797                                          plen=global_pref64_len)
7798         self.pg0.add_stream(pkts)
7799         self.pg_enable_capture(self.pg_interfaces)
7800         self.pg_start()
7801         capture = self.pg1.get_capture(len(pkts))
7802         self.verify_capture_out(capture, nat_ip=self.nat_addr,
7803                                 dst_ip=self.pg1.remote_ip4)
7804
7805         pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7806         self.pg1.add_stream(pkts)
7807         self.pg_enable_capture(self.pg_interfaces)
7808         self.pg_start()
7809         capture = self.pg0.get_capture(len(pkts))
7810         dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7811                                   global_pref64,
7812                                   global_pref64_len)
7813         self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
7814
7815         # Tenant specific prefix
7816         pkts = self.create_stream_in_ip6(self.pg2,
7817                                          self.pg1,
7818                                          pref=vrf1_pref64,
7819                                          plen=vrf1_pref64_len)
7820         self.pg2.add_stream(pkts)
7821         self.pg_enable_capture(self.pg_interfaces)
7822         self.pg_start()
7823         capture = self.pg1.get_capture(len(pkts))
7824         self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7825                                 dst_ip=self.pg1.remote_ip4)
7826
7827         pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7828         self.pg1.add_stream(pkts)
7829         self.pg_enable_capture(self.pg_interfaces)
7830         self.pg_start()
7831         capture = self.pg2.get_capture(len(pkts))
7832         dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7833                                   vrf1_pref64,
7834                                   vrf1_pref64_len)
7835         self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
7836
7837     def test_unknown_proto(self):
7838         """ NAT64 translate packet with unknown protocol """
7839
7840         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7841                                                 self.nat_addr_n)
7842         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7843         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7844         remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7845
7846         # in2out
7847         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7848              IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
7849              TCP(sport=self.tcp_port_in, dport=20))
7850         self.pg0.add_stream(p)
7851         self.pg_enable_capture(self.pg_interfaces)
7852         self.pg_start()
7853         p = self.pg1.get_capture(1)
7854
7855         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7856              IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
7857              GRE() /
7858              IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7859              TCP(sport=1234, dport=1234))
7860         self.pg0.add_stream(p)
7861         self.pg_enable_capture(self.pg_interfaces)
7862         self.pg_start()
7863         p = self.pg1.get_capture(1)
7864         packet = p[0]
7865         try:
7866             self.assertEqual(packet[IP].src, self.nat_addr)
7867             self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
7868             self.assertEqual(packet.haslayer(GRE), 1)
7869             self.assert_packet_checksums_valid(packet)
7870         except:
7871             self.logger.error(ppp("Unexpected or invalid packet:", packet))
7872             raise
7873
7874         # out2in
7875         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7876              IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7877              GRE() /
7878              IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7879              TCP(sport=1234, dport=1234))
7880         self.pg1.add_stream(p)
7881         self.pg_enable_capture(self.pg_interfaces)
7882         self.pg_start()
7883         p = self.pg0.get_capture(1)
7884         packet = p[0]
7885         try:
7886             self.assertEqual(packet[IPv6].src, remote_ip6)
7887             self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7888             self.assertEqual(packet[IPv6].nh, 47)
7889         except:
7890             self.logger.error(ppp("Unexpected or invalid packet:", packet))
7891             raise
7892
7893     def test_hairpinning_unknown_proto(self):
7894         """ NAT64 translate packet with unknown protocol - hairpinning """
7895
7896         client = self.pg0.remote_hosts[0]
7897         server = self.pg0.remote_hosts[1]
7898         server_tcp_in_port = 22
7899         server_tcp_out_port = 4022
7900         client_tcp_in_port = 1234
7901         client_tcp_out_port = 1235
7902         server_nat_ip = "10.0.0.100"
7903         client_nat_ip = "10.0.0.110"
7904         server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
7905         client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
7906         server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
7907         client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
7908
7909         self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
7910                                                 client_nat_ip_n)
7911         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7912         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7913
7914         self.vapi.nat64_add_del_static_bib(server.ip6n,
7915                                            server_nat_ip_n,
7916                                            server_tcp_in_port,
7917                                            server_tcp_out_port,
7918                                            IP_PROTOS.tcp)
7919
7920         self.vapi.nat64_add_del_static_bib(server.ip6n,
7921                                            server_nat_ip_n,
7922                                            0,
7923                                            0,
7924                                            IP_PROTOS.gre)
7925
7926         self.vapi.nat64_add_del_static_bib(client.ip6n,
7927                                            client_nat_ip_n,
7928                                            client_tcp_in_port,
7929                                            client_tcp_out_port,
7930                                            IP_PROTOS.tcp)
7931
7932         # client to server
7933         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7934              IPv6(src=client.ip6, dst=server_nat_ip6) /
7935              TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7936         self.pg0.add_stream(p)
7937         self.pg_enable_capture(self.pg_interfaces)
7938         self.pg_start()
7939         p = self.pg0.get_capture(1)
7940
7941         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7942              IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
7943              GRE() /
7944              IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7945              TCP(sport=1234, dport=1234))
7946         self.pg0.add_stream(p)
7947         self.pg_enable_capture(self.pg_interfaces)
7948         self.pg_start()
7949         p = self.pg0.get_capture(1)
7950         packet = p[0]
7951         try:
7952             self.assertEqual(packet[IPv6].src, client_nat_ip6)
7953             self.assertEqual(packet[IPv6].dst, server.ip6)
7954             self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
7955         except:
7956             self.logger.error(ppp("Unexpected or invalid packet:", packet))
7957             raise
7958
7959         # server to client
7960         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7961              IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
7962              GRE() /
7963              IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7964              TCP(sport=1234, dport=1234))
7965         self.pg0.add_stream(p)
7966         self.pg_enable_capture(self.pg_interfaces)
7967         self.pg_start()
7968         p = self.pg0.get_capture(1)
7969         packet = p[0]
7970         try:
7971             self.assertEqual(packet[IPv6].src, server_nat_ip6)
7972             self.assertEqual(packet[IPv6].dst, client.ip6)
7973             self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
7974         except:
7975             self.logger.error(ppp("Unexpected or invalid packet:", packet))
7976             raise
7977
7978     def test_one_armed_nat64(self):
7979         """ One armed NAT64 """
7980         external_port = 0
7981         remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
7982                                            '64:ff9b::',
7983                                            96)
7984
7985         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7986                                                 self.nat_addr_n)
7987         self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
7988         self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
7989
7990         # in2out
7991         p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
7992              IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
7993              TCP(sport=12345, dport=80))
7994         self.pg3.add_stream(p)
7995         self.pg_enable_capture(self.pg_interfaces)
7996         self.pg_start()
7997         capture = self.pg3.get_capture(1)
7998         p = capture[0]
7999         try:
8000             ip = p[IP]
8001             tcp = p[TCP]
8002             self.assertEqual(ip.src, self.nat_addr)
8003             self.assertEqual(ip.dst, self.pg3.remote_ip4)
8004             self.assertNotEqual(tcp.sport, 12345)
8005             external_port = tcp.sport
8006             self.assertEqual(tcp.dport, 80)
8007             self.assert_packet_checksums_valid(p)
8008         except:
8009             self.logger.error(ppp("Unexpected or invalid packet:", p))
8010             raise
8011
8012         # out2in
8013         p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8014              IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
8015              TCP(sport=80, dport=external_port))
8016         self.pg3.add_stream(p)
8017         self.pg_enable_capture(self.pg_interfaces)
8018         self.pg_start()
8019         capture = self.pg3.get_capture(1)
8020         p = capture[0]
8021         try:
8022             ip = p[IPv6]
8023             tcp = p[TCP]
8024             self.assertEqual(ip.src, remote_host_ip6)
8025             self.assertEqual(ip.dst, self.pg3.remote_ip6)
8026             self.assertEqual(tcp.sport, 80)
8027             self.assertEqual(tcp.dport, 12345)
8028             self.assert_packet_checksums_valid(p)
8029         except:
8030             self.logger.error(ppp("Unexpected or invalid packet:", p))
8031             raise
8032
8033     def test_frag_in_order(self):
8034         """ NAT64 translate fragments arriving in order """
8035         self.tcp_port_in = random.randint(1025, 65535)
8036
8037         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8038                                                 self.nat_addr_n)
8039         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8040         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8041
8042         reass = self.vapi.nat_reass_dump()
8043         reass_n_start = len(reass)
8044
8045         # in2out
8046         data = 'a' * 200
8047         pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8048                                            self.tcp_port_in, 20, data)
8049         self.pg0.add_stream(pkts)
8050         self.pg_enable_capture(self.pg_interfaces)
8051         self.pg_start()
8052         frags = self.pg1.get_capture(len(pkts))
8053         p = self.reass_frags_and_verify(frags,
8054                                         self.nat_addr,
8055                                         self.pg1.remote_ip4)
8056         self.assertEqual(p[TCP].dport, 20)
8057         self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8058         self.tcp_port_out = p[TCP].sport
8059         self.assertEqual(data, p[Raw].load)
8060
8061         # out2in
8062         data = "A" * 4 + "b" * 16 + "C" * 3
8063         pkts = self.create_stream_frag(self.pg1,
8064                                        self.nat_addr,
8065                                        20,
8066                                        self.tcp_port_out,
8067                                        data)
8068         self.pg1.add_stream(pkts)
8069         self.pg_enable_capture(self.pg_interfaces)
8070         self.pg_start()
8071         frags = self.pg0.get_capture(len(pkts))
8072         src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8073         p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8074         self.assertEqual(p[TCP].sport, 20)
8075         self.assertEqual(p[TCP].dport, self.tcp_port_in)
8076         self.assertEqual(data, p[Raw].load)
8077
8078         reass = self.vapi.nat_reass_dump()
8079         reass_n_end = len(reass)
8080
8081         self.assertEqual(reass_n_end - reass_n_start, 2)
8082
8083     def test_reass_hairpinning(self):
8084         """ NAT64 fragments hairpinning """
8085         data = 'a' * 200
8086         server = self.pg0.remote_hosts[1]
8087         server_in_port = random.randint(1025, 65535)
8088         server_out_port = random.randint(1025, 65535)
8089         client_in_port = random.randint(1025, 65535)
8090         ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8091         nat_addr_ip6 = ip.src
8092
8093         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8094                                                 self.nat_addr_n)
8095         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8096         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8097
8098         # add static BIB entry for server
8099         self.vapi.nat64_add_del_static_bib(server.ip6n,
8100                                            self.nat_addr_n,
8101                                            server_in_port,
8102                                            server_out_port,
8103                                            IP_PROTOS.tcp)
8104
8105         # send packet from host to server
8106         pkts = self.create_stream_frag_ip6(self.pg0,
8107                                            self.nat_addr,
8108                                            client_in_port,
8109                                            server_out_port,
8110                                            data)
8111         self.pg0.add_stream(pkts)
8112         self.pg_enable_capture(self.pg_interfaces)
8113         self.pg_start()
8114         frags = self.pg0.get_capture(len(pkts))
8115         p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
8116         self.assertNotEqual(p[TCP].sport, client_in_port)
8117         self.assertEqual(p[TCP].dport, server_in_port)
8118         self.assertEqual(data, p[Raw].load)
8119
8120     def test_frag_out_of_order(self):
8121         """ NAT64 translate fragments arriving out of order """
8122         self.tcp_port_in = random.randint(1025, 65535)
8123
8124         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8125                                                 self.nat_addr_n)
8126         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8127         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8128
8129         # in2out
8130         data = 'a' * 200
8131         pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8132                                            self.tcp_port_in, 20, data)
8133         pkts.reverse()
8134         self.pg0.add_stream(pkts)
8135         self.pg_enable_capture(self.pg_interfaces)
8136         self.pg_start()
8137         frags = self.pg1.get_capture(len(pkts))
8138         p = self.reass_frags_and_verify(frags,
8139                                         self.nat_addr,
8140                                         self.pg1.remote_ip4)
8141         self.assertEqual(p[TCP].dport, 20)
8142         self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8143         self.tcp_port_out = p[TCP].sport
8144         self.assertEqual(data, p[Raw].load)
8145
8146         # out2in
8147         data = "A" * 4 + "B" * 16 + "C" * 3
8148         pkts = self.create_stream_frag(self.pg1,
8149                                        self.nat_addr,
8150                                        20,
8151                                        self.tcp_port_out,
8152                                        data)
8153         pkts.reverse()
8154         self.pg1.add_stream(pkts)
8155         self.pg_enable_capture(self.pg_interfaces)
8156         self.pg_start()
8157         frags = self.pg0.get_capture(len(pkts))
8158         src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8159         p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8160         self.assertEqual(p[TCP].sport, 20)
8161         self.assertEqual(p[TCP].dport, self.tcp_port_in)
8162         self.assertEqual(data, p[Raw].load)
8163
8164     def test_interface_addr(self):
8165         """ Acquire NAT64 pool addresses from interface """
8166         self.vapi.nat64_add_del_interface_addr(self.pg4.sw_if_index)
8167
8168         # no address in NAT64 pool
8169         adresses = self.vapi.nat44_address_dump()
8170         self.assertEqual(0, len(adresses))
8171
8172         # configure interface address and check NAT64 address pool
8173         self.pg4.config_ip4()
8174         addresses = self.vapi.nat64_pool_addr_dump()
8175         self.assertEqual(len(addresses), 1)
8176         self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
8177
8178         # remove interface address and check NAT64 address pool
8179         self.pg4.unconfig_ip4()
8180         addresses = self.vapi.nat64_pool_addr_dump()
8181         self.assertEqual(0, len(adresses))
8182
8183     @unittest.skipUnless(running_extended_tests, "part of extended tests")
8184     def test_ipfix_max_bibs_sessions(self):
8185         """ IPFIX logging maximum session and BIB entries exceeded """
8186         max_bibs = 1280
8187         max_sessions = 2560
8188         remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8189                                            '64:ff9b::',
8190                                            96)
8191
8192         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8193                                                 self.nat_addr_n)
8194         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8195         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8196
8197         pkts = []
8198         src = ""
8199         for i in range(0, max_bibs):
8200             src = "fd01:aa::%x" % (i)
8201             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8202                  IPv6(src=src, dst=remote_host_ip6) /
8203                  TCP(sport=12345, dport=80))
8204             pkts.append(p)
8205             p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8206                  IPv6(src=src, dst=remote_host_ip6) /
8207                  TCP(sport=12345, dport=22))
8208             pkts.append(p)
8209         self.pg0.add_stream(pkts)
8210         self.pg_enable_capture(self.pg_interfaces)
8211         self.pg_start()
8212         self.pg1.get_capture(max_sessions)
8213
8214         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8215                                      src_address=self.pg3.local_ip4n,
8216                                      path_mtu=512,
8217                                      template_interval=10)
8218         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8219                                            src_port=self.ipfix_src_port)
8220
8221         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8222              IPv6(src=src, dst=remote_host_ip6) /
8223              TCP(sport=12345, dport=25))
8224         self.pg0.add_stream(p)
8225         self.pg_enable_capture(self.pg_interfaces)
8226         self.pg_start()
8227         self.pg1.assert_nothing_captured()
8228         sleep(1)
8229         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
8230         capture = self.pg3.get_capture(9)
8231         ipfix = IPFIXDecoder()
8232         # first load template
8233         for p in capture:
8234             self.assertTrue(p.haslayer(IPFIX))
8235             self.assertEqual(p[IP].src, self.pg3.local_ip4)
8236             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8237             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8238             self.assertEqual(p[UDP].dport, 4739)
8239             self.assertEqual(p[IPFIX].observationDomainID,
8240                              self.ipfix_domain_id)
8241             if p.haslayer(Template):
8242                 ipfix.add_template(p.getlayer(Template))
8243         # verify events in data set
8244         for p in capture:
8245             if p.haslayer(Data):
8246                 data = ipfix.decode_data_set(p.getlayer(Set))
8247                 self.verify_ipfix_max_sessions(data, max_sessions)
8248
8249         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8250              IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8251              TCP(sport=12345, dport=80))
8252         self.pg0.add_stream(p)
8253         self.pg_enable_capture(self.pg_interfaces)
8254         self.pg_start()
8255         self.pg1.assert_nothing_captured()
8256         sleep(1)
8257         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
8258         capture = self.pg3.get_capture(1)
8259         # verify events in data set
8260         for p in capture:
8261             self.assertTrue(p.haslayer(IPFIX))
8262             self.assertEqual(p[IP].src, self.pg3.local_ip4)
8263             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8264             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8265             self.assertEqual(p[UDP].dport, 4739)
8266             self.assertEqual(p[IPFIX].observationDomainID,
8267                              self.ipfix_domain_id)
8268             if p.haslayer(Data):
8269                 data = ipfix.decode_data_set(p.getlayer(Set))
8270                 self.verify_ipfix_max_bibs(data, max_bibs)
8271
8272     def test_ipfix_max_frags(self):
8273         """ IPFIX logging maximum fragments pending reassembly exceeded """
8274         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8275                                                 self.nat_addr_n)
8276         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8277         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8278         self.vapi.nat_set_reass(max_frag=1, is_ip6=1)
8279         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8280                                      src_address=self.pg3.local_ip4n,
8281                                      path_mtu=512,
8282                                      template_interval=10)
8283         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8284                                            src_port=self.ipfix_src_port)
8285
8286         data = 'a' * 200
8287         pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8288                                            self.tcp_port_in, 20, data)
8289         pkts.reverse()
8290         self.pg0.add_stream(pkts)
8291         self.pg_enable_capture(self.pg_interfaces)
8292         self.pg_start()
8293         self.pg1.assert_nothing_captured()
8294         sleep(1)
8295         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
8296         capture = self.pg3.get_capture(9)
8297         ipfix = IPFIXDecoder()
8298         # first load template
8299         for p in capture:
8300             self.assertTrue(p.haslayer(IPFIX))
8301             self.assertEqual(p[IP].src, self.pg3.local_ip4)
8302             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8303             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8304             self.assertEqual(p[UDP].dport, 4739)
8305             self.assertEqual(p[IPFIX].observationDomainID,
8306                              self.ipfix_domain_id)
8307             if p.haslayer(Template):
8308                 ipfix.add_template(p.getlayer(Template))
8309         # verify events in data set
8310         for p in capture:
8311             if p.haslayer(Data):
8312                 data = ipfix.decode_data_set(p.getlayer(Set))
8313                 self.verify_ipfix_max_fragments_ip6(data, 1,
8314                                                     self.pg0.remote_ip6n)
8315
8316     def test_ipfix_bib_ses(self):
8317         """ IPFIX logging NAT64 BIB/session create and delete events """
8318         self.tcp_port_in = random.randint(1025, 65535)
8319         remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8320                                            '64:ff9b::',
8321                                            96)
8322
8323         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8324                                                 self.nat_addr_n)
8325         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8326         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8327         self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8328                                      src_address=self.pg3.local_ip4n,
8329                                      path_mtu=512,
8330                                      template_interval=10)
8331         self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8332                                            src_port=self.ipfix_src_port)
8333
8334         # Create
8335         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8336              IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8337              TCP(sport=self.tcp_port_in, dport=25))
8338         self.pg0.add_stream(p)
8339         self.pg_enable_capture(self.pg_interfaces)
8340         self.pg_start()
8341         p = self.pg1.get_capture(1)
8342         self.tcp_port_out = p[0][TCP].sport
8343         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
8344         capture = self.pg3.get_capture(10)
8345         ipfix = IPFIXDecoder()
8346         # first load template
8347         for p in capture:
8348             self.assertTrue(p.haslayer(IPFIX))
8349             self.assertEqual(p[IP].src, self.pg3.local_ip4)
8350             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8351             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8352             self.assertEqual(p[UDP].dport, 4739)
8353             self.assertEqual(p[IPFIX].observationDomainID,
8354                              self.ipfix_domain_id)
8355             if p.haslayer(Template):
8356                 ipfix.add_template(p.getlayer(Template))
8357         # verify events in data set
8358         for p in capture:
8359             if p.haslayer(Data):
8360                 data = ipfix.decode_data_set(p.getlayer(Set))
8361                 if ord(data[0][230]) == 10:
8362                     self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
8363                 elif ord(data[0][230]) == 6:
8364                     self.verify_ipfix_nat64_ses(data,
8365                                                 1,
8366                                                 self.pg0.remote_ip6n,
8367                                                 self.pg1.remote_ip4,
8368                                                 25)
8369                 else:
8370                     self.logger.error(ppp("Unexpected or invalid packet: ", p))
8371
8372         # Delete
8373         self.pg_enable_capture(self.pg_interfaces)
8374         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8375                                                 self.nat_addr_n,
8376                                                 is_add=0)
8377         self.vapi.cli("ipfix flush")  # FIXME this should be an API call
8378         capture = self.pg3.get_capture(2)
8379         # verify events in data set
8380         for p in capture:
8381             self.assertTrue(p.haslayer(IPFIX))
8382             self.assertEqual(p[IP].src, self.pg3.local_ip4)
8383             self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8384             self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8385             self.assertEqual(p[UDP].dport, 4739)
8386             self.assertEqual(p[IPFIX].observationDomainID,
8387                              self.ipfix_domain_id)
8388             if p.haslayer(Data):
8389                 data = ipfix.decode_data_set(p.getlayer(Set))
8390                 if ord(data[0][230]) == 11:
8391                     self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
8392                 elif ord(data[0][230]) == 7:
8393                     self.verify_ipfix_nat64_ses(data,
8394                                                 0,
8395                                                 self.pg0.remote_ip6n,
8396                                                 self.pg1.remote_ip4,
8397                                                 25)
8398                 else:
8399                     self.logger.error(ppp("Unexpected or invalid packet: ", p))
8400
8401     def test_syslog_sess(self):
8402         """ Test syslog session creation and deletion """
8403         self.tcp_port_in = random.randint(1025, 65535)
8404         remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8405                                            '64:ff9b::',
8406                                            96)
8407
8408         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8409                                                 self.nat_addr_n)
8410         self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8411         self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8412         self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
8413         self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
8414
8415         p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8416              IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8417              TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
8418         self.pg0.add_stream(p)
8419         self.pg_enable_capture(self.pg_interfaces)
8420         self.pg_start()
8421         p = self.pg1.get_capture(1)
8422         self.tcp_port_out = p[0][TCP].sport
8423         capture = self.pg3.get_capture(1)
8424         self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
8425
8426         self.pg_enable_capture(self.pg_interfaces)
8427         self.pg_start()
8428         self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8429                                                 self.nat_addr_n,
8430                                                 is_add=0)
8431         capture = self.pg3.get_capture(1)
8432         self.verify_syslog_sess(capture[0][Raw].load, False, True)
8433
8434     def nat64_get_ses_num(self):
8435         """
8436         Return number of active NAT64 sessions.
8437         """
8438         st = self.vapi.nat64_st_dump()
8439         return len(st)
8440
8441     def clear_nat64(self):
8442         """
8443         Clear NAT64 configuration.
8444         """
8445         self.vapi.nat_ipfix_enable_disable(enable=0,
8446                                            src_port=self.ipfix_src_port,
8447                                            domain_id=self.ipfix_domain_id)
8448         self.ipfix_src_port = 4739
8449         self.ipfix_domain_id = 1
8450
8451         self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
8452
8453         self.vapi.nat_set_timeouts()
8454
8455         interfaces = self.vapi.nat64_interface_dump()
8456         for intf in interfaces:
8457             if intf.is_inside > 1:
8458                 self.vapi.nat64_add_del_interface(intf.sw_if_index,
8459                                                   0,
8460                                                   is_add=0)
8461             self.vapi.nat64_add_del_interface(intf.sw_if_index,
8462                                               intf.is_inside,
8463                                               is_add=0)
8464
8465         bib = self.vapi.nat64_bib_dump(255)
8466         for bibe in bib:
8467             if bibe.is_static:
8468                 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
8469                                                    bibe.o_addr,
8470                                                    bibe.i_port,
8471                                                    bibe.o_port,
8472                                                    bibe.proto,
8473                                                    bibe.vrf_id,
8474                                                    is_add=0)
8475
8476         adresses = self.vapi.nat64_pool_addr_dump()
8477         for addr in adresses:
8478             self.vapi.nat64_add_del_pool_addr_range(addr.address,
8479                                                     addr.address,
8480                                                     vrf_id=addr.vrf_id,
8481                                                     is_add=0)
8482
8483         prefixes = self.vapi.nat64_prefix_dump()
8484         for prefix in prefixes:
8485             self.vapi.nat64_add_del_prefix(prefix.prefix,
8486                                            prefix.prefix_len,
8487                                            vrf_id=prefix.vrf_id,
8488                                            is_add=0)
8489
8490         bibs = self.statistics.get_counter('/nat64/total-bibs')
8491         self.assertEqual(bibs[0][0], 0)
8492         sessions = self.statistics.get_counter('/nat64/total-sessions')
8493         self.assertEqual(sessions[0][0], 0)
8494
8495     def tearDown(self):
8496         super(TestNAT64, self).tearDown()
8497         if not self.vpp_dead:
8498             self.logger.info(self.vapi.cli("show nat64 pool"))
8499             self.logger.info(self.vapi.cli("show nat64 interfaces"))
8500             self.logger.info(self.vapi.cli("show nat64 prefix"))
8501             self.logger.info(self.vapi.cli("show nat64 bib all"))
8502             self.logger.info(self.vapi.cli("show nat64 session table all"))
8503             self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
8504             self.clear_nat64()
8505
8506
8507 class TestDSlite(MethodHolder):
8508     """ DS-Lite Test Cases """
8509
8510     @classmethod
8511     def setUpClass(cls):
8512         super(TestDSlite, cls).setUpClass()
8513
8514         try:
8515             cls.nat_addr = '10.0.0.3'
8516             cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
8517
8518             cls.create_pg_interfaces(range(3))
8519             cls.pg0.admin_up()
8520             cls.pg0.config_ip4()
8521             cls.pg0.resolve_arp()
8522             cls.pg1.admin_up()
8523             cls.pg1.config_ip6()
8524             cls.pg1.generate_remote_hosts(2)
8525             cls.pg1.configure_ipv6_neighbors()
8526             cls.pg2.admin_up()
8527             cls.pg2.config_ip4()
8528             cls.pg2.resolve_arp()
8529
8530         except Exception:
8531             super(TestDSlite, cls).tearDownClass()
8532             raise
8533
8534     def verify_syslog_apmadd(self, data, isaddr, isport, xsaddr, xsport,
8535                              sv6enc, proto):
8536         message = data.decode('utf-8')
8537         try:
8538             message = SyslogMessage.parse(message)
8539         except ParseError as e:
8540             self.logger.error(e)
8541         else:
8542             self.assertEqual(message.severity, SyslogSeverity.info)
8543             self.assertEqual(message.appname, 'NAT')
8544             self.assertEqual(message.msgid, 'APMADD')
8545             sd_params = message.sd.get('napmap')
8546             self.assertTrue(sd_params is not None)
8547             self.assertEqual(sd_params.get('IATYP'), 'IPv4')
8548             self.assertEqual(sd_params.get('ISADDR'), isaddr)
8549             self.assertEqual(sd_params.get('ISPORT'), "%d" % isport)
8550             self.assertEqual(sd_params.get('XATYP'), 'IPv4')
8551             self.assertEqual(sd_params.get('XSADDR'), xsaddr)
8552             self.assertEqual(sd_params.get('XSPORT'), "%d" % xsport)
8553             self.assertEqual(sd_params.get('PROTO'), "%d" % proto)
8554             self.assertTrue(sd_params.get('SSUBIX') is not None)
8555             self.assertEqual(sd_params.get('SV6ENC'), sv6enc)
8556
8557     def test_dslite(self):
8558         """ Test DS-Lite """
8559         nat_config = self.vapi.nat_show_config()
8560         self.assertEqual(0, nat_config.dslite_ce)
8561
8562         self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
8563                                                  self.nat_addr_n)
8564         aftr_ip4 = '192.0.0.1'
8565         aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
8566         aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
8567         aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
8568         self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
8569         self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
8570
8571         # UDP
8572         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8573              IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
8574              IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8575              UDP(sport=20000, dport=10000))
8576         self.pg1.add_stream(p)
8577         self.pg_enable_capture(self.pg_interfaces)
8578         self.pg_start()
8579         capture = self.pg0.get_capture(1)
8580         capture = capture[0]
8581         self.assertFalse(capture.haslayer(IPv6))
8582         self.assertEqual(capture[IP].src, self.nat_addr)
8583         self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8584         self.assertNotEqual(capture[UDP].sport, 20000)
8585         self.assertEqual(capture[UDP].dport, 10000)
8586         self.assert_packet_checksums_valid(capture)
8587         out_port = capture[UDP].sport
8588         capture = self.pg2.get_capture(1)
8589         self.verify_syslog_apmadd(capture[0][Raw].load, '192.168.1.1',
8590                                   20000, self.nat_addr, out_port,
8591                                   self.pg1.remote_hosts[0].ip6, IP_PROTOS.udp)
8592
8593         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8594              IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8595              UDP(sport=10000, dport=out_port))
8596         self.pg0.add_stream(p)
8597         self.pg_enable_capture(self.pg_interfaces)
8598         self.pg_start()
8599         capture = self.pg1.get_capture(1)
8600         capture = capture[0]
8601         self.assertEqual(capture[IPv6].src, aftr_ip6)
8602         self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8603         self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8604         self.assertEqual(capture[IP].dst, '192.168.1.1')
8605         self.assertEqual(capture[UDP].sport, 10000)
8606         self.assertEqual(capture[UDP].dport, 20000)
8607         self.assert_packet_checksums_valid(capture)
8608
8609         # TCP
8610         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8611              IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8612              IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8613              TCP(sport=20001, dport=10001))
8614         self.pg1.add_stream(p)
8615         self.pg_enable_capture(self.pg_interfaces)
8616         self.pg_start()
8617         capture = self.pg0.get_capture(1)
8618         capture = capture[0]
8619         self.assertFalse(capture.haslayer(IPv6))
8620         self.assertEqual(capture[IP].src, self.nat_addr)
8621         self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8622         self.assertNotEqual(capture[TCP].sport, 20001)
8623         self.assertEqual(capture[TCP].dport, 10001)
8624         self.assert_packet_checksums_valid(capture)
8625         out_port = capture[TCP].sport
8626
8627         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8628              IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8629              TCP(sport=10001, dport=out_port))
8630         self.pg0.add_stream(p)
8631         self.pg_enable_capture(self.pg_interfaces)
8632         self.pg_start()
8633         capture = self.pg1.get_capture(1)
8634         capture = capture[0]
8635         self.assertEqual(capture[IPv6].src, aftr_ip6)
8636         self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8637         self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8638         self.assertEqual(capture[IP].dst, '192.168.1.1')
8639         self.assertEqual(capture[TCP].sport, 10001)
8640         self.assertEqual(capture[TCP].dport, 20001)
8641         self.assert_packet_checksums_valid(capture)
8642
8643         # ICMP
8644         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8645              IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8646              IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8647              ICMP(id=4000, type='echo-request'))
8648         self.pg1.add_stream(p)
8649         self.pg_enable_capture(self.pg_interfaces)
8650         self.pg_start()
8651         capture = self.pg0.get_capture(1)
8652         capture = capture[0]
8653         self.assertFalse(capture.haslayer(IPv6))
8654         self.assertEqual(capture[IP].src, self.nat_addr)
8655         self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8656         self.assertNotEqual(capture[ICMP].id, 4000)
8657         self.assert_packet_checksums_valid(capture)
8658         out_id = capture[ICMP].id
8659
8660         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8661              IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8662              ICMP(id=out_id, type='echo-reply'))
8663         self.pg0.add_stream(p)
8664         self.pg_enable_capture(self.pg_interfaces)
8665         self.pg_start()
8666         capture = self.pg1.get_capture(1)
8667         capture = capture[0]
8668         self.assertEqual(capture[IPv6].src, aftr_ip6)
8669         self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8670         self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8671         self.assertEqual(capture[IP].dst, '192.168.1.1')
8672         self.assertEqual(capture[ICMP].id, 4000)
8673         self.assert_packet_checksums_valid(capture)
8674
8675         # ping DS-Lite AFTR tunnel endpoint address
8676         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8677              IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
8678              ICMPv6EchoRequest())
8679         self.pg1.add_stream(p)
8680         self.pg_enable_capture(self.pg_interfaces)
8681         self.pg_start()
8682         capture = self.pg1.get_capture(1)
8683         capture = capture[0]
8684         self.assertEqual(capture[IPv6].src, aftr_ip6)
8685         self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8686         self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8687
8688         b4s = self.statistics.get_counter('/dslite/total-b4s')
8689         self.assertEqual(b4s[0][0], 2)
8690         sessions = self.statistics.get_counter('/dslite/total-sessions')
8691         self.assertEqual(sessions[0][0], 3)
8692
8693     def tearDown(self):
8694         super(TestDSlite, self).tearDown()
8695         if not self.vpp_dead:
8696             self.logger.info(self.vapi.cli("show dslite pool"))
8697             self.logger.info(
8698                 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8699             self.logger.info(self.vapi.cli("show dslite sessions"))
8700
8701
8702 class TestDSliteCE(MethodHolder):
8703     """ DS-Lite CE Test Cases """
8704
8705     @classmethod
8706     def setUpConstants(cls):
8707         super(TestDSliteCE, cls).setUpConstants()
8708         cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
8709
8710     @classmethod
8711     def setUpClass(cls):
8712         super(TestDSliteCE, cls).setUpClass()
8713
8714         try:
8715             cls.create_pg_interfaces(range(2))
8716             cls.pg0.admin_up()
8717             cls.pg0.config_ip4()
8718             cls.pg0.resolve_arp()
8719             cls.pg1.admin_up()
8720             cls.pg1.config_ip6()
8721             cls.pg1.generate_remote_hosts(1)
8722             cls.pg1.configure_ipv6_neighbors()
8723
8724         except Exception:
8725             super(TestDSliteCE, cls).tearDownClass()
8726             raise
8727
8728     def test_dslite_ce(self):
8729         """ Test DS-Lite CE """
8730
8731         nat_config = self.vapi.nat_show_config()
8732         self.assertEqual(1, nat_config.dslite_ce)
8733
8734         b4_ip4 = '192.0.0.2'
8735         b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
8736         b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
8737         b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
8738         self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
8739
8740         aftr_ip4 = '192.0.0.1'
8741         aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
8742         aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
8743         aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
8744         self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
8745
8746         self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
8747                                    dst_address_length=128,
8748                                    next_hop_address=self.pg1.remote_ip6n,
8749                                    next_hop_sw_if_index=self.pg1.sw_if_index,
8750                                    is_ipv6=1)
8751
8752         # UDP encapsulation
8753         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8754              IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
8755              UDP(sport=10000, dport=20000))
8756         self.pg0.add_stream(p)
8757         self.pg_enable_capture(self.pg_interfaces)
8758         self.pg_start()
8759         capture = self.pg1.get_capture(1)
8760         capture = capture[0]
8761         self.assertEqual(capture[IPv6].src, b4_ip6)
8762         self.assertEqual(capture[IPv6].dst, aftr_ip6)
8763         self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8764         self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
8765         self.assertEqual(capture[UDP].sport, 10000)
8766         self.assertEqual(capture[UDP].dport, 20000)
8767         self.assert_packet_checksums_valid(capture)
8768
8769         # UDP decapsulation
8770         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8771              IPv6(dst=b4_ip6, src=aftr_ip6) /
8772              IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
8773              UDP(sport=20000, dport=10000))
8774         self.pg1.add_stream(p)
8775         self.pg_enable_capture(self.pg_interfaces)
8776         self.pg_start()
8777         capture = self.pg0.get_capture(1)
8778         capture = capture[0]
8779         self.assertFalse(capture.haslayer(IPv6))
8780         self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
8781         self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8782         self.assertEqual(capture[UDP].sport, 20000)
8783         self.assertEqual(capture[UDP].dport, 10000)
8784         self.assert_packet_checksums_valid(capture)
8785
8786         # ping DS-Lite B4 tunnel endpoint address
8787         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8788              IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
8789              ICMPv6EchoRequest())
8790         self.pg1.add_stream(p)
8791         self.pg_enable_capture(self.pg_interfaces)
8792         self.pg_start()
8793         capture = self.pg1.get_capture(1)
8794         capture = capture[0]
8795         self.assertEqual(capture[IPv6].src, b4_ip6)
8796         self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8797         self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8798
8799     def tearDown(self):
8800         super(TestDSliteCE, self).tearDown()
8801         if not self.vpp_dead:
8802             self.logger.info(
8803                 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8804             self.logger.info(
8805                 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
8806
8807
8808 class TestNAT66(MethodHolder):
8809     """ NAT66 Test Cases """
8810
8811     @classmethod
8812     def setUpClass(cls):
8813         super(TestNAT66, cls).setUpClass()
8814
8815         try:
8816             cls.nat_addr = 'fd01:ff::2'
8817             cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
8818
8819             cls.create_pg_interfaces(range(2))
8820             cls.interfaces = list(cls.pg_interfaces)
8821
8822             for i in cls.interfaces:
8823                 i.admin_up()
8824                 i.config_ip6()
8825                 i.configure_ipv6_neighbors()
8826
8827         except Exception:
8828             super(TestNAT66, cls).tearDownClass()
8829             raise
8830
8831     def test_static(self):
8832         """ 1:1 NAT66 test """
8833         self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8834         self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8835         self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8836                                                self.nat_addr_n)
8837
8838         # in2out
8839         pkts = []
8840         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8841              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8842              TCP())
8843         pkts.append(p)
8844         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8845              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8846              UDP())
8847         pkts.append(p)
8848         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8849              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8850              ICMPv6EchoRequest())
8851         pkts.append(p)
8852         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8853              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8854              GRE() / IP() / TCP())
8855         pkts.append(p)
8856         self.pg0.add_stream(pkts)
8857         self.pg_enable_capture(self.pg_interfaces)
8858         self.pg_start()
8859         capture = self.pg1.get_capture(len(pkts))
8860         for packet in capture:
8861             try:
8862                 self.assertEqual(packet[IPv6].src, self.nat_addr)
8863                 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
8864                 self.assert_packet_checksums_valid(packet)
8865             except:
8866                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8867                 raise
8868
8869         # out2in
8870         pkts = []
8871         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8872              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8873              TCP())
8874         pkts.append(p)
8875         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8876              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8877              UDP())
8878         pkts.append(p)
8879         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8880              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8881              ICMPv6EchoReply())
8882         pkts.append(p)
8883         p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8884              IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8885              GRE() / IP() / TCP())
8886         pkts.append(p)
8887         self.pg1.add_stream(pkts)
8888         self.pg_enable_capture(self.pg_interfaces)
8889         self.pg_start()
8890         capture = self.pg0.get_capture(len(pkts))
8891         for packet in capture:
8892             try:
8893                 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
8894                 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8895                 self.assert_packet_checksums_valid(packet)
8896             except:
8897                 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8898                 raise
8899
8900         sm = self.vapi.nat66_static_mapping_dump()
8901         self.assertEqual(len(sm), 1)
8902         self.assertEqual(sm[0].total_pkts, 8)
8903
8904     def test_check_no_translate(self):
8905         """ NAT66 translate only when egress interface is outside interface """
8906         self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8907         self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
8908         self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8909                                                self.nat_addr_n)
8910
8911         # in2out
8912         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8913              IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8914              UDP())
8915         self.pg0.add_stream([p])
8916         self.pg_enable_capture(self.pg_interfaces)
8917         self.pg_start()
8918         capture = self.pg1.get_capture(1)
8919         packet = capture[0]
8920         try:
8921             self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
8922             self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
8923         except:
8924             self.logger.error(ppp("Unexpected or invalid packet:", packet))
8925             raise
8926
8927     def clear_nat66(self):
8928         """
8929         Clear NAT66 configuration.
8930         """
8931         interfaces = self.vapi.nat66_interface_dump()
8932         for intf in interfaces:
8933             self.vapi.nat66_add_del_interface(intf.sw_if_index,
8934                                               intf.is_inside,
8935                                               is_add=0)
8936
8937         static_mappings = self.vapi.nat66_static_mapping_dump()
8938         for sm in static_mappings:
8939             self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
8940                                                    sm.external_ip_address,
8941                                                    sm.vrf_id,
8942                                                    is_add=0)
8943
8944     def tearDown(self):
8945         super(TestNAT66, self).tearDown()
8946         if not self.vpp_dead:
8947             self.logger.info(self.vapi.cli("show nat66 interfaces"))
8948             self.logger.info(self.vapi.cli("show nat66 static mappings"))
8949             self.clear_nat66()
8950
8951
8952 if __name__ == '__main__':
8953     unittest.main(testRunner=VppTestRunner)