8 from framework import VppTestCase, VppTestRunner, running_extended_tests
11 from scapy.layers.inet import IP, TCP, UDP, ICMP
12 from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
13 from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply, \
14 ICMPv6ND_NS, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr, fragment6
15 from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
16 from scapy.layers.l2 import Ether, ARP, GRE
17 from scapy.data import IP_PROTOS
18 from scapy.packet import bind_layers, Raw
20 from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
21 from time import sleep
22 from util import ip4_range
23 from vpp_papi import mac_pton
24 from syslog_rfc5424_parser import SyslogMessage, ParseError
25 from syslog_rfc5424_parser.constants import SyslogFacility, SyslogSeverity
26 from io import BytesIO
27 from vpp_papi import VppEnum
28 from vpp_ip_route import VppIpRoute, VppRoutePath, FibPathType
29 from vpp_neighbor import VppNeighbor
30 from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \
31 IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \
33 from ipaddress import IPv6Network
34 from util import ppc, ppp
35 from socket import inet_pton, AF_INET
36 from vpp_acl import AclRule, VppAcl, VppAclInterface
39 # NAT HA protocol event data
42 fields_desc = [ByteEnumField("event_type", None,
43 {1: "add", 2: "del", 3: "refresh"}),
44 ByteEnumField("protocol", None,
45 {0: "udp", 1: "tcp", 2: "icmp"}),
46 ShortField("flags", 0),
47 IPField("in_addr", None),
48 IPField("out_addr", None),
49 ShortField("in_port", None),
50 ShortField("out_port", None),
51 IPField("eh_addr", None),
52 IPField("ehn_addr", None),
53 ShortField("eh_port", None),
54 ShortField("ehn_port", None),
55 IntField("fib_index", None),
56 IntField("total_pkts", 0),
57 LongField("total_bytes", 0)]
59 def extract_padding(self, s):
63 # NAT HA protocol header
64 class HANATStateSync(Packet):
65 name = "HA NAT state sync"
66 fields_desc = [XByteField("version", 1),
67 FlagsField("flags", 0, 8, ['ACK']),
68 FieldLenField("count", None, count_of="events"),
69 IntField("sequence_number", 1),
70 IntField("thread_index", 0),
71 PacketListField("events", [], Event,
72 count_from=lambda pkt: pkt.count)]
75 class MethodHolder(VppTestCase):
76 """ NAT create capture and verify method holder """
79 def config_flags(self):
80 return VppEnum.vl_api_nat_config_flags_t
83 def SYSLOG_SEVERITY(self):
84 return VppEnum.vl_api_syslog_severity_t
86 def clear_nat44(self):
88 Clear NAT44 configuration.
90 if hasattr(self, 'pg7') and hasattr(self, 'pg8'):
91 if self.pg7.has_ip4_config:
92 self.pg7.unconfig_ip4()
94 self.vapi.nat44_forwarding_enable_disable(enable=0)
96 interfaces = self.vapi.nat44_interface_addr_dump()
97 for intf in interfaces:
98 self.vapi.nat44_add_del_interface_addr(
100 sw_if_index=intf.sw_if_index,
103 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
104 src_port=self.ipfix_src_port,
106 self.ipfix_src_port = 4739
107 self.ipfix_domain_id = 1
109 self.vapi.syslog_set_filter(
110 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_EMERG)
112 self.vapi.nat_ha_set_listener(ip_address='0.0.0.0', port=0,
114 self.vapi.nat_ha_set_failover(ip_address='0.0.0.0', port=0,
115 session_refresh_interval=10)
117 interfaces = self.vapi.nat44_interface_dump()
118 for intf in interfaces:
119 if intf.flags & self.config_flags.NAT_IS_INSIDE and \
120 intf.flags & self.config_flags.NAT_IS_OUTSIDE:
121 self.vapi.nat44_interface_add_del_feature(
122 sw_if_index=intf.sw_if_index)
123 self.vapi.nat44_interface_add_del_feature(
124 sw_if_index=intf.sw_if_index,
127 interfaces = self.vapi.nat44_interface_output_feature_dump()
128 for intf in interfaces:
129 self.vapi.nat44_interface_add_del_output_feature(
132 sw_if_index=intf.sw_if_index)
133 static_mappings = self.vapi.nat44_static_mapping_dump()
134 for sm in static_mappings:
135 self.vapi.nat44_add_del_static_mapping(
137 local_ip_address=sm.local_ip_address,
138 external_ip_address=sm.external_ip_address,
139 external_sw_if_index=sm.external_sw_if_index,
140 local_port=sm.local_port,
141 external_port=sm.external_port,
143 protocol=sm.protocol,
144 flags=sm.flags, tag=sm.tag)
146 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
147 for lb_sm in lb_static_mappings:
148 self.vapi.nat44_add_del_lb_static_mapping(
151 external_addr=lb_sm.external_addr,
152 external_port=lb_sm.external_port,
153 protocol=lb_sm.protocol,
154 local_num=0, locals=[],
157 identity_mappings = self.vapi.nat44_identity_mapping_dump()
158 for id_m in identity_mappings:
159 self.vapi.nat44_add_del_identity_mapping(
160 ip_address=id_m.ip_address,
161 sw_if_index=id_m.sw_if_index,
165 protocol=id_m.protocol)
167 addresses = self.vapi.nat44_address_dump()
168 for addr in addresses:
169 self.vapi.nat44_add_del_address_range(
170 first_ip_address=addr.ip_address,
171 last_ip_address=addr.ip_address,
172 vrf_id=0xFFFFFFFF, flags=addr.flags)
174 self.verify_no_nat44_user()
175 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
176 tcp_transitory=240, icmp=60)
177 self.vapi.nat_set_addr_and_port_alloc_alg()
178 self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
180 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
181 local_port=0, external_port=0, vrf_id=0,
182 is_add=1, external_sw_if_index=0xFFFFFFFF,
183 proto=0, tag="", flags=0):
185 Add/delete NAT44 static mapping
187 :param local_ip: Local IP address
188 :param external_ip: External IP address
189 :param local_port: Local port number (Optional)
190 :param external_port: External port number (Optional)
191 :param vrf_id: VRF ID (Default 0)
192 :param is_add: 1 if add, 0 if delete (Default add)
193 :param external_sw_if_index: External interface instead of IP address
194 :param proto: IP protocol (Mandatory if port specified)
195 :param tag: Opaque string tag
196 :param flags: NAT configuration flags
199 if not (local_port and external_port):
200 flags |= self.config_flags.NAT_IS_ADDR_ONLY
202 self.vapi.nat44_add_del_static_mapping(
204 local_ip_address=local_ip,
205 external_ip_address=external_ip,
206 external_sw_if_index=external_sw_if_index,
207 local_port=local_port,
208 external_port=external_port,
209 vrf_id=vrf_id, protocol=proto,
213 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
215 Add/delete NAT44 address
217 :param ip: IP address
218 :param is_add: 1 if add, 0 if delete (Default add)
219 :param twice_nat: twice NAT address for external hosts
221 flags = self.config_flags.NAT_IS_TWICE_NAT if twice_nat else 0
222 self.vapi.nat44_add_del_address_range(first_ip_address=ip,
228 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
230 Create packet stream for inside network
232 :param in_if: Inside interface
233 :param out_if: Outside interface
234 :param dst_ip: Destination address
235 :param ttl: TTL of generated packets
238 dst_ip = out_if.remote_ip4
242 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
243 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
244 TCP(sport=self.tcp_port_in, dport=20))
248 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
249 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
250 UDP(sport=self.udp_port_in, dport=20))
254 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
255 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
256 ICMP(id=self.icmp_id_in, type='echo-request'))
261 def compose_ip6(self, ip4, pref, plen):
263 Compose IPv4-embedded IPv6 addresses
265 :param ip4: IPv4 address
266 :param pref: IPv6 prefix
267 :param plen: IPv6 prefix length
268 :returns: IPv4-embedded IPv6 addresses
270 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
271 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
286 pref_n[10] = ip4_n[3]
290 pref_n[10] = ip4_n[2]
291 pref_n[11] = ip4_n[3]
294 pref_n[10] = ip4_n[1]
295 pref_n[11] = ip4_n[2]
296 pref_n[12] = ip4_n[3]
298 pref_n[12] = ip4_n[0]
299 pref_n[13] = ip4_n[1]
300 pref_n[14] = ip4_n[2]
301 pref_n[15] = ip4_n[3]
302 packed_pref_n = b''.join([scapy.compat.chb(x) for x in pref_n])
303 return socket.inet_ntop(socket.AF_INET6, packed_pref_n)
305 def extract_ip4(self, ip6, plen):
307 Extract IPv4 address embedded in IPv6 addresses
309 :param ip6: IPv6 address
310 :param plen: IPv6 prefix length
311 :returns: extracted IPv4 address
313 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
345 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
347 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
349 Create IPv6 packet stream for inside network
351 :param in_if: Inside interface
352 :param out_if: Outside interface
353 :param ttl: Hop Limit of generated packets
354 :param pref: NAT64 prefix
355 :param plen: NAT64 prefix length
359 dst = ''.join(['64:ff9b::', out_if.remote_ip4])
361 dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
364 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
365 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
366 TCP(sport=self.tcp_port_in, dport=20))
370 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
371 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
372 UDP(sport=self.udp_port_in, dport=20))
376 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
377 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
378 ICMPv6EchoRequest(id=self.icmp_id_in))
383 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
384 use_inside_ports=False):
386 Create packet stream for outside network
388 :param out_if: Outside interface
389 :param dst_ip: Destination IP address (Default use global NAT address)
390 :param ttl: TTL of generated packets
391 :param use_inside_ports: Use inside NAT ports as destination ports
392 instead of outside ports
395 dst_ip = self.nat_addr
396 if not use_inside_ports:
397 tcp_port = self.tcp_port_out
398 udp_port = self.udp_port_out
399 icmp_id = self.icmp_id_out
401 tcp_port = self.tcp_port_in
402 udp_port = self.udp_port_in
403 icmp_id = self.icmp_id_in
406 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
407 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
408 TCP(dport=tcp_port, sport=20))
412 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
413 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
414 UDP(dport=udp_port, sport=20))
418 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
419 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
420 ICMP(id=icmp_id, type='echo-reply'))
425 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
427 Create packet stream for outside network
429 :param out_if: Outside interface
430 :param dst_ip: Destination IP address (Default use global NAT address)
431 :param hl: HL of generated packets
435 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
436 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
437 TCP(dport=self.tcp_port_out, sport=20))
441 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
442 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
443 UDP(dport=self.udp_port_out, sport=20))
447 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
448 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
449 ICMPv6EchoReply(id=self.icmp_id_out))
454 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
455 dst_ip=None, is_ip6=False):
457 Verify captured packets on outside network
459 :param capture: Captured packets
460 :param nat_ip: Translated IP address (Default use global NAT address)
461 :param same_port: Source port number is not translated (Default False)
462 :param dst_ip: Destination IP address (Default do not verify)
463 :param is_ip6: If L3 protocol is IPv6 (Default False)
467 ICMP46 = ICMPv6EchoRequest
472 nat_ip = self.nat_addr
473 for packet in capture:
476 self.assert_packet_checksums_valid(packet)
477 self.assertEqual(packet[IP46].src, nat_ip)
478 if dst_ip is not None:
479 self.assertEqual(packet[IP46].dst, dst_ip)
480 if packet.haslayer(TCP):
482 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
485 packet[TCP].sport, self.tcp_port_in)
486 self.tcp_port_out = packet[TCP].sport
487 self.assert_packet_checksums_valid(packet)
488 elif packet.haslayer(UDP):
490 self.assertEqual(packet[UDP].sport, self.udp_port_in)
493 packet[UDP].sport, self.udp_port_in)
494 self.udp_port_out = packet[UDP].sport
497 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
499 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
500 self.icmp_id_out = packet[ICMP46].id
501 self.assert_packet_checksums_valid(packet)
503 self.logger.error(ppp("Unexpected or invalid packet "
504 "(outside network):", packet))
507 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
510 Verify captured packets on outside network
512 :param capture: Captured packets
513 :param nat_ip: Translated IP address
514 :param same_port: Source port number is not translated (Default False)
515 :param dst_ip: Destination IP address (Default do not verify)
517 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
520 def verify_capture_in(self, capture, in_if):
522 Verify captured packets on inside network
524 :param capture: Captured packets
525 :param in_if: Inside interface
527 for packet in capture:
529 self.assert_packet_checksums_valid(packet)
530 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
531 if packet.haslayer(TCP):
532 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
533 elif packet.haslayer(UDP):
534 self.assertEqual(packet[UDP].dport, self.udp_port_in)
536 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
538 self.logger.error(ppp("Unexpected or invalid packet "
539 "(inside network):", packet))
542 def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
544 Verify captured IPv6 packets on inside network
546 :param capture: Captured packets
547 :param src_ip: Source IP
548 :param dst_ip: Destination IP address
550 for packet in capture:
552 self.assertEqual(packet[IPv6].src, src_ip)
553 self.assertEqual(packet[IPv6].dst, dst_ip)
554 self.assert_packet_checksums_valid(packet)
555 if packet.haslayer(TCP):
556 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
557 elif packet.haslayer(UDP):
558 self.assertEqual(packet[UDP].dport, self.udp_port_in)
560 self.assertEqual(packet[ICMPv6EchoReply].id,
563 self.logger.error(ppp("Unexpected or invalid packet "
564 "(inside network):", packet))
567 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
569 Verify captured packet that don't have to be translated
571 :param capture: Captured packets
572 :param ingress_if: Ingress interface
573 :param egress_if: Egress interface
575 for packet in capture:
577 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
578 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
579 if packet.haslayer(TCP):
580 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
581 elif packet.haslayer(UDP):
582 self.assertEqual(packet[UDP].sport, self.udp_port_in)
584 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
586 self.logger.error(ppp("Unexpected or invalid packet "
587 "(inside network):", packet))
590 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
593 Verify captured packets with ICMP errors on outside network
595 :param capture: Captured packets
596 :param src_ip: Translated IP address or IP address of VPP
597 (Default use global NAT address)
598 :param icmp_type: Type of error ICMP packet
599 we are expecting (Default 11)
602 src_ip = self.nat_addr
603 for packet in capture:
605 self.assertEqual(packet[IP].src, src_ip)
606 self.assertEqual(packet.haslayer(ICMP), 1)
608 self.assertEqual(icmp.type, icmp_type)
609 self.assertTrue(icmp.haslayer(IPerror))
610 inner_ip = icmp[IPerror]
611 if inner_ip.haslayer(TCPerror):
612 self.assertEqual(inner_ip[TCPerror].dport,
614 elif inner_ip.haslayer(UDPerror):
615 self.assertEqual(inner_ip[UDPerror].dport,
618 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
620 self.logger.error(ppp("Unexpected or invalid packet "
621 "(outside network):", packet))
624 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
626 Verify captured packets with ICMP errors on inside network
628 :param capture: Captured packets
629 :param in_if: Inside interface
630 :param icmp_type: Type of error ICMP packet
631 we are expecting (Default 11)
633 for packet in capture:
635 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
636 self.assertEqual(packet.haslayer(ICMP), 1)
638 self.assertEqual(icmp.type, icmp_type)
639 self.assertTrue(icmp.haslayer(IPerror))
640 inner_ip = icmp[IPerror]
641 if inner_ip.haslayer(TCPerror):
642 self.assertEqual(inner_ip[TCPerror].sport,
644 elif inner_ip.haslayer(UDPerror):
645 self.assertEqual(inner_ip[UDPerror].sport,
648 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
650 self.logger.error(ppp("Unexpected or invalid packet "
651 "(inside network):", packet))
654 def create_stream_frag(self, src_if, dst, sport, dport, data,
655 proto=IP_PROTOS.tcp, echo_reply=False):
657 Create fragmented packet stream
659 :param src_if: Source interface
660 :param dst: Destination IPv4 address
661 :param sport: Source port
662 :param dport: Destination port
663 :param data: Payload data
664 :param proto: protocol (TCP, UDP, ICMP)
665 :param echo_reply: use echo_reply if protocol is ICMP
668 if proto == IP_PROTOS.tcp:
669 p = (IP(src=src_if.remote_ip4, dst=dst) /
670 TCP(sport=sport, dport=dport) /
672 p = p.__class__(scapy.compat.raw(p))
673 chksum = p[TCP].chksum
674 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
675 elif proto == IP_PROTOS.udp:
676 proto_header = UDP(sport=sport, dport=dport)
677 elif proto == IP_PROTOS.icmp:
679 proto_header = ICMP(id=sport, type='echo-request')
681 proto_header = ICMP(id=sport, type='echo-reply')
683 raise Exception("Unsupported protocol")
684 id = random.randint(0, 65535)
686 if proto == IP_PROTOS.tcp:
689 raw = Raw(data[0:16])
690 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
691 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
695 if proto == IP_PROTOS.tcp:
696 raw = Raw(data[4:20])
698 raw = Raw(data[16:32])
699 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
700 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
704 if proto == IP_PROTOS.tcp:
708 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
709 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
715 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
716 pref=None, plen=0, frag_size=128):
718 Create fragmented packet stream
720 :param src_if: Source interface
721 :param dst: Destination IPv4 address
722 :param sport: Source TCP port
723 :param dport: Destination TCP port
724 :param data: Payload data
725 :param pref: NAT64 prefix
726 :param plen: NAT64 prefix length
727 :param fragsize: size of fragments
731 dst_ip6 = ''.join(['64:ff9b::', dst])
733 dst_ip6 = self.compose_ip6(dst, pref, plen)
735 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
736 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
737 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
738 TCP(sport=sport, dport=dport) /
741 return fragment6(p, frag_size)
743 def reass_frags_and_verify(self, frags, src, dst):
745 Reassemble and verify fragmented packet
747 :param frags: Captured fragments
748 :param src: Source IPv4 address to verify
749 :param dst: Destination IPv4 address to verify
751 :returns: Reassembled IPv4 packet
755 self.assertEqual(p[IP].src, src)
756 self.assertEqual(p[IP].dst, dst)
757 self.assert_ip_checksum_valid(p)
758 buffer.seek(p[IP].frag * 8)
759 buffer.write(bytes(p[IP].payload))
760 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
761 proto=frags[0][IP].proto)
762 if ip.proto == IP_PROTOS.tcp:
763 p = (ip / TCP(buffer.getvalue()))
764 self.logger.debug(ppp("Reassembled:", p))
765 self.assert_tcp_checksum_valid(p)
766 elif ip.proto == IP_PROTOS.udp:
767 p = (ip / UDP(buffer.getvalue()[:8]) /
768 Raw(buffer.getvalue()[8:]))
769 elif ip.proto == IP_PROTOS.icmp:
770 p = (ip / ICMP(buffer.getvalue()))
773 def reass_frags_and_verify_ip6(self, frags, src, dst):
775 Reassemble and verify fragmented packet
777 :param frags: Captured fragments
778 :param src: Source IPv6 address to verify
779 :param dst: Destination IPv6 address to verify
781 :returns: Reassembled IPv6 packet
785 self.assertEqual(p[IPv6].src, src)
786 self.assertEqual(p[IPv6].dst, dst)
787 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
788 buffer.write(bytes(p[IPv6ExtHdrFragment].payload))
789 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
790 nh=frags[0][IPv6ExtHdrFragment].nh)
791 if ip.nh == IP_PROTOS.tcp:
792 p = (ip / TCP(buffer.getvalue()))
793 elif ip.nh == IP_PROTOS.udp:
794 p = (ip / UDP(buffer.getvalue()))
795 self.logger.debug(ppp("Reassembled:", p))
796 self.assert_packet_checksums_valid(p)
799 def initiate_tcp_session(self, in_if, out_if):
801 Initiates TCP session
803 :param in_if: Inside interface
804 :param out_if: Outside interface
808 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
809 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
810 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
813 self.pg_enable_capture(self.pg_interfaces)
815 capture = out_if.get_capture(1)
817 self.tcp_port_out = p[TCP].sport
819 # SYN + ACK packet out->in
820 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
821 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
822 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
825 self.pg_enable_capture(self.pg_interfaces)
830 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
831 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
832 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
835 self.pg_enable_capture(self.pg_interfaces)
837 out_if.get_capture(1)
840 self.logger.error("TCP 3 way handshake failed")
843 def verify_ipfix_nat44_ses(self, data):
845 Verify IPFIX NAT44 session create/delete event
847 :param data: Decoded IPFIX data records
849 nat44_ses_create_num = 0
850 nat44_ses_delete_num = 0
851 self.assertEqual(6, len(data))
854 self.assertIn(scapy.compat.orb(record[230]), [4, 5])
855 if scapy.compat.orb(record[230]) == 4:
856 nat44_ses_create_num += 1
858 nat44_ses_delete_num += 1
860 self.assertEqual(self.pg0.remote_ip4n, record[8])
861 # postNATSourceIPv4Address
862 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
865 self.assertEqual(struct.pack("!I", 0), record[234])
866 # protocolIdentifier/sourceTransportPort
867 # /postNAPTSourceTransportPort
868 if IP_PROTOS.icmp == scapy.compat.orb(record[4]):
869 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
870 self.assertEqual(struct.pack("!H", self.icmp_id_out),
872 elif IP_PROTOS.tcp == scapy.compat.orb(record[4]):
873 self.assertEqual(struct.pack("!H", self.tcp_port_in),
875 self.assertEqual(struct.pack("!H", self.tcp_port_out),
877 elif IP_PROTOS.udp == scapy.compat.orb(record[4]):
878 self.assertEqual(struct.pack("!H", self.udp_port_in),
880 self.assertEqual(struct.pack("!H", self.udp_port_out),
883 self.fail("Invalid protocol")
884 self.assertEqual(3, nat44_ses_create_num)
885 self.assertEqual(3, nat44_ses_delete_num)
887 def verify_ipfix_addr_exhausted(self, data):
889 Verify IPFIX NAT addresses event
891 :param data: Decoded IPFIX data records
893 self.assertEqual(1, len(data))
896 self.assertEqual(scapy.compat.orb(record[230]), 3)
898 self.assertEqual(struct.pack("!I", 0), record[283])
900 def verify_ipfix_max_sessions(self, data, limit):
902 Verify IPFIX maximum session entries exceeded event
904 :param data: Decoded IPFIX data records
905 :param limit: Number of maximum session entries that can be created.
907 self.assertEqual(1, len(data))
910 self.assertEqual(scapy.compat.orb(record[230]), 13)
911 # natQuotaExceededEvent
912 self.assertEqual(struct.pack("I", 1), record[466])
914 self.assertEqual(struct.pack("I", limit), record[471])
916 def verify_ipfix_max_bibs(self, data, limit):
918 Verify IPFIX maximum BIB entries exceeded event
920 :param data: Decoded IPFIX data records
921 :param limit: Number of maximum BIB entries that can be created.
923 self.assertEqual(1, len(data))
926 self.assertEqual(scapy.compat.orb(record[230]), 13)
927 # natQuotaExceededEvent
928 self.assertEqual(struct.pack("I", 2), record[466])
930 self.assertEqual(struct.pack("I", limit), record[472])
932 def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
934 Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
936 :param data: Decoded IPFIX data records
937 :param limit: Number of maximum fragments pending reassembly
938 :param src_addr: IPv6 source address
940 self.assertEqual(1, len(data))
943 self.assertEqual(scapy.compat.orb(record[230]), 13)
944 # natQuotaExceededEvent
945 self.assertEqual(struct.pack("I", 5), record[466])
946 # maxFragmentsPendingReassembly
947 self.assertEqual(struct.pack("I", limit), record[475])
949 self.assertEqual(src_addr, record[27])
951 def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
953 Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
955 :param data: Decoded IPFIX data records
956 :param limit: Number of maximum fragments pending reassembly
957 :param src_addr: IPv4 source address
959 self.assertEqual(1, len(data))
962 self.assertEqual(scapy.compat.orb(record[230]), 13)
963 # natQuotaExceededEvent
964 self.assertEqual(struct.pack("I", 5), record[466])
965 # maxFragmentsPendingReassembly
966 self.assertEqual(struct.pack("I", limit), record[475])
968 self.assertEqual(src_addr, record[8])
970 def verify_ipfix_bib(self, data, is_create, src_addr):
972 Verify IPFIX NAT64 BIB create and delete events
974 :param data: Decoded IPFIX data records
975 :param is_create: Create event if nonzero value otherwise delete event
976 :param src_addr: IPv6 source address
978 self.assertEqual(1, len(data))
982 self.assertEqual(scapy.compat.orb(record[230]), 10)
984 self.assertEqual(scapy.compat.orb(record[230]), 11)
986 self.assertEqual(src_addr, record[27])
987 # postNATSourceIPv4Address
988 self.assertEqual(self.nat_addr_n, record[225])
990 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
992 self.assertEqual(struct.pack("!I", 0), record[234])
993 # sourceTransportPort
994 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
995 # postNAPTSourceTransportPort
996 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
998 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
1001 Verify IPFIX NAT64 session create and delete events
1003 :param data: Decoded IPFIX data records
1004 :param is_create: Create event if nonzero value otherwise delete event
1005 :param src_addr: IPv6 source address
1006 :param dst_addr: IPv4 destination address
1007 :param dst_port: destination TCP port
1009 self.assertEqual(1, len(data))
1013 self.assertEqual(scapy.compat.orb(record[230]), 6)
1015 self.assertEqual(scapy.compat.orb(record[230]), 7)
1017 self.assertEqual(src_addr, record[27])
1018 # destinationIPv6Address
1019 self.assertEqual(socket.inet_pton(socket.AF_INET6,
1020 self.compose_ip6(dst_addr,
1024 # postNATSourceIPv4Address
1025 self.assertEqual(self.nat_addr_n, record[225])
1026 # postNATDestinationIPv4Address
1027 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
1029 # protocolIdentifier
1030 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
1032 self.assertEqual(struct.pack("!I", 0), record[234])
1033 # sourceTransportPort
1034 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1035 # postNAPTSourceTransportPort
1036 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1037 # destinationTransportPort
1038 self.assertEqual(struct.pack("!H", dst_port), record[11])
1039 # postNAPTDestinationTransportPort
1040 self.assertEqual(struct.pack("!H", dst_port), record[228])
1042 def verify_no_nat44_user(self):
1043 """ Verify that there is no NAT44 user """
1044 users = self.vapi.nat44_user_dump()
1045 self.assertEqual(len(users), 0)
1046 users = self.statistics.get_counter('/nat44/total-users')
1047 self.assertEqual(users[0][0], 0)
1048 sessions = self.statistics.get_counter('/nat44/total-sessions')
1049 self.assertEqual(sessions[0][0], 0)
1051 def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
1053 Verify IPFIX maximum entries per user exceeded event
1055 :param data: Decoded IPFIX data records
1056 :param limit: Number of maximum entries per user
1057 :param src_addr: IPv4 source address
1059 self.assertEqual(1, len(data))
1062 self.assertEqual(scapy.compat.orb(record[230]), 13)
1063 # natQuotaExceededEvent
1064 self.assertEqual(struct.pack("I", 3), record[466])
1066 self.assertEqual(struct.pack("I", limit), record[473])
1068 self.assertEqual(socket.inet_pton(socket.AF_INET, src_addr), record[8])
1070 def verify_syslog_apmap(self, data, is_add=True):
1071 message = data.decode('utf-8')
1073 message = SyslogMessage.parse(message)
1074 except ParseError as e:
1075 self.logger.error(e)
1078 self.assertEqual(message.severity, SyslogSeverity.info)
1079 self.assertEqual(message.appname, 'NAT')
1080 self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
1081 sd_params = message.sd.get('napmap')
1082 self.assertTrue(sd_params is not None)
1083 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1084 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1085 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1086 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1087 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1088 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1089 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1090 self.assertTrue(sd_params.get('SSUBIX') is not None)
1091 self.assertEqual(sd_params.get('SVLAN'), '0')
1093 def verify_syslog_sess(self, data, is_add=True, is_ip6=False):
1094 message = data.decode('utf-8')
1096 message = SyslogMessage.parse(message)
1097 except ParseError as e:
1098 self.logger.error(e)
1101 self.assertEqual(message.severity, SyslogSeverity.info)
1102 self.assertEqual(message.appname, 'NAT')
1103 self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL')
1104 sd_params = message.sd.get('nsess')
1105 self.assertTrue(sd_params is not None)
1107 self.assertEqual(sd_params.get('IATYP'), 'IPv6')
1108 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
1110 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1111 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1112 self.assertTrue(sd_params.get('SSUBIX') is not None)
1113 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1114 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1115 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1116 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1117 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1118 self.assertEqual(sd_params.get('SVLAN'), '0')
1119 self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
1120 self.assertEqual(sd_params.get('XDPORT'),
1121 "%d" % self.tcp_external_port)
1123 def verify_mss_value(self, pkt, mss):
1125 Verify TCP MSS value
1130 if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
1131 raise TypeError("Not a TCP/IP packet")
1133 for option in pkt[TCP].options:
1134 if option[0] == 'MSS':
1135 self.assertEqual(option[1], mss)
1136 self.assert_tcp_checksum_valid(pkt)
1139 def proto2layer(proto):
1140 if proto == IP_PROTOS.tcp:
1142 elif proto == IP_PROTOS.udp:
1144 elif proto == IP_PROTOS.icmp:
1147 raise Exception("Unsupported protocol")
1149 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1150 layer = self.proto2layer(proto)
1152 if proto == IP_PROTOS.tcp:
1153 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1155 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1156 self.port_in = random.randint(1025, 65535)
1159 pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
1160 self.port_in, 20, data, proto)
1161 self.pg0.add_stream(pkts)
1162 self.pg_enable_capture(self.pg_interfaces)
1164 frags = self.pg1.get_capture(len(pkts))
1165 if not dont_translate:
1166 p = self.reass_frags_and_verify(frags,
1168 self.pg1.remote_ip4)
1170 p = self.reass_frags_and_verify(frags,
1171 self.pg0.remote_ip4,
1172 self.pg1.remote_ip4)
1173 if proto != IP_PROTOS.icmp:
1174 if not dont_translate:
1175 self.assertEqual(p[layer].dport, 20)
1176 self.assertNotEqual(p[layer].sport, self.port_in)
1178 self.assertEqual(p[layer].sport, self.port_in)
1180 if not dont_translate:
1181 self.assertNotEqual(p[layer].id, self.port_in)
1183 self.assertEqual(p[layer].id, self.port_in)
1184 self.assertEqual(data, p[Raw].load)
1187 if not dont_translate:
1188 dst_addr = self.nat_addr
1190 dst_addr = self.pg0.remote_ip4
1191 if proto != IP_PROTOS.icmp:
1193 dport = p[layer].sport
1197 pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport, data,
1198 proto, echo_reply=True)
1199 self.pg1.add_stream(pkts)
1200 self.pg_enable_capture(self.pg_interfaces)
1202 frags = self.pg0.get_capture(len(pkts))
1203 p = self.reass_frags_and_verify(frags,
1204 self.pg1.remote_ip4,
1205 self.pg0.remote_ip4)
1206 if proto != IP_PROTOS.icmp:
1207 self.assertEqual(p[layer].sport, 20)
1208 self.assertEqual(p[layer].dport, self.port_in)
1210 self.assertEqual(p[layer].id, self.port_in)
1211 self.assertEqual(data, p[Raw].load)
1213 def frag_in_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1214 layer = self.proto2layer(proto)
1216 if proto == IP_PROTOS.tcp:
1217 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1219 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1220 self.port_in = random.randint(1025, 65535)
1224 pkts = self.create_stream_frag(self.pg0, self.server_out_addr,
1225 self.port_in, self.server_out_port,
1227 self.pg0.add_stream(pkts)
1228 self.pg_enable_capture(self.pg_interfaces)
1230 frags = self.pg1.get_capture(len(pkts))
1231 p = self.reass_frags_and_verify(frags,
1232 self.pg0.remote_ip4,
1233 self.server_in_addr)
1234 if proto != IP_PROTOS.icmp:
1235 self.assertEqual(p[layer].sport, self.port_in)
1236 self.assertEqual(p[layer].dport, self.server_in_port)
1238 self.assertEqual(p[layer].id, self.port_in)
1239 self.assertEqual(data, p[Raw].load)
1242 if proto != IP_PROTOS.icmp:
1243 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1244 self.server_in_port,
1245 p[layer].sport, data, proto)
1247 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1248 p[layer].id, 0, data, proto,
1250 self.pg1.add_stream(pkts)
1251 self.pg_enable_capture(self.pg_interfaces)
1253 frags = self.pg0.get_capture(len(pkts))
1254 p = self.reass_frags_and_verify(frags,
1255 self.server_out_addr,
1256 self.pg0.remote_ip4)
1257 if proto != IP_PROTOS.icmp:
1258 self.assertEqual(p[layer].sport, self.server_out_port)
1259 self.assertEqual(p[layer].dport, self.port_in)
1261 self.assertEqual(p[layer].id, self.port_in)
1262 self.assertEqual(data, p[Raw].load)
1264 def reass_hairpinning(self, proto=IP_PROTOS.tcp):
1265 layer = self.proto2layer(proto)
1267 if proto == IP_PROTOS.tcp:
1268 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1270 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1272 # send packet from host to server
1273 pkts = self.create_stream_frag(self.pg0,
1276 self.server_out_port,
1279 self.pg0.add_stream(pkts)
1280 self.pg_enable_capture(self.pg_interfaces)
1282 frags = self.pg0.get_capture(len(pkts))
1283 p = self.reass_frags_and_verify(frags,
1286 if proto != IP_PROTOS.icmp:
1287 self.assertNotEqual(p[layer].sport, self.host_in_port)
1288 self.assertEqual(p[layer].dport, self.server_in_port)
1290 self.assertNotEqual(p[layer].id, self.host_in_port)
1291 self.assertEqual(data, p[Raw].load)
1293 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1294 layer = self.proto2layer(proto)
1296 if proto == IP_PROTOS.tcp:
1297 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1299 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1300 self.port_in = random.randint(1025, 65535)
1304 pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
1305 self.port_in, 20, data, proto)
1307 self.pg0.add_stream(pkts)
1308 self.pg_enable_capture(self.pg_interfaces)
1310 frags = self.pg1.get_capture(len(pkts))
1311 if not dont_translate:
1312 p = self.reass_frags_and_verify(frags,
1314 self.pg1.remote_ip4)
1316 p = self.reass_frags_and_verify(frags,
1317 self.pg0.remote_ip4,
1318 self.pg1.remote_ip4)
1319 if proto != IP_PROTOS.icmp:
1320 if not dont_translate:
1321 self.assertEqual(p[layer].dport, 20)
1322 self.assertNotEqual(p[layer].sport, self.port_in)
1324 self.assertEqual(p[layer].sport, self.port_in)
1326 if not dont_translate:
1327 self.assertNotEqual(p[layer].id, self.port_in)
1329 self.assertEqual(p[layer].id, self.port_in)
1330 self.assertEqual(data, p[Raw].load)
1333 if not dont_translate:
1334 dst_addr = self.nat_addr
1336 dst_addr = self.pg0.remote_ip4
1337 if proto != IP_PROTOS.icmp:
1339 dport = p[layer].sport
1343 pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport,
1344 data, proto, echo_reply=True)
1346 self.pg1.add_stream(pkts)
1347 self.pg_enable_capture(self.pg_interfaces)
1349 frags = self.pg0.get_capture(len(pkts))
1350 p = self.reass_frags_and_verify(frags,
1351 self.pg1.remote_ip4,
1352 self.pg0.remote_ip4)
1353 if proto != IP_PROTOS.icmp:
1354 self.assertEqual(p[layer].sport, 20)
1355 self.assertEqual(p[layer].dport, self.port_in)
1357 self.assertEqual(p[layer].id, self.port_in)
1358 self.assertEqual(data, p[Raw].load)
1360 def frag_out_of_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1361 layer = self.proto2layer(proto)
1363 if proto == IP_PROTOS.tcp:
1364 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1366 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1367 self.port_in = random.randint(1025, 65535)
1371 pkts = self.create_stream_frag(self.pg0, self.server_out_addr,
1372 self.port_in, self.server_out_port,
1375 self.pg0.add_stream(pkts)
1376 self.pg_enable_capture(self.pg_interfaces)
1378 frags = self.pg1.get_capture(len(pkts))
1379 p = self.reass_frags_and_verify(frags,
1380 self.pg0.remote_ip4,
1381 self.server_in_addr)
1382 if proto != IP_PROTOS.icmp:
1383 self.assertEqual(p[layer].dport, self.server_in_port)
1384 self.assertEqual(p[layer].sport, self.port_in)
1385 self.assertEqual(p[layer].dport, self.server_in_port)
1387 self.assertEqual(p[layer].id, self.port_in)
1388 self.assertEqual(data, p[Raw].load)
1391 if proto != IP_PROTOS.icmp:
1392 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1393 self.server_in_port,
1394 p[layer].sport, data, proto)
1396 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1397 p[layer].id, 0, data, proto,
1400 self.pg1.add_stream(pkts)
1401 self.pg_enable_capture(self.pg_interfaces)
1403 frags = self.pg0.get_capture(len(pkts))
1404 p = self.reass_frags_and_verify(frags,
1405 self.server_out_addr,
1406 self.pg0.remote_ip4)
1407 if proto != IP_PROTOS.icmp:
1408 self.assertEqual(p[layer].sport, self.server_out_port)
1409 self.assertEqual(p[layer].dport, self.port_in)
1411 self.assertEqual(p[layer].id, self.port_in)
1412 self.assertEqual(data, p[Raw].load)
1415 class TestNAT44(MethodHolder):
1416 """ NAT44 Test Cases """
1419 def setUpClass(cls):
1420 super(TestNAT44, cls).setUpClass()
1421 cls.vapi.cli("set log class nat level debug")
1423 cls.tcp_port_in = 6303
1424 cls.tcp_port_out = 6303
1425 cls.udp_port_in = 6304
1426 cls.udp_port_out = 6304
1427 cls.icmp_id_in = 6305
1428 cls.icmp_id_out = 6305
1429 cls.nat_addr = '10.0.0.3'
1430 cls.ipfix_src_port = 4739
1431 cls.ipfix_domain_id = 1
1432 cls.tcp_external_port = 80
1433 cls.udp_external_port = 69
1435 cls.create_pg_interfaces(range(10))
1436 cls.interfaces = list(cls.pg_interfaces[0:4])
1438 for i in cls.interfaces:
1443 cls.pg0.generate_remote_hosts(3)
1444 cls.pg0.configure_ipv4_neighbors()
1446 cls.pg1.generate_remote_hosts(1)
1447 cls.pg1.configure_ipv4_neighbors()
1449 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
1450 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 10})
1451 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 20})
1453 cls.pg4._local_ip4 = "172.16.255.1"
1454 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1455 cls.pg4.set_table_ip4(10)
1456 cls.pg5._local_ip4 = "172.17.255.3"
1457 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
1458 cls.pg5.set_table_ip4(10)
1459 cls.pg6._local_ip4 = "172.16.255.1"
1460 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1461 cls.pg6.set_table_ip4(20)
1462 for i in cls.overlapping_interfaces:
1470 cls.pg9.generate_remote_hosts(2)
1471 cls.pg9.config_ip4()
1472 cls.vapi.sw_interface_add_del_address(
1473 sw_if_index=cls.pg9.sw_if_index,
1474 prefix="10.0.0.1/24")
1477 cls.pg9.resolve_arp()
1478 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1479 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1480 cls.pg9.resolve_arp()
1483 def tearDownClass(cls):
1484 super(TestNAT44, cls).tearDownClass()
1486 def test_dynamic(self):
1487 """ NAT44 dynamic translation test """
1488 self.nat44_add_address(self.nat_addr)
1489 flags = self.config_flags.NAT_IS_INSIDE
1490 self.vapi.nat44_interface_add_del_feature(
1491 sw_if_index=self.pg0.sw_if_index,
1492 flags=flags, is_add=1)
1493 self.vapi.nat44_interface_add_del_feature(
1494 sw_if_index=self.pg1.sw_if_index,
1498 tcpn = self.statistics.get_err_counter(
1499 '/err/nat44-in2out-slowpath/TCP packets')
1500 udpn = self.statistics.get_err_counter(
1501 '/err/nat44-in2out-slowpath/UDP packets')
1502 icmpn = self.statistics.get_err_counter(
1503 '/err/nat44-in2out-slowpath/ICMP packets')
1504 totaln = self.statistics.get_err_counter(
1505 '/err/nat44-in2out-slowpath/good in2out packets processed')
1507 pkts = self.create_stream_in(self.pg0, self.pg1)
1508 self.pg0.add_stream(pkts)
1509 self.pg_enable_capture(self.pg_interfaces)
1511 capture = self.pg1.get_capture(len(pkts))
1512 self.verify_capture_out(capture)
1514 err = self.statistics.get_err_counter(
1515 '/err/nat44-in2out-slowpath/TCP packets')
1516 self.assertEqual(err - tcpn, 2)
1517 err = self.statistics.get_err_counter(
1518 '/err/nat44-in2out-slowpath/UDP packets')
1519 self.assertEqual(err - udpn, 1)
1520 err = self.statistics.get_err_counter(
1521 '/err/nat44-in2out-slowpath/ICMP packets')
1522 self.assertEqual(err - icmpn, 1)
1523 err = self.statistics.get_err_counter(
1524 '/err/nat44-in2out-slowpath/good in2out packets processed')
1525 self.assertEqual(err - totaln, 4)
1528 tcpn = self.statistics.get_err_counter('/err/nat44-out2in/TCP packets')
1529 udpn = self.statistics.get_err_counter('/err/nat44-out2in/UDP packets')
1530 icmpn = self.statistics.get_err_counter(
1531 '/err/nat44-out2in/ICMP packets')
1532 totaln = self.statistics.get_err_counter(
1533 '/err/nat44-out2in/good out2in packets processed')
1535 pkts = self.create_stream_out(self.pg1)
1536 self.pg1.add_stream(pkts)
1537 self.pg_enable_capture(self.pg_interfaces)
1539 capture = self.pg0.get_capture(len(pkts))
1540 self.verify_capture_in(capture, self.pg0)
1542 err = self.statistics.get_err_counter('/err/nat44-out2in/TCP packets')
1543 self.assertEqual(err - tcpn, 2)
1544 err = self.statistics.get_err_counter('/err/nat44-out2in/UDP packets')
1545 self.assertEqual(err - udpn, 1)
1546 err = self.statistics.get_err_counter('/err/nat44-out2in/ICMP packets')
1547 self.assertEqual(err - icmpn, 1)
1548 err = self.statistics.get_err_counter(
1549 '/err/nat44-out2in/good out2in packets processed')
1550 self.assertEqual(err - totaln, 4)
1552 users = self.statistics.get_counter('/nat44/total-users')
1553 self.assertEqual(users[0][0], 1)
1554 sessions = self.statistics.get_counter('/nat44/total-sessions')
1555 self.assertEqual(sessions[0][0], 3)
1557 def test_dynamic_icmp_errors_in2out_ttl_1(self):
1558 """ NAT44 handling of client packets with TTL=1 """
1560 self.nat44_add_address(self.nat_addr)
1561 flags = self.config_flags.NAT_IS_INSIDE
1562 self.vapi.nat44_interface_add_del_feature(
1563 sw_if_index=self.pg0.sw_if_index,
1564 flags=flags, is_add=1)
1565 self.vapi.nat44_interface_add_del_feature(
1566 sw_if_index=self.pg1.sw_if_index,
1569 # Client side - generate traffic
1570 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1571 self.pg0.add_stream(pkts)
1572 self.pg_enable_capture(self.pg_interfaces)
1575 # Client side - verify ICMP type 11 packets
1576 capture = self.pg0.get_capture(len(pkts))
1577 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1579 def test_dynamic_icmp_errors_out2in_ttl_1(self):
1580 """ NAT44 handling of server packets with TTL=1 """
1582 self.nat44_add_address(self.nat_addr)
1583 flags = self.config_flags.NAT_IS_INSIDE
1584 self.vapi.nat44_interface_add_del_feature(
1585 sw_if_index=self.pg0.sw_if_index,
1586 flags=flags, is_add=1)
1587 self.vapi.nat44_interface_add_del_feature(
1588 sw_if_index=self.pg1.sw_if_index,
1591 # Client side - create sessions
1592 pkts = self.create_stream_in(self.pg0, self.pg1)
1593 self.pg0.add_stream(pkts)
1594 self.pg_enable_capture(self.pg_interfaces)
1597 # Server side - generate traffic
1598 capture = self.pg1.get_capture(len(pkts))
1599 self.verify_capture_out(capture)
1600 pkts = self.create_stream_out(self.pg1, ttl=1)
1601 self.pg1.add_stream(pkts)
1602 self.pg_enable_capture(self.pg_interfaces)
1605 # Server side - verify ICMP type 11 packets
1606 capture = self.pg1.get_capture(len(pkts))
1607 self.verify_capture_out_with_icmp_errors(capture,
1608 src_ip=self.pg1.local_ip4)
1610 def test_dynamic_icmp_errors_in2out_ttl_2(self):
1611 """ NAT44 handling of error responses to client packets with TTL=2 """
1613 self.nat44_add_address(self.nat_addr)
1614 flags = self.config_flags.NAT_IS_INSIDE
1615 self.vapi.nat44_interface_add_del_feature(
1616 sw_if_index=self.pg0.sw_if_index,
1617 flags=flags, is_add=1)
1618 self.vapi.nat44_interface_add_del_feature(
1619 sw_if_index=self.pg1.sw_if_index,
1622 # Client side - generate traffic
1623 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1624 self.pg0.add_stream(pkts)
1625 self.pg_enable_capture(self.pg_interfaces)
1628 # Server side - simulate ICMP type 11 response
1629 capture = self.pg1.get_capture(len(pkts))
1630 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1631 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1632 ICMP(type=11) / packet[IP] for packet in capture]
1633 self.pg1.add_stream(pkts)
1634 self.pg_enable_capture(self.pg_interfaces)
1637 # Client side - verify ICMP type 11 packets
1638 capture = self.pg0.get_capture(len(pkts))
1639 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1641 def test_dynamic_icmp_errors_out2in_ttl_2(self):
1642 """ NAT44 handling of error responses to server packets with TTL=2 """
1644 self.nat44_add_address(self.nat_addr)
1645 flags = self.config_flags.NAT_IS_INSIDE
1646 self.vapi.nat44_interface_add_del_feature(
1647 sw_if_index=self.pg0.sw_if_index,
1648 flags=flags, is_add=1)
1649 self.vapi.nat44_interface_add_del_feature(
1650 sw_if_index=self.pg1.sw_if_index,
1653 # Client side - create sessions
1654 pkts = self.create_stream_in(self.pg0, self.pg1)
1655 self.pg0.add_stream(pkts)
1656 self.pg_enable_capture(self.pg_interfaces)
1659 # Server side - generate traffic
1660 capture = self.pg1.get_capture(len(pkts))
1661 self.verify_capture_out(capture)
1662 pkts = self.create_stream_out(self.pg1, ttl=2)
1663 self.pg1.add_stream(pkts)
1664 self.pg_enable_capture(self.pg_interfaces)
1667 # Client side - simulate ICMP type 11 response
1668 capture = self.pg0.get_capture(len(pkts))
1669 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1670 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1671 ICMP(type=11) / packet[IP] for packet in capture]
1672 self.pg0.add_stream(pkts)
1673 self.pg_enable_capture(self.pg_interfaces)
1676 # Server side - verify ICMP type 11 packets
1677 capture = self.pg1.get_capture(len(pkts))
1678 self.verify_capture_out_with_icmp_errors(capture)
1680 def test_ping_out_interface_from_outside(self):
1681 """ Ping NAT44 out interface from outside network """
1683 self.nat44_add_address(self.nat_addr)
1684 flags = self.config_flags.NAT_IS_INSIDE
1685 self.vapi.nat44_interface_add_del_feature(
1686 sw_if_index=self.pg0.sw_if_index,
1687 flags=flags, is_add=1)
1688 self.vapi.nat44_interface_add_del_feature(
1689 sw_if_index=self.pg1.sw_if_index,
1692 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1693 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1694 ICMP(id=self.icmp_id_out, type='echo-request'))
1696 self.pg1.add_stream(pkts)
1697 self.pg_enable_capture(self.pg_interfaces)
1699 capture = self.pg1.get_capture(len(pkts))
1702 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1703 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1704 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1705 self.assertEqual(packet[ICMP].type, 0) # echo reply
1707 self.logger.error(ppp("Unexpected or invalid packet "
1708 "(outside network):", packet))
1711 def test_ping_internal_host_from_outside(self):
1712 """ Ping internal host from outside network """
1714 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1715 flags = self.config_flags.NAT_IS_INSIDE
1716 self.vapi.nat44_interface_add_del_feature(
1717 sw_if_index=self.pg0.sw_if_index,
1718 flags=flags, is_add=1)
1719 self.vapi.nat44_interface_add_del_feature(
1720 sw_if_index=self.pg1.sw_if_index,
1724 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1725 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
1726 ICMP(id=self.icmp_id_out, type='echo-request'))
1727 self.pg1.add_stream(pkt)
1728 self.pg_enable_capture(self.pg_interfaces)
1730 capture = self.pg0.get_capture(1)
1731 self.verify_capture_in(capture, self.pg0)
1732 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1735 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1736 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1737 ICMP(id=self.icmp_id_in, type='echo-reply'))
1738 self.pg0.add_stream(pkt)
1739 self.pg_enable_capture(self.pg_interfaces)
1741 capture = self.pg1.get_capture(1)
1742 self.verify_capture_out(capture, same_port=True)
1743 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1745 def test_forwarding(self):
1746 """ NAT44 forwarding test """
1748 flags = self.config_flags.NAT_IS_INSIDE
1749 self.vapi.nat44_interface_add_del_feature(
1750 sw_if_index=self.pg0.sw_if_index,
1751 flags=flags, is_add=1)
1752 self.vapi.nat44_interface_add_del_feature(
1753 sw_if_index=self.pg1.sw_if_index,
1755 self.vapi.nat44_forwarding_enable_disable(enable=1)
1757 real_ip = self.pg0.remote_ip4
1758 alias_ip = self.nat_addr
1759 flags = self.config_flags.NAT_IS_ADDR_ONLY
1760 self.vapi.nat44_add_del_static_mapping(is_add=1,
1761 local_ip_address=real_ip,
1762 external_ip_address=alias_ip,
1763 external_sw_if_index=0xFFFFFFFF,
1767 # static mapping match
1769 pkts = self.create_stream_out(self.pg1)
1770 self.pg1.add_stream(pkts)
1771 self.pg_enable_capture(self.pg_interfaces)
1773 capture = self.pg0.get_capture(len(pkts))
1774 self.verify_capture_in(capture, self.pg0)
1776 pkts = self.create_stream_in(self.pg0, self.pg1)
1777 self.pg0.add_stream(pkts)
1778 self.pg_enable_capture(self.pg_interfaces)
1780 capture = self.pg1.get_capture(len(pkts))
1781 self.verify_capture_out(capture, same_port=True)
1783 # no static mapping match
1785 host0 = self.pg0.remote_hosts[0]
1786 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1788 pkts = self.create_stream_out(self.pg1,
1789 dst_ip=self.pg0.remote_ip4,
1790 use_inside_ports=True)
1791 self.pg1.add_stream(pkts)
1792 self.pg_enable_capture(self.pg_interfaces)
1794 capture = self.pg0.get_capture(len(pkts))
1795 self.verify_capture_in(capture, self.pg0)
1797 pkts = self.create_stream_in(self.pg0, self.pg1)
1798 self.pg0.add_stream(pkts)
1799 self.pg_enable_capture(self.pg_interfaces)
1801 capture = self.pg1.get_capture(len(pkts))
1802 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1805 self.pg0.remote_hosts[0] = host0
1808 self.vapi.nat44_forwarding_enable_disable(enable=0)
1809 flags = self.config_flags.NAT_IS_ADDR_ONLY
1810 self.vapi.nat44_add_del_static_mapping(
1812 local_ip_address=real_ip,
1813 external_ip_address=alias_ip,
1814 external_sw_if_index=0xFFFFFFFF,
1817 def test_static_in(self):
1818 """ 1:1 NAT initialized from inside network """
1820 nat_ip = "10.0.0.10"
1821 self.tcp_port_out = 6303
1822 self.udp_port_out = 6304
1823 self.icmp_id_out = 6305
1825 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1826 flags = self.config_flags.NAT_IS_INSIDE
1827 self.vapi.nat44_interface_add_del_feature(
1828 sw_if_index=self.pg0.sw_if_index,
1829 flags=flags, is_add=1)
1830 self.vapi.nat44_interface_add_del_feature(
1831 sw_if_index=self.pg1.sw_if_index,
1833 sm = self.vapi.nat44_static_mapping_dump()
1834 self.assertEqual(len(sm), 1)
1835 self.assertEqual(sm[0].tag, '')
1836 self.assertEqual(sm[0].protocol, 0)
1837 self.assertEqual(sm[0].local_port, 0)
1838 self.assertEqual(sm[0].external_port, 0)
1841 pkts = self.create_stream_in(self.pg0, self.pg1)
1842 self.pg0.add_stream(pkts)
1843 self.pg_enable_capture(self.pg_interfaces)
1845 capture = self.pg1.get_capture(len(pkts))
1846 self.verify_capture_out(capture, nat_ip, True)
1849 pkts = self.create_stream_out(self.pg1, nat_ip)
1850 self.pg1.add_stream(pkts)
1851 self.pg_enable_capture(self.pg_interfaces)
1853 capture = self.pg0.get_capture(len(pkts))
1854 self.verify_capture_in(capture, self.pg0)
1856 def test_static_out(self):
1857 """ 1:1 NAT initialized from outside network """
1859 nat_ip = "10.0.0.20"
1860 self.tcp_port_out = 6303
1861 self.udp_port_out = 6304
1862 self.icmp_id_out = 6305
1865 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
1866 flags = self.config_flags.NAT_IS_INSIDE
1867 self.vapi.nat44_interface_add_del_feature(
1868 sw_if_index=self.pg0.sw_if_index,
1869 flags=flags, is_add=1)
1870 self.vapi.nat44_interface_add_del_feature(
1871 sw_if_index=self.pg1.sw_if_index,
1873 sm = self.vapi.nat44_static_mapping_dump()
1874 self.assertEqual(len(sm), 1)
1875 self.assertEqual(sm[0].tag, tag)
1878 pkts = self.create_stream_out(self.pg1, nat_ip)
1879 self.pg1.add_stream(pkts)
1880 self.pg_enable_capture(self.pg_interfaces)
1882 capture = self.pg0.get_capture(len(pkts))
1883 self.verify_capture_in(capture, self.pg0)
1886 pkts = self.create_stream_in(self.pg0, self.pg1)
1887 self.pg0.add_stream(pkts)
1888 self.pg_enable_capture(self.pg_interfaces)
1890 capture = self.pg1.get_capture(len(pkts))
1891 self.verify_capture_out(capture, nat_ip, True)
1893 def test_static_with_port_in(self):
1894 """ 1:1 NAPT initialized from inside network """
1896 self.tcp_port_out = 3606
1897 self.udp_port_out = 3607
1898 self.icmp_id_out = 3608
1900 self.nat44_add_address(self.nat_addr)
1901 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1902 self.tcp_port_in, self.tcp_port_out,
1903 proto=IP_PROTOS.tcp)
1904 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1905 self.udp_port_in, self.udp_port_out,
1906 proto=IP_PROTOS.udp)
1907 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1908 self.icmp_id_in, self.icmp_id_out,
1909 proto=IP_PROTOS.icmp)
1910 flags = self.config_flags.NAT_IS_INSIDE
1911 self.vapi.nat44_interface_add_del_feature(
1912 sw_if_index=self.pg0.sw_if_index,
1913 flags=flags, is_add=1)
1914 self.vapi.nat44_interface_add_del_feature(
1915 sw_if_index=self.pg1.sw_if_index,
1919 pkts = self.create_stream_in(self.pg0, self.pg1)
1920 self.pg0.add_stream(pkts)
1921 self.pg_enable_capture(self.pg_interfaces)
1923 capture = self.pg1.get_capture(len(pkts))
1924 self.verify_capture_out(capture)
1927 pkts = self.create_stream_out(self.pg1)
1928 self.pg1.add_stream(pkts)
1929 self.pg_enable_capture(self.pg_interfaces)
1931 capture = self.pg0.get_capture(len(pkts))
1932 self.verify_capture_in(capture, self.pg0)
1934 def test_static_with_port_out(self):
1935 """ 1:1 NAPT initialized from outside network """
1937 self.tcp_port_out = 30606
1938 self.udp_port_out = 30607
1939 self.icmp_id_out = 30608
1941 self.nat44_add_address(self.nat_addr)
1942 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1943 self.tcp_port_in, self.tcp_port_out,
1944 proto=IP_PROTOS.tcp)
1945 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1946 self.udp_port_in, self.udp_port_out,
1947 proto=IP_PROTOS.udp)
1948 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1949 self.icmp_id_in, self.icmp_id_out,
1950 proto=IP_PROTOS.icmp)
1951 flags = self.config_flags.NAT_IS_INSIDE
1952 self.vapi.nat44_interface_add_del_feature(
1953 sw_if_index=self.pg0.sw_if_index,
1954 flags=flags, is_add=1)
1955 self.vapi.nat44_interface_add_del_feature(
1956 sw_if_index=self.pg1.sw_if_index,
1960 pkts = self.create_stream_out(self.pg1)
1961 self.pg1.add_stream(pkts)
1962 self.pg_enable_capture(self.pg_interfaces)
1964 capture = self.pg0.get_capture(len(pkts))
1965 self.verify_capture_in(capture, self.pg0)
1968 pkts = self.create_stream_in(self.pg0, self.pg1)
1969 self.pg0.add_stream(pkts)
1970 self.pg_enable_capture(self.pg_interfaces)
1972 capture = self.pg1.get_capture(len(pkts))
1973 self.verify_capture_out(capture)
1975 def test_static_vrf_aware(self):
1976 """ 1:1 NAT VRF awareness """
1978 nat_ip1 = "10.0.0.30"
1979 nat_ip2 = "10.0.0.40"
1980 self.tcp_port_out = 6303
1981 self.udp_port_out = 6304
1982 self.icmp_id_out = 6305
1984 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1986 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1988 flags = self.config_flags.NAT_IS_INSIDE
1989 self.vapi.nat44_interface_add_del_feature(
1990 sw_if_index=self.pg3.sw_if_index,
1992 self.vapi.nat44_interface_add_del_feature(
1993 sw_if_index=self.pg0.sw_if_index,
1994 flags=flags, is_add=1)
1995 self.vapi.nat44_interface_add_del_feature(
1996 sw_if_index=self.pg4.sw_if_index,
1997 flags=flags, is_add=1)
1999 # inside interface VRF match NAT44 static mapping VRF
2000 pkts = self.create_stream_in(self.pg4, self.pg3)
2001 self.pg4.add_stream(pkts)
2002 self.pg_enable_capture(self.pg_interfaces)
2004 capture = self.pg3.get_capture(len(pkts))
2005 self.verify_capture_out(capture, nat_ip1, True)
2007 # inside interface VRF don't match NAT44 static mapping VRF (packets
2009 pkts = self.create_stream_in(self.pg0, self.pg3)
2010 self.pg0.add_stream(pkts)
2011 self.pg_enable_capture(self.pg_interfaces)
2013 self.pg3.assert_nothing_captured()
2015 def test_dynamic_to_static(self):
2016 """ Switch from dynamic translation to 1:1NAT """
2017 nat_ip = "10.0.0.10"
2018 self.tcp_port_out = 6303
2019 self.udp_port_out = 6304
2020 self.icmp_id_out = 6305
2022 self.nat44_add_address(self.nat_addr)
2023 flags = self.config_flags.NAT_IS_INSIDE
2024 self.vapi.nat44_interface_add_del_feature(
2025 sw_if_index=self.pg0.sw_if_index,
2026 flags=flags, is_add=1)
2027 self.vapi.nat44_interface_add_del_feature(
2028 sw_if_index=self.pg1.sw_if_index,
2032 pkts = self.create_stream_in(self.pg0, self.pg1)
2033 self.pg0.add_stream(pkts)
2034 self.pg_enable_capture(self.pg_interfaces)
2036 capture = self.pg1.get_capture(len(pkts))
2037 self.verify_capture_out(capture)
2040 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2041 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
2042 self.assertEqual(len(sessions), 0)
2043 pkts = self.create_stream_in(self.pg0, self.pg1)
2044 self.pg0.add_stream(pkts)
2045 self.pg_enable_capture(self.pg_interfaces)
2047 capture = self.pg1.get_capture(len(pkts))
2048 self.verify_capture_out(capture, nat_ip, True)
2050 def test_identity_nat(self):
2051 """ Identity NAT """
2052 flags = self.config_flags.NAT_IS_ADDR_ONLY
2053 self.vapi.nat44_add_del_identity_mapping(
2054 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
2055 flags=flags, is_add=1)
2056 flags = self.config_flags.NAT_IS_INSIDE
2057 self.vapi.nat44_interface_add_del_feature(
2058 sw_if_index=self.pg0.sw_if_index,
2059 flags=flags, is_add=1)
2060 self.vapi.nat44_interface_add_del_feature(
2061 sw_if_index=self.pg1.sw_if_index,
2064 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2065 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2066 TCP(sport=12345, dport=56789))
2067 self.pg1.add_stream(p)
2068 self.pg_enable_capture(self.pg_interfaces)
2070 capture = self.pg0.get_capture(1)
2075 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2076 self.assertEqual(ip.src, self.pg1.remote_ip4)
2077 self.assertEqual(tcp.dport, 56789)
2078 self.assertEqual(tcp.sport, 12345)
2079 self.assert_packet_checksums_valid(p)
2081 self.logger.error(ppp("Unexpected or invalid packet:", p))
2084 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
2085 self.assertEqual(len(sessions), 0)
2086 flags = self.config_flags.NAT_IS_ADDR_ONLY
2087 self.vapi.nat44_add_del_identity_mapping(
2088 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
2089 flags=flags, vrf_id=1, is_add=1)
2090 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2091 self.assertEqual(len(identity_mappings), 2)
2093 def test_multiple_inside_interfaces(self):
2094 """ NAT44 multiple non-overlapping address space inside interfaces """
2096 self.nat44_add_address(self.nat_addr)
2097 flags = self.config_flags.NAT_IS_INSIDE
2098 self.vapi.nat44_interface_add_del_feature(
2099 sw_if_index=self.pg0.sw_if_index,
2100 flags=flags, is_add=1)
2101 self.vapi.nat44_interface_add_del_feature(
2102 sw_if_index=self.pg1.sw_if_index,
2103 flags=flags, is_add=1)
2104 self.vapi.nat44_interface_add_del_feature(
2105 sw_if_index=self.pg3.sw_if_index,
2108 # between two NAT44 inside interfaces (no translation)
2109 pkts = self.create_stream_in(self.pg0, self.pg1)
2110 self.pg0.add_stream(pkts)
2111 self.pg_enable_capture(self.pg_interfaces)
2113 capture = self.pg1.get_capture(len(pkts))
2114 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
2116 # from NAT44 inside to interface without NAT44 feature (no translation)
2117 pkts = self.create_stream_in(self.pg0, self.pg2)
2118 self.pg0.add_stream(pkts)
2119 self.pg_enable_capture(self.pg_interfaces)
2121 capture = self.pg2.get_capture(len(pkts))
2122 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2124 # in2out 1st interface
2125 pkts = self.create_stream_in(self.pg0, self.pg3)
2126 self.pg0.add_stream(pkts)
2127 self.pg_enable_capture(self.pg_interfaces)
2129 capture = self.pg3.get_capture(len(pkts))
2130 self.verify_capture_out(capture)
2132 # out2in 1st interface
2133 pkts = self.create_stream_out(self.pg3)
2134 self.pg3.add_stream(pkts)
2135 self.pg_enable_capture(self.pg_interfaces)
2137 capture = self.pg0.get_capture(len(pkts))
2138 self.verify_capture_in(capture, self.pg0)
2140 # in2out 2nd interface
2141 pkts = self.create_stream_in(self.pg1, self.pg3)
2142 self.pg1.add_stream(pkts)
2143 self.pg_enable_capture(self.pg_interfaces)
2145 capture = self.pg3.get_capture(len(pkts))
2146 self.verify_capture_out(capture)
2148 # out2in 2nd interface
2149 pkts = self.create_stream_out(self.pg3)
2150 self.pg3.add_stream(pkts)
2151 self.pg_enable_capture(self.pg_interfaces)
2153 capture = self.pg1.get_capture(len(pkts))
2154 self.verify_capture_in(capture, self.pg1)
2156 def test_inside_overlapping_interfaces(self):
2157 """ NAT44 multiple inside interfaces with overlapping address space """
2159 static_nat_ip = "10.0.0.10"
2160 self.nat44_add_address(self.nat_addr)
2161 flags = self.config_flags.NAT_IS_INSIDE
2162 self.vapi.nat44_interface_add_del_feature(
2163 sw_if_index=self.pg3.sw_if_index,
2165 self.vapi.nat44_interface_add_del_feature(
2166 sw_if_index=self.pg4.sw_if_index,
2167 flags=flags, is_add=1)
2168 self.vapi.nat44_interface_add_del_feature(
2169 sw_if_index=self.pg5.sw_if_index,
2170 flags=flags, is_add=1)
2171 self.vapi.nat44_interface_add_del_feature(
2172 sw_if_index=self.pg6.sw_if_index,
2173 flags=flags, is_add=1)
2174 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2177 # between NAT44 inside interfaces with same VRF (no translation)
2178 pkts = self.create_stream_in(self.pg4, self.pg5)
2179 self.pg4.add_stream(pkts)
2180 self.pg_enable_capture(self.pg_interfaces)
2182 capture = self.pg5.get_capture(len(pkts))
2183 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2185 # between NAT44 inside interfaces with different VRF (hairpinning)
2186 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2187 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2188 TCP(sport=1234, dport=5678))
2189 self.pg4.add_stream(p)
2190 self.pg_enable_capture(self.pg_interfaces)
2192 capture = self.pg6.get_capture(1)
2197 self.assertEqual(ip.src, self.nat_addr)
2198 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2199 self.assertNotEqual(tcp.sport, 1234)
2200 self.assertEqual(tcp.dport, 5678)
2202 self.logger.error(ppp("Unexpected or invalid packet:", p))
2205 # in2out 1st interface
2206 pkts = self.create_stream_in(self.pg4, self.pg3)
2207 self.pg4.add_stream(pkts)
2208 self.pg_enable_capture(self.pg_interfaces)
2210 capture = self.pg3.get_capture(len(pkts))
2211 self.verify_capture_out(capture)
2213 # out2in 1st interface
2214 pkts = self.create_stream_out(self.pg3)
2215 self.pg3.add_stream(pkts)
2216 self.pg_enable_capture(self.pg_interfaces)
2218 capture = self.pg4.get_capture(len(pkts))
2219 self.verify_capture_in(capture, self.pg4)
2221 # in2out 2nd interface
2222 pkts = self.create_stream_in(self.pg5, self.pg3)
2223 self.pg5.add_stream(pkts)
2224 self.pg_enable_capture(self.pg_interfaces)
2226 capture = self.pg3.get_capture(len(pkts))
2227 self.verify_capture_out(capture)
2229 # out2in 2nd interface
2230 pkts = self.create_stream_out(self.pg3)
2231 self.pg3.add_stream(pkts)
2232 self.pg_enable_capture(self.pg_interfaces)
2234 capture = self.pg5.get_capture(len(pkts))
2235 self.verify_capture_in(capture, self.pg5)
2238 addresses = self.vapi.nat44_address_dump()
2239 self.assertEqual(len(addresses), 1)
2240 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4, 10)
2241 self.assertEqual(len(sessions), 3)
2242 for session in sessions:
2243 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2244 self.assertEqual(str(session.inside_ip_address),
2245 self.pg5.remote_ip4)
2246 self.assertEqual(session.outside_ip_address,
2247 addresses[0].ip_address)
2248 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2249 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2250 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2251 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2252 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2253 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2254 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2255 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2256 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2258 # in2out 3rd interface
2259 pkts = self.create_stream_in(self.pg6, self.pg3)
2260 self.pg6.add_stream(pkts)
2261 self.pg_enable_capture(self.pg_interfaces)
2263 capture = self.pg3.get_capture(len(pkts))
2264 self.verify_capture_out(capture, static_nat_ip, True)
2266 # out2in 3rd interface
2267 pkts = self.create_stream_out(self.pg3, static_nat_ip)
2268 self.pg3.add_stream(pkts)
2269 self.pg_enable_capture(self.pg_interfaces)
2271 capture = self.pg6.get_capture(len(pkts))
2272 self.verify_capture_in(capture, self.pg6)
2274 # general user and session dump verifications
2275 users = self.vapi.nat44_user_dump()
2276 self.assertGreaterEqual(len(users), 3)
2277 addresses = self.vapi.nat44_address_dump()
2278 self.assertEqual(len(addresses), 1)
2280 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2282 for session in sessions:
2283 self.assertEqual(user.ip_address, session.inside_ip_address)
2284 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2285 self.assertTrue(session.protocol in
2286 [IP_PROTOS.tcp, IP_PROTOS.udp,
2288 self.assertFalse(session.flags &
2289 self.config_flags.NAT_IS_EXT_HOST_VALID)
2292 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4, 10)
2293 self.assertGreaterEqual(len(sessions), 4)
2294 for session in sessions:
2295 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2296 self.assertEqual(str(session.inside_ip_address),
2297 self.pg4.remote_ip4)
2298 self.assertEqual(session.outside_ip_address,
2299 addresses[0].ip_address)
2302 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4, 20)
2303 self.assertGreaterEqual(len(sessions), 3)
2304 for session in sessions:
2305 self.assertTrue(session.flags & self.config_flags.NAT_IS_STATIC)
2306 self.assertEqual(str(session.inside_ip_address),
2307 self.pg6.remote_ip4)
2308 self.assertEqual(str(session.outside_ip_address),
2310 self.assertTrue(session.inside_port in
2311 [self.tcp_port_in, self.udp_port_in,
2314 def test_hairpinning(self):
2315 """ NAT44 hairpinning - 1:1 NAPT """
2317 host = self.pg0.remote_hosts[0]
2318 server = self.pg0.remote_hosts[1]
2321 server_in_port = 5678
2322 server_out_port = 8765
2324 self.nat44_add_address(self.nat_addr)
2325 flags = self.config_flags.NAT_IS_INSIDE
2326 self.vapi.nat44_interface_add_del_feature(
2327 sw_if_index=self.pg0.sw_if_index,
2328 flags=flags, is_add=1)
2329 self.vapi.nat44_interface_add_del_feature(
2330 sw_if_index=self.pg1.sw_if_index,
2333 # add static mapping for server
2334 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2335 server_in_port, server_out_port,
2336 proto=IP_PROTOS.tcp)
2338 # send packet from host to server
2339 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2340 IP(src=host.ip4, dst=self.nat_addr) /
2341 TCP(sport=host_in_port, dport=server_out_port))
2342 self.pg0.add_stream(p)
2343 self.pg_enable_capture(self.pg_interfaces)
2345 capture = self.pg0.get_capture(1)
2350 self.assertEqual(ip.src, self.nat_addr)
2351 self.assertEqual(ip.dst, server.ip4)
2352 self.assertNotEqual(tcp.sport, host_in_port)
2353 self.assertEqual(tcp.dport, server_in_port)
2354 self.assert_packet_checksums_valid(p)
2355 host_out_port = tcp.sport
2357 self.logger.error(ppp("Unexpected or invalid packet:", p))
2360 # send reply from server to host
2361 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2362 IP(src=server.ip4, dst=self.nat_addr) /
2363 TCP(sport=server_in_port, dport=host_out_port))
2364 self.pg0.add_stream(p)
2365 self.pg_enable_capture(self.pg_interfaces)
2367 capture = self.pg0.get_capture(1)
2372 self.assertEqual(ip.src, self.nat_addr)
2373 self.assertEqual(ip.dst, host.ip4)
2374 self.assertEqual(tcp.sport, server_out_port)
2375 self.assertEqual(tcp.dport, host_in_port)
2376 self.assert_packet_checksums_valid(p)
2378 self.logger.error(ppp("Unexpected or invalid packet:", p))
2381 def test_hairpinning2(self):
2382 """ NAT44 hairpinning - 1:1 NAT"""
2384 server1_nat_ip = "10.0.0.10"
2385 server2_nat_ip = "10.0.0.11"
2386 host = self.pg0.remote_hosts[0]
2387 server1 = self.pg0.remote_hosts[1]
2388 server2 = self.pg0.remote_hosts[2]
2389 server_tcp_port = 22
2390 server_udp_port = 20
2392 self.nat44_add_address(self.nat_addr)
2393 flags = self.config_flags.NAT_IS_INSIDE
2394 self.vapi.nat44_interface_add_del_feature(
2395 sw_if_index=self.pg0.sw_if_index,
2396 flags=flags, is_add=1)
2397 self.vapi.nat44_interface_add_del_feature(
2398 sw_if_index=self.pg1.sw_if_index,
2401 # add static mapping for servers
2402 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2403 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
2407 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2408 IP(src=host.ip4, dst=server1_nat_ip) /
2409 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2411 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2412 IP(src=host.ip4, dst=server1_nat_ip) /
2413 UDP(sport=self.udp_port_in, dport=server_udp_port))
2415 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2416 IP(src=host.ip4, dst=server1_nat_ip) /
2417 ICMP(id=self.icmp_id_in, type='echo-request'))
2419 self.pg0.add_stream(pkts)
2420 self.pg_enable_capture(self.pg_interfaces)
2422 capture = self.pg0.get_capture(len(pkts))
2423 for packet in capture:
2425 self.assertEqual(packet[IP].src, self.nat_addr)
2426 self.assertEqual(packet[IP].dst, server1.ip4)
2427 if packet.haslayer(TCP):
2428 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2429 self.assertEqual(packet[TCP].dport, server_tcp_port)
2430 self.tcp_port_out = packet[TCP].sport
2431 self.assert_packet_checksums_valid(packet)
2432 elif packet.haslayer(UDP):
2433 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2434 self.assertEqual(packet[UDP].dport, server_udp_port)
2435 self.udp_port_out = packet[UDP].sport
2437 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2438 self.icmp_id_out = packet[ICMP].id
2440 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2445 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2446 IP(src=server1.ip4, dst=self.nat_addr) /
2447 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2449 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2450 IP(src=server1.ip4, dst=self.nat_addr) /
2451 UDP(sport=server_udp_port, dport=self.udp_port_out))
2453 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2454 IP(src=server1.ip4, dst=self.nat_addr) /
2455 ICMP(id=self.icmp_id_out, type='echo-reply'))
2457 self.pg0.add_stream(pkts)
2458 self.pg_enable_capture(self.pg_interfaces)
2460 capture = self.pg0.get_capture(len(pkts))
2461 for packet in capture:
2463 self.assertEqual(packet[IP].src, server1_nat_ip)
2464 self.assertEqual(packet[IP].dst, host.ip4)
2465 if packet.haslayer(TCP):
2466 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2467 self.assertEqual(packet[TCP].sport, server_tcp_port)
2468 self.assert_packet_checksums_valid(packet)
2469 elif packet.haslayer(UDP):
2470 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2471 self.assertEqual(packet[UDP].sport, server_udp_port)
2473 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2475 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2478 # server2 to server1
2480 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2481 IP(src=server2.ip4, dst=server1_nat_ip) /
2482 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2484 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2485 IP(src=server2.ip4, dst=server1_nat_ip) /
2486 UDP(sport=self.udp_port_in, dport=server_udp_port))
2488 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2489 IP(src=server2.ip4, dst=server1_nat_ip) /
2490 ICMP(id=self.icmp_id_in, type='echo-request'))
2492 self.pg0.add_stream(pkts)
2493 self.pg_enable_capture(self.pg_interfaces)
2495 capture = self.pg0.get_capture(len(pkts))
2496 for packet in capture:
2498 self.assertEqual(packet[IP].src, server2_nat_ip)
2499 self.assertEqual(packet[IP].dst, server1.ip4)
2500 if packet.haslayer(TCP):
2501 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2502 self.assertEqual(packet[TCP].dport, server_tcp_port)
2503 self.tcp_port_out = packet[TCP].sport
2504 self.assert_packet_checksums_valid(packet)
2505 elif packet.haslayer(UDP):
2506 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2507 self.assertEqual(packet[UDP].dport, server_udp_port)
2508 self.udp_port_out = packet[UDP].sport
2510 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2511 self.icmp_id_out = packet[ICMP].id
2513 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2516 # server1 to server2
2518 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2519 IP(src=server1.ip4, dst=server2_nat_ip) /
2520 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2522 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2523 IP(src=server1.ip4, dst=server2_nat_ip) /
2524 UDP(sport=server_udp_port, dport=self.udp_port_out))
2526 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2527 IP(src=server1.ip4, dst=server2_nat_ip) /
2528 ICMP(id=self.icmp_id_out, type='echo-reply'))
2530 self.pg0.add_stream(pkts)
2531 self.pg_enable_capture(self.pg_interfaces)
2533 capture = self.pg0.get_capture(len(pkts))
2534 for packet in capture:
2536 self.assertEqual(packet[IP].src, server1_nat_ip)
2537 self.assertEqual(packet[IP].dst, server2.ip4)
2538 if packet.haslayer(TCP):
2539 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2540 self.assertEqual(packet[TCP].sport, server_tcp_port)
2541 self.assert_packet_checksums_valid(packet)
2542 elif packet.haslayer(UDP):
2543 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2544 self.assertEqual(packet[UDP].sport, server_udp_port)
2546 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2548 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2551 def test_interface_addr(self):
2552 """ Acquire NAT44 addresses from interface """
2553 self.vapi.nat44_add_del_interface_addr(
2555 sw_if_index=self.pg7.sw_if_index)
2557 # no address in NAT pool
2558 addresses = self.vapi.nat44_address_dump()
2559 self.assertEqual(0, len(addresses))
2561 # configure interface address and check NAT address pool
2562 self.pg7.config_ip4()
2563 addresses = self.vapi.nat44_address_dump()
2564 self.assertEqual(1, len(addresses))
2565 self.assertEqual(str(addresses[0].ip_address), self.pg7.local_ip4)
2567 # remove interface address and check NAT address pool
2568 self.pg7.unconfig_ip4()
2569 addresses = self.vapi.nat44_address_dump()
2570 self.assertEqual(0, len(addresses))
2572 def test_interface_addr_static_mapping(self):
2573 """ Static mapping with addresses from interface """
2576 self.vapi.nat44_add_del_interface_addr(
2578 sw_if_index=self.pg7.sw_if_index)
2579 self.nat44_add_static_mapping(
2581 external_sw_if_index=self.pg7.sw_if_index,
2584 # static mappings with external interface
2585 static_mappings = self.vapi.nat44_static_mapping_dump()
2586 self.assertEqual(1, len(static_mappings))
2587 self.assertEqual(self.pg7.sw_if_index,
2588 static_mappings[0].external_sw_if_index)
2589 self.assertEqual(static_mappings[0].tag, tag)
2591 # configure interface address and check static mappings
2592 self.pg7.config_ip4()
2593 static_mappings = self.vapi.nat44_static_mapping_dump()
2594 self.assertEqual(2, len(static_mappings))
2596 for sm in static_mappings:
2597 if sm.external_sw_if_index == 0xFFFFFFFF:
2598 self.assertEqual(str(sm.external_ip_address),
2600 self.assertEqual(sm.tag, tag)
2602 self.assertTrue(resolved)
2604 # remove interface address and check static mappings
2605 self.pg7.unconfig_ip4()
2606 static_mappings = self.vapi.nat44_static_mapping_dump()
2607 self.assertEqual(1, len(static_mappings))
2608 self.assertEqual(self.pg7.sw_if_index,
2609 static_mappings[0].external_sw_if_index)
2610 self.assertEqual(static_mappings[0].tag, tag)
2612 # configure interface address again and check static mappings
2613 self.pg7.config_ip4()
2614 static_mappings = self.vapi.nat44_static_mapping_dump()
2615 self.assertEqual(2, len(static_mappings))
2617 for sm in static_mappings:
2618 if sm.external_sw_if_index == 0xFFFFFFFF:
2619 self.assertEqual(str(sm.external_ip_address),
2621 self.assertEqual(sm.tag, tag)
2623 self.assertTrue(resolved)
2625 # remove static mapping
2626 self.nat44_add_static_mapping(
2628 external_sw_if_index=self.pg7.sw_if_index,
2631 static_mappings = self.vapi.nat44_static_mapping_dump()
2632 self.assertEqual(0, len(static_mappings))
2634 def test_interface_addr_identity_nat(self):
2635 """ Identity NAT with addresses from interface """
2638 self.vapi.nat44_add_del_interface_addr(
2640 sw_if_index=self.pg7.sw_if_index)
2641 self.vapi.nat44_add_del_identity_mapping(
2643 sw_if_index=self.pg7.sw_if_index,
2645 protocol=IP_PROTOS.tcp,
2648 # identity mappings with external interface
2649 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2650 self.assertEqual(1, len(identity_mappings))
2651 self.assertEqual(self.pg7.sw_if_index,
2652 identity_mappings[0].sw_if_index)
2654 # configure interface address and check identity mappings
2655 self.pg7.config_ip4()
2656 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2658 self.assertEqual(2, len(identity_mappings))
2659 for sm in identity_mappings:
2660 if sm.sw_if_index == 0xFFFFFFFF:
2661 self.assertEqual(str(identity_mappings[0].ip_address),
2663 self.assertEqual(port, identity_mappings[0].port)
2664 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2666 self.assertTrue(resolved)
2668 # remove interface address and check identity mappings
2669 self.pg7.unconfig_ip4()
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)
2675 def test_ipfix_nat44_sess(self):
2676 """ IPFIX logging NAT44 session created/deleted """
2677 self.ipfix_domain_id = 10
2678 self.ipfix_src_port = 20202
2679 collector_port = 30303
2680 bind_layers(UDP, IPFIX, dport=30303)
2681 self.nat44_add_address(self.nat_addr)
2682 flags = self.config_flags.NAT_IS_INSIDE
2683 self.vapi.nat44_interface_add_del_feature(
2684 sw_if_index=self.pg0.sw_if_index,
2685 flags=flags, is_add=1)
2686 self.vapi.nat44_interface_add_del_feature(
2687 sw_if_index=self.pg1.sw_if_index,
2689 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2690 src_address=self.pg3.local_ip4,
2692 template_interval=10,
2693 collector_port=collector_port)
2694 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2695 src_port=self.ipfix_src_port,
2698 pkts = self.create_stream_in(self.pg0, self.pg1)
2699 self.pg0.add_stream(pkts)
2700 self.pg_enable_capture(self.pg_interfaces)
2702 capture = self.pg1.get_capture(len(pkts))
2703 self.verify_capture_out(capture)
2704 self.nat44_add_address(self.nat_addr, is_add=0)
2705 self.vapi.ipfix_flush()
2706 capture = self.pg3.get_capture(9)
2707 ipfix = IPFIXDecoder()
2708 # first load template
2710 self.assertTrue(p.haslayer(IPFIX))
2711 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2712 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2713 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2714 self.assertEqual(p[UDP].dport, collector_port)
2715 self.assertEqual(p[IPFIX].observationDomainID,
2716 self.ipfix_domain_id)
2717 if p.haslayer(Template):
2718 ipfix.add_template(p.getlayer(Template))
2719 # verify events in data set
2721 if p.haslayer(Data):
2722 data = ipfix.decode_data_set(p.getlayer(Set))
2723 self.verify_ipfix_nat44_ses(data)
2725 def test_ipfix_addr_exhausted(self):
2726 """ IPFIX logging NAT addresses exhausted """
2727 flags = self.config_flags.NAT_IS_INSIDE
2728 self.vapi.nat44_interface_add_del_feature(
2729 sw_if_index=self.pg0.sw_if_index,
2730 flags=flags, is_add=1)
2731 self.vapi.nat44_interface_add_del_feature(
2732 sw_if_index=self.pg1.sw_if_index,
2734 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2735 src_address=self.pg3.local_ip4,
2737 template_interval=10)
2738 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2739 src_port=self.ipfix_src_port,
2742 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2743 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2745 self.pg0.add_stream(p)
2746 self.pg_enable_capture(self.pg_interfaces)
2748 self.pg1.assert_nothing_captured()
2750 self.vapi.ipfix_flush()
2751 capture = self.pg3.get_capture(9)
2752 ipfix = IPFIXDecoder()
2753 # first load template
2755 self.assertTrue(p.haslayer(IPFIX))
2756 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2757 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2758 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2759 self.assertEqual(p[UDP].dport, 4739)
2760 self.assertEqual(p[IPFIX].observationDomainID,
2761 self.ipfix_domain_id)
2762 if p.haslayer(Template):
2763 ipfix.add_template(p.getlayer(Template))
2764 # verify events in data set
2766 if p.haslayer(Data):
2767 data = ipfix.decode_data_set(p.getlayer(Set))
2768 self.verify_ipfix_addr_exhausted(data)
2770 @unittest.skipUnless(running_extended_tests, "part of extended tests")
2771 def test_ipfix_max_sessions(self):
2772 """ IPFIX logging maximum session entries exceeded """
2773 self.nat44_add_address(self.nat_addr)
2774 flags = self.config_flags.NAT_IS_INSIDE
2775 self.vapi.nat44_interface_add_del_feature(
2776 sw_if_index=self.pg0.sw_if_index,
2777 flags=flags, is_add=1)
2778 self.vapi.nat44_interface_add_del_feature(
2779 sw_if_index=self.pg1.sw_if_index,
2782 nat44_config = self.vapi.nat_show_config()
2783 max_sessions = 10 * nat44_config.translation_buckets
2786 for i in range(0, max_sessions):
2787 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2788 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2789 IP(src=src, dst=self.pg1.remote_ip4) /
2792 self.pg0.add_stream(pkts)
2793 self.pg_enable_capture(self.pg_interfaces)
2796 self.pg1.get_capture(max_sessions)
2797 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2798 src_address=self.pg3.local_ip4,
2800 template_interval=10)
2801 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2802 src_port=self.ipfix_src_port,
2805 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2806 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2808 self.pg0.add_stream(p)
2809 self.pg_enable_capture(self.pg_interfaces)
2811 self.pg1.assert_nothing_captured()
2813 self.vapi.ipfix_flush()
2814 capture = self.pg3.get_capture(9)
2815 ipfix = IPFIXDecoder()
2816 # first load template
2818 self.assertTrue(p.haslayer(IPFIX))
2819 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2820 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2821 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2822 self.assertEqual(p[UDP].dport, 4739)
2823 self.assertEqual(p[IPFIX].observationDomainID,
2824 self.ipfix_domain_id)
2825 if p.haslayer(Template):
2826 ipfix.add_template(p.getlayer(Template))
2827 # verify events in data set
2829 if p.haslayer(Data):
2830 data = ipfix.decode_data_set(p.getlayer(Set))
2831 self.verify_ipfix_max_sessions(data, max_sessions)
2833 def test_syslog_apmap(self):
2834 """ Test syslog address and port mapping creation and deletion """
2835 self.vapi.syslog_set_filter(
2836 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
2837 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
2838 self.nat44_add_address(self.nat_addr)
2839 flags = self.config_flags.NAT_IS_INSIDE
2840 self.vapi.nat44_interface_add_del_feature(
2841 sw_if_index=self.pg0.sw_if_index,
2842 flags=flags, is_add=1)
2843 self.vapi.nat44_interface_add_del_feature(
2844 sw_if_index=self.pg1.sw_if_index,
2847 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2848 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2849 TCP(sport=self.tcp_port_in, dport=20))
2850 self.pg0.add_stream(p)
2851 self.pg_enable_capture(self.pg_interfaces)
2853 capture = self.pg1.get_capture(1)
2854 self.tcp_port_out = capture[0][TCP].sport
2855 capture = self.pg3.get_capture(1)
2856 self.verify_syslog_apmap(capture[0][Raw].load)
2858 self.pg_enable_capture(self.pg_interfaces)
2860 self.nat44_add_address(self.nat_addr, is_add=0)
2861 capture = self.pg3.get_capture(1)
2862 self.verify_syslog_apmap(capture[0][Raw].load, False)
2864 def test_pool_addr_fib(self):
2865 """ NAT44 add pool addresses to FIB """
2866 static_addr = '10.0.0.10'
2867 self.nat44_add_address(self.nat_addr)
2868 flags = self.config_flags.NAT_IS_INSIDE
2869 self.vapi.nat44_interface_add_del_feature(
2870 sw_if_index=self.pg0.sw_if_index,
2871 flags=flags, is_add=1)
2872 self.vapi.nat44_interface_add_del_feature(
2873 sw_if_index=self.pg1.sw_if_index,
2875 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
2878 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2879 ARP(op=ARP.who_has, pdst=self.nat_addr,
2880 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2881 self.pg1.add_stream(p)
2882 self.pg_enable_capture(self.pg_interfaces)
2884 capture = self.pg1.get_capture(1)
2885 self.assertTrue(capture[0].haslayer(ARP))
2886 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2889 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2890 ARP(op=ARP.who_has, pdst=static_addr,
2891 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2892 self.pg1.add_stream(p)
2893 self.pg_enable_capture(self.pg_interfaces)
2895 capture = self.pg1.get_capture(1)
2896 self.assertTrue(capture[0].haslayer(ARP))
2897 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2899 # send ARP to non-NAT44 interface
2900 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2901 ARP(op=ARP.who_has, pdst=self.nat_addr,
2902 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2903 self.pg2.add_stream(p)
2904 self.pg_enable_capture(self.pg_interfaces)
2906 self.pg1.assert_nothing_captured()
2908 # remove addresses and verify
2909 self.nat44_add_address(self.nat_addr, is_add=0)
2910 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2913 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2914 ARP(op=ARP.who_has, pdst=self.nat_addr,
2915 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2916 self.pg1.add_stream(p)
2917 self.pg_enable_capture(self.pg_interfaces)
2919 self.pg1.assert_nothing_captured()
2921 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2922 ARP(op=ARP.who_has, pdst=static_addr,
2923 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2924 self.pg1.add_stream(p)
2925 self.pg_enable_capture(self.pg_interfaces)
2927 self.pg1.assert_nothing_captured()
2929 def test_vrf_mode(self):
2930 """ NAT44 tenant VRF aware address pool mode """
2934 nat_ip1 = "10.0.0.10"
2935 nat_ip2 = "10.0.0.11"
2937 self.pg0.unconfig_ip4()
2938 self.pg1.unconfig_ip4()
2939 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
2940 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
2941 self.pg0.set_table_ip4(vrf_id1)
2942 self.pg1.set_table_ip4(vrf_id2)
2943 self.pg0.config_ip4()
2944 self.pg1.config_ip4()
2945 self.pg0.resolve_arp()
2946 self.pg1.resolve_arp()
2948 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2949 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2950 flags = self.config_flags.NAT_IS_INSIDE
2951 self.vapi.nat44_interface_add_del_feature(
2952 sw_if_index=self.pg0.sw_if_index,
2953 flags=flags, is_add=1)
2954 self.vapi.nat44_interface_add_del_feature(
2955 sw_if_index=self.pg1.sw_if_index,
2956 flags=flags, is_add=1)
2957 self.vapi.nat44_interface_add_del_feature(
2958 sw_if_index=self.pg2.sw_if_index,
2963 pkts = self.create_stream_in(self.pg0, self.pg2)
2964 self.pg0.add_stream(pkts)
2965 self.pg_enable_capture(self.pg_interfaces)
2967 capture = self.pg2.get_capture(len(pkts))
2968 self.verify_capture_out(capture, nat_ip1)
2971 pkts = self.create_stream_in(self.pg1, self.pg2)
2972 self.pg1.add_stream(pkts)
2973 self.pg_enable_capture(self.pg_interfaces)
2975 capture = self.pg2.get_capture(len(pkts))
2976 self.verify_capture_out(capture, nat_ip2)
2979 self.pg0.unconfig_ip4()
2980 self.pg1.unconfig_ip4()
2981 self.pg0.set_table_ip4(0)
2982 self.pg1.set_table_ip4(0)
2983 self.pg0.config_ip4()
2984 self.pg1.config_ip4()
2985 self.pg0.resolve_arp()
2986 self.pg1.resolve_arp()
2987 self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id1})
2988 self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id2})
2990 def test_vrf_feature_independent(self):
2991 """ NAT44 tenant VRF independent address pool mode """
2993 nat_ip1 = "10.0.0.10"
2994 nat_ip2 = "10.0.0.11"
2996 self.nat44_add_address(nat_ip1)
2997 self.nat44_add_address(nat_ip2, vrf_id=99)
2998 flags = self.config_flags.NAT_IS_INSIDE
2999 self.vapi.nat44_interface_add_del_feature(
3000 sw_if_index=self.pg0.sw_if_index,
3001 flags=flags, is_add=1)
3002 self.vapi.nat44_interface_add_del_feature(
3003 sw_if_index=self.pg1.sw_if_index,
3004 flags=flags, is_add=1)
3005 self.vapi.nat44_interface_add_del_feature(
3006 sw_if_index=self.pg2.sw_if_index,
3010 pkts = self.create_stream_in(self.pg0, self.pg2)
3011 self.pg0.add_stream(pkts)
3012 self.pg_enable_capture(self.pg_interfaces)
3014 capture = self.pg2.get_capture(len(pkts))
3015 self.verify_capture_out(capture, nat_ip1)
3018 pkts = self.create_stream_in(self.pg1, self.pg2)
3019 self.pg1.add_stream(pkts)
3020 self.pg_enable_capture(self.pg_interfaces)
3022 capture = self.pg2.get_capture(len(pkts))
3023 self.verify_capture_out(capture, nat_ip1)
3025 def create_routes_and_neigbors(self):
3026 r1 = VppIpRoute(self, self.pg7.remote_ip4, 32,
3027 [VppRoutePath(self.pg7.remote_ip4,
3028 self.pg7.sw_if_index)])
3029 r2 = VppIpRoute(self, self.pg8.remote_ip4, 32,
3030 [VppRoutePath(self.pg8.remote_ip4,
3031 self.pg8.sw_if_index)])
3035 n1 = VppNeighbor(self,
3036 self.pg7.sw_if_index,
3037 self.pg7.remote_mac,
3038 self.pg7.remote_ip4,
3040 n2 = VppNeighbor(self,
3041 self.pg8.sw_if_index,
3042 self.pg8.remote_mac,
3043 self.pg8.remote_ip4,
3048 def test_dynamic_ipless_interfaces(self):
3049 """ NAT44 interfaces without configured IP address """
3050 self.create_routes_and_neigbors()
3051 self.nat44_add_address(self.nat_addr)
3052 flags = self.config_flags.NAT_IS_INSIDE
3053 self.vapi.nat44_interface_add_del_feature(
3054 sw_if_index=self.pg7.sw_if_index,
3055 flags=flags, is_add=1)
3056 self.vapi.nat44_interface_add_del_feature(
3057 sw_if_index=self.pg8.sw_if_index,
3061 pkts = self.create_stream_in(self.pg7, self.pg8)
3062 self.pg7.add_stream(pkts)
3063 self.pg_enable_capture(self.pg_interfaces)
3065 capture = self.pg8.get_capture(len(pkts))
3066 self.verify_capture_out(capture)
3069 pkts = self.create_stream_out(self.pg8, self.nat_addr)
3070 self.pg8.add_stream(pkts)
3071 self.pg_enable_capture(self.pg_interfaces)
3073 capture = self.pg7.get_capture(len(pkts))
3074 self.verify_capture_in(capture, self.pg7)
3076 def test_static_ipless_interfaces(self):
3077 """ NAT44 interfaces without configured IP address - 1:1 NAT """
3079 self.create_routes_and_neigbors()
3080 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
3081 flags = self.config_flags.NAT_IS_INSIDE
3082 self.vapi.nat44_interface_add_del_feature(
3083 sw_if_index=self.pg7.sw_if_index,
3084 flags=flags, is_add=1)
3085 self.vapi.nat44_interface_add_del_feature(
3086 sw_if_index=self.pg8.sw_if_index,
3090 pkts = self.create_stream_out(self.pg8)
3091 self.pg8.add_stream(pkts)
3092 self.pg_enable_capture(self.pg_interfaces)
3094 capture = self.pg7.get_capture(len(pkts))
3095 self.verify_capture_in(capture, self.pg7)
3098 pkts = self.create_stream_in(self.pg7, self.pg8)
3099 self.pg7.add_stream(pkts)
3100 self.pg_enable_capture(self.pg_interfaces)
3102 capture = self.pg8.get_capture(len(pkts))
3103 self.verify_capture_out(capture, self.nat_addr, True)
3105 def test_static_with_port_ipless_interfaces(self):
3106 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
3108 self.tcp_port_out = 30606
3109 self.udp_port_out = 30607
3110 self.icmp_id_out = 30608
3112 self.create_routes_and_neigbors()
3113 self.nat44_add_address(self.nat_addr)
3114 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3115 self.tcp_port_in, self.tcp_port_out,
3116 proto=IP_PROTOS.tcp)
3117 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3118 self.udp_port_in, self.udp_port_out,
3119 proto=IP_PROTOS.udp)
3120 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3121 self.icmp_id_in, self.icmp_id_out,
3122 proto=IP_PROTOS.icmp)
3123 flags = self.config_flags.NAT_IS_INSIDE
3124 self.vapi.nat44_interface_add_del_feature(
3125 sw_if_index=self.pg7.sw_if_index,
3126 flags=flags, is_add=1)
3127 self.vapi.nat44_interface_add_del_feature(
3128 sw_if_index=self.pg8.sw_if_index,
3132 pkts = self.create_stream_out(self.pg8)
3133 self.pg8.add_stream(pkts)
3134 self.pg_enable_capture(self.pg_interfaces)
3136 capture = self.pg7.get_capture(len(pkts))
3137 self.verify_capture_in(capture, self.pg7)
3140 pkts = self.create_stream_in(self.pg7, self.pg8)
3141 self.pg7.add_stream(pkts)
3142 self.pg_enable_capture(self.pg_interfaces)
3144 capture = self.pg8.get_capture(len(pkts))
3145 self.verify_capture_out(capture)
3147 def test_static_unknown_proto(self):
3148 """ 1:1 NAT translate packet with unknown protocol """
3149 nat_ip = "10.0.0.10"
3150 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
3151 flags = self.config_flags.NAT_IS_INSIDE
3152 self.vapi.nat44_interface_add_del_feature(
3153 sw_if_index=self.pg0.sw_if_index,
3154 flags=flags, is_add=1)
3155 self.vapi.nat44_interface_add_del_feature(
3156 sw_if_index=self.pg1.sw_if_index,
3160 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3161 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3163 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3164 TCP(sport=1234, dport=1234))
3165 self.pg0.add_stream(p)
3166 self.pg_enable_capture(self.pg_interfaces)
3168 p = self.pg1.get_capture(1)
3171 self.assertEqual(packet[IP].src, nat_ip)
3172 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3173 self.assertEqual(packet.haslayer(GRE), 1)
3174 self.assert_packet_checksums_valid(packet)
3176 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3180 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3181 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3183 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3184 TCP(sport=1234, dport=1234))
3185 self.pg1.add_stream(p)
3186 self.pg_enable_capture(self.pg_interfaces)
3188 p = self.pg0.get_capture(1)
3191 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3192 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3193 self.assertEqual(packet.haslayer(GRE), 1)
3194 self.assert_packet_checksums_valid(packet)
3196 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3199 def test_hairpinning_static_unknown_proto(self):
3200 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3202 host = self.pg0.remote_hosts[0]
3203 server = self.pg0.remote_hosts[1]
3205 host_nat_ip = "10.0.0.10"
3206 server_nat_ip = "10.0.0.11"
3208 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3209 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3210 flags = self.config_flags.NAT_IS_INSIDE
3211 self.vapi.nat44_interface_add_del_feature(
3212 sw_if_index=self.pg0.sw_if_index,
3213 flags=flags, is_add=1)
3214 self.vapi.nat44_interface_add_del_feature(
3215 sw_if_index=self.pg1.sw_if_index,
3219 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3220 IP(src=host.ip4, dst=server_nat_ip) /
3222 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3223 TCP(sport=1234, dport=1234))
3224 self.pg0.add_stream(p)
3225 self.pg_enable_capture(self.pg_interfaces)
3227 p = self.pg0.get_capture(1)
3230 self.assertEqual(packet[IP].src, host_nat_ip)
3231 self.assertEqual(packet[IP].dst, server.ip4)
3232 self.assertEqual(packet.haslayer(GRE), 1)
3233 self.assert_packet_checksums_valid(packet)
3235 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3239 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3240 IP(src=server.ip4, dst=host_nat_ip) /
3242 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3243 TCP(sport=1234, dport=1234))
3244 self.pg0.add_stream(p)
3245 self.pg_enable_capture(self.pg_interfaces)
3247 p = self.pg0.get_capture(1)
3250 self.assertEqual(packet[IP].src, server_nat_ip)
3251 self.assertEqual(packet[IP].dst, host.ip4)
3252 self.assertEqual(packet.haslayer(GRE), 1)
3253 self.assert_packet_checksums_valid(packet)
3255 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3258 def test_output_feature(self):
3259 """ NAT44 interface output feature (in2out postrouting) """
3260 self.nat44_add_address(self.nat_addr)
3261 flags = self.config_flags.NAT_IS_INSIDE
3262 self.vapi.nat44_interface_add_del_output_feature(
3263 is_add=1, flags=flags,
3264 sw_if_index=self.pg0.sw_if_index)
3265 self.vapi.nat44_interface_add_del_output_feature(
3266 is_add=1, flags=flags,
3267 sw_if_index=self.pg1.sw_if_index)
3268 self.vapi.nat44_interface_add_del_output_feature(
3270 sw_if_index=self.pg3.sw_if_index)
3273 pkts = self.create_stream_in(self.pg0, self.pg3)
3274 self.pg0.add_stream(pkts)
3275 self.pg_enable_capture(self.pg_interfaces)
3277 capture = self.pg3.get_capture(len(pkts))
3278 self.verify_capture_out(capture)
3281 pkts = self.create_stream_out(self.pg3)
3282 self.pg3.add_stream(pkts)
3283 self.pg_enable_capture(self.pg_interfaces)
3285 capture = self.pg0.get_capture(len(pkts))
3286 self.verify_capture_in(capture, self.pg0)
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)
3293 capture = self.pg0.get_capture(len(pkts))
3294 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
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"
3301 r1 = VppIpRoute(self, self.pg3.remote_ip4, 32,
3302 [VppRoutePath(self.pg3.remote_ip4,
3303 self.pg3.sw_if_index)],
3305 r2 = VppIpRoute(self, self.pg3.remote_ip4, 32,
3306 [VppRoutePath(self.pg3.remote_ip4,
3307 self.pg3.sw_if_index)],
3312 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3313 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3314 flags = self.config_flags.NAT_IS_INSIDE
3315 self.vapi.nat44_interface_add_del_output_feature(
3316 is_add=1, flags=flags,
3317 sw_if_index=self.pg4.sw_if_index)
3318 self.vapi.nat44_interface_add_del_output_feature(
3319 is_add=1, flags=flags,
3320 sw_if_index=self.pg6.sw_if_index)
3321 self.vapi.nat44_interface_add_del_output_feature(
3323 sw_if_index=self.pg3.sw_if_index)
3326 pkts = self.create_stream_in(self.pg4, self.pg3)
3327 self.pg4.add_stream(pkts)
3328 self.pg_enable_capture(self.pg_interfaces)
3330 capture = self.pg3.get_capture(len(pkts))
3331 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3334 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3335 self.pg3.add_stream(pkts)
3336 self.pg_enable_capture(self.pg_interfaces)
3338 capture = self.pg4.get_capture(len(pkts))
3339 self.verify_capture_in(capture, self.pg4)
3342 pkts = self.create_stream_in(self.pg6, self.pg3)
3343 self.pg6.add_stream(pkts)
3344 self.pg_enable_capture(self.pg_interfaces)
3346 capture = self.pg3.get_capture(len(pkts))
3347 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3350 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3351 self.pg3.add_stream(pkts)
3352 self.pg_enable_capture(self.pg_interfaces)
3354 capture = self.pg6.get_capture(len(pkts))
3355 self.verify_capture_in(capture, self.pg6)
3357 def test_output_feature_hairpinning(self):
3358 """ NAT44 interface output feature hairpinning (in2out postrouting) """
3359 host = self.pg0.remote_hosts[0]
3360 server = self.pg0.remote_hosts[1]
3363 server_in_port = 5678
3364 server_out_port = 8765
3366 self.nat44_add_address(self.nat_addr)
3367 flags = self.config_flags.NAT_IS_INSIDE
3368 self.vapi.nat44_interface_add_del_output_feature(
3369 is_add=1, flags=flags,
3370 sw_if_index=self.pg0.sw_if_index)
3371 self.vapi.nat44_interface_add_del_output_feature(
3373 sw_if_index=self.pg1.sw_if_index)
3375 # add static mapping for server
3376 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3377 server_in_port, server_out_port,
3378 proto=IP_PROTOS.tcp)
3380 # send packet from host to server
3381 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3382 IP(src=host.ip4, dst=self.nat_addr) /
3383 TCP(sport=host_in_port, dport=server_out_port))
3384 self.pg0.add_stream(p)
3385 self.pg_enable_capture(self.pg_interfaces)
3387 capture = self.pg0.get_capture(1)
3392 self.assertEqual(ip.src, self.nat_addr)
3393 self.assertEqual(ip.dst, server.ip4)
3394 self.assertNotEqual(tcp.sport, host_in_port)
3395 self.assertEqual(tcp.dport, server_in_port)
3396 self.assert_packet_checksums_valid(p)
3397 host_out_port = tcp.sport
3399 self.logger.error(ppp("Unexpected or invalid packet:", p))
3402 # send reply from server to host
3403 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3404 IP(src=server.ip4, dst=self.nat_addr) /
3405 TCP(sport=server_in_port, dport=host_out_port))
3406 self.pg0.add_stream(p)
3407 self.pg_enable_capture(self.pg_interfaces)
3409 capture = self.pg0.get_capture(1)
3414 self.assertEqual(ip.src, self.nat_addr)
3415 self.assertEqual(ip.dst, host.ip4)
3416 self.assertEqual(tcp.sport, server_out_port)
3417 self.assertEqual(tcp.dport, host_in_port)
3418 self.assert_packet_checksums_valid(p)
3420 self.logger.error(ppp("Unexpected or invalid packet:", p))
3423 def test_one_armed_nat44(self):
3424 """ One armed NAT44 """
3425 remote_host = self.pg9.remote_hosts[0]
3426 local_host = self.pg9.remote_hosts[1]
3429 self.nat44_add_address(self.nat_addr)
3430 flags = self.config_flags.NAT_IS_INSIDE
3431 self.vapi.nat44_interface_add_del_feature(
3432 sw_if_index=self.pg9.sw_if_index,
3434 self.vapi.nat44_interface_add_del_feature(
3435 sw_if_index=self.pg9.sw_if_index,
3436 flags=flags, is_add=1)
3439 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3440 IP(src=local_host.ip4, dst=remote_host.ip4) /
3441 TCP(sport=12345, dport=80))
3442 self.pg9.add_stream(p)
3443 self.pg_enable_capture(self.pg_interfaces)
3445 capture = self.pg9.get_capture(1)
3450 self.assertEqual(ip.src, self.nat_addr)
3451 self.assertEqual(ip.dst, remote_host.ip4)
3452 self.assertNotEqual(tcp.sport, 12345)
3453 external_port = tcp.sport
3454 self.assertEqual(tcp.dport, 80)
3455 self.assert_packet_checksums_valid(p)
3457 self.logger.error(ppp("Unexpected or invalid packet:", p))
3461 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3462 IP(src=remote_host.ip4, dst=self.nat_addr) /
3463 TCP(sport=80, dport=external_port))
3464 self.pg9.add_stream(p)
3465 self.pg_enable_capture(self.pg_interfaces)
3467 capture = self.pg9.get_capture(1)
3472 self.assertEqual(ip.src, remote_host.ip4)
3473 self.assertEqual(ip.dst, local_host.ip4)
3474 self.assertEqual(tcp.sport, 80)
3475 self.assertEqual(tcp.dport, 12345)
3476 self.assert_packet_checksums_valid(p)
3478 self.logger.error(ppp("Unexpected or invalid packet:", p))
3481 err = self.statistics.get_err_counter(
3482 '/err/nat44-classify/next in2out')
3483 self.assertEqual(err, 1)
3484 err = self.statistics.get_err_counter(
3485 '/err/nat44-classify/next out2in')
3486 self.assertEqual(err, 1)
3488 def test_del_session(self):
3489 """ Delete NAT44 session """
3490 self.nat44_add_address(self.nat_addr)
3491 flags = self.config_flags.NAT_IS_INSIDE
3492 self.vapi.nat44_interface_add_del_feature(
3493 sw_if_index=self.pg0.sw_if_index,
3494 flags=flags, is_add=1)
3495 self.vapi.nat44_interface_add_del_feature(
3496 sw_if_index=self.pg1.sw_if_index,
3499 pkts = self.create_stream_in(self.pg0, self.pg1)
3500 self.pg0.add_stream(pkts)
3501 self.pg_enable_capture(self.pg_interfaces)
3503 self.pg1.get_capture(len(pkts))
3505 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3506 nsessions = len(sessions)
3508 self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3509 port=sessions[0].inside_port,
3510 protocol=sessions[0].protocol,
3511 flags=self.config_flags.NAT_IS_INSIDE)
3512 self.vapi.nat44_del_session(address=sessions[1].outside_ip_address,
3513 port=sessions[1].outside_port,
3514 protocol=sessions[1].protocol)
3516 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3517 self.assertEqual(nsessions - len(sessions), 2)
3519 self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3520 port=sessions[0].inside_port,
3521 protocol=sessions[0].protocol,
3522 flags=self.config_flags.NAT_IS_INSIDE)
3524 self.verify_no_nat44_user()
3526 def test_frag_in_order(self):
3527 """ NAT44 translate fragments arriving in order """
3529 self.nat44_add_address(self.nat_addr)
3530 flags = self.config_flags.NAT_IS_INSIDE
3531 self.vapi.nat44_interface_add_del_feature(
3532 sw_if_index=self.pg0.sw_if_index,
3533 flags=flags, is_add=1)
3534 self.vapi.nat44_interface_add_del_feature(
3535 sw_if_index=self.pg1.sw_if_index,
3538 self.frag_in_order(proto=IP_PROTOS.tcp)
3539 self.frag_in_order(proto=IP_PROTOS.udp)
3540 self.frag_in_order(proto=IP_PROTOS.icmp)
3542 def test_frag_forwarding(self):
3543 """ NAT44 forwarding fragment test """
3544 self.vapi.nat44_add_del_interface_addr(
3546 sw_if_index=self.pg1.sw_if_index)
3547 flags = self.config_flags.NAT_IS_INSIDE
3548 self.vapi.nat44_interface_add_del_feature(
3549 sw_if_index=self.pg0.sw_if_index,
3550 flags=flags, is_add=1)
3551 self.vapi.nat44_interface_add_del_feature(
3552 sw_if_index=self.pg1.sw_if_index,
3554 self.vapi.nat44_forwarding_enable_disable(enable=1)
3556 data = b"A" * 16 + b"B" * 16 + b"C" * 3
3557 pkts = self.create_stream_frag(self.pg1,
3558 self.pg0.remote_ip4,
3562 proto=IP_PROTOS.udp)
3563 self.pg1.add_stream(pkts)
3564 self.pg_enable_capture(self.pg_interfaces)
3566 frags = self.pg0.get_capture(len(pkts))
3567 p = self.reass_frags_and_verify(frags,
3568 self.pg1.remote_ip4,
3569 self.pg0.remote_ip4)
3570 self.assertEqual(p[UDP].sport, 4789)
3571 self.assertEqual(p[UDP].dport, 4789)
3572 self.assertEqual(data, p[Raw].load)
3574 def test_reass_hairpinning(self):
3575 """ NAT44 fragments hairpinning """
3577 self.server = self.pg0.remote_hosts[1]
3578 self.host_in_port = random.randint(1025, 65535)
3579 self.server_in_port = random.randint(1025, 65535)
3580 self.server_out_port = random.randint(1025, 65535)
3582 self.nat44_add_address(self.nat_addr)
3583 flags = self.config_flags.NAT_IS_INSIDE
3584 self.vapi.nat44_interface_add_del_feature(
3585 sw_if_index=self.pg0.sw_if_index,
3586 flags=flags, is_add=1)
3587 self.vapi.nat44_interface_add_del_feature(
3588 sw_if_index=self.pg1.sw_if_index,
3590 # add static mapping for server
3591 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3592 self.server_in_port,
3593 self.server_out_port,
3594 proto=IP_PROTOS.tcp)
3595 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3596 self.server_in_port,
3597 self.server_out_port,
3598 proto=IP_PROTOS.udp)
3599 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
3601 self.reass_hairpinning(proto=IP_PROTOS.tcp)
3602 self.reass_hairpinning(proto=IP_PROTOS.udp)
3603 self.reass_hairpinning(proto=IP_PROTOS.icmp)
3605 def test_frag_out_of_order(self):
3606 """ NAT44 translate fragments arriving out of order """
3608 self.nat44_add_address(self.nat_addr)
3609 flags = self.config_flags.NAT_IS_INSIDE
3610 self.vapi.nat44_interface_add_del_feature(
3611 sw_if_index=self.pg0.sw_if_index,
3612 flags=flags, is_add=1)
3613 self.vapi.nat44_interface_add_del_feature(
3614 sw_if_index=self.pg1.sw_if_index,
3617 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3618 self.frag_out_of_order(proto=IP_PROTOS.udp)
3619 self.frag_out_of_order(proto=IP_PROTOS.icmp)
3621 def test_port_restricted(self):
3622 """ Port restricted NAT44 (MAP-E CE) """
3623 self.nat44_add_address(self.nat_addr)
3624 flags = self.config_flags.NAT_IS_INSIDE
3625 self.vapi.nat44_interface_add_del_feature(
3626 sw_if_index=self.pg0.sw_if_index,
3627 flags=flags, is_add=1)
3628 self.vapi.nat44_interface_add_del_feature(
3629 sw_if_index=self.pg1.sw_if_index,
3631 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3636 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3637 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3638 TCP(sport=4567, dport=22))
3639 self.pg0.add_stream(p)
3640 self.pg_enable_capture(self.pg_interfaces)
3642 capture = self.pg1.get_capture(1)
3647 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3648 self.assertEqual(ip.src, self.nat_addr)
3649 self.assertEqual(tcp.dport, 22)
3650 self.assertNotEqual(tcp.sport, 4567)
3651 self.assertEqual((tcp.sport >> 6) & 63, 10)
3652 self.assert_packet_checksums_valid(p)
3654 self.logger.error(ppp("Unexpected or invalid packet:", p))
3657 def test_port_range(self):
3658 """ External address port range """
3659 self.nat44_add_address(self.nat_addr)
3660 flags = self.config_flags.NAT_IS_INSIDE
3661 self.vapi.nat44_interface_add_del_feature(
3662 sw_if_index=self.pg0.sw_if_index,
3663 flags=flags, is_add=1)
3664 self.vapi.nat44_interface_add_del_feature(
3665 sw_if_index=self.pg1.sw_if_index,
3667 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3672 for port in range(0, 5):
3673 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3674 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3675 TCP(sport=1125 + port))
3677 self.pg0.add_stream(pkts)
3678 self.pg_enable_capture(self.pg_interfaces)
3680 capture = self.pg1.get_capture(3)
3683 self.assertGreaterEqual(tcp.sport, 1025)
3684 self.assertLessEqual(tcp.sport, 1027)
3686 def test_multiple_outside_vrf(self):
3687 """ Multiple outside VRF """
3691 self.pg1.unconfig_ip4()
3692 self.pg2.unconfig_ip4()
3693 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
3694 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
3695 self.pg1.set_table_ip4(vrf_id1)
3696 self.pg2.set_table_ip4(vrf_id2)
3697 self.pg1.config_ip4()
3698 self.pg2.config_ip4()
3699 self.pg1.resolve_arp()
3700 self.pg2.resolve_arp()
3702 self.nat44_add_address(self.nat_addr)
3703 flags = self.config_flags.NAT_IS_INSIDE
3704 self.vapi.nat44_interface_add_del_feature(
3705 sw_if_index=self.pg0.sw_if_index,
3706 flags=flags, is_add=1)
3707 self.vapi.nat44_interface_add_del_feature(
3708 sw_if_index=self.pg1.sw_if_index,
3710 self.vapi.nat44_interface_add_del_feature(
3711 sw_if_index=self.pg2.sw_if_index,
3716 pkts = self.create_stream_in(self.pg0, self.pg1)
3717 self.pg0.add_stream(pkts)
3718 self.pg_enable_capture(self.pg_interfaces)
3720 capture = self.pg1.get_capture(len(pkts))
3721 self.verify_capture_out(capture, self.nat_addr)
3723 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3724 self.pg1.add_stream(pkts)
3725 self.pg_enable_capture(self.pg_interfaces)
3727 capture = self.pg0.get_capture(len(pkts))
3728 self.verify_capture_in(capture, self.pg0)
3730 self.tcp_port_in = 60303
3731 self.udp_port_in = 60304
3732 self.icmp_id_in = 60305
3735 pkts = self.create_stream_in(self.pg0, self.pg2)
3736 self.pg0.add_stream(pkts)
3737 self.pg_enable_capture(self.pg_interfaces)
3739 capture = self.pg2.get_capture(len(pkts))
3740 self.verify_capture_out(capture, self.nat_addr)
3742 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3743 self.pg2.add_stream(pkts)
3744 self.pg_enable_capture(self.pg_interfaces)
3746 capture = self.pg0.get_capture(len(pkts))
3747 self.verify_capture_in(capture, self.pg0)
3750 self.nat44_add_address(self.nat_addr, is_add=0)
3751 self.pg1.unconfig_ip4()
3752 self.pg2.unconfig_ip4()
3753 self.pg1.set_table_ip4(0)
3754 self.pg2.set_table_ip4(0)
3755 self.pg1.config_ip4()
3756 self.pg2.config_ip4()
3757 self.pg1.resolve_arp()
3758 self.pg2.resolve_arp()
3760 @unittest.skipUnless(running_extended_tests, "part of extended tests")
3761 def test_session_timeout(self):
3762 """ NAT44 session timeouts """
3763 self.nat44_add_address(self.nat_addr)
3764 flags = self.config_flags.NAT_IS_INSIDE
3765 self.vapi.nat44_interface_add_del_feature(
3766 sw_if_index=self.pg0.sw_if_index,
3767 flags=flags, is_add=1)
3768 self.vapi.nat44_interface_add_del_feature(
3769 sw_if_index=self.pg1.sw_if_index,
3771 self.vapi.nat_set_timeouts(udp=5, tcp_established=7440,
3772 tcp_transitory=240, icmp=60)
3776 for i in range(0, max_sessions):
3777 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3778 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3779 IP(src=src, dst=self.pg1.remote_ip4) /
3780 UDP(sport=1025, dport=53))
3782 self.pg0.add_stream(pkts)
3783 self.pg_enable_capture(self.pg_interfaces)
3785 self.pg1.get_capture(max_sessions)
3790 for i in range(0, max_sessions):
3791 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3792 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3793 IP(src=src, dst=self.pg1.remote_ip4) /
3794 UDP(sport=1026, dport=53))
3796 self.pg0.add_stream(pkts)
3797 self.pg_enable_capture(self.pg_interfaces)
3799 self.pg1.get_capture(max_sessions)
3802 users = self.vapi.nat44_user_dump()
3804 nsessions = nsessions + user.nsessions
3805 self.assertLess(nsessions, 2 * max_sessions)
3807 def test_mss_clamping(self):
3808 """ TCP MSS clamping """
3809 self.nat44_add_address(self.nat_addr)
3810 flags = self.config_flags.NAT_IS_INSIDE
3811 self.vapi.nat44_interface_add_del_feature(
3812 sw_if_index=self.pg0.sw_if_index,
3813 flags=flags, is_add=1)
3814 self.vapi.nat44_interface_add_del_feature(
3815 sw_if_index=self.pg1.sw_if_index,
3818 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3819 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3820 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3821 flags="S", options=[('MSS', 1400)]))
3823 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3824 self.pg0.add_stream(p)
3825 self.pg_enable_capture(self.pg_interfaces)
3827 capture = self.pg1.get_capture(1)
3828 # Negotiated MSS value greater than configured - changed
3829 self.verify_mss_value(capture[0], 1000)
3831 self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
3832 self.pg0.add_stream(p)
3833 self.pg_enable_capture(self.pg_interfaces)
3835 capture = self.pg1.get_capture(1)
3836 # MSS clamping disabled - negotiated MSS unchanged
3837 self.verify_mss_value(capture[0], 1400)
3839 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3840 self.pg0.add_stream(p)
3841 self.pg_enable_capture(self.pg_interfaces)
3843 capture = self.pg1.get_capture(1)
3844 # Negotiated MSS value smaller than configured - unchanged
3845 self.verify_mss_value(capture[0], 1400)
3847 @unittest.skipUnless(running_extended_tests, "part of extended tests")
3848 def test_ha_send(self):
3849 """ Send HA session synchronization events (active) """
3850 self.nat44_add_address(self.nat_addr)
3851 flags = self.config_flags.NAT_IS_INSIDE
3852 self.vapi.nat44_interface_add_del_feature(
3853 sw_if_index=self.pg0.sw_if_index,
3854 flags=flags, is_add=1)
3855 self.vapi.nat44_interface_add_del_feature(
3856 sw_if_index=self.pg1.sw_if_index,
3858 self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
3861 self.vapi.nat_ha_set_failover(ip_address=self.pg3.remote_ip4,
3862 port=12346, session_refresh_interval=10)
3863 bind_layers(UDP, HANATStateSync, sport=12345)
3866 pkts = self.create_stream_in(self.pg0, self.pg1)
3867 self.pg0.add_stream(pkts)
3868 self.pg_enable_capture(self.pg_interfaces)
3870 capture = self.pg1.get_capture(len(pkts))
3871 self.verify_capture_out(capture)
3872 # active send HA events
3873 self.vapi.nat_ha_flush()
3874 stats = self.statistics.get_counter('/nat44/ha/add-event-send')
3875 self.assertEqual(stats[0][0], 3)
3876 capture = self.pg3.get_capture(1)
3878 self.assert_packet_checksums_valid(p)
3882 hanat = p[HANATStateSync]
3884 self.logger.error(ppp("Invalid packet:", p))
3887 self.assertEqual(ip.src, self.pg3.local_ip4)
3888 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3889 self.assertEqual(udp.sport, 12345)
3890 self.assertEqual(udp.dport, 12346)
3891 self.assertEqual(hanat.version, 1)
3892 self.assertEqual(hanat.thread_index, 0)
3893 self.assertEqual(hanat.count, 3)
3894 seq = hanat.sequence_number
3895 for event in hanat.events:
3896 self.assertEqual(event.event_type, 1)
3897 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
3898 self.assertEqual(event.out_addr, self.nat_addr)
3899 self.assertEqual(event.fib_index, 0)
3901 # ACK received events
3902 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3903 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3904 UDP(sport=12346, dport=12345) /
3905 HANATStateSync(sequence_number=seq, flags='ACK'))
3906 self.pg3.add_stream(ack)
3908 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3909 self.assertEqual(stats[0][0], 1)
3911 # delete one session
3912 self.pg_enable_capture(self.pg_interfaces)
3913 self.vapi.nat44_del_session(address=self.pg0.remote_ip4,
3914 port=self.tcp_port_in,
3915 protocol=IP_PROTOS.tcp,
3916 flags=self.config_flags.NAT_IS_INSIDE)
3917 self.vapi.nat_ha_flush()
3918 stats = self.statistics.get_counter('/nat44/ha/del-event-send')
3919 self.assertEqual(stats[0][0], 1)
3920 capture = self.pg3.get_capture(1)
3923 hanat = p[HANATStateSync]
3925 self.logger.error(ppp("Invalid packet:", p))
3928 self.assertGreater(hanat.sequence_number, seq)
3930 # do not send ACK, active retry send HA event again
3931 self.pg_enable_capture(self.pg_interfaces)
3933 stats = self.statistics.get_counter('/nat44/ha/retry-count')
3934 self.assertEqual(stats[0][0], 3)
3935 stats = self.statistics.get_counter('/nat44/ha/missed-count')
3936 self.assertEqual(stats[0][0], 1)
3937 capture = self.pg3.get_capture(3)
3938 for packet in capture:
3939 self.assertEqual(packet, p)
3941 # session counters refresh
3942 pkts = self.create_stream_out(self.pg1)
3943 self.pg1.add_stream(pkts)
3944 self.pg_enable_capture(self.pg_interfaces)
3946 self.pg0.get_capture(2)
3947 self.vapi.nat_ha_flush()
3948 stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
3949 self.assertEqual(stats[0][0], 2)
3950 capture = self.pg3.get_capture(1)
3952 self.assert_packet_checksums_valid(p)
3956 hanat = p[HANATStateSync]
3958 self.logger.error(ppp("Invalid packet:", p))
3961 self.assertEqual(ip.src, self.pg3.local_ip4)
3962 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3963 self.assertEqual(udp.sport, 12345)
3964 self.assertEqual(udp.dport, 12346)
3965 self.assertEqual(hanat.version, 1)
3966 self.assertEqual(hanat.count, 2)
3967 seq = hanat.sequence_number
3968 for event in hanat.events:
3969 self.assertEqual(event.event_type, 3)
3970 self.assertEqual(event.out_addr, self.nat_addr)
3971 self.assertEqual(event.fib_index, 0)
3972 self.assertEqual(event.total_pkts, 2)
3973 self.assertGreater(event.total_bytes, 0)
3975 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3976 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3977 UDP(sport=12346, dport=12345) /
3978 HANATStateSync(sequence_number=seq, flags='ACK'))
3979 self.pg3.add_stream(ack)
3981 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3982 self.assertEqual(stats[0][0], 2)
3984 def test_ha_recv(self):
3985 """ Receive HA session synchronization events (passive) """
3986 self.nat44_add_address(self.nat_addr)
3987 flags = self.config_flags.NAT_IS_INSIDE
3988 self.vapi.nat44_interface_add_del_feature(
3989 sw_if_index=self.pg0.sw_if_index,
3990 flags=flags, is_add=1)
3991 self.vapi.nat44_interface_add_del_feature(
3992 sw_if_index=self.pg1.sw_if_index,
3994 self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
3997 bind_layers(UDP, HANATStateSync, sport=12345)
3999 self.tcp_port_out = random.randint(1025, 65535)
4000 self.udp_port_out = random.randint(1025, 65535)
4002 # send HA session add events to failover/passive
4003 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4004 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4005 UDP(sport=12346, dport=12345) /
4006 HANATStateSync(sequence_number=1, events=[
4007 Event(event_type='add', protocol='tcp',
4008 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4009 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4010 eh_addr=self.pg1.remote_ip4,
4011 ehn_addr=self.pg1.remote_ip4,
4012 eh_port=self.tcp_external_port,
4013 ehn_port=self.tcp_external_port, fib_index=0),
4014 Event(event_type='add', protocol='udp',
4015 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4016 in_port=self.udp_port_in, out_port=self.udp_port_out,
4017 eh_addr=self.pg1.remote_ip4,
4018 ehn_addr=self.pg1.remote_ip4,
4019 eh_port=self.udp_external_port,
4020 ehn_port=self.udp_external_port, fib_index=0)]))
4022 self.pg3.add_stream(p)
4023 self.pg_enable_capture(self.pg_interfaces)
4026 capture = self.pg3.get_capture(1)
4029 hanat = p[HANATStateSync]
4031 self.logger.error(ppp("Invalid packet:", p))
4034 self.assertEqual(hanat.sequence_number, 1)
4035 self.assertEqual(hanat.flags, 'ACK')
4036 self.assertEqual(hanat.version, 1)
4037 self.assertEqual(hanat.thread_index, 0)
4038 stats = self.statistics.get_counter('/nat44/ha/ack-send')
4039 self.assertEqual(stats[0][0], 1)
4040 stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
4041 self.assertEqual(stats[0][0], 2)
4042 users = self.statistics.get_counter('/nat44/total-users')
4043 self.assertEqual(users[0][0], 1)
4044 sessions = self.statistics.get_counter('/nat44/total-sessions')
4045 self.assertEqual(sessions[0][0], 2)
4046 users = self.vapi.nat44_user_dump()
4047 self.assertEqual(len(users), 1)
4048 self.assertEqual(str(users[0].ip_address),
4049 self.pg0.remote_ip4)
4050 # there should be 2 sessions created by HA
4051 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4053 self.assertEqual(len(sessions), 2)
4054 for session in sessions:
4055 self.assertEqual(str(session.inside_ip_address),
4056 self.pg0.remote_ip4)
4057 self.assertEqual(str(session.outside_ip_address),
4059 self.assertIn(session.inside_port,
4060 [self.tcp_port_in, self.udp_port_in])
4061 self.assertIn(session.outside_port,
4062 [self.tcp_port_out, self.udp_port_out])
4063 self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
4065 # send HA session delete event to failover/passive
4066 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4067 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4068 UDP(sport=12346, dport=12345) /
4069 HANATStateSync(sequence_number=2, events=[
4070 Event(event_type='del', protocol='udp',
4071 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4072 in_port=self.udp_port_in, out_port=self.udp_port_out,
4073 eh_addr=self.pg1.remote_ip4,
4074 ehn_addr=self.pg1.remote_ip4,
4075 eh_port=self.udp_external_port,
4076 ehn_port=self.udp_external_port, fib_index=0)]))
4078 self.pg3.add_stream(p)
4079 self.pg_enable_capture(self.pg_interfaces)
4082 capture = self.pg3.get_capture(1)
4085 hanat = p[HANATStateSync]
4087 self.logger.error(ppp("Invalid packet:", p))
4090 self.assertEqual(hanat.sequence_number, 2)
4091 self.assertEqual(hanat.flags, 'ACK')
4092 self.assertEqual(hanat.version, 1)
4093 users = self.vapi.nat44_user_dump()
4094 self.assertEqual(len(users), 1)
4095 self.assertEqual(str(users[0].ip_address),
4096 self.pg0.remote_ip4)
4097 # now we should have only 1 session, 1 deleted by HA
4098 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4100 self.assertEqual(len(sessions), 1)
4101 stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
4102 self.assertEqual(stats[0][0], 1)
4104 stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
4105 self.assertEqual(stats, 2)
4107 # send HA session refresh event to failover/passive
4108 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4109 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4110 UDP(sport=12346, dport=12345) /
4111 HANATStateSync(sequence_number=3, events=[
4112 Event(event_type='refresh', protocol='tcp',
4113 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4114 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4115 eh_addr=self.pg1.remote_ip4,
4116 ehn_addr=self.pg1.remote_ip4,
4117 eh_port=self.tcp_external_port,
4118 ehn_port=self.tcp_external_port, fib_index=0,
4119 total_bytes=1024, total_pkts=2)]))
4120 self.pg3.add_stream(p)
4121 self.pg_enable_capture(self.pg_interfaces)
4124 capture = self.pg3.get_capture(1)
4127 hanat = p[HANATStateSync]
4129 self.logger.error(ppp("Invalid packet:", p))
4132 self.assertEqual(hanat.sequence_number, 3)
4133 self.assertEqual(hanat.flags, 'ACK')
4134 self.assertEqual(hanat.version, 1)
4135 users = self.vapi.nat44_user_dump()
4136 self.assertEqual(len(users), 1)
4137 self.assertEqual(str(users[0].ip_address),
4138 self.pg0.remote_ip4)
4139 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4141 self.assertEqual(len(sessions), 1)
4142 session = sessions[0]
4143 self.assertEqual(session.total_bytes, 1024)
4144 self.assertEqual(session.total_pkts, 2)
4145 stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
4146 self.assertEqual(stats[0][0], 1)
4148 stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
4149 self.assertEqual(stats, 3)
4151 # send packet to test session created by HA
4152 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4153 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4154 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
4155 self.pg1.add_stream(p)
4156 self.pg_enable_capture(self.pg_interfaces)
4158 capture = self.pg0.get_capture(1)
4164 self.logger.error(ppp("Invalid packet:", p))
4167 self.assertEqual(ip.src, self.pg1.remote_ip4)
4168 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4169 self.assertEqual(tcp.sport, self.tcp_external_port)
4170 self.assertEqual(tcp.dport, self.tcp_port_in)
4173 super(TestNAT44, self).tearDown()
4175 self.vapi.cli("clear logging")
4177 def show_commands_at_teardown(self):
4178 self.logger.info(self.vapi.cli("show nat44 addresses"))
4179 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4180 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4181 self.logger.info(self.vapi.cli("show nat44 interface address"))
4182 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
4183 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
4184 self.logger.info(self.vapi.cli("show nat timeouts"))
4186 self.vapi.cli("show nat addr-port-assignment-alg"))
4187 self.logger.info(self.vapi.cli("show nat ha"))
4190 class TestNAT44EndpointDependent(MethodHolder):
4191 """ Endpoint-Dependent mapping and filtering test cases """
4194 def setUpConstants(cls):
4195 super(TestNAT44EndpointDependent, cls).setUpConstants()
4196 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4199 def setUpClass(cls):
4200 super(TestNAT44EndpointDependent, cls).setUpClass()
4201 cls.vapi.cli("set log class nat level debug")
4203 cls.tcp_port_in = 6303
4204 cls.tcp_port_out = 6303
4205 cls.udp_port_in = 6304
4206 cls.udp_port_out = 6304
4207 cls.icmp_id_in = 6305
4208 cls.icmp_id_out = 6305
4209 cls.nat_addr = '10.0.0.3'
4210 cls.ipfix_src_port = 4739
4211 cls.ipfix_domain_id = 1
4212 cls.tcp_external_port = 80
4214 cls.create_pg_interfaces(range(9))
4215 cls.interfaces = list(cls.pg_interfaces[0:3])
4217 for i in cls.interfaces:
4222 cls.pg0.generate_remote_hosts(3)
4223 cls.pg0.configure_ipv4_neighbors()
4227 cls.pg4.generate_remote_hosts(2)
4228 cls.pg4.config_ip4()
4229 cls.vapi.sw_interface_add_del_address(
4230 sw_if_index=cls.pg4.sw_if_index,
4231 prefix="10.0.0.1/24")
4234 cls.pg4.resolve_arp()
4235 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4236 cls.pg4.resolve_arp()
4238 zero_ip4 = socket.inet_pton(socket.AF_INET, "0.0.0.0")
4239 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 1})
4241 cls.pg5._local_ip4 = "10.1.1.1"
4242 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4243 cls.pg5.set_table_ip4(1)
4244 cls.pg5.config_ip4()
4246 r1 = VppIpRoute(cls, cls.pg5.remote_ip4, 32,
4247 [VppRoutePath("0.0.0.0",
4248 cls.pg5.sw_if_index)],
4253 cls.pg6._local_ip4 = "10.1.2.1"
4254 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4255 cls.pg6.set_table_ip4(1)
4256 cls.pg6.config_ip4()
4259 r2 = VppIpRoute(cls, cls.pg6.remote_ip4, 32,
4260 [VppRoutePath("0.0.0.0",
4261 cls.pg6.sw_if_index)],
4264 r3 = VppIpRoute(cls, cls.pg6.remote_ip4, 16,
4265 [VppRoutePath("0.0.0.0",
4270 r4 = VppIpRoute(cls, "0.0.0.0", 0,
4271 [VppRoutePath("0.0.0.0", 0xffffffff,
4275 r5 = VppIpRoute(cls, "0.0.0.0", 0,
4276 [VppRoutePath(cls.pg1.local_ip4,
4277 cls.pg1.sw_if_index)],
4284 cls.pg5.resolve_arp()
4285 cls.pg6.resolve_arp()
4288 cls.pg7.config_ip4()
4289 cls.pg7.resolve_arp()
4290 cls.pg7.generate_remote_hosts(3)
4291 cls.pg7.configure_ipv4_neighbors()
4294 cls.pg8.config_ip4()
4295 cls.pg8.resolve_arp()
4298 super(TestNAT44EndpointDependent, self).setUp()
4299 self.vapi.nat_set_timeouts(
4300 udp=300, tcp_established=7440, tcp_transitory=240, icmp=60)
4303 def tearDownClass(cls):
4304 super(TestNAT44EndpointDependent, cls).tearDownClass()
4306 def test_frag_in_order(self):
4307 """ NAT44 translate fragments arriving in order """
4308 self.nat44_add_address(self.nat_addr)
4309 flags = self.config_flags.NAT_IS_INSIDE
4310 self.vapi.nat44_interface_add_del_feature(
4311 sw_if_index=self.pg0.sw_if_index,
4312 flags=flags, is_add=1)
4313 self.vapi.nat44_interface_add_del_feature(
4314 sw_if_index=self.pg1.sw_if_index,
4316 self.frag_in_order(proto=IP_PROTOS.tcp)
4317 self.frag_in_order(proto=IP_PROTOS.udp)
4318 self.frag_in_order(proto=IP_PROTOS.icmp)
4320 def test_frag_in_order_dont_translate(self):
4321 """ NAT44 don't translate fragments arriving in order """
4322 flags = self.config_flags.NAT_IS_INSIDE
4323 self.vapi.nat44_interface_add_del_feature(
4324 sw_if_index=self.pg0.sw_if_index,
4325 flags=flags, is_add=1)
4326 self.vapi.nat44_interface_add_del_feature(
4327 sw_if_index=self.pg1.sw_if_index,
4329 self.vapi.nat44_forwarding_enable_disable(enable=True)
4330 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4332 def test_frag_out_of_order(self):
4333 """ NAT44 translate fragments arriving out of order """
4334 self.nat44_add_address(self.nat_addr)
4335 flags = self.config_flags.NAT_IS_INSIDE
4336 self.vapi.nat44_interface_add_del_feature(
4337 sw_if_index=self.pg0.sw_if_index,
4338 flags=flags, is_add=1)
4339 self.vapi.nat44_interface_add_del_feature(
4340 sw_if_index=self.pg1.sw_if_index,
4342 self.frag_out_of_order(proto=IP_PROTOS.tcp)
4343 self.frag_out_of_order(proto=IP_PROTOS.udp)
4344 self.frag_out_of_order(proto=IP_PROTOS.icmp)
4346 def test_frag_out_of_order_dont_translate(self):
4347 """ NAT44 don't translate fragments arriving out of order """
4348 flags = self.config_flags.NAT_IS_INSIDE
4349 self.vapi.nat44_interface_add_del_feature(
4350 sw_if_index=self.pg0.sw_if_index,
4351 flags=flags, is_add=1)
4352 self.vapi.nat44_interface_add_del_feature(
4353 sw_if_index=self.pg1.sw_if_index,
4355 self.vapi.nat44_forwarding_enable_disable(enable=True)
4356 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4358 def test_frag_in_order_in_plus_out(self):
4359 """ in+out interface fragments in order """
4360 flags = self.config_flags.NAT_IS_INSIDE
4361 self.vapi.nat44_interface_add_del_feature(
4362 sw_if_index=self.pg0.sw_if_index,
4364 self.vapi.nat44_interface_add_del_feature(
4365 sw_if_index=self.pg0.sw_if_index,
4366 flags=flags, is_add=1)
4367 self.vapi.nat44_interface_add_del_feature(
4368 sw_if_index=self.pg1.sw_if_index,
4370 self.vapi.nat44_interface_add_del_feature(
4371 sw_if_index=self.pg1.sw_if_index,
4372 flags=flags, is_add=1)
4374 self.server = self.pg1.remote_hosts[0]
4376 self.server_in_addr = self.server.ip4
4377 self.server_out_addr = '11.11.11.11'
4378 self.server_in_port = random.randint(1025, 65535)
4379 self.server_out_port = random.randint(1025, 65535)
4381 self.nat44_add_address(self.server_out_addr)
4383 # add static mappings for server
4384 self.nat44_add_static_mapping(self.server_in_addr,
4385 self.server_out_addr,
4386 self.server_in_port,
4387 self.server_out_port,
4388 proto=IP_PROTOS.tcp)
4389 self.nat44_add_static_mapping(self.server_in_addr,
4390 self.server_out_addr,
4391 self.server_in_port,
4392 self.server_out_port,
4393 proto=IP_PROTOS.udp)
4394 self.nat44_add_static_mapping(self.server_in_addr,
4395 self.server_out_addr,
4396 proto=IP_PROTOS.icmp)
4398 self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4399 self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4400 self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4402 def test_frag_out_of_order_in_plus_out(self):
4403 """ in+out interface fragments out of order """
4404 flags = self.config_flags.NAT_IS_INSIDE
4405 self.vapi.nat44_interface_add_del_feature(
4406 sw_if_index=self.pg0.sw_if_index,
4408 self.vapi.nat44_interface_add_del_feature(
4409 sw_if_index=self.pg0.sw_if_index,
4410 flags=flags, is_add=1)
4411 self.vapi.nat44_interface_add_del_feature(
4412 sw_if_index=self.pg1.sw_if_index,
4414 self.vapi.nat44_interface_add_del_feature(
4415 sw_if_index=self.pg1.sw_if_index,
4416 flags=flags, is_add=1)
4418 self.server = self.pg1.remote_hosts[0]
4420 self.server_in_addr = self.server.ip4
4421 self.server_out_addr = '11.11.11.11'
4422 self.server_in_port = random.randint(1025, 65535)
4423 self.server_out_port = random.randint(1025, 65535)
4425 self.nat44_add_address(self.server_out_addr)
4427 # add static mappings for server
4428 self.nat44_add_static_mapping(self.server_in_addr,
4429 self.server_out_addr,
4430 self.server_in_port,
4431 self.server_out_port,
4432 proto=IP_PROTOS.tcp)
4433 self.nat44_add_static_mapping(self.server_in_addr,
4434 self.server_out_addr,
4435 self.server_in_port,
4436 self.server_out_port,
4437 proto=IP_PROTOS.udp)
4438 self.nat44_add_static_mapping(self.server_in_addr,
4439 self.server_out_addr,
4440 proto=IP_PROTOS.icmp)
4442 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4443 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4444 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4446 def test_reass_hairpinning(self):
4447 """ NAT44 fragments hairpinning """
4448 self.server = self.pg0.remote_hosts[1]
4449 self.host_in_port = random.randint(1025, 65535)
4450 self.server_in_port = random.randint(1025, 65535)
4451 self.server_out_port = random.randint(1025, 65535)
4453 self.nat44_add_address(self.nat_addr)
4454 flags = self.config_flags.NAT_IS_INSIDE
4455 self.vapi.nat44_interface_add_del_feature(
4456 sw_if_index=self.pg0.sw_if_index,
4457 flags=flags, is_add=1)
4458 self.vapi.nat44_interface_add_del_feature(
4459 sw_if_index=self.pg1.sw_if_index,
4461 # add static mapping for server
4462 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4463 self.server_in_port,
4464 self.server_out_port,
4465 proto=IP_PROTOS.tcp)
4466 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4467 self.server_in_port,
4468 self.server_out_port,
4469 proto=IP_PROTOS.udp)
4470 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
4472 self.reass_hairpinning(proto=IP_PROTOS.tcp)
4473 self.reass_hairpinning(proto=IP_PROTOS.udp)
4474 self.reass_hairpinning(proto=IP_PROTOS.icmp)
4476 def test_dynamic(self):
4477 """ NAT44 dynamic translation test """
4479 self.nat44_add_address(self.nat_addr)
4480 flags = self.config_flags.NAT_IS_INSIDE
4481 self.vapi.nat44_interface_add_del_feature(
4482 sw_if_index=self.pg0.sw_if_index,
4483 flags=flags, is_add=1)
4484 self.vapi.nat44_interface_add_del_feature(
4485 sw_if_index=self.pg1.sw_if_index,
4488 nat_config = self.vapi.nat_show_config()
4489 self.assertEqual(1, nat_config.endpoint_dependent)
4492 tcpn = self.statistics.get_err_counter(
4493 '/err/nat44-ed-in2out-slowpath/TCP packets')
4494 udpn = self.statistics.get_err_counter(
4495 '/err/nat44-ed-in2out-slowpath/UDP packets')
4496 icmpn = self.statistics.get_err_counter(
4497 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4498 totaln = self.statistics.get_err_counter(
4499 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4501 pkts = self.create_stream_in(self.pg0, self.pg1)
4502 self.pg0.add_stream(pkts)
4503 self.pg_enable_capture(self.pg_interfaces)
4505 capture = self.pg1.get_capture(len(pkts))
4506 self.verify_capture_out(capture)
4508 err = self.statistics.get_err_counter(
4509 '/err/nat44-ed-in2out-slowpath/TCP packets')
4510 self.assertEqual(err - tcpn, 2)
4511 err = self.statistics.get_err_counter(
4512 '/err/nat44-ed-in2out-slowpath/UDP packets')
4513 self.assertEqual(err - udpn, 1)
4514 err = self.statistics.get_err_counter(
4515 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4516 self.assertEqual(err - icmpn, 1)
4517 err = self.statistics.get_err_counter(
4518 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4519 self.assertEqual(err - totaln, 4)
4522 tcpn = self.statistics.get_err_counter(
4523 '/err/nat44-ed-out2in/TCP packets')
4524 udpn = self.statistics.get_err_counter(
4525 '/err/nat44-ed-out2in/UDP packets')
4526 icmpn = self.statistics.get_err_counter(
4527 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4528 totaln = self.statistics.get_err_counter(
4529 '/err/nat44-ed-out2in/good out2in packets processed')
4531 pkts = self.create_stream_out(self.pg1)
4532 self.pg1.add_stream(pkts)
4533 self.pg_enable_capture(self.pg_interfaces)
4535 capture = self.pg0.get_capture(len(pkts))
4536 self.verify_capture_in(capture, self.pg0)
4538 err = self.statistics.get_err_counter(
4539 '/err/nat44-ed-out2in/TCP packets')
4540 self.assertEqual(err - tcpn, 2)
4541 err = self.statistics.get_err_counter(
4542 '/err/nat44-ed-out2in/UDP packets')
4543 self.assertEqual(err - udpn, 1)
4544 err = self.statistics.get_err_counter(
4545 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4546 self.assertEqual(err - icmpn, 1)
4547 err = self.statistics.get_err_counter(
4548 '/err/nat44-ed-out2in/good out2in packets processed')
4549 self.assertEqual(err - totaln, 3)
4551 users = self.statistics.get_counter('/nat44/total-users')
4552 self.assertEqual(users[0][0], 1)
4553 sessions = self.statistics.get_counter('/nat44/total-sessions')
4554 self.assertEqual(sessions[0][0], 3)
4556 def test_dynamic_output_feature_vrf(self):
4557 """ NAT44 dynamic translation test: output-feature, VRF"""
4559 # other then default (0)
4562 self.nat44_add_address(self.nat_addr)
4563 flags = self.config_flags.NAT_IS_INSIDE
4564 self.vapi.nat44_interface_add_del_output_feature(
4565 sw_if_index=self.pg7.sw_if_index,
4566 flags=flags, is_add=1)
4567 self.vapi.nat44_interface_add_del_output_feature(
4568 sw_if_index=self.pg8.sw_if_index,
4572 self.vapi.ip_table_add_del(is_add=1,
4573 table={'table_id': new_vrf_id})
4575 self.pg7.unconfig_ip4()
4576 self.pg7.set_table_ip4(new_vrf_id)
4577 self.pg7.config_ip4()
4578 self.pg7.resolve_arp()
4580 self.pg8.unconfig_ip4()
4581 self.pg8.set_table_ip4(new_vrf_id)
4582 self.pg8.config_ip4()
4583 self.pg8.resolve_arp()
4585 nat_config = self.vapi.nat_show_config()
4586 self.assertEqual(1, nat_config.endpoint_dependent)
4589 tcpn = self.statistics.get_err_counter(
4590 '/err/nat44-ed-in2out-slowpath/TCP packets')
4591 udpn = self.statistics.get_err_counter(
4592 '/err/nat44-ed-in2out-slowpath/UDP packets')
4593 icmpn = self.statistics.get_err_counter(
4594 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4595 totaln = self.statistics.get_err_counter(
4596 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4598 pkts = self.create_stream_in(self.pg7, self.pg8)
4599 self.pg7.add_stream(pkts)
4600 self.pg_enable_capture(self.pg_interfaces)
4602 capture = self.pg8.get_capture(len(pkts))
4603 self.verify_capture_out(capture)
4605 err = self.statistics.get_err_counter(
4606 '/err/nat44-ed-in2out-slowpath/TCP packets')
4607 self.assertEqual(err - tcpn, 2)
4608 err = self.statistics.get_err_counter(
4609 '/err/nat44-ed-in2out-slowpath/UDP packets')
4610 self.assertEqual(err - udpn, 1)
4611 err = self.statistics.get_err_counter(
4612 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4613 self.assertEqual(err - icmpn, 1)
4614 err = self.statistics.get_err_counter(
4615 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4616 self.assertEqual(err - totaln, 4)
4619 tcpn = self.statistics.get_err_counter(
4620 '/err/nat44-ed-out2in/TCP packets')
4621 udpn = self.statistics.get_err_counter(
4622 '/err/nat44-ed-out2in/UDP packets')
4623 icmpn = self.statistics.get_err_counter(
4624 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4625 totaln = self.statistics.get_err_counter(
4626 '/err/nat44-ed-out2in/good out2in packets processed')
4628 pkts = self.create_stream_out(self.pg8)
4629 self.pg8.add_stream(pkts)
4630 self.pg_enable_capture(self.pg_interfaces)
4632 capture = self.pg7.get_capture(len(pkts))
4633 self.verify_capture_in(capture, self.pg7)
4635 err = self.statistics.get_err_counter(
4636 '/err/nat44-ed-out2in/TCP packets')
4637 self.assertEqual(err - tcpn, 2)
4638 err = self.statistics.get_err_counter(
4639 '/err/nat44-ed-out2in/UDP packets')
4640 self.assertEqual(err - udpn, 1)
4641 err = self.statistics.get_err_counter(
4642 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4643 self.assertEqual(err - icmpn, 1)
4644 err = self.statistics.get_err_counter(
4645 '/err/nat44-ed-out2in/good out2in packets processed')
4646 self.assertEqual(err - totaln, 3)
4648 users = self.statistics.get_counter('/nat44/total-users')
4649 self.assertEqual(users[0][0], 1)
4650 sessions = self.statistics.get_counter('/nat44/total-sessions')
4651 self.assertEqual(sessions[0][0], 3)
4654 self.pg7.unconfig_ip4()
4655 self.pg7.set_table_ip4(1)
4656 self.pg7.config_ip4()
4657 self.pg7.resolve_arp()
4659 self.pg8.unconfig_ip4()
4660 self.pg8.set_table_ip4(1)
4661 self.pg8.config_ip4()
4662 self.pg8.resolve_arp()
4664 self.vapi.ip_table_add_del(is_add=0,
4665 table={'table_id': new_vrf_id})
4667 def test_forwarding(self):
4668 """ NAT44 forwarding test """
4670 flags = self.config_flags.NAT_IS_INSIDE
4671 self.vapi.nat44_interface_add_del_feature(
4672 sw_if_index=self.pg0.sw_if_index,
4673 flags=flags, is_add=1)
4674 self.vapi.nat44_interface_add_del_feature(
4675 sw_if_index=self.pg1.sw_if_index,
4677 self.vapi.nat44_forwarding_enable_disable(enable=1)
4679 real_ip = self.pg0.remote_ip4
4680 alias_ip = self.nat_addr
4681 flags = self.config_flags.NAT_IS_ADDR_ONLY
4682 self.vapi.nat44_add_del_static_mapping(is_add=1,
4683 local_ip_address=real_ip,
4684 external_ip_address=alias_ip,
4685 external_sw_if_index=0xFFFFFFFF,
4689 # in2out - static mapping match
4691 pkts = self.create_stream_out(self.pg1)
4692 self.pg1.add_stream(pkts)
4693 self.pg_enable_capture(self.pg_interfaces)
4695 capture = self.pg0.get_capture(len(pkts))
4696 self.verify_capture_in(capture, self.pg0)
4698 pkts = self.create_stream_in(self.pg0, self.pg1)
4699 self.pg0.add_stream(pkts)
4700 self.pg_enable_capture(self.pg_interfaces)
4702 capture = self.pg1.get_capture(len(pkts))
4703 self.verify_capture_out(capture, same_port=True)
4705 # in2out - no static mapping match
4707 host0 = self.pg0.remote_hosts[0]
4708 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4710 pkts = self.create_stream_out(self.pg1,
4711 dst_ip=self.pg0.remote_ip4,
4712 use_inside_ports=True)
4713 self.pg1.add_stream(pkts)
4714 self.pg_enable_capture(self.pg_interfaces)
4716 capture = self.pg0.get_capture(len(pkts))
4717 self.verify_capture_in(capture, self.pg0)
4719 pkts = self.create_stream_in(self.pg0, self.pg1)
4720 self.pg0.add_stream(pkts)
4721 self.pg_enable_capture(self.pg_interfaces)
4723 capture = self.pg1.get_capture(len(pkts))
4724 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4727 self.pg0.remote_hosts[0] = host0
4729 user = self.pg0.remote_hosts[1]
4730 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4731 self.assertEqual(len(sessions), 3)
4732 self.assertTrue(sessions[0].flags &
4733 self.config_flags.NAT_IS_EXT_HOST_VALID)
4734 self.vapi.nat44_del_session(
4735 address=sessions[0].inside_ip_address,
4736 port=sessions[0].inside_port,
4737 protocol=sessions[0].protocol,
4738 flags=(self.config_flags.NAT_IS_INSIDE |
4739 self.config_flags.NAT_IS_EXT_HOST_VALID),
4740 ext_host_address=sessions[0].ext_host_address,
4741 ext_host_port=sessions[0].ext_host_port)
4742 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4743 self.assertEqual(len(sessions), 2)
4746 self.vapi.nat44_forwarding_enable_disable(enable=0)
4747 flags = self.config_flags.NAT_IS_ADDR_ONLY
4748 self.vapi.nat44_add_del_static_mapping(
4750 local_ip_address=real_ip,
4751 external_ip_address=alias_ip,
4752 external_sw_if_index=0xFFFFFFFF,
4755 def test_static_lb(self):
4756 """ NAT44 local service load balancing """
4757 external_addr_n = self.nat_addr
4760 server1 = self.pg0.remote_hosts[0]
4761 server2 = self.pg0.remote_hosts[1]
4763 locals = [{'addr': server1.ip4,
4767 {'addr': server2.ip4,
4772 self.nat44_add_address(self.nat_addr)
4773 self.vapi.nat44_add_del_lb_static_mapping(
4775 external_addr=external_addr_n,
4776 external_port=external_port,
4777 protocol=IP_PROTOS.tcp,
4778 local_num=len(locals),
4780 flags = self.config_flags.NAT_IS_INSIDE
4781 self.vapi.nat44_interface_add_del_feature(
4782 sw_if_index=self.pg0.sw_if_index,
4783 flags=flags, is_add=1)
4784 self.vapi.nat44_interface_add_del_feature(
4785 sw_if_index=self.pg1.sw_if_index,
4788 # from client to service
4789 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4790 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4791 TCP(sport=12345, dport=external_port))
4792 self.pg1.add_stream(p)
4793 self.pg_enable_capture(self.pg_interfaces)
4795 capture = self.pg0.get_capture(1)
4801 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4802 if ip.dst == server1.ip4:
4806 self.assertEqual(tcp.dport, local_port)
4807 self.assert_packet_checksums_valid(p)
4809 self.logger.error(ppp("Unexpected or invalid packet:", p))
4812 # from service back to client
4813 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4814 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4815 TCP(sport=local_port, dport=12345))
4816 self.pg0.add_stream(p)
4817 self.pg_enable_capture(self.pg_interfaces)
4819 capture = self.pg1.get_capture(1)
4824 self.assertEqual(ip.src, self.nat_addr)
4825 self.assertEqual(tcp.sport, external_port)
4826 self.assert_packet_checksums_valid(p)
4828 self.logger.error(ppp("Unexpected or invalid packet:", p))
4831 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
4832 self.assertEqual(len(sessions), 1)
4833 self.assertTrue(sessions[0].flags &
4834 self.config_flags.NAT_IS_EXT_HOST_VALID)
4835 self.vapi.nat44_del_session(
4836 address=sessions[0].inside_ip_address,
4837 port=sessions[0].inside_port,
4838 protocol=sessions[0].protocol,
4839 flags=(self.config_flags.NAT_IS_INSIDE |
4840 self.config_flags.NAT_IS_EXT_HOST_VALID),
4841 ext_host_address=sessions[0].ext_host_address,
4842 ext_host_port=sessions[0].ext_host_port)
4843 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
4844 self.assertEqual(len(sessions), 0)
4846 @unittest.skipUnless(running_extended_tests, "part of extended tests")
4847 def test_static_lb_multi_clients(self):
4848 """ NAT44 local service load balancing - multiple clients"""
4850 external_addr = self.nat_addr
4853 server1 = self.pg0.remote_hosts[0]
4854 server2 = self.pg0.remote_hosts[1]
4855 server3 = self.pg0.remote_hosts[2]
4857 locals = [{'addr': server1.ip4,
4861 {'addr': server2.ip4,
4866 self.nat44_add_address(self.nat_addr)
4867 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
4868 external_addr=external_addr,
4869 external_port=external_port,
4870 protocol=IP_PROTOS.tcp,
4871 local_num=len(locals),
4873 flags = self.config_flags.NAT_IS_INSIDE
4874 self.vapi.nat44_interface_add_del_feature(
4875 sw_if_index=self.pg0.sw_if_index,
4876 flags=flags, is_add=1)
4877 self.vapi.nat44_interface_add_del_feature(
4878 sw_if_index=self.pg1.sw_if_index,
4883 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4885 for client in clients:
4886 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4887 IP(src=client, dst=self.nat_addr) /
4888 TCP(sport=12345, dport=external_port))
4890 self.pg1.add_stream(pkts)
4891 self.pg_enable_capture(self.pg_interfaces)
4893 capture = self.pg0.get_capture(len(pkts))
4895 if p[IP].dst == server1.ip4:
4899 self.assertGreater(server1_n, server2_n)
4902 'addr': server3.ip4,
4909 self.vapi.nat44_lb_static_mapping_add_del_local(
4911 external_addr=external_addr,
4912 external_port=external_port,
4914 protocol=IP_PROTOS.tcp)
4918 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
4920 for client in clients:
4921 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4922 IP(src=client, dst=self.nat_addr) /
4923 TCP(sport=12346, dport=external_port))
4925 self.assertGreater(len(pkts), 0)
4926 self.pg1.add_stream(pkts)
4927 self.pg_enable_capture(self.pg_interfaces)
4929 capture = self.pg0.get_capture(len(pkts))
4931 if p[IP].dst == server1.ip4:
4933 elif p[IP].dst == server2.ip4:
4937 self.assertGreater(server1_n, 0)
4938 self.assertGreater(server2_n, 0)
4939 self.assertGreater(server3_n, 0)
4942 'addr': server2.ip4,
4948 # remove one back-end
4949 self.vapi.nat44_lb_static_mapping_add_del_local(
4951 external_addr=external_addr,
4952 external_port=external_port,
4954 protocol=IP_PROTOS.tcp)
4958 self.pg1.add_stream(pkts)
4959 self.pg_enable_capture(self.pg_interfaces)
4961 capture = self.pg0.get_capture(len(pkts))
4963 if p[IP].dst == server1.ip4:
4965 elif p[IP].dst == server2.ip4:
4969 self.assertGreater(server1_n, 0)
4970 self.assertEqual(server2_n, 0)
4971 self.assertGreater(server3_n, 0)
4973 def test_static_lb_2(self):
4974 """ NAT44 local service load balancing (asymmetrical rule) """
4975 external_addr = self.nat_addr
4978 server1 = self.pg0.remote_hosts[0]
4979 server2 = self.pg0.remote_hosts[1]
4981 locals = [{'addr': server1.ip4,
4985 {'addr': server2.ip4,
4990 self.vapi.nat44_forwarding_enable_disable(enable=1)
4991 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
4992 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
4993 external_addr=external_addr,
4994 external_port=external_port,
4995 protocol=IP_PROTOS.tcp,
4996 local_num=len(locals),
4998 flags = self.config_flags.NAT_IS_INSIDE
4999 self.vapi.nat44_interface_add_del_feature(
5000 sw_if_index=self.pg0.sw_if_index,
5001 flags=flags, is_add=1)
5002 self.vapi.nat44_interface_add_del_feature(
5003 sw_if_index=self.pg1.sw_if_index,
5006 # from client to service
5007 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5008 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5009 TCP(sport=12345, dport=external_port))
5010 self.pg1.add_stream(p)
5011 self.pg_enable_capture(self.pg_interfaces)
5013 capture = self.pg0.get_capture(1)
5019 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
5020 if ip.dst == server1.ip4:
5024 self.assertEqual(tcp.dport, local_port)
5025 self.assert_packet_checksums_valid(p)
5027 self.logger.error(ppp("Unexpected or invalid packet:", p))
5030 # from service back to client
5031 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
5032 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
5033 TCP(sport=local_port, dport=12345))
5034 self.pg0.add_stream(p)
5035 self.pg_enable_capture(self.pg_interfaces)
5037 capture = self.pg1.get_capture(1)
5042 self.assertEqual(ip.src, self.nat_addr)
5043 self.assertEqual(tcp.sport, external_port)
5044 self.assert_packet_checksums_valid(p)
5046 self.logger.error(ppp("Unexpected or invalid packet:", p))
5049 # from client to server (no translation)
5050 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5051 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
5052 TCP(sport=12346, dport=local_port))
5053 self.pg1.add_stream(p)
5054 self.pg_enable_capture(self.pg_interfaces)
5056 capture = self.pg0.get_capture(1)
5062 self.assertEqual(ip.dst, server1.ip4)
5063 self.assertEqual(tcp.dport, local_port)
5064 self.assert_packet_checksums_valid(p)
5066 self.logger.error(ppp("Unexpected or invalid packet:", p))
5069 # from service back to client (no translation)
5070 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
5071 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
5072 TCP(sport=local_port, dport=12346))
5073 self.pg0.add_stream(p)
5074 self.pg_enable_capture(self.pg_interfaces)
5076 capture = self.pg1.get_capture(1)
5081 self.assertEqual(ip.src, server1.ip4)
5082 self.assertEqual(tcp.sport, local_port)
5083 self.assert_packet_checksums_valid(p)
5085 self.logger.error(ppp("Unexpected or invalid packet:", p))
5088 def test_lb_affinity(self):
5089 """ NAT44 local service load balancing affinity """
5090 external_addr = self.nat_addr
5093 server1 = self.pg0.remote_hosts[0]
5094 server2 = self.pg0.remote_hosts[1]
5096 locals = [{'addr': server1.ip4,
5100 {'addr': server2.ip4,
5105 self.nat44_add_address(self.nat_addr)
5106 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
5107 external_addr=external_addr,
5108 external_port=external_port,
5109 protocol=IP_PROTOS.tcp,
5111 local_num=len(locals),
5113 flags = self.config_flags.NAT_IS_INSIDE
5114 self.vapi.nat44_interface_add_del_feature(
5115 sw_if_index=self.pg0.sw_if_index,
5116 flags=flags, is_add=1)
5117 self.vapi.nat44_interface_add_del_feature(
5118 sw_if_index=self.pg1.sw_if_index,
5121 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5122 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5123 TCP(sport=1025, dport=external_port))
5124 self.pg1.add_stream(p)
5125 self.pg_enable_capture(self.pg_interfaces)
5127 capture = self.pg0.get_capture(1)
5128 backend = capture[0][IP].dst
5130 sessions = self.vapi.nat44_user_session_dump(backend, 0)
5131 self.assertEqual(len(sessions), 1)
5132 self.assertTrue(sessions[0].flags &
5133 self.config_flags.NAT_IS_EXT_HOST_VALID)
5134 self.vapi.nat44_del_session(
5135 address=sessions[0].inside_ip_address,
5136 port=sessions[0].inside_port,
5137 protocol=sessions[0].protocol,
5138 flags=(self.config_flags.NAT_IS_INSIDE |
5139 self.config_flags.NAT_IS_EXT_HOST_VALID),
5140 ext_host_address=sessions[0].ext_host_address,
5141 ext_host_port=sessions[0].ext_host_port)
5144 for port in range(1030, 1100):
5145 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5146 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5147 TCP(sport=port, dport=external_port))
5149 self.pg1.add_stream(pkts)
5150 self.pg_enable_capture(self.pg_interfaces)
5152 capture = self.pg0.get_capture(len(pkts))
5154 self.assertEqual(p[IP].dst, backend)
5156 def test_unknown_proto(self):
5157 """ NAT44 translate packet with unknown protocol """
5158 self.nat44_add_address(self.nat_addr)
5159 flags = self.config_flags.NAT_IS_INSIDE
5160 self.vapi.nat44_interface_add_del_feature(
5161 sw_if_index=self.pg0.sw_if_index,
5162 flags=flags, is_add=1)
5163 self.vapi.nat44_interface_add_del_feature(
5164 sw_if_index=self.pg1.sw_if_index,
5168 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5169 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5170 TCP(sport=self.tcp_port_in, dport=20))
5171 self.pg0.add_stream(p)
5172 self.pg_enable_capture(self.pg_interfaces)
5174 p = self.pg1.get_capture(1)
5176 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5177 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5179 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5180 TCP(sport=1234, dport=1234))
5181 self.pg0.add_stream(p)
5182 self.pg_enable_capture(self.pg_interfaces)
5184 p = self.pg1.get_capture(1)
5187 self.assertEqual(packet[IP].src, self.nat_addr)
5188 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5189 self.assertEqual(packet.haslayer(GRE), 1)
5190 self.assert_packet_checksums_valid(packet)
5192 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5196 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5197 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5199 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5200 TCP(sport=1234, dport=1234))
5201 self.pg1.add_stream(p)
5202 self.pg_enable_capture(self.pg_interfaces)
5204 p = self.pg0.get_capture(1)
5207 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
5208 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
5209 self.assertEqual(packet.haslayer(GRE), 1)
5210 self.assert_packet_checksums_valid(packet)
5212 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5215 def test_hairpinning_unknown_proto(self):
5216 """ NAT44 translate packet with unknown protocol - hairpinning """
5217 host = self.pg0.remote_hosts[0]
5218 server = self.pg0.remote_hosts[1]
5220 server_out_port = 8765
5221 server_nat_ip = "10.0.0.11"
5223 self.nat44_add_address(self.nat_addr)
5224 flags = self.config_flags.NAT_IS_INSIDE
5225 self.vapi.nat44_interface_add_del_feature(
5226 sw_if_index=self.pg0.sw_if_index,
5227 flags=flags, is_add=1)
5228 self.vapi.nat44_interface_add_del_feature(
5229 sw_if_index=self.pg1.sw_if_index,
5232 # add static mapping for server
5233 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
5236 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
5237 IP(src=host.ip4, dst=server_nat_ip) /
5238 TCP(sport=host_in_port, dport=server_out_port))
5239 self.pg0.add_stream(p)
5240 self.pg_enable_capture(self.pg_interfaces)
5242 self.pg0.get_capture(1)
5244 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5245 IP(src=host.ip4, dst=server_nat_ip) /
5247 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5248 TCP(sport=1234, dport=1234))
5249 self.pg0.add_stream(p)
5250 self.pg_enable_capture(self.pg_interfaces)
5252 p = self.pg0.get_capture(1)
5255 self.assertEqual(packet[IP].src, self.nat_addr)
5256 self.assertEqual(packet[IP].dst, server.ip4)
5257 self.assertEqual(packet.haslayer(GRE), 1)
5258 self.assert_packet_checksums_valid(packet)
5260 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5264 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5265 IP(src=server.ip4, dst=self.nat_addr) /
5267 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5268 TCP(sport=1234, dport=1234))
5269 self.pg0.add_stream(p)
5270 self.pg_enable_capture(self.pg_interfaces)
5272 p = self.pg0.get_capture(1)
5275 self.assertEqual(packet[IP].src, server_nat_ip)
5276 self.assertEqual(packet[IP].dst, host.ip4)
5277 self.assertEqual(packet.haslayer(GRE), 1)
5278 self.assert_packet_checksums_valid(packet)
5280 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5283 def test_output_feature_and_service(self):
5284 """ NAT44 interface output feature and services """
5285 external_addr = '1.2.3.4'
5289 self.vapi.nat44_forwarding_enable_disable(enable=1)
5290 self.nat44_add_address(self.nat_addr)
5291 flags = self.config_flags.NAT_IS_ADDR_ONLY
5292 self.vapi.nat44_add_del_identity_mapping(
5293 ip_address=self.pg1.remote_ip4, sw_if_index=0xFFFFFFFF,
5294 flags=flags, is_add=1)
5295 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5296 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5297 local_port, external_port,
5298 proto=IP_PROTOS.tcp, flags=flags)
5299 flags = self.config_flags.NAT_IS_INSIDE
5300 self.vapi.nat44_interface_add_del_feature(
5301 sw_if_index=self.pg0.sw_if_index,
5303 self.vapi.nat44_interface_add_del_feature(
5304 sw_if_index=self.pg0.sw_if_index,
5305 flags=flags, is_add=1)
5306 self.vapi.nat44_interface_add_del_output_feature(
5308 sw_if_index=self.pg1.sw_if_index)
5310 # from client to service
5311 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5312 IP(src=self.pg1.remote_ip4, dst=external_addr) /
5313 TCP(sport=12345, dport=external_port))
5314 self.pg1.add_stream(p)
5315 self.pg_enable_capture(self.pg_interfaces)
5317 capture = self.pg0.get_capture(1)
5322 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5323 self.assertEqual(tcp.dport, local_port)
5324 self.assert_packet_checksums_valid(p)
5326 self.logger.error(ppp("Unexpected or invalid packet:", p))
5329 # from service back to client
5330 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5331 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5332 TCP(sport=local_port, dport=12345))
5333 self.pg0.add_stream(p)
5334 self.pg_enable_capture(self.pg_interfaces)
5336 capture = self.pg1.get_capture(1)
5341 self.assertEqual(ip.src, external_addr)
5342 self.assertEqual(tcp.sport, external_port)
5343 self.assert_packet_checksums_valid(p)
5345 self.logger.error(ppp("Unexpected or invalid packet:", p))
5348 # from local network host to external network
5349 pkts = self.create_stream_in(self.pg0, self.pg1)
5350 self.pg0.add_stream(pkts)
5351 self.pg_enable_capture(self.pg_interfaces)
5353 capture = self.pg1.get_capture(len(pkts))
5354 self.verify_capture_out(capture)
5355 pkts = self.create_stream_in(self.pg0, self.pg1)
5356 self.pg0.add_stream(pkts)
5357 self.pg_enable_capture(self.pg_interfaces)
5359 capture = self.pg1.get_capture(len(pkts))
5360 self.verify_capture_out(capture)
5362 # from external network back to local network host
5363 pkts = self.create_stream_out(self.pg1)
5364 self.pg1.add_stream(pkts)
5365 self.pg_enable_capture(self.pg_interfaces)
5367 capture = self.pg0.get_capture(len(pkts))
5368 self.verify_capture_in(capture, self.pg0)
5370 def test_output_feature_and_service2(self):
5371 """ NAT44 interface output feature and service host direct access """
5372 self.vapi.nat44_forwarding_enable_disable(enable=1)
5373 self.nat44_add_address(self.nat_addr)
5374 self.vapi.nat44_interface_add_del_output_feature(
5376 sw_if_index=self.pg1.sw_if_index)
5378 # session initiated from service host - translate
5379 pkts = self.create_stream_in(self.pg0, self.pg1)
5380 self.pg0.add_stream(pkts)
5381 self.pg_enable_capture(self.pg_interfaces)
5383 capture = self.pg1.get_capture(len(pkts))
5384 self.verify_capture_out(capture)
5386 pkts = self.create_stream_out(self.pg1)
5387 self.pg1.add_stream(pkts)
5388 self.pg_enable_capture(self.pg_interfaces)
5390 capture = self.pg0.get_capture(len(pkts))
5391 self.verify_capture_in(capture, self.pg0)
5393 # session initiated from remote host - do not translate
5394 self.tcp_port_in = 60303
5395 self.udp_port_in = 60304
5396 self.icmp_id_in = 60305
5397 pkts = self.create_stream_out(self.pg1,
5398 self.pg0.remote_ip4,
5399 use_inside_ports=True)
5400 self.pg1.add_stream(pkts)
5401 self.pg_enable_capture(self.pg_interfaces)
5403 capture = self.pg0.get_capture(len(pkts))
5404 self.verify_capture_in(capture, self.pg0)
5406 pkts = self.create_stream_in(self.pg0, self.pg1)
5407 self.pg0.add_stream(pkts)
5408 self.pg_enable_capture(self.pg_interfaces)
5410 capture = self.pg1.get_capture(len(pkts))
5411 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5414 def test_output_feature_and_service3(self):
5415 """ NAT44 interface output feature and DST NAT """
5416 external_addr = '1.2.3.4'
5420 self.vapi.nat44_forwarding_enable_disable(enable=1)
5421 self.nat44_add_address(self.nat_addr)
5422 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5423 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5424 local_port, external_port,
5425 proto=IP_PROTOS.tcp, flags=flags)
5426 flags = self.config_flags.NAT_IS_INSIDE
5427 self.vapi.nat44_interface_add_del_feature(
5428 sw_if_index=self.pg0.sw_if_index,
5430 self.vapi.nat44_interface_add_del_feature(
5431 sw_if_index=self.pg0.sw_if_index,
5432 flags=flags, is_add=1)
5433 self.vapi.nat44_interface_add_del_output_feature(
5435 sw_if_index=self.pg1.sw_if_index)
5437 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5438 IP(src=self.pg0.remote_ip4, dst=external_addr) /
5439 TCP(sport=12345, dport=external_port))
5440 self.pg0.add_stream(p)
5441 self.pg_enable_capture(self.pg_interfaces)
5443 capture = self.pg1.get_capture(1)
5448 self.assertEqual(ip.src, self.pg0.remote_ip4)
5449 self.assertEqual(tcp.sport, 12345)
5450 self.assertEqual(ip.dst, self.pg1.remote_ip4)
5451 self.assertEqual(tcp.dport, local_port)
5452 self.assert_packet_checksums_valid(p)
5454 self.logger.error(ppp("Unexpected or invalid packet:", p))
5457 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5458 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5459 TCP(sport=local_port, dport=12345))
5460 self.pg1.add_stream(p)
5461 self.pg_enable_capture(self.pg_interfaces)
5463 capture = self.pg0.get_capture(1)
5468 self.assertEqual(ip.src, external_addr)
5469 self.assertEqual(tcp.sport, external_port)
5470 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5471 self.assertEqual(tcp.dport, 12345)
5472 self.assert_packet_checksums_valid(p)
5474 self.logger.error(ppp("Unexpected or invalid packet:", p))
5477 def test_next_src_nat(self):
5478 """ On way back forward packet to nat44-in2out node. """
5479 twice_nat_addr = '10.0.1.3'
5482 post_twice_nat_port = 0
5484 self.vapi.nat44_forwarding_enable_disable(enable=1)
5485 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5486 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5487 self.config_flags.NAT_IS_SELF_TWICE_NAT)
5488 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5489 local_port, external_port,
5490 proto=IP_PROTOS.tcp, vrf_id=1,
5492 self.vapi.nat44_interface_add_del_feature(
5493 sw_if_index=self.pg6.sw_if_index,
5496 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5497 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5498 TCP(sport=12345, dport=external_port))
5499 self.pg6.add_stream(p)
5500 self.pg_enable_capture(self.pg_interfaces)
5502 capture = self.pg6.get_capture(1)
5507 self.assertEqual(ip.src, twice_nat_addr)
5508 self.assertNotEqual(tcp.sport, 12345)
5509 post_twice_nat_port = tcp.sport
5510 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5511 self.assertEqual(tcp.dport, local_port)
5512 self.assert_packet_checksums_valid(p)
5514 self.logger.error(ppp("Unexpected or invalid packet:", p))
5517 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5518 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5519 TCP(sport=local_port, dport=post_twice_nat_port))
5520 self.pg6.add_stream(p)
5521 self.pg_enable_capture(self.pg_interfaces)
5523 capture = self.pg6.get_capture(1)
5528 self.assertEqual(ip.src, self.pg1.remote_ip4)
5529 self.assertEqual(tcp.sport, external_port)
5530 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5531 self.assertEqual(tcp.dport, 12345)
5532 self.assert_packet_checksums_valid(p)
5534 self.logger.error(ppp("Unexpected or invalid packet:", p))
5537 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5539 twice_nat_addr = '10.0.1.3'
5547 port_in1 = port_in + 1
5548 port_in2 = port_in + 2
5553 server1 = self.pg0.remote_hosts[0]
5554 server2 = self.pg0.remote_hosts[1]
5566 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5569 self.nat44_add_address(self.nat_addr)
5570 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5574 flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
5576 flags |= self.config_flags.NAT_IS_TWICE_NAT
5579 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5581 proto=IP_PROTOS.tcp,
5584 locals = [{'addr': server1.ip4,
5588 {'addr': server2.ip4,
5592 out_addr = self.nat_addr
5594 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5595 external_addr=out_addr,
5596 external_port=port_out,
5597 protocol=IP_PROTOS.tcp,
5598 local_num=len(locals),
5600 flags = self.config_flags.NAT_IS_INSIDE
5601 self.vapi.nat44_interface_add_del_feature(
5602 sw_if_index=pg0.sw_if_index,
5603 flags=flags, is_add=1)
5604 self.vapi.nat44_interface_add_del_feature(
5605 sw_if_index=pg1.sw_if_index,
5612 assert client_id is not None
5614 client = self.pg0.remote_hosts[0]
5615 elif client_id == 2:
5616 client = self.pg0.remote_hosts[1]
5618 client = pg1.remote_hosts[0]
5619 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5620 IP(src=client.ip4, dst=self.nat_addr) /
5621 TCP(sport=eh_port_out, dport=port_out))
5623 self.pg_enable_capture(self.pg_interfaces)
5625 capture = pg0.get_capture(1)
5631 if ip.dst == server1.ip4:
5637 self.assertEqual(ip.dst, server.ip4)
5639 self.assertIn(tcp.dport, [port_in1, port_in2])
5641 self.assertEqual(tcp.dport, port_in)
5643 self.assertEqual(ip.src, twice_nat_addr)
5644 self.assertNotEqual(tcp.sport, eh_port_out)
5646 self.assertEqual(ip.src, client.ip4)
5647 self.assertEqual(tcp.sport, eh_port_out)
5649 eh_port_in = tcp.sport
5650 saved_port_in = tcp.dport
5651 self.assert_packet_checksums_valid(p)
5653 self.logger.error(ppp("Unexpected or invalid packet:", p))
5656 p = (Ether(src=server.mac, dst=pg0.local_mac) /
5657 IP(src=server.ip4, dst=eh_addr_in) /
5658 TCP(sport=saved_port_in, dport=eh_port_in))
5660 self.pg_enable_capture(self.pg_interfaces)
5662 capture = pg1.get_capture(1)
5667 self.assertEqual(ip.dst, client.ip4)
5668 self.assertEqual(ip.src, self.nat_addr)
5669 self.assertEqual(tcp.dport, eh_port_out)
5670 self.assertEqual(tcp.sport, port_out)
5671 self.assert_packet_checksums_valid(p)
5673 self.logger.error(ppp("Unexpected or invalid packet:", p))
5677 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5678 self.assertEqual(len(sessions), 1)
5679 self.assertTrue(sessions[0].flags &
5680 self.config_flags.NAT_IS_EXT_HOST_VALID)
5681 self.assertTrue(sessions[0].flags &
5682 self.config_flags.NAT_IS_TWICE_NAT)
5683 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
5684 self.vapi.nat44_del_session(
5685 address=sessions[0].inside_ip_address,
5686 port=sessions[0].inside_port,
5687 protocol=sessions[0].protocol,
5688 flags=(self.config_flags.NAT_IS_INSIDE |
5689 self.config_flags.NAT_IS_EXT_HOST_VALID),
5690 ext_host_address=sessions[0].ext_host_nat_address,
5691 ext_host_port=sessions[0].ext_host_nat_port)
5692 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5693 self.assertEqual(len(sessions), 0)
5695 def test_twice_nat(self):
5697 self.twice_nat_common()
5699 def test_self_twice_nat_positive(self):
5700 """ Self Twice NAT44 (positive test) """
5701 self.twice_nat_common(self_twice_nat=True, same_pg=True)
5703 def test_self_twice_nat_negative(self):
5704 """ Self Twice NAT44 (negative test) """
5705 self.twice_nat_common(self_twice_nat=True)
5707 def test_twice_nat_lb(self):
5708 """ Twice NAT44 local service load balancing """
5709 self.twice_nat_common(lb=True)
5711 def test_self_twice_nat_lb_positive(self):
5712 """ Self Twice NAT44 local service load balancing (positive test) """
5713 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5716 def test_self_twice_nat_lb_negative(self):
5717 """ Self Twice NAT44 local service load balancing (negative test) """
5718 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5721 def test_twice_nat_interface_addr(self):
5722 """ Acquire twice NAT44 addresses from interface """
5723 flags = self.config_flags.NAT_IS_TWICE_NAT
5724 self.vapi.nat44_add_del_interface_addr(
5726 sw_if_index=self.pg3.sw_if_index,
5729 # no address in NAT pool
5730 adresses = self.vapi.nat44_address_dump()
5731 self.assertEqual(0, len(adresses))
5733 # configure interface address and check NAT address pool
5734 self.pg3.config_ip4()
5735 adresses = self.vapi.nat44_address_dump()
5736 self.assertEqual(1, len(adresses))
5737 self.assertEqual(str(adresses[0].ip_address),
5739 self.assertEqual(adresses[0].flags, flags)
5741 # remove interface address and check NAT address pool
5742 self.pg3.unconfig_ip4()
5743 adresses = self.vapi.nat44_address_dump()
5744 self.assertEqual(0, len(adresses))
5746 def test_tcp_close(self):
5747 """ Close TCP session from inside network - output feature """
5748 self.vapi.nat44_forwarding_enable_disable(enable=1)
5749 self.nat44_add_address(self.pg1.local_ip4)
5750 twice_nat_addr = '10.0.1.3'
5751 service_ip = '192.168.16.150'
5752 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5753 flags = self.config_flags.NAT_IS_INSIDE
5754 self.vapi.nat44_interface_add_del_feature(
5755 sw_if_index=self.pg0.sw_if_index,
5757 self.vapi.nat44_interface_add_del_feature(
5758 sw_if_index=self.pg0.sw_if_index,
5759 flags=flags, is_add=1)
5760 self.vapi.nat44_interface_add_del_output_feature(
5762 sw_if_index=self.pg1.sw_if_index)
5763 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5764 self.config_flags.NAT_IS_TWICE_NAT)
5765 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5769 proto=IP_PROTOS.tcp,
5771 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5772 start_sessnum = len(sessions)
5774 # SYN packet out->in
5775 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5776 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5777 TCP(sport=33898, dport=80, flags="S"))
5778 self.pg1.add_stream(p)
5779 self.pg_enable_capture(self.pg_interfaces)
5781 capture = self.pg0.get_capture(1)
5783 tcp_port = p[TCP].sport
5785 # SYN + ACK packet in->out
5786 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5787 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5788 TCP(sport=80, dport=tcp_port, flags="SA"))
5789 self.pg0.add_stream(p)
5790 self.pg_enable_capture(self.pg_interfaces)
5792 self.pg1.get_capture(1)
5794 # ACK packet out->in
5795 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5796 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5797 TCP(sport=33898, dport=80, flags="A"))
5798 self.pg1.add_stream(p)
5799 self.pg_enable_capture(self.pg_interfaces)
5801 self.pg0.get_capture(1)
5803 # FIN packet in -> out
5804 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5805 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5806 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5807 self.pg0.add_stream(p)
5808 self.pg_enable_capture(self.pg_interfaces)
5810 self.pg1.get_capture(1)
5812 # FIN+ACK packet out -> in
5813 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5814 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5815 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5816 self.pg1.add_stream(p)
5817 self.pg_enable_capture(self.pg_interfaces)
5819 self.pg0.get_capture(1)
5821 # ACK packet in -> out
5822 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5823 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5824 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5825 self.pg0.add_stream(p)
5826 self.pg_enable_capture(self.pg_interfaces)
5828 self.pg1.get_capture(1)
5830 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4,
5832 self.assertEqual(len(sessions) - start_sessnum, 0)
5834 def test_tcp_session_close_in(self):
5835 """ Close TCP session from inside network """
5836 self.tcp_port_out = 10505
5837 self.nat44_add_address(self.nat_addr)
5838 flags = self.config_flags.NAT_IS_TWICE_NAT
5839 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5843 proto=IP_PROTOS.tcp,
5845 flags = self.config_flags.NAT_IS_INSIDE
5846 self.vapi.nat44_interface_add_del_feature(
5847 sw_if_index=self.pg0.sw_if_index,
5848 flags=flags, is_add=1)
5849 self.vapi.nat44_interface_add_del_feature(
5850 sw_if_index=self.pg1.sw_if_index,
5853 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5854 start_sessnum = len(sessions)
5856 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
5857 tcp_transitory=2, icmp=5)
5859 self.initiate_tcp_session(self.pg0, self.pg1)
5861 # FIN packet in -> out
5862 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5863 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5864 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5865 flags="FA", seq=100, ack=300))
5866 self.pg0.add_stream(p)
5867 self.pg_enable_capture(self.pg_interfaces)
5869 self.pg1.get_capture(1)
5873 # ACK packet out -> in
5874 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5875 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5876 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5877 flags="A", seq=300, ack=101))
5880 # FIN packet out -> in
5881 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5882 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5883 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5884 flags="FA", seq=300, ack=101))
5887 self.pg1.add_stream(pkts)
5888 self.pg_enable_capture(self.pg_interfaces)
5890 self.pg0.get_capture(2)
5892 # ACK packet in -> out
5893 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5894 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5895 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5896 flags="A", seq=101, ack=301))
5897 self.pg0.add_stream(p)
5898 self.pg_enable_capture(self.pg_interfaces)
5900 self.pg1.get_capture(1)
5902 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5903 self.assertEqual(len(sessions) - start_sessnum, 1)
5905 stats = self.statistics.get_counter(
5906 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
5907 out2in_drops = stats[0]
5908 stats = self.statistics.get_counter(
5909 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
5910 in2out_drops = stats[0]
5912 # extra FIN packet out -> in - this should be dropped
5913 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5914 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5915 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5916 flags="FA", seq=300, ack=101))
5918 self.pg1.add_stream(p)
5919 self.pg_enable_capture(self.pg_interfaces)
5921 self.pg0.assert_nothing_captured()
5923 # extra ACK packet in -> out - this should be dropped
5924 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5925 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5926 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5927 flags="A", seq=101, ack=301))
5928 self.pg0.add_stream(p)
5929 self.pg_enable_capture(self.pg_interfaces)
5931 self.pg1.assert_nothing_captured()
5933 stats = self.statistics.get_counter(
5934 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
5935 self.assertEqual(stats[0] - out2in_drops, 1)
5936 stats = self.statistics.get_counter(
5937 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
5938 self.assertEqual(stats[0] - in2out_drops, 1)
5941 # extra ACK packet in -> out - this will cause session to be wiped
5942 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5943 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5944 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5945 flags="A", seq=101, ack=301))
5946 self.pg0.add_stream(p)
5947 self.pg_enable_capture(self.pg_interfaces)
5949 self.pg1.assert_nothing_captured()
5950 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5951 self.assertEqual(len(sessions) - start_sessnum, 0)
5953 def test_tcp_session_close_out(self):
5954 """ Close TCP session from outside network """
5955 self.tcp_port_out = 10505
5956 self.nat44_add_address(self.nat_addr)
5957 flags = self.config_flags.NAT_IS_TWICE_NAT
5958 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5962 proto=IP_PROTOS.tcp,
5964 flags = self.config_flags.NAT_IS_INSIDE
5965 self.vapi.nat44_interface_add_del_feature(
5966 sw_if_index=self.pg0.sw_if_index,
5967 flags=flags, is_add=1)
5968 self.vapi.nat44_interface_add_del_feature(
5969 sw_if_index=self.pg1.sw_if_index,
5972 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5973 start_sessnum = len(sessions)
5975 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
5976 tcp_transitory=2, icmp=5)
5978 self.initiate_tcp_session(self.pg0, self.pg1)
5980 # FIN packet out -> in
5981 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5982 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5983 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5984 flags="FA", seq=100, ack=300))
5985 self.pg1.add_stream(p)
5986 self.pg_enable_capture(self.pg_interfaces)
5988 self.pg0.get_capture(1)
5990 # FIN+ACK packet in -> out
5991 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5992 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5993 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5994 flags="FA", seq=300, ack=101))
5996 self.pg0.add_stream(p)
5997 self.pg_enable_capture(self.pg_interfaces)
5999 self.pg1.get_capture(1)
6001 # ACK packet out -> in
6002 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6003 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6004 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6005 flags="A", seq=101, ack=301))
6006 self.pg1.add_stream(p)
6007 self.pg_enable_capture(self.pg_interfaces)
6009 self.pg0.get_capture(1)
6011 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6012 self.assertEqual(len(sessions) - start_sessnum, 1)
6014 stats = self.statistics.get_counter(
6015 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6016 out2in_drops = stats[0]
6017 stats = self.statistics.get_counter(
6018 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6019 in2out_drops = stats[0]
6021 # extra FIN packet out -> in - this should be dropped
6022 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6023 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6024 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6025 flags="FA", seq=300, ack=101))
6027 self.pg1.add_stream(p)
6028 self.pg_enable_capture(self.pg_interfaces)
6030 self.pg0.assert_nothing_captured()
6032 # extra ACK packet in -> out - this should be dropped
6033 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6034 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6035 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6036 flags="A", seq=101, ack=301))
6037 self.pg0.add_stream(p)
6038 self.pg_enable_capture(self.pg_interfaces)
6040 self.pg1.assert_nothing_captured()
6042 stats = self.statistics.get_counter(
6043 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6044 self.assertEqual(stats[0] - out2in_drops, 1)
6045 stats = self.statistics.get_counter(
6046 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6047 self.assertEqual(stats[0] - in2out_drops, 1)
6050 # extra ACK packet in -> out - this will cause session to be wiped
6051 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6052 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6053 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6054 flags="A", seq=101, ack=301))
6055 self.pg0.add_stream(p)
6056 self.pg_enable_capture(self.pg_interfaces)
6058 self.pg1.assert_nothing_captured()
6059 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6060 self.assertEqual(len(sessions) - start_sessnum, 0)
6062 def test_tcp_session_close_simultaneous(self):
6063 """ Close TCP session from inside network """
6064 self.tcp_port_out = 10505
6065 self.nat44_add_address(self.nat_addr)
6066 flags = self.config_flags.NAT_IS_TWICE_NAT
6067 self.nat44_add_static_mapping(self.pg0.remote_ip4,
6071 proto=IP_PROTOS.tcp,
6073 flags = self.config_flags.NAT_IS_INSIDE
6074 self.vapi.nat44_interface_add_del_feature(
6075 sw_if_index=self.pg0.sw_if_index,
6076 flags=flags, is_add=1)
6077 self.vapi.nat44_interface_add_del_feature(
6078 sw_if_index=self.pg1.sw_if_index,
6081 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6082 start_sessnum = len(sessions)
6084 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6085 tcp_transitory=2, icmp=5)
6087 self.initiate_tcp_session(self.pg0, self.pg1)
6089 # FIN packet in -> out
6090 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6091 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6092 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6093 flags="FA", seq=100, ack=300))
6094 self.pg0.add_stream(p)
6095 self.pg_enable_capture(self.pg_interfaces)
6097 self.pg1.get_capture(1)
6099 # FIN packet out -> in
6100 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6101 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6102 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6103 flags="FA", seq=300, ack=100))
6104 self.pg1.add_stream(p)
6105 self.pg_enable_capture(self.pg_interfaces)
6107 self.pg0.get_capture(1)
6109 # ACK packet in -> out
6110 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6111 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6112 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6113 flags="A", seq=101, ack=301))
6114 self.pg0.add_stream(p)
6115 self.pg_enable_capture(self.pg_interfaces)
6117 self.pg1.get_capture(1)
6119 # ACK packet out -> in
6120 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6121 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6122 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6123 flags="A", seq=301, ack=101))
6124 self.pg1.add_stream(p)
6125 self.pg_enable_capture(self.pg_interfaces)
6127 self.pg0.get_capture(1)
6129 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6130 self.assertEqual(len(sessions) - start_sessnum, 1)
6132 stats = self.statistics.get_counter(
6133 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6134 out2in_drops = stats[0]
6135 stats = self.statistics.get_counter(
6136 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6137 in2out_drops = stats[0]
6139 # extra FIN packet out -> in - this should be dropped
6140 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6141 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6142 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6143 flags="FA", seq=300, ack=101))
6145 self.pg1.add_stream(p)
6146 self.pg_enable_capture(self.pg_interfaces)
6148 self.pg0.assert_nothing_captured()
6150 # extra ACK packet in -> out - this should be dropped
6151 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6152 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6153 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6154 flags="A", seq=101, ack=301))
6155 self.pg0.add_stream(p)
6156 self.pg_enable_capture(self.pg_interfaces)
6158 self.pg1.assert_nothing_captured()
6160 stats = self.statistics.get_counter(
6161 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6162 self.assertEqual(stats[0] - out2in_drops, 1)
6163 stats = self.statistics.get_counter(
6164 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6165 self.assertEqual(stats[0] - in2out_drops, 1)
6168 # extra ACK packet in -> out - this will cause session to be wiped
6169 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6170 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6171 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6172 flags="A", seq=101, ack=301))
6173 self.pg0.add_stream(p)
6174 self.pg_enable_capture(self.pg_interfaces)
6176 self.pg1.assert_nothing_captured()
6177 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6178 self.assertEqual(len(sessions) - start_sessnum, 0)
6180 def test_one_armed_nat44_static(self):
6181 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
6182 remote_host = self.pg4.remote_hosts[0]
6183 local_host = self.pg4.remote_hosts[1]
6188 self.vapi.nat44_forwarding_enable_disable(enable=1)
6189 self.nat44_add_address(self.nat_addr, twice_nat=1)
6190 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
6191 self.config_flags.NAT_IS_TWICE_NAT)
6192 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
6193 local_port, external_port,
6194 proto=IP_PROTOS.tcp, flags=flags)
6195 flags = self.config_flags.NAT_IS_INSIDE
6196 self.vapi.nat44_interface_add_del_feature(
6197 sw_if_index=self.pg4.sw_if_index,
6199 self.vapi.nat44_interface_add_del_feature(
6200 sw_if_index=self.pg4.sw_if_index,
6201 flags=flags, is_add=1)
6203 # from client to service
6204 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6205 IP(src=remote_host.ip4, dst=self.nat_addr) /
6206 TCP(sport=12345, dport=external_port))
6207 self.pg4.add_stream(p)
6208 self.pg_enable_capture(self.pg_interfaces)
6210 capture = self.pg4.get_capture(1)
6215 self.assertEqual(ip.dst, local_host.ip4)
6216 self.assertEqual(ip.src, self.nat_addr)
6217 self.assertEqual(tcp.dport, local_port)
6218 self.assertNotEqual(tcp.sport, 12345)
6219 eh_port_in = tcp.sport
6220 self.assert_packet_checksums_valid(p)
6222 self.logger.error(ppp("Unexpected or invalid packet:", p))
6225 # from service back to client
6226 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6227 IP(src=local_host.ip4, dst=self.nat_addr) /
6228 TCP(sport=local_port, dport=eh_port_in))
6229 self.pg4.add_stream(p)
6230 self.pg_enable_capture(self.pg_interfaces)
6232 capture = self.pg4.get_capture(1)
6237 self.assertEqual(ip.src, self.nat_addr)
6238 self.assertEqual(ip.dst, remote_host.ip4)
6239 self.assertEqual(tcp.sport, external_port)
6240 self.assertEqual(tcp.dport, 12345)
6241 self.assert_packet_checksums_valid(p)
6243 self.logger.error(ppp("Unexpected or invalid packet:", p))
6246 def test_static_with_port_out2(self):
6247 """ 1:1 NAPT asymmetrical rule """
6252 self.vapi.nat44_forwarding_enable_disable(enable=1)
6253 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6254 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
6255 local_port, external_port,
6256 proto=IP_PROTOS.tcp, flags=flags)
6257 flags = self.config_flags.NAT_IS_INSIDE
6258 self.vapi.nat44_interface_add_del_feature(
6259 sw_if_index=self.pg0.sw_if_index,
6260 flags=flags, is_add=1)
6261 self.vapi.nat44_interface_add_del_feature(
6262 sw_if_index=self.pg1.sw_if_index,
6265 # from client to service
6266 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6267 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6268 TCP(sport=12345, dport=external_port))
6269 self.pg1.add_stream(p)
6270 self.pg_enable_capture(self.pg_interfaces)
6272 capture = self.pg0.get_capture(1)
6277 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6278 self.assertEqual(tcp.dport, local_port)
6279 self.assert_packet_checksums_valid(p)
6281 self.logger.error(ppp("Unexpected or invalid packet:", p))
6285 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6286 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6287 ICMP(type=11) / capture[0][IP])
6288 self.pg0.add_stream(p)
6289 self.pg_enable_capture(self.pg_interfaces)
6291 capture = self.pg1.get_capture(1)
6294 self.assertEqual(p[IP].src, self.nat_addr)
6296 self.assertEqual(inner.dst, self.nat_addr)
6297 self.assertEqual(inner[TCPerror].dport, external_port)
6299 self.logger.error(ppp("Unexpected or invalid packet:", p))
6302 # from service back to client
6303 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6304 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6305 TCP(sport=local_port, dport=12345))
6306 self.pg0.add_stream(p)
6307 self.pg_enable_capture(self.pg_interfaces)
6309 capture = self.pg1.get_capture(1)
6314 self.assertEqual(ip.src, self.nat_addr)
6315 self.assertEqual(tcp.sport, external_port)
6316 self.assert_packet_checksums_valid(p)
6318 self.logger.error(ppp("Unexpected or invalid packet:", p))
6322 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6323 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6324 ICMP(type=11) / capture[0][IP])
6325 self.pg1.add_stream(p)
6326 self.pg_enable_capture(self.pg_interfaces)
6328 capture = self.pg0.get_capture(1)
6331 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
6333 self.assertEqual(inner.src, self.pg0.remote_ip4)
6334 self.assertEqual(inner[TCPerror].sport, local_port)
6336 self.logger.error(ppp("Unexpected or invalid packet:", p))
6339 # from client to server (no translation)
6340 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6341 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
6342 TCP(sport=12346, dport=local_port))
6343 self.pg1.add_stream(p)
6344 self.pg_enable_capture(self.pg_interfaces)
6346 capture = self.pg0.get_capture(1)
6351 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6352 self.assertEqual(tcp.dport, local_port)
6353 self.assert_packet_checksums_valid(p)
6355 self.logger.error(ppp("Unexpected or invalid packet:", p))
6358 # from service back to client (no translation)
6359 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6360 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6361 TCP(sport=local_port, dport=12346))
6362 self.pg0.add_stream(p)
6363 self.pg_enable_capture(self.pg_interfaces)
6365 capture = self.pg1.get_capture(1)
6370 self.assertEqual(ip.src, self.pg0.remote_ip4)
6371 self.assertEqual(tcp.sport, local_port)
6372 self.assert_packet_checksums_valid(p)
6374 self.logger.error(ppp("Unexpected or invalid packet:", p))
6377 def test_output_feature(self):
6378 """ NAT44 interface output feature (in2out postrouting) """
6379 self.vapi.nat44_forwarding_enable_disable(enable=1)
6380 self.nat44_add_address(self.nat_addr)
6381 self.vapi.nat44_interface_add_del_feature(
6382 sw_if_index=self.pg0.sw_if_index,
6384 self.vapi.nat44_interface_add_del_output_feature(
6386 sw_if_index=self.pg1.sw_if_index)
6389 pkts = self.create_stream_in(self.pg0, self.pg1)
6390 self.pg0.add_stream(pkts)
6391 self.pg_enable_capture(self.pg_interfaces)
6393 capture = self.pg1.get_capture(len(pkts))
6394 self.verify_capture_out(capture)
6397 pkts = self.create_stream_out(self.pg1)
6398 self.pg1.add_stream(pkts)
6399 self.pg_enable_capture(self.pg_interfaces)
6401 capture = self.pg0.get_capture(len(pkts))
6402 self.verify_capture_in(capture, self.pg0)
6404 def test_output_feature_stateful_acl(self):
6405 """ NAT44 endpoint-dependent output feature works with stateful ACL """
6406 self.nat44_add_address(self.nat_addr)
6407 self.vapi.nat44_interface_add_del_output_feature(
6408 sw_if_index=self.pg0.sw_if_index,
6409 flags=self.config_flags.NAT_IS_INSIDE,
6411 self.vapi.nat44_interface_add_del_output_feature(
6412 sw_if_index=self.pg1.sw_if_index,
6413 flags=self.config_flags.NAT_IS_OUTSIDE,
6416 # First ensure that the NAT is working sans ACL
6418 # send packets out2in, no sessions yet so packets should drop
6419 pkts_out2in = self.create_stream_out(self.pg1)
6420 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
6422 # send packets into inside intf, ensure received via outside intf
6423 pkts_in2out = self.create_stream_in(self.pg0, self.pg1)
6424 capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
6426 self.verify_capture_out(capture)
6428 # send out2in again, with sessions created it should work now
6429 pkts_out2in = self.create_stream_out(self.pg1)
6430 capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
6432 self.verify_capture_in(capture, self.pg0)
6434 # Create an ACL blocking everything
6435 out2in_deny_rule = AclRule(is_permit=0)
6436 out2in_acl = VppAcl(self, rules=[out2in_deny_rule])
6437 out2in_acl.add_vpp_config()
6439 # create an ACL to permit/reflect everything
6440 in2out_reflect_rule = AclRule(is_permit=2)
6441 in2out_acl = VppAcl(self, rules=[in2out_reflect_rule])
6442 in2out_acl.add_vpp_config()
6444 # apply as input acl on interface and confirm it blocks everything
6445 acl_if = VppAclInterface(self, sw_if_index=self.pg1.sw_if_index,
6446 n_input=1, acls=[out2in_acl])
6447 acl_if.add_vpp_config()
6448 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
6451 acl_if.acls = [out2in_acl, in2out_acl]
6452 acl_if.add_vpp_config()
6453 # send in2out to generate ACL state (NAT state was created earlier)
6454 capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
6456 self.verify_capture_out(capture)
6458 # send out2in again. ACL state exists so it should work now.
6459 # TCP packets with the syn flag set also need the ack flag
6460 for p in pkts_out2in:
6461 if p.haslayer(TCP) and p[TCP].flags & 0x02:
6462 p[TCP].flags |= 0x10
6463 capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
6465 self.verify_capture_in(capture, self.pg0)
6466 self.logger.info(self.vapi.cli("show trace"))
6468 def test_multiple_vrf(self):
6469 """ Multiple VRF setup """
6470 external_addr = '1.2.3.4'
6475 self.vapi.nat44_forwarding_enable_disable(enable=1)
6476 self.nat44_add_address(self.nat_addr)
6477 flags = self.config_flags.NAT_IS_INSIDE
6478 self.vapi.nat44_interface_add_del_feature(
6479 sw_if_index=self.pg0.sw_if_index,
6481 self.vapi.nat44_interface_add_del_feature(
6482 sw_if_index=self.pg0.sw_if_index,
6483 flags=flags, is_add=1)
6484 self.vapi.nat44_interface_add_del_output_feature(
6486 sw_if_index=self.pg1.sw_if_index)
6487 self.vapi.nat44_interface_add_del_feature(
6488 sw_if_index=self.pg5.sw_if_index,
6490 self.vapi.nat44_interface_add_del_feature(
6491 sw_if_index=self.pg5.sw_if_index,
6492 flags=flags, is_add=1)
6493 self.vapi.nat44_interface_add_del_feature(
6494 sw_if_index=self.pg6.sw_if_index,
6496 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6497 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
6498 local_port, external_port, vrf_id=1,
6499 proto=IP_PROTOS.tcp, flags=flags)
6500 self.nat44_add_static_mapping(
6501 self.pg0.remote_ip4,
6502 external_sw_if_index=self.pg0.sw_if_index,
6503 local_port=local_port,
6505 external_port=external_port,
6506 proto=IP_PROTOS.tcp,
6510 # from client to service (both VRF1)
6511 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6512 IP(src=self.pg6.remote_ip4, dst=external_addr) /
6513 TCP(sport=12345, dport=external_port))
6514 self.pg6.add_stream(p)
6515 self.pg_enable_capture(self.pg_interfaces)
6517 capture = self.pg5.get_capture(1)
6522 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6523 self.assertEqual(tcp.dport, local_port)
6524 self.assert_packet_checksums_valid(p)
6526 self.logger.error(ppp("Unexpected or invalid packet:", p))
6529 # from service back to client (both VRF1)
6530 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6531 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6532 TCP(sport=local_port, dport=12345))
6533 self.pg5.add_stream(p)
6534 self.pg_enable_capture(self.pg_interfaces)
6536 capture = self.pg6.get_capture(1)
6541 self.assertEqual(ip.src, external_addr)
6542 self.assertEqual(tcp.sport, external_port)
6543 self.assert_packet_checksums_valid(p)
6545 self.logger.error(ppp("Unexpected or invalid packet:", p))
6548 # dynamic NAT from VRF1 to VRF0 (output-feature)
6549 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6550 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6551 TCP(sport=2345, dport=22))
6552 self.pg5.add_stream(p)
6553 self.pg_enable_capture(self.pg_interfaces)
6555 capture = self.pg1.get_capture(1)
6560 self.assertEqual(ip.src, self.nat_addr)
6561 self.assertNotEqual(tcp.sport, 2345)
6562 self.assert_packet_checksums_valid(p)
6565 self.logger.error(ppp("Unexpected or invalid packet:", p))
6568 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6569 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6570 TCP(sport=22, dport=port))
6571 self.pg1.add_stream(p)
6572 self.pg_enable_capture(self.pg_interfaces)
6574 capture = self.pg5.get_capture(1)
6579 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6580 self.assertEqual(tcp.dport, 2345)
6581 self.assert_packet_checksums_valid(p)
6583 self.logger.error(ppp("Unexpected or invalid packet:", p))
6586 # from client VRF1 to service VRF0
6587 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6588 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6589 TCP(sport=12346, dport=external_port))
6590 self.pg6.add_stream(p)
6591 self.pg_enable_capture(self.pg_interfaces)
6593 capture = self.pg0.get_capture(1)
6598 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6599 self.assertEqual(tcp.dport, local_port)
6600 self.assert_packet_checksums_valid(p)
6602 self.logger.error(ppp("Unexpected or invalid packet:", p))
6605 # from service VRF0 back to client VRF1
6606 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6607 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6608 TCP(sport=local_port, dport=12346))
6609 self.pg0.add_stream(p)
6610 self.pg_enable_capture(self.pg_interfaces)
6612 capture = self.pg6.get_capture(1)
6617 self.assertEqual(ip.src, self.pg0.local_ip4)
6618 self.assertEqual(tcp.sport, external_port)
6619 self.assert_packet_checksums_valid(p)
6621 self.logger.error(ppp("Unexpected or invalid packet:", p))
6624 # from client VRF0 to service VRF1
6625 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6626 IP(src=self.pg0.remote_ip4, dst=external_addr) /
6627 TCP(sport=12347, dport=external_port))
6628 self.pg0.add_stream(p)
6629 self.pg_enable_capture(self.pg_interfaces)
6631 capture = self.pg5.get_capture(1)
6636 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6637 self.assertEqual(tcp.dport, local_port)
6638 self.assert_packet_checksums_valid(p)
6640 self.logger.error(ppp("Unexpected or invalid packet:", p))
6643 # from service VRF1 back to client VRF0
6644 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6645 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6646 TCP(sport=local_port, dport=12347))
6647 self.pg5.add_stream(p)
6648 self.pg_enable_capture(self.pg_interfaces)
6650 capture = self.pg0.get_capture(1)
6655 self.assertEqual(ip.src, external_addr)
6656 self.assertEqual(tcp.sport, external_port)
6657 self.assert_packet_checksums_valid(p)
6659 self.logger.error(ppp("Unexpected or invalid packet:", p))
6662 # from client to server (both VRF1, no translation)
6663 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6664 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6665 TCP(sport=12348, dport=local_port))
6666 self.pg6.add_stream(p)
6667 self.pg_enable_capture(self.pg_interfaces)
6669 capture = self.pg5.get_capture(1)
6674 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6675 self.assertEqual(tcp.dport, local_port)
6676 self.assert_packet_checksums_valid(p)
6678 self.logger.error(ppp("Unexpected or invalid packet:", p))
6681 # from server back to client (both VRF1, no translation)
6682 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6683 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6684 TCP(sport=local_port, dport=12348))
6685 self.pg5.add_stream(p)
6686 self.pg_enable_capture(self.pg_interfaces)
6688 capture = self.pg6.get_capture(1)
6693 self.assertEqual(ip.src, self.pg5.remote_ip4)
6694 self.assertEqual(tcp.sport, local_port)
6695 self.assert_packet_checksums_valid(p)
6697 self.logger.error(ppp("Unexpected or invalid packet:", p))
6700 # from client VRF1 to server VRF0 (no translation)
6701 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6702 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6703 TCP(sport=local_port, dport=12349))
6704 self.pg0.add_stream(p)
6705 self.pg_enable_capture(self.pg_interfaces)
6707 capture = self.pg6.get_capture(1)
6712 self.assertEqual(ip.src, self.pg0.remote_ip4)
6713 self.assertEqual(tcp.sport, local_port)
6714 self.assert_packet_checksums_valid(p)
6716 self.logger.error(ppp("Unexpected or invalid packet:", p))
6719 # from server VRF0 back to client VRF1 (no translation)
6720 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6721 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6722 TCP(sport=local_port, dport=12349))
6723 self.pg0.add_stream(p)
6724 self.pg_enable_capture(self.pg_interfaces)
6726 capture = self.pg6.get_capture(1)
6731 self.assertEqual(ip.src, self.pg0.remote_ip4)
6732 self.assertEqual(tcp.sport, local_port)
6733 self.assert_packet_checksums_valid(p)
6735 self.logger.error(ppp("Unexpected or invalid packet:", p))
6738 # from client VRF0 to server VRF1 (no translation)
6739 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6740 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6741 TCP(sport=12344, dport=local_port))
6742 self.pg0.add_stream(p)
6743 self.pg_enable_capture(self.pg_interfaces)
6745 capture = self.pg5.get_capture(1)
6750 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6751 self.assertEqual(tcp.dport, local_port)
6752 self.assert_packet_checksums_valid(p)
6754 self.logger.error(ppp("Unexpected or invalid packet:", p))
6757 # from server VRF1 back to client VRF0 (no translation)
6758 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6759 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6760 TCP(sport=local_port, dport=12344))
6761 self.pg5.add_stream(p)
6762 self.pg_enable_capture(self.pg_interfaces)
6764 capture = self.pg0.get_capture(1)
6769 self.assertEqual(ip.src, self.pg5.remote_ip4)
6770 self.assertEqual(tcp.sport, local_port)
6771 self.assert_packet_checksums_valid(p)
6773 self.logger.error(ppp("Unexpected or invalid packet:", p))
6776 @unittest.skipUnless(running_extended_tests, "part of extended tests")
6777 def test_session_timeout(self):
6778 """ NAT44 session timeouts """
6779 self.nat44_add_address(self.nat_addr)
6780 flags = self.config_flags.NAT_IS_INSIDE
6781 self.vapi.nat44_interface_add_del_feature(
6782 sw_if_index=self.pg0.sw_if_index,
6783 flags=flags, is_add=1)
6784 self.vapi.nat44_interface_add_del_feature(
6785 sw_if_index=self.pg1.sw_if_index,
6787 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6788 tcp_transitory=240, icmp=5)
6792 for i in range(0, max_sessions):
6793 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6794 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6795 IP(src=src, dst=self.pg1.remote_ip4) /
6796 ICMP(id=1025, type='echo-request'))
6798 self.pg0.add_stream(pkts)
6799 self.pg_enable_capture(self.pg_interfaces)
6801 self.pg1.get_capture(max_sessions)
6806 for i in range(0, max_sessions):
6807 src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6808 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6809 IP(src=src, dst=self.pg1.remote_ip4) /
6810 ICMP(id=1026, type='echo-request'))
6812 self.pg0.add_stream(pkts)
6813 self.pg_enable_capture(self.pg_interfaces)
6815 self.pg1.get_capture(max_sessions)
6818 users = self.vapi.nat44_user_dump()
6820 nsessions = nsessions + user.nsessions
6821 self.assertLess(nsessions, 2 * max_sessions)
6823 @unittest.skipUnless(running_extended_tests, "part of extended tests")
6824 def test_session_rst_timeout(self):
6825 """ NAT44 session RST timeouts """
6826 self.nat44_add_address(self.nat_addr)
6827 flags = self.config_flags.NAT_IS_INSIDE
6828 self.vapi.nat44_interface_add_del_feature(
6829 sw_if_index=self.pg0.sw_if_index,
6830 flags=flags, is_add=1)
6831 self.vapi.nat44_interface_add_del_feature(
6832 sw_if_index=self.pg1.sw_if_index,
6834 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6835 tcp_transitory=5, icmp=60)
6837 self.initiate_tcp_session(self.pg0, self.pg1)
6838 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6839 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6840 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6842 self.pg0.add_stream(p)
6843 self.pg_enable_capture(self.pg_interfaces)
6845 self.pg1.get_capture(1)
6849 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6850 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6851 TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6853 self.pg0.add_stream(p)
6854 self.pg_enable_capture(self.pg_interfaces)
6856 self.pg1.get_capture(1)
6859 users = self.vapi.nat44_user_dump()
6860 self.assertEqual(len(users), 1)
6861 self.assertEqual(str(users[0].ip_address),
6862 self.pg0.remote_ip4)
6863 self.assertEqual(users[0].nsessions, 1)
6865 def test_syslog_sess(self):
6866 """ Test syslog session creation and deletion """
6867 self.vapi.syslog_set_filter(
6868 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
6869 self.vapi.syslog_set_sender(self.pg2.local_ip4, self.pg2.remote_ip4)
6870 self.nat44_add_address(self.nat_addr)
6871 flags = self.config_flags.NAT_IS_INSIDE
6872 self.vapi.nat44_interface_add_del_feature(
6873 sw_if_index=self.pg0.sw_if_index,
6874 flags=flags, is_add=1)
6875 self.vapi.nat44_interface_add_del_feature(
6876 sw_if_index=self.pg1.sw_if_index,
6879 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6880 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6881 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6882 self.pg0.add_stream(p)
6883 self.pg_enable_capture(self.pg_interfaces)
6885 capture = self.pg1.get_capture(1)
6886 self.tcp_port_out = capture[0][TCP].sport
6887 capture = self.pg2.get_capture(1)
6888 self.verify_syslog_sess(capture[0][Raw].load)
6890 self.pg_enable_capture(self.pg_interfaces)
6892 self.nat44_add_address(self.nat_addr, is_add=0)
6893 capture = self.pg2.get_capture(1)
6894 self.verify_syslog_sess(capture[0][Raw].load, False)
6897 super(TestNAT44EndpointDependent, self).tearDown()
6898 if not self.vpp_dead:
6900 self.vapi.cli("clear logging")
6902 def show_commands_at_teardown(self):
6903 self.logger.info(self.vapi.cli("show nat44 addresses"))
6904 self.logger.info(self.vapi.cli("show nat44 interfaces"))
6905 self.logger.info(self.vapi.cli("show nat44 static mappings"))
6906 self.logger.info(self.vapi.cli("show nat44 interface address"))
6907 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
6908 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
6909 self.logger.info(self.vapi.cli("show nat timeouts"))
6912 class TestNAT44Out2InDPO(MethodHolder):
6913 """ NAT44 Test Cases using out2in DPO """
6916 def setUpConstants(cls):
6917 super(TestNAT44Out2InDPO, cls).setUpConstants()
6918 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
6921 def setUpClass(cls):
6922 super(TestNAT44Out2InDPO, cls).setUpClass()
6923 cls.vapi.cli("set log class nat level debug")
6925 cls.tcp_port_in = 6303
6926 cls.tcp_port_out = 6303
6927 cls.udp_port_in = 6304
6928 cls.udp_port_out = 6304
6929 cls.icmp_id_in = 6305
6930 cls.icmp_id_out = 6305
6931 cls.nat_addr = '10.0.0.3'
6932 cls.dst_ip4 = '192.168.70.1'
6934 cls.create_pg_interfaces(range(2))
6937 cls.pg0.config_ip4()
6938 cls.pg0.resolve_arp()
6941 cls.pg1.config_ip6()
6942 cls.pg1.resolve_ndp()
6944 r1 = VppIpRoute(cls, "::", 0,
6945 [VppRoutePath(cls.pg1.remote_ip6,
6946 cls.pg1.sw_if_index)],
6951 def tearDownClass(cls):
6952 super(TestNAT44Out2InDPO, cls).tearDownClass()
6954 def configure_xlat(self):
6955 self.dst_ip6_pfx = '1:2:3::'
6956 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6958 self.dst_ip6_pfx_len = 96
6959 self.src_ip6_pfx = '4:5:6::'
6960 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6962 self.src_ip6_pfx_len = 96
6963 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
6964 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
6965 '\x00\x00\x00\x00', 0)
6967 @unittest.skip('Temporary disabled')
6968 def test_464xlat_ce(self):
6969 """ Test 464XLAT CE with NAT44 """
6971 nat_config = self.vapi.nat_show_config()
6972 self.assertEqual(1, nat_config.out2in_dpo)
6974 self.configure_xlat()
6976 flags = self.config_flags.NAT_IS_INSIDE
6977 self.vapi.nat44_interface_add_del_feature(
6978 sw_if_index=self.pg0.sw_if_index,
6979 flags=flags, is_add=1)
6980 self.vapi.nat44_add_del_address_range(first_ip_address=self.nat_addr_n,
6981 last_ip_address=self.nat_addr_n,
6982 vrf_id=0xFFFFFFFF, is_add=1)
6984 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6985 self.dst_ip6_pfx_len)
6986 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
6987 self.src_ip6_pfx_len)
6990 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6991 self.pg0.add_stream(pkts)
6992 self.pg_enable_capture(self.pg_interfaces)
6994 capture = self.pg1.get_capture(len(pkts))
6995 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
6998 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
7000 self.pg1.add_stream(pkts)
7001 self.pg_enable_capture(self.pg_interfaces)
7003 capture = self.pg0.get_capture(len(pkts))
7004 self.verify_capture_in(capture, self.pg0)
7006 self.vapi.nat44_interface_add_del_feature(
7007 sw_if_index=self.pg0.sw_if_index,
7009 self.vapi.nat44_add_del_address_range(
7010 first_ip_address=self.nat_addr_n,
7011 last_ip_address=self.nat_addr_n,
7014 @unittest.skip('Temporary disabled')
7015 def test_464xlat_ce_no_nat(self):
7016 """ Test 464XLAT CE without NAT44 """
7018 self.configure_xlat()
7020 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7021 self.dst_ip6_pfx_len)
7022 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
7023 self.src_ip6_pfx_len)
7025 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7026 self.pg0.add_stream(pkts)
7027 self.pg_enable_capture(self.pg_interfaces)
7029 capture = self.pg1.get_capture(len(pkts))
7030 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
7031 nat_ip=out_dst_ip6, same_port=True)
7033 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
7034 self.pg1.add_stream(pkts)
7035 self.pg_enable_capture(self.pg_interfaces)
7037 capture = self.pg0.get_capture(len(pkts))
7038 self.verify_capture_in(capture, self.pg0)
7041 class TestDeterministicNAT(MethodHolder):
7042 """ Deterministic NAT Test Cases """
7045 def setUpConstants(cls):
7046 super(TestDeterministicNAT, cls).setUpConstants()
7047 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
7050 def setUpClass(cls):
7051 super(TestDeterministicNAT, cls).setUpClass()
7052 cls.vapi.cli("set log class nat level debug")
7054 cls.tcp_port_in = 6303
7055 cls.tcp_external_port = 6303
7056 cls.udp_port_in = 6304
7057 cls.udp_external_port = 6304
7058 cls.icmp_id_in = 6305
7059 cls.nat_addr = '10.0.0.3'
7061 cls.create_pg_interfaces(range(3))
7062 cls.interfaces = list(cls.pg_interfaces)
7064 for i in cls.interfaces:
7069 cls.pg0.generate_remote_hosts(2)
7070 cls.pg0.configure_ipv4_neighbors()
7073 def tearDownClass(cls):
7074 super(TestDeterministicNAT, cls).tearDownClass()
7076 def create_stream_in(self, in_if, out_if, ttl=64):
7078 Create packet stream for inside network
7080 :param in_if: Inside interface
7081 :param out_if: Outside interface
7082 :param ttl: TTL of generated packets
7086 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7087 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7088 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
7092 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7093 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7094 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
7098 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7099 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7100 ICMP(id=self.icmp_id_in, type='echo-request'))
7105 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
7107 Create packet stream for outside network
7109 :param out_if: Outside interface
7110 :param dst_ip: Destination IP address (Default use global NAT address)
7111 :param ttl: TTL of generated packets
7114 dst_ip = self.nat_addr
7117 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7118 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7119 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
7123 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7124 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7125 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
7129 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7130 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7131 ICMP(id=self.icmp_external_id, type='echo-reply'))
7136 def verify_capture_out(self, capture, nat_ip=None):
7138 Verify captured packets on outside network
7140 :param capture: Captured packets
7141 :param nat_ip: Translated IP address (Default use global NAT address)
7142 :param same_port: Source port number is not translated (Default False)
7145 nat_ip = self.nat_addr
7146 for packet in capture:
7148 self.assertEqual(packet[IP].src, nat_ip)
7149 if packet.haslayer(TCP):
7150 self.tcp_port_out = packet[TCP].sport
7151 elif packet.haslayer(UDP):
7152 self.udp_port_out = packet[UDP].sport
7154 self.icmp_external_id = packet[ICMP].id
7156 self.logger.error(ppp("Unexpected or invalid packet "
7157 "(outside network):", packet))
7160 def test_deterministic_mode(self):
7161 """ NAT plugin run deterministic mode """
7162 in_addr = '172.16.255.0'
7163 out_addr = '172.17.255.50'
7164 in_addr_t = '172.16.255.20'
7168 nat_config = self.vapi.nat_show_config()
7169 self.assertEqual(1, nat_config.deterministic)
7171 self.vapi.nat_det_add_del_map(is_add=1, in_addr=in_addr,
7172 in_plen=in_plen, out_addr=out_addr,
7175 rep1 = self.vapi.nat_det_forward(in_addr_t)
7176 self.assertEqual(str(rep1.out_addr), out_addr)
7177 rep2 = self.vapi.nat_det_reverse(rep1.out_port_hi, out_addr)
7179 self.assertEqual(str(rep2.in_addr), in_addr_t)
7181 deterministic_mappings = self.vapi.nat_det_map_dump()
7182 self.assertEqual(len(deterministic_mappings), 1)
7183 dsm = deterministic_mappings[0]
7184 self.assertEqual(in_addr, str(dsm.in_addr))
7185 self.assertEqual(in_plen, dsm.in_plen)
7186 self.assertEqual(out_addr, str(dsm.out_addr))
7187 self.assertEqual(out_plen, dsm.out_plen)
7189 self.clear_nat_det()
7190 deterministic_mappings = self.vapi.nat_det_map_dump()
7191 self.assertEqual(len(deterministic_mappings), 0)
7193 def test_set_timeouts(self):
7194 """ Set deterministic NAT timeouts """
7195 timeouts_before = self.vapi.nat_get_timeouts()
7197 self.vapi.nat_set_timeouts(
7198 udp=timeouts_before.udp + 10,
7199 tcp_established=timeouts_before.tcp_established + 10,
7200 tcp_transitory=timeouts_before.tcp_transitory + 10,
7201 icmp=timeouts_before.icmp + 10)
7203 timeouts_after = self.vapi.nat_get_timeouts()
7205 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
7206 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
7207 self.assertNotEqual(timeouts_before.tcp_established,
7208 timeouts_after.tcp_established)
7209 self.assertNotEqual(timeouts_before.tcp_transitory,
7210 timeouts_after.tcp_transitory)
7212 def test_det_in(self):
7213 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
7215 nat_ip = "10.0.0.10"
7217 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7219 out_addr=socket.inet_aton(nat_ip),
7222 flags = self.config_flags.NAT_IS_INSIDE
7223 self.vapi.nat44_interface_add_del_feature(
7224 sw_if_index=self.pg0.sw_if_index,
7225 flags=flags, is_add=1)
7226 self.vapi.nat44_interface_add_del_feature(
7227 sw_if_index=self.pg1.sw_if_index,
7231 pkts = self.create_stream_in(self.pg0, self.pg1)
7232 self.pg0.add_stream(pkts)
7233 self.pg_enable_capture(self.pg_interfaces)
7235 capture = self.pg1.get_capture(len(pkts))
7236 self.verify_capture_out(capture, nat_ip)
7239 pkts = self.create_stream_out(self.pg1, nat_ip)
7240 self.pg1.add_stream(pkts)
7241 self.pg_enable_capture(self.pg_interfaces)
7243 capture = self.pg0.get_capture(len(pkts))
7244 self.verify_capture_in(capture, self.pg0)
7247 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4)
7248 self.assertEqual(len(sessions), 3)
7252 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7253 self.assertEqual(s.in_port, self.tcp_port_in)
7254 self.assertEqual(s.out_port, self.tcp_port_out)
7255 self.assertEqual(s.ext_port, self.tcp_external_port)
7259 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7260 self.assertEqual(s.in_port, self.udp_port_in)
7261 self.assertEqual(s.out_port, self.udp_port_out)
7262 self.assertEqual(s.ext_port, self.udp_external_port)
7266 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7267 self.assertEqual(s.in_port, self.icmp_id_in)
7268 self.assertEqual(s.out_port, self.icmp_external_id)
7270 def test_multiple_users(self):
7271 """ Deterministic NAT multiple users """
7273 nat_ip = "10.0.0.10"
7275 external_port = 6303
7277 host0 = self.pg0.remote_hosts[0]
7278 host1 = self.pg0.remote_hosts[1]
7280 self.vapi.nat_det_add_del_map(is_add=1, in_addr=host0.ip4, in_plen=24,
7281 out_addr=socket.inet_aton(nat_ip),
7283 flags = self.config_flags.NAT_IS_INSIDE
7284 self.vapi.nat44_interface_add_del_feature(
7285 sw_if_index=self.pg0.sw_if_index,
7286 flags=flags, is_add=1)
7287 self.vapi.nat44_interface_add_del_feature(
7288 sw_if_index=self.pg1.sw_if_index,
7292 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
7293 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
7294 TCP(sport=port_in, dport=external_port))
7295 self.pg0.add_stream(p)
7296 self.pg_enable_capture(self.pg_interfaces)
7298 capture = self.pg1.get_capture(1)
7303 self.assertEqual(ip.src, nat_ip)
7304 self.assertEqual(ip.dst, self.pg1.remote_ip4)
7305 self.assertEqual(tcp.dport, external_port)
7306 port_out0 = tcp.sport
7308 self.logger.error(ppp("Unexpected or invalid packet:", p))
7312 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
7313 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
7314 TCP(sport=port_in, dport=external_port))
7315 self.pg0.add_stream(p)
7316 self.pg_enable_capture(self.pg_interfaces)
7318 capture = self.pg1.get_capture(1)
7323 self.assertEqual(ip.src, nat_ip)
7324 self.assertEqual(ip.dst, self.pg1.remote_ip4)
7325 self.assertEqual(tcp.dport, external_port)
7326 port_out1 = tcp.sport
7328 self.logger.error(ppp("Unexpected or invalid packet:", p))
7331 dms = self.vapi.nat_det_map_dump()
7332 self.assertEqual(1, len(dms))
7333 self.assertEqual(2, dms[0].ses_num)
7336 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7337 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
7338 TCP(sport=external_port, dport=port_out0))
7339 self.pg1.add_stream(p)
7340 self.pg_enable_capture(self.pg_interfaces)
7342 capture = self.pg0.get_capture(1)
7347 self.assertEqual(ip.src, self.pg1.remote_ip4)
7348 self.assertEqual(ip.dst, host0.ip4)
7349 self.assertEqual(tcp.dport, port_in)
7350 self.assertEqual(tcp.sport, external_port)
7352 self.logger.error(ppp("Unexpected or invalid packet:", p))
7356 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7357 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
7358 TCP(sport=external_port, dport=port_out1))
7359 self.pg1.add_stream(p)
7360 self.pg_enable_capture(self.pg_interfaces)
7362 capture = self.pg0.get_capture(1)
7367 self.assertEqual(ip.src, self.pg1.remote_ip4)
7368 self.assertEqual(ip.dst, host1.ip4)
7369 self.assertEqual(tcp.dport, port_in)
7370 self.assertEqual(tcp.sport, external_port)
7372 self.logger.error(ppp("Unexpected or invalid packet", p))
7375 # session close api test
7376 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
7378 self.pg1.remote_ip4,
7380 dms = self.vapi.nat_det_map_dump()
7381 self.assertEqual(dms[0].ses_num, 1)
7383 self.vapi.nat_det_close_session_in(host0.ip4,
7385 self.pg1.remote_ip4,
7387 dms = self.vapi.nat_det_map_dump()
7388 self.assertEqual(dms[0].ses_num, 0)
7390 def test_tcp_session_close_detection_in(self):
7391 """ Deterministic NAT TCP session close from inside network """
7392 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7394 out_addr=socket.inet_aton(self.nat_addr),
7396 flags = self.config_flags.NAT_IS_INSIDE
7397 self.vapi.nat44_interface_add_del_feature(
7398 sw_if_index=self.pg0.sw_if_index,
7399 flags=flags, is_add=1)
7400 self.vapi.nat44_interface_add_del_feature(
7401 sw_if_index=self.pg1.sw_if_index,
7404 self.initiate_tcp_session(self.pg0, self.pg1)
7406 # close the session from inside
7408 # FIN packet in -> out
7409 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7410 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7411 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7413 self.pg0.add_stream(p)
7414 self.pg_enable_capture(self.pg_interfaces)
7416 self.pg1.get_capture(1)
7420 # ACK packet out -> in
7421 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7422 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7423 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7427 # FIN packet out -> in
7428 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7429 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7430 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7434 self.pg1.add_stream(pkts)
7435 self.pg_enable_capture(self.pg_interfaces)
7437 self.pg0.get_capture(2)
7439 # ACK packet in -> out
7440 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7441 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7442 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7444 self.pg0.add_stream(p)
7445 self.pg_enable_capture(self.pg_interfaces)
7447 self.pg1.get_capture(1)
7449 # Check if deterministic NAT44 closed the session
7450 dms = self.vapi.nat_det_map_dump()
7451 self.assertEqual(0, dms[0].ses_num)
7453 self.logger.error("TCP session termination failed")
7456 def test_tcp_session_close_detection_out(self):
7457 """ Deterministic NAT TCP session close from outside network """
7458 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7460 out_addr=socket.inet_aton(self.nat_addr),
7462 flags = self.config_flags.NAT_IS_INSIDE
7463 self.vapi.nat44_interface_add_del_feature(
7464 sw_if_index=self.pg0.sw_if_index,
7465 flags=flags, is_add=1)
7466 self.vapi.nat44_interface_add_del_feature(
7467 sw_if_index=self.pg1.sw_if_index,
7470 self.initiate_tcp_session(self.pg0, self.pg1)
7472 # close the session from outside
7474 # FIN packet out -> in
7475 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7476 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7477 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7479 self.pg1.add_stream(p)
7480 self.pg_enable_capture(self.pg_interfaces)
7482 self.pg0.get_capture(1)
7486 # ACK packet in -> out
7487 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7488 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7489 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7493 # ACK packet in -> out
7494 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7495 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7496 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7500 self.pg0.add_stream(pkts)
7501 self.pg_enable_capture(self.pg_interfaces)
7503 self.pg1.get_capture(2)
7505 # ACK packet out -> in
7506 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7507 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7508 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7510 self.pg1.add_stream(p)
7511 self.pg_enable_capture(self.pg_interfaces)
7513 self.pg0.get_capture(1)
7515 # Check if deterministic NAT44 closed the session
7516 dms = self.vapi.nat_det_map_dump()
7517 self.assertEqual(0, dms[0].ses_num)
7519 self.logger.error("TCP session termination failed")
7522 @unittest.skipUnless(running_extended_tests, "part of extended tests")
7523 def test_session_timeout(self):
7524 """ Deterministic NAT session timeouts """
7525 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7527 out_addr=socket.inet_aton(self.nat_addr),
7529 flags = self.config_flags.NAT_IS_INSIDE
7530 self.vapi.nat44_interface_add_del_feature(
7531 sw_if_index=self.pg0.sw_if_index,
7532 flags=flags, is_add=1)
7533 self.vapi.nat44_interface_add_del_feature(
7534 sw_if_index=self.pg1.sw_if_index,
7537 self.initiate_tcp_session(self.pg0, self.pg1)
7538 self.vapi.nat_set_timeouts(udp=5, tcp_established=5, tcp_transitory=5,
7540 pkts = self.create_stream_in(self.pg0, self.pg1)
7541 self.pg0.add_stream(pkts)
7542 self.pg_enable_capture(self.pg_interfaces)
7544 capture = self.pg1.get_capture(len(pkts))
7547 dms = self.vapi.nat_det_map_dump()
7548 self.assertEqual(0, dms[0].ses_num)
7550 @unittest.skipUnless(running_extended_tests, "part of extended tests")
7551 def test_session_limit_per_user(self):
7552 """ Deterministic NAT maximum sessions per user limit """
7553 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7555 out_addr=socket.inet_aton(self.nat_addr),
7557 flags = self.config_flags.NAT_IS_INSIDE
7558 self.vapi.nat44_interface_add_del_feature(
7559 sw_if_index=self.pg0.sw_if_index,
7560 flags=flags, is_add=1)
7561 self.vapi.nat44_interface_add_del_feature(
7562 sw_if_index=self.pg1.sw_if_index,
7564 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4,
7565 src_address=self.pg2.local_ip4,
7567 template_interval=10)
7568 self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7572 for port in range(1025, 2025):
7573 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7574 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7575 UDP(sport=port, dport=port))
7578 self.pg0.add_stream(pkts)
7579 self.pg_enable_capture(self.pg_interfaces)
7581 capture = self.pg1.get_capture(len(pkts))
7583 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7584 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7585 UDP(sport=3001, dport=3002))
7586 self.pg0.add_stream(p)
7587 self.pg_enable_capture(self.pg_interfaces)
7589 capture = self.pg1.assert_nothing_captured()
7591 # verify ICMP error packet
7592 capture = self.pg0.get_capture(1)
7594 self.assertTrue(p.haslayer(ICMP))
7596 self.assertEqual(icmp.type, 3)
7597 self.assertEqual(icmp.code, 1)
7598 self.assertTrue(icmp.haslayer(IPerror))
7599 inner_ip = icmp[IPerror]
7600 self.assertEqual(inner_ip[UDPerror].sport, 3001)
7601 self.assertEqual(inner_ip[UDPerror].dport, 3002)
7603 dms = self.vapi.nat_det_map_dump()
7605 self.assertEqual(1000, dms[0].ses_num)
7607 # verify IPFIX logging
7608 self.vapi.ipfix_flush()
7610 capture = self.pg2.get_capture(2)
7611 ipfix = IPFIXDecoder()
7612 # first load template
7614 self.assertTrue(p.haslayer(IPFIX))
7615 if p.haslayer(Template):
7616 ipfix.add_template(p.getlayer(Template))
7617 # verify events in data set
7619 if p.haslayer(Data):
7620 data = ipfix.decode_data_set(p.getlayer(Set))
7621 self.verify_ipfix_max_entries_per_user(data,
7623 self.pg0.remote_ip4)
7625 def clear_nat_det(self):
7627 Clear deterministic NAT configuration.
7629 self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7631 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
7632 tcp_transitory=240, icmp=60)
7633 deterministic_mappings = self.vapi.nat_det_map_dump()
7634 for dsm in deterministic_mappings:
7635 self.vapi.nat_det_add_del_map(is_add=0, in_addr=dsm.in_addr,
7636 in_plen=dsm.in_plen,
7637 out_addr=dsm.out_addr,
7638 out_plen=dsm.out_plen)
7640 interfaces = self.vapi.nat44_interface_dump()
7641 for intf in interfaces:
7642 self.vapi.nat44_interface_add_del_feature(
7643 sw_if_index=intf.sw_if_index,
7647 super(TestDeterministicNAT, self).tearDown()
7648 if not self.vpp_dead:
7649 self.clear_nat_det()
7651 def show_commands_at_teardown(self):
7652 self.logger.info(self.vapi.cli("show nat44 interfaces"))
7653 self.logger.info(self.vapi.cli("show nat timeouts"))
7655 self.vapi.cli("show nat44 deterministic mappings"))
7657 self.vapi.cli("show nat44 deterministic sessions"))
7660 class TestNAT64(MethodHolder):
7661 """ NAT64 Test Cases """
7664 def setUpConstants(cls):
7665 super(TestNAT64, cls).setUpConstants()
7666 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
7667 "nat64 st hash buckets 256", "}"])
7670 def setUpClass(cls):
7671 super(TestNAT64, cls).setUpClass()
7673 cls.tcp_port_in = 6303
7674 cls.tcp_port_out = 6303
7675 cls.udp_port_in = 6304
7676 cls.udp_port_out = 6304
7677 cls.icmp_id_in = 6305
7678 cls.icmp_id_out = 6305
7679 cls.tcp_external_port = 80
7680 cls.nat_addr = '10.0.0.3'
7681 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
7683 cls.vrf1_nat_addr = '10.0.10.3'
7684 cls.ipfix_src_port = 4739
7685 cls.ipfix_domain_id = 1
7687 cls.create_pg_interfaces(range(6))
7688 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
7689 cls.ip6_interfaces.append(cls.pg_interfaces[2])
7690 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
7692 cls.vapi.ip_table_add_del(is_add=1,
7693 table={'table_id': cls.vrf1_id,
7696 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
7698 cls.pg0.generate_remote_hosts(2)
7700 for i in cls.ip6_interfaces:
7703 i.configure_ipv6_neighbors()
7705 for i in cls.ip4_interfaces:
7711 cls.pg3.config_ip4()
7712 cls.pg3.resolve_arp()
7713 cls.pg3.config_ip6()
7714 cls.pg3.configure_ipv6_neighbors()
7717 cls.pg5.config_ip6()
7720 def tearDownClass(cls):
7721 super(TestNAT64, cls).tearDownClass()
7723 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
7724 """ NAT64 inside interface handles Neighbor Advertisement """
7726 flags = self.config_flags.NAT_IS_INSIDE
7727 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7728 sw_if_index=self.pg5.sw_if_index)
7731 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7732 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7733 ICMPv6EchoRequest())
7735 self.pg5.add_stream(pkts)
7736 self.pg_enable_capture(self.pg_interfaces)
7739 # Wait for Neighbor Solicitation
7740 capture = self.pg5.get_capture(len(pkts))
7743 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7744 self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
7745 tgt = packet[ICMPv6ND_NS].tgt
7747 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7750 # Send Neighbor Advertisement
7751 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7752 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7753 ICMPv6ND_NA(tgt=tgt) /
7754 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
7756 self.pg5.add_stream(pkts)
7757 self.pg_enable_capture(self.pg_interfaces)
7760 # Try to send ping again
7762 self.pg5.add_stream(pkts)
7763 self.pg_enable_capture(self.pg_interfaces)
7766 # Wait for ping reply
7767 capture = self.pg5.get_capture(len(pkts))
7770 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7771 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
7772 self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
7774 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7777 def test_pool(self):
7778 """ Add/delete address to NAT64 pool """
7779 nat_addr = '1.2.3.4'
7781 self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7783 vrf_id=0xFFFFFFFF, is_add=1)
7785 addresses = self.vapi.nat64_pool_addr_dump()
7786 self.assertEqual(len(addresses), 1)
7787 self.assertEqual(str(addresses[0].address), nat_addr)
7789 self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7791 vrf_id=0xFFFFFFFF, is_add=0)
7793 addresses = self.vapi.nat64_pool_addr_dump()
7794 self.assertEqual(len(addresses), 0)
7796 def test_interface(self):
7797 """ Enable/disable NAT64 feature on the interface """
7798 flags = self.config_flags.NAT_IS_INSIDE
7799 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7800 sw_if_index=self.pg0.sw_if_index)
7801 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7802 sw_if_index=self.pg1.sw_if_index)
7804 interfaces = self.vapi.nat64_interface_dump()
7805 self.assertEqual(len(interfaces), 2)
7808 for intf in interfaces:
7809 if intf.sw_if_index == self.pg0.sw_if_index:
7810 self.assertEqual(intf.flags, self.config_flags.NAT_IS_INSIDE)
7812 elif intf.sw_if_index == self.pg1.sw_if_index:
7813 self.assertEqual(intf.flags, self.config_flags.NAT_IS_OUTSIDE)
7815 self.assertTrue(pg0_found)
7816 self.assertTrue(pg1_found)
7818 features = self.vapi.cli("show interface features pg0")
7819 self.assertIn('nat64-in2out', features)
7820 features = self.vapi.cli("show interface features pg1")
7821 self.assertIn('nat64-out2in', features)
7823 self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7824 sw_if_index=self.pg0.sw_if_index)
7825 self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7826 sw_if_index=self.pg1.sw_if_index)
7828 interfaces = self.vapi.nat64_interface_dump()
7829 self.assertEqual(len(interfaces), 0)
7831 def test_static_bib(self):
7832 """ Add/delete static BIB entry """
7833 in_addr = '2001:db8:85a3::8a2e:370:7334'
7834 out_addr = '10.1.1.3'
7837 proto = IP_PROTOS.tcp
7839 self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7840 i_port=in_port, o_port=out_port,
7841 proto=proto, vrf_id=0, is_add=1)
7842 bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
7845 if bibe.flags & self.config_flags.NAT_IS_STATIC:
7847 self.assertEqual(str(bibe.i_addr), in_addr)
7848 self.assertEqual(str(bibe.o_addr), out_addr)
7849 self.assertEqual(bibe.i_port, in_port)
7850 self.assertEqual(bibe.o_port, out_port)
7851 self.assertEqual(static_bib_num, 1)
7852 bibs = self.statistics.get_counter('/nat64/total-bibs')
7853 self.assertEqual(bibs[0][0], 1)
7855 self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7856 i_port=in_port, o_port=out_port,
7857 proto=proto, vrf_id=0, is_add=0)
7858 bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
7861 if bibe.flags & self.config_flags.NAT_IS_STATIC:
7863 self.assertEqual(static_bib_num, 0)
7864 bibs = self.statistics.get_counter('/nat64/total-bibs')
7865 self.assertEqual(bibs[0][0], 0)
7867 def test_set_timeouts(self):
7868 """ Set NAT64 timeouts """
7869 # verify default values
7870 timeouts = self.vapi.nat_get_timeouts()
7871 self.assertEqual(timeouts.udp, 300)
7872 self.assertEqual(timeouts.icmp, 60)
7873 self.assertEqual(timeouts.tcp_transitory, 240)
7874 self.assertEqual(timeouts.tcp_established, 7440)
7876 # set and verify custom values
7877 self.vapi.nat_set_timeouts(udp=200, tcp_established=7450,
7878 tcp_transitory=250, icmp=30)
7879 timeouts = self.vapi.nat_get_timeouts()
7880 self.assertEqual(timeouts.udp, 200)
7881 self.assertEqual(timeouts.icmp, 30)
7882 self.assertEqual(timeouts.tcp_transitory, 250)
7883 self.assertEqual(timeouts.tcp_established, 7450)
7885 def test_dynamic(self):
7886 """ NAT64 dynamic translation test """
7887 self.tcp_port_in = 6303
7888 self.udp_port_in = 6304
7889 self.icmp_id_in = 6305
7891 ses_num_start = self.nat64_get_ses_num()
7893 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
7894 end_addr=self.nat_addr,
7897 flags = self.config_flags.NAT_IS_INSIDE
7898 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7899 sw_if_index=self.pg0.sw_if_index)
7900 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7901 sw_if_index=self.pg1.sw_if_index)
7904 tcpn = self.statistics.get_err_counter('/err/nat64-in2out/TCP packets')
7905 udpn = self.statistics.get_err_counter('/err/nat64-in2out/UDP packets')
7906 icmpn = self.statistics.get_err_counter(
7907 '/err/nat64-in2out/ICMP packets')
7908 totaln = self.statistics.get_err_counter(
7909 '/err/nat64-in2out/good in2out packets processed')
7911 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7912 self.pg0.add_stream(pkts)
7913 self.pg_enable_capture(self.pg_interfaces)
7915 capture = self.pg1.get_capture(len(pkts))
7916 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7917 dst_ip=self.pg1.remote_ip4)
7919 err = self.statistics.get_err_counter('/err/nat64-in2out/TCP packets')
7920 self.assertEqual(err - tcpn, 1)
7921 err = self.statistics.get_err_counter('/err/nat64-in2out/UDP packets')
7922 self.assertEqual(err - udpn, 1)
7923 err = self.statistics.get_err_counter('/err/nat64-in2out/ICMP packets')
7924 self.assertEqual(err - icmpn, 1)
7925 err = self.statistics.get_err_counter(
7926 '/err/nat64-in2out/good in2out packets processed')
7927 self.assertEqual(err - totaln, 3)
7930 tcpn = self.statistics.get_err_counter('/err/nat64-out2in/TCP packets')
7931 udpn = self.statistics.get_err_counter('/err/nat64-out2in/UDP packets')
7932 icmpn = self.statistics.get_err_counter(
7933 '/err/nat64-out2in/ICMP packets')
7934 totaln = self.statistics.get_err_counter(
7935 '/err/nat64-out2in/good out2in packets processed')
7937 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7938 self.pg1.add_stream(pkts)
7939 self.pg_enable_capture(self.pg_interfaces)
7941 capture = self.pg0.get_capture(len(pkts))
7942 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7943 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7945 err = self.statistics.get_err_counter('/err/nat64-out2in/TCP packets')
7946 self.assertEqual(err - tcpn, 2)
7947 err = self.statistics.get_err_counter('/err/nat64-out2in/UDP packets')
7948 self.assertEqual(err - udpn, 1)
7949 err = self.statistics.get_err_counter('/err/nat64-out2in/ICMP packets')
7950 self.assertEqual(err - icmpn, 1)
7951 err = self.statistics.get_err_counter(
7952 '/err/nat64-out2in/good out2in packets processed')
7953 self.assertEqual(err - totaln, 4)
7955 bibs = self.statistics.get_counter('/nat64/total-bibs')
7956 self.assertEqual(bibs[0][0], 3)
7957 sessions = self.statistics.get_counter('/nat64/total-sessions')
7958 self.assertEqual(sessions[0][0], 3)
7961 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7962 self.pg0.add_stream(pkts)
7963 self.pg_enable_capture(self.pg_interfaces)
7965 capture = self.pg1.get_capture(len(pkts))
7966 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7967 dst_ip=self.pg1.remote_ip4)
7970 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7971 self.pg1.add_stream(pkts)
7972 self.pg_enable_capture(self.pg_interfaces)
7974 capture = self.pg0.get_capture(len(pkts))
7975 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7977 ses_num_end = self.nat64_get_ses_num()
7979 self.assertEqual(ses_num_end - ses_num_start, 3)
7981 # tenant with specific VRF
7982 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
7983 end_addr=self.vrf1_nat_addr,
7984 vrf_id=self.vrf1_id, is_add=1)
7985 flags = self.config_flags.NAT_IS_INSIDE
7986 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7987 sw_if_index=self.pg2.sw_if_index)
7989 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
7990 self.pg2.add_stream(pkts)
7991 self.pg_enable_capture(self.pg_interfaces)
7993 capture = self.pg1.get_capture(len(pkts))
7994 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7995 dst_ip=self.pg1.remote_ip4)
7997 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7998 self.pg1.add_stream(pkts)
7999 self.pg_enable_capture(self.pg_interfaces)
8001 capture = self.pg2.get_capture(len(pkts))
8002 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
8004 def test_static(self):
8005 """ NAT64 static translation test """
8006 self.tcp_port_in = 60303
8007 self.udp_port_in = 60304
8008 self.icmp_id_in = 60305
8009 self.tcp_port_out = 60303
8010 self.udp_port_out = 60304
8011 self.icmp_id_out = 60305
8013 ses_num_start = self.nat64_get_ses_num()
8015 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8016 end_addr=self.nat_addr,
8019 flags = self.config_flags.NAT_IS_INSIDE
8020 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8021 sw_if_index=self.pg0.sw_if_index)
8022 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8023 sw_if_index=self.pg1.sw_if_index)
8025 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8026 o_addr=self.nat_addr,
8027 i_port=self.tcp_port_in,
8028 o_port=self.tcp_port_out,
8029 proto=IP_PROTOS.tcp, vrf_id=0,
8031 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8032 o_addr=self.nat_addr,
8033 i_port=self.udp_port_in,
8034 o_port=self.udp_port_out,
8035 proto=IP_PROTOS.udp, vrf_id=0,
8037 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8038 o_addr=self.nat_addr,
8039 i_port=self.icmp_id_in,
8040 o_port=self.icmp_id_out,
8041 proto=IP_PROTOS.icmp, vrf_id=0,
8045 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8046 self.pg0.add_stream(pkts)
8047 self.pg_enable_capture(self.pg_interfaces)
8049 capture = self.pg1.get_capture(len(pkts))
8050 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8051 dst_ip=self.pg1.remote_ip4, same_port=True)
8054 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8055 self.pg1.add_stream(pkts)
8056 self.pg_enable_capture(self.pg_interfaces)
8058 capture = self.pg0.get_capture(len(pkts))
8059 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8060 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8062 ses_num_end = self.nat64_get_ses_num()
8064 self.assertEqual(ses_num_end - ses_num_start, 3)
8066 @unittest.skipUnless(running_extended_tests, "part of extended tests")
8067 def test_session_timeout(self):
8068 """ NAT64 session timeout """
8069 self.icmp_id_in = 1234
8070 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8071 end_addr=self.nat_addr,
8074 flags = self.config_flags.NAT_IS_INSIDE
8075 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8076 sw_if_index=self.pg0.sw_if_index)
8077 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8078 sw_if_index=self.pg1.sw_if_index)
8079 self.vapi.nat_set_timeouts(udp=300, tcp_established=5,
8083 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8084 self.pg0.add_stream(pkts)
8085 self.pg_enable_capture(self.pg_interfaces)
8087 capture = self.pg1.get_capture(len(pkts))
8089 ses_num_before_timeout = self.nat64_get_ses_num()
8093 # ICMP and TCP session after timeout
8094 ses_num_after_timeout = self.nat64_get_ses_num()
8095 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
8097 def test_icmp_error(self):
8098 """ NAT64 ICMP Error message translation """
8099 self.tcp_port_in = 6303
8100 self.udp_port_in = 6304
8101 self.icmp_id_in = 6305
8103 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8104 end_addr=self.nat_addr,
8107 flags = self.config_flags.NAT_IS_INSIDE
8108 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8109 sw_if_index=self.pg0.sw_if_index)
8110 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8111 sw_if_index=self.pg1.sw_if_index)
8113 # send some packets to create sessions
8114 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8115 self.pg0.add_stream(pkts)
8116 self.pg_enable_capture(self.pg_interfaces)
8118 capture_ip4 = self.pg1.get_capture(len(pkts))
8119 self.verify_capture_out(capture_ip4,
8120 nat_ip=self.nat_addr,
8121 dst_ip=self.pg1.remote_ip4)
8123 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8124 self.pg1.add_stream(pkts)
8125 self.pg_enable_capture(self.pg_interfaces)
8127 capture_ip6 = self.pg0.get_capture(len(pkts))
8128 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8129 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
8130 self.pg0.remote_ip6)
8133 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8134 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
8135 ICMPv6DestUnreach(code=1) /
8136 packet[IPv6] for packet in capture_ip6]
8137 self.pg0.add_stream(pkts)
8138 self.pg_enable_capture(self.pg_interfaces)
8140 capture = self.pg1.get_capture(len(pkts))
8141 for packet in capture:
8143 self.assertEqual(packet[IP].src, self.nat_addr)
8144 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
8145 self.assertEqual(packet[ICMP].type, 3)
8146 self.assertEqual(packet[ICMP].code, 13)
8147 inner = packet[IPerror]
8148 self.assertEqual(inner.src, self.pg1.remote_ip4)
8149 self.assertEqual(inner.dst, self.nat_addr)
8150 self.assert_packet_checksums_valid(packet)
8151 if inner.haslayer(TCPerror):
8152 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
8153 elif inner.haslayer(UDPerror):
8154 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
8156 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
8158 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8162 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8163 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8164 ICMP(type=3, code=13) /
8165 packet[IP] for packet in capture_ip4]
8166 self.pg1.add_stream(pkts)
8167 self.pg_enable_capture(self.pg_interfaces)
8169 capture = self.pg0.get_capture(len(pkts))
8170 for packet in capture:
8172 self.assertEqual(packet[IPv6].src, ip.src)
8173 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8174 icmp = packet[ICMPv6DestUnreach]
8175 self.assertEqual(icmp.code, 1)
8176 inner = icmp[IPerror6]
8177 self.assertEqual(inner.src, self.pg0.remote_ip6)
8178 self.assertEqual(inner.dst, ip.src)
8179 self.assert_icmpv6_checksum_valid(packet)
8180 if inner.haslayer(TCPerror):
8181 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
8182 elif inner.haslayer(UDPerror):
8183 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
8185 self.assertEqual(inner[ICMPv6EchoRequest].id,
8188 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8191 def test_hairpinning(self):
8192 """ NAT64 hairpinning """
8194 client = self.pg0.remote_hosts[0]
8195 server = self.pg0.remote_hosts[1]
8196 server_tcp_in_port = 22
8197 server_tcp_out_port = 4022
8198 server_udp_in_port = 23
8199 server_udp_out_port = 4023
8200 client_tcp_in_port = 1234
8201 client_udp_in_port = 1235
8202 client_tcp_out_port = 0
8203 client_udp_out_port = 0
8204 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8205 nat_addr_ip6 = ip.src
8207 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8208 end_addr=self.nat_addr,
8211 flags = self.config_flags.NAT_IS_INSIDE
8212 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8213 sw_if_index=self.pg0.sw_if_index)
8214 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8215 sw_if_index=self.pg1.sw_if_index)
8217 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8218 o_addr=self.nat_addr,
8219 i_port=server_tcp_in_port,
8220 o_port=server_tcp_out_port,
8221 proto=IP_PROTOS.tcp, vrf_id=0,
8223 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8224 o_addr=self.nat_addr,
8225 i_port=server_udp_in_port,
8226 o_port=server_udp_out_port,
8227 proto=IP_PROTOS.udp, vrf_id=0,
8232 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8233 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8234 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8236 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8237 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8238 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
8240 self.pg0.add_stream(pkts)
8241 self.pg_enable_capture(self.pg_interfaces)
8243 capture = self.pg0.get_capture(len(pkts))
8244 for packet in capture:
8246 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8247 self.assertEqual(packet[IPv6].dst, server.ip6)
8248 self.assert_packet_checksums_valid(packet)
8249 if packet.haslayer(TCP):
8250 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
8251 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
8252 client_tcp_out_port = packet[TCP].sport
8254 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
8255 self.assertEqual(packet[UDP].dport, server_udp_in_port)
8256 client_udp_out_port = packet[UDP].sport
8258 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8263 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8264 IPv6(src=server.ip6, dst=nat_addr_ip6) /
8265 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
8267 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8268 IPv6(src=server.ip6, dst=nat_addr_ip6) /
8269 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
8271 self.pg0.add_stream(pkts)
8272 self.pg_enable_capture(self.pg_interfaces)
8274 capture = self.pg0.get_capture(len(pkts))
8275 for packet in capture:
8277 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8278 self.assertEqual(packet[IPv6].dst, client.ip6)
8279 self.assert_packet_checksums_valid(packet)
8280 if packet.haslayer(TCP):
8281 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
8282 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
8284 self.assertEqual(packet[UDP].sport, server_udp_out_port)
8285 self.assertEqual(packet[UDP].dport, client_udp_in_port)
8287 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8292 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8293 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8294 ICMPv6DestUnreach(code=1) /
8295 packet[IPv6] for packet in capture]
8296 self.pg0.add_stream(pkts)
8297 self.pg_enable_capture(self.pg_interfaces)
8299 capture = self.pg0.get_capture(len(pkts))
8300 for packet in capture:
8302 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8303 self.assertEqual(packet[IPv6].dst, server.ip6)
8304 icmp = packet[ICMPv6DestUnreach]
8305 self.assertEqual(icmp.code, 1)
8306 inner = icmp[IPerror6]
8307 self.assertEqual(inner.src, server.ip6)
8308 self.assertEqual(inner.dst, nat_addr_ip6)
8309 self.assert_packet_checksums_valid(packet)
8310 if inner.haslayer(TCPerror):
8311 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
8312 self.assertEqual(inner[TCPerror].dport,
8313 client_tcp_out_port)
8315 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
8316 self.assertEqual(inner[UDPerror].dport,
8317 client_udp_out_port)
8319 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8322 def test_prefix(self):
8323 """ NAT64 Network-Specific Prefix """
8325 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8326 end_addr=self.nat_addr,
8329 flags = self.config_flags.NAT_IS_INSIDE
8330 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8331 sw_if_index=self.pg0.sw_if_index)
8332 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8333 sw_if_index=self.pg1.sw_if_index)
8334 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
8335 end_addr=self.vrf1_nat_addr,
8336 vrf_id=self.vrf1_id, is_add=1)
8337 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8338 sw_if_index=self.pg2.sw_if_index)
8341 global_pref64 = "2001:db8::"
8342 global_pref64_len = 32
8343 global_pref64_str = "{}/{}".format(global_pref64, global_pref64_len)
8344 self.vapi.nat64_add_del_prefix(prefix=global_pref64_str, vrf_id=0,
8347 prefix = self.vapi.nat64_prefix_dump()
8348 self.assertEqual(len(prefix), 1)
8349 self.assertEqual(str(prefix[0].prefix), global_pref64_str)
8350 self.assertEqual(prefix[0].vrf_id, 0)
8352 # Add tenant specific prefix
8353 vrf1_pref64 = "2001:db8:122:300::"
8354 vrf1_pref64_len = 56
8355 vrf1_pref64_str = "{}/{}".format(vrf1_pref64, vrf1_pref64_len)
8356 self.vapi.nat64_add_del_prefix(prefix=vrf1_pref64_str,
8357 vrf_id=self.vrf1_id, is_add=1)
8359 prefix = self.vapi.nat64_prefix_dump()
8360 self.assertEqual(len(prefix), 2)
8363 pkts = self.create_stream_in_ip6(self.pg0,
8366 plen=global_pref64_len)
8367 self.pg0.add_stream(pkts)
8368 self.pg_enable_capture(self.pg_interfaces)
8370 capture = self.pg1.get_capture(len(pkts))
8371 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8372 dst_ip=self.pg1.remote_ip4)
8374 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8375 self.pg1.add_stream(pkts)
8376 self.pg_enable_capture(self.pg_interfaces)
8378 capture = self.pg0.get_capture(len(pkts))
8379 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8382 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
8384 # Tenant specific prefix
8385 pkts = self.create_stream_in_ip6(self.pg2,
8388 plen=vrf1_pref64_len)
8389 self.pg2.add_stream(pkts)
8390 self.pg_enable_capture(self.pg_interfaces)
8392 capture = self.pg1.get_capture(len(pkts))
8393 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
8394 dst_ip=self.pg1.remote_ip4)
8396 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
8397 self.pg1.add_stream(pkts)
8398 self.pg_enable_capture(self.pg_interfaces)
8400 capture = self.pg2.get_capture(len(pkts))
8401 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8404 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
8406 def test_unknown_proto(self):
8407 """ NAT64 translate packet with unknown protocol """
8409 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8410 end_addr=self.nat_addr,
8413 flags = self.config_flags.NAT_IS_INSIDE
8414 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8415 sw_if_index=self.pg0.sw_if_index)
8416 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8417 sw_if_index=self.pg1.sw_if_index)
8418 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8421 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8422 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
8423 TCP(sport=self.tcp_port_in, dport=20))
8424 self.pg0.add_stream(p)
8425 self.pg_enable_capture(self.pg_interfaces)
8427 p = self.pg1.get_capture(1)
8429 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8430 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
8432 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8433 TCP(sport=1234, dport=1234))
8434 self.pg0.add_stream(p)
8435 self.pg_enable_capture(self.pg_interfaces)
8437 p = self.pg1.get_capture(1)
8440 self.assertEqual(packet[IP].src, self.nat_addr)
8441 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
8442 self.assertEqual(packet.haslayer(GRE), 1)
8443 self.assert_packet_checksums_valid(packet)
8445 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8449 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8450 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8452 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8453 TCP(sport=1234, dport=1234))
8454 self.pg1.add_stream(p)
8455 self.pg_enable_capture(self.pg_interfaces)
8457 p = self.pg0.get_capture(1)
8460 self.assertEqual(packet[IPv6].src, remote_ip6)
8461 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8462 self.assertEqual(packet[IPv6].nh, 47)
8464 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8467 def test_hairpinning_unknown_proto(self):
8468 """ NAT64 translate packet with unknown protocol - hairpinning """
8470 client = self.pg0.remote_hosts[0]
8471 server = self.pg0.remote_hosts[1]
8472 server_tcp_in_port = 22
8473 server_tcp_out_port = 4022
8474 client_tcp_in_port = 1234
8475 client_tcp_out_port = 1235
8476 server_nat_ip = "10.0.0.100"
8477 client_nat_ip = "10.0.0.110"
8478 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
8479 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
8481 self.vapi.nat64_add_del_pool_addr_range(start_addr=server_nat_ip,
8482 end_addr=client_nat_ip,
8485 flags = self.config_flags.NAT_IS_INSIDE
8486 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8487 sw_if_index=self.pg0.sw_if_index)
8488 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8489 sw_if_index=self.pg1.sw_if_index)
8491 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8492 o_addr=server_nat_ip,
8493 i_port=server_tcp_in_port,
8494 o_port=server_tcp_out_port,
8495 proto=IP_PROTOS.tcp, vrf_id=0,
8498 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8499 o_addr=server_nat_ip, i_port=0,
8501 proto=IP_PROTOS.gre, vrf_id=0,
8504 self.vapi.nat64_add_del_static_bib(i_addr=client.ip6n,
8505 o_addr=client_nat_ip,
8506 i_port=client_tcp_in_port,
8507 o_port=client_tcp_out_port,
8508 proto=IP_PROTOS.tcp, vrf_id=0,
8512 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8513 IPv6(src=client.ip6, dst=server_nat_ip6) /
8514 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8515 self.pg0.add_stream(p)
8516 self.pg_enable_capture(self.pg_interfaces)
8518 p = self.pg0.get_capture(1)
8520 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8521 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
8523 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8524 TCP(sport=1234, dport=1234))
8525 self.pg0.add_stream(p)
8526 self.pg_enable_capture(self.pg_interfaces)
8528 p = self.pg0.get_capture(1)
8531 self.assertEqual(packet[IPv6].src, client_nat_ip6)
8532 self.assertEqual(packet[IPv6].dst, server.ip6)
8533 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
8535 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8539 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8540 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
8542 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8543 TCP(sport=1234, dport=1234))
8544 self.pg0.add_stream(p)
8545 self.pg_enable_capture(self.pg_interfaces)
8547 p = self.pg0.get_capture(1)
8550 self.assertEqual(packet[IPv6].src, server_nat_ip6)
8551 self.assertEqual(packet[IPv6].dst, client.ip6)
8552 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
8554 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8557 def test_one_armed_nat64(self):
8558 """ One armed NAT64 """
8560 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
8564 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8565 end_addr=self.nat_addr,
8568 flags = self.config_flags.NAT_IS_INSIDE
8569 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8570 sw_if_index=self.pg3.sw_if_index)
8571 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8572 sw_if_index=self.pg3.sw_if_index)
8575 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8576 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
8577 TCP(sport=12345, dport=80))
8578 self.pg3.add_stream(p)
8579 self.pg_enable_capture(self.pg_interfaces)
8581 capture = self.pg3.get_capture(1)
8586 self.assertEqual(ip.src, self.nat_addr)
8587 self.assertEqual(ip.dst, self.pg3.remote_ip4)
8588 self.assertNotEqual(tcp.sport, 12345)
8589 external_port = tcp.sport
8590 self.assertEqual(tcp.dport, 80)
8591 self.assert_packet_checksums_valid(p)
8593 self.logger.error(ppp("Unexpected or invalid packet:", p))
8597 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8598 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
8599 TCP(sport=80, dport=external_port))
8600 self.pg3.add_stream(p)
8601 self.pg_enable_capture(self.pg_interfaces)
8603 capture = self.pg3.get_capture(1)
8608 self.assertEqual(ip.src, remote_host_ip6)
8609 self.assertEqual(ip.dst, self.pg3.remote_ip6)
8610 self.assertEqual(tcp.sport, 80)
8611 self.assertEqual(tcp.dport, 12345)
8612 self.assert_packet_checksums_valid(p)
8614 self.logger.error(ppp("Unexpected or invalid packet:", p))
8617 def test_frag_in_order(self):
8618 """ NAT64 translate fragments arriving in order """
8619 self.tcp_port_in = random.randint(1025, 65535)
8621 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8622 end_addr=self.nat_addr,
8625 flags = self.config_flags.NAT_IS_INSIDE
8626 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8627 sw_if_index=self.pg0.sw_if_index)
8628 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8629 sw_if_index=self.pg1.sw_if_index)
8633 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8634 self.tcp_port_in, 20, data)
8635 self.pg0.add_stream(pkts)
8636 self.pg_enable_capture(self.pg_interfaces)
8638 frags = self.pg1.get_capture(len(pkts))
8639 p = self.reass_frags_and_verify(frags,
8641 self.pg1.remote_ip4)
8642 self.assertEqual(p[TCP].dport, 20)
8643 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8644 self.tcp_port_out = p[TCP].sport
8645 self.assertEqual(data, p[Raw].load)
8648 data = b"A" * 4 + b"b" * 16 + b"C" * 3
8649 pkts = self.create_stream_frag(self.pg1,
8654 self.pg1.add_stream(pkts)
8655 self.pg_enable_capture(self.pg_interfaces)
8657 frags = self.pg0.get_capture(len(pkts))
8658 self.logger.debug(ppc("Captured:", frags))
8659 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8660 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8661 self.assertEqual(p[TCP].sport, 20)
8662 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8663 self.assertEqual(data, p[Raw].load)
8665 def test_reass_hairpinning(self):
8666 """ NAT64 fragments hairpinning """
8668 server = self.pg0.remote_hosts[1]
8669 server_in_port = random.randint(1025, 65535)
8670 server_out_port = random.randint(1025, 65535)
8671 client_in_port = random.randint(1025, 65535)
8672 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8673 nat_addr_ip6 = ip.src
8675 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8676 end_addr=self.nat_addr,
8679 flags = self.config_flags.NAT_IS_INSIDE
8680 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8681 sw_if_index=self.pg0.sw_if_index)
8682 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8683 sw_if_index=self.pg1.sw_if_index)
8685 # add static BIB entry for server
8686 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8687 o_addr=self.nat_addr,
8688 i_port=server_in_port,
8689 o_port=server_out_port,
8690 proto=IP_PROTOS.tcp, vrf_id=0,
8693 # send packet from host to server
8694 pkts = self.create_stream_frag_ip6(self.pg0,
8699 self.pg0.add_stream(pkts)
8700 self.pg_enable_capture(self.pg_interfaces)
8702 frags = self.pg0.get_capture(len(pkts))
8703 self.logger.debug(ppc("Captured:", frags))
8704 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
8705 self.assertNotEqual(p[TCP].sport, client_in_port)
8706 self.assertEqual(p[TCP].dport, server_in_port)
8707 self.assertEqual(data, p[Raw].load)
8709 def test_frag_out_of_order(self):
8710 """ NAT64 translate fragments arriving out of order """
8711 self.tcp_port_in = random.randint(1025, 65535)
8713 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8714 end_addr=self.nat_addr,
8717 flags = self.config_flags.NAT_IS_INSIDE
8718 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8719 sw_if_index=self.pg0.sw_if_index)
8720 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8721 sw_if_index=self.pg1.sw_if_index)
8725 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8726 self.tcp_port_in, 20, data)
8728 self.pg0.add_stream(pkts)
8729 self.pg_enable_capture(self.pg_interfaces)
8731 frags = self.pg1.get_capture(len(pkts))
8732 p = self.reass_frags_and_verify(frags,
8734 self.pg1.remote_ip4)
8735 self.assertEqual(p[TCP].dport, 20)
8736 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8737 self.tcp_port_out = p[TCP].sport
8738 self.assertEqual(data, p[Raw].load)
8741 data = b"A" * 4 + b"B" * 16 + b"C" * 3
8742 pkts = self.create_stream_frag(self.pg1,
8748 self.pg1.add_stream(pkts)
8749 self.pg_enable_capture(self.pg_interfaces)
8751 frags = self.pg0.get_capture(len(pkts))
8752 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8753 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8754 self.assertEqual(p[TCP].sport, 20)
8755 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8756 self.assertEqual(data, p[Raw].load)
8758 def test_interface_addr(self):
8759 """ Acquire NAT64 pool addresses from interface """
8760 self.vapi.nat64_add_del_interface_addr(
8762 sw_if_index=self.pg4.sw_if_index)
8764 # no address in NAT64 pool
8765 addresses = self.vapi.nat44_address_dump()
8766 self.assertEqual(0, len(addresses))
8768 # configure interface address and check NAT64 address pool
8769 self.pg4.config_ip4()
8770 addresses = self.vapi.nat64_pool_addr_dump()
8771 self.assertEqual(len(addresses), 1)
8773 self.assertEqual(str(addresses[0].address),
8776 # remove interface address and check NAT64 address pool
8777 self.pg4.unconfig_ip4()
8778 addresses = self.vapi.nat64_pool_addr_dump()
8779 self.assertEqual(0, len(addresses))
8781 @unittest.skipUnless(running_extended_tests, "part of extended tests")
8782 def test_ipfix_max_bibs_sessions(self):
8783 """ IPFIX logging maximum session and BIB entries exceeded """
8786 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8790 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8791 end_addr=self.nat_addr,
8794 flags = self.config_flags.NAT_IS_INSIDE
8795 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8796 sw_if_index=self.pg0.sw_if_index)
8797 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8798 sw_if_index=self.pg1.sw_if_index)
8802 for i in range(0, max_bibs):
8803 src = "fd01:aa::%x" % (i)
8804 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8805 IPv6(src=src, dst=remote_host_ip6) /
8806 TCP(sport=12345, dport=80))
8808 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8809 IPv6(src=src, dst=remote_host_ip6) /
8810 TCP(sport=12345, dport=22))
8812 self.pg0.add_stream(pkts)
8813 self.pg_enable_capture(self.pg_interfaces)
8815 self.pg1.get_capture(max_sessions)
8817 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
8818 src_address=self.pg3.local_ip4,
8820 template_interval=10)
8821 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8822 src_port=self.ipfix_src_port,
8825 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8826 IPv6(src=src, dst=remote_host_ip6) /
8827 TCP(sport=12345, dport=25))
8828 self.pg0.add_stream(p)
8829 self.pg_enable_capture(self.pg_interfaces)
8831 self.pg1.assert_nothing_captured()
8833 self.vapi.ipfix_flush()
8834 capture = self.pg3.get_capture(9)
8835 ipfix = IPFIXDecoder()
8836 # first load template
8838 self.assertTrue(p.haslayer(IPFIX))
8839 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8840 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8841 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8842 self.assertEqual(p[UDP].dport, 4739)
8843 self.assertEqual(p[IPFIX].observationDomainID,
8844 self.ipfix_domain_id)
8845 if p.haslayer(Template):
8846 ipfix.add_template(p.getlayer(Template))
8847 # verify events in data set
8849 if p.haslayer(Data):
8850 data = ipfix.decode_data_set(p.getlayer(Set))
8851 self.verify_ipfix_max_sessions(data, max_sessions)
8853 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8854 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8855 TCP(sport=12345, dport=80))
8856 self.pg0.add_stream(p)
8857 self.pg_enable_capture(self.pg_interfaces)
8859 self.pg1.assert_nothing_captured()
8861 self.vapi.ipfix_flush()
8862 capture = self.pg3.get_capture(1)
8863 # verify events in data set
8865 self.assertTrue(p.haslayer(IPFIX))
8866 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8867 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8868 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8869 self.assertEqual(p[UDP].dport, 4739)
8870 self.assertEqual(p[IPFIX].observationDomainID,
8871 self.ipfix_domain_id)
8872 if p.haslayer(Data):
8873 data = ipfix.decode_data_set(p.getlayer(Set))
8874 self.verify_ipfix_max_bibs(data, max_bibs)
8876 def test_ipfix_bib_ses(self):
8877 """ IPFIX logging NAT64 BIB/session create and delete events """
8878 self.tcp_port_in = random.randint(1025, 65535)
8879 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8883 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8884 end_addr=self.nat_addr,
8887 flags = self.config_flags.NAT_IS_INSIDE
8888 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8889 sw_if_index=self.pg0.sw_if_index)
8890 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8891 sw_if_index=self.pg1.sw_if_index)
8892 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
8893 src_address=self.pg3.local_ip4,
8895 template_interval=10)
8896 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8897 src_port=self.ipfix_src_port,
8901 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8902 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8903 TCP(sport=self.tcp_port_in, dport=25))
8904 self.pg0.add_stream(p)
8905 self.pg_enable_capture(self.pg_interfaces)
8907 p = self.pg1.get_capture(1)
8908 self.tcp_port_out = p[0][TCP].sport
8909 self.vapi.ipfix_flush()
8910 capture = self.pg3.get_capture(10)
8911 ipfix = IPFIXDecoder()
8912 # first load template
8914 self.assertTrue(p.haslayer(IPFIX))
8915 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8916 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8917 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8918 self.assertEqual(p[UDP].dport, 4739)
8919 self.assertEqual(p[IPFIX].observationDomainID,
8920 self.ipfix_domain_id)
8921 if p.haslayer(Template):
8922 ipfix.add_template(p.getlayer(Template))
8923 # verify events in data set
8925 if p.haslayer(Data):
8926 data = ipfix.decode_data_set(p.getlayer(Set))
8927 if scapy.compat.orb(data[0][230]) == 10:
8928 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
8929 elif scapy.compat.orb(data[0][230]) == 6:
8930 self.verify_ipfix_nat64_ses(data,
8932 self.pg0.remote_ip6n,
8933 self.pg1.remote_ip4,
8936 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8939 self.pg_enable_capture(self.pg_interfaces)
8940 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8941 end_addr=self.nat_addr,
8944 self.vapi.ipfix_flush()
8945 capture = self.pg3.get_capture(2)
8946 # verify events in data set
8948 self.assertTrue(p.haslayer(IPFIX))
8949 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8950 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8951 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8952 self.assertEqual(p[UDP].dport, 4739)
8953 self.assertEqual(p[IPFIX].observationDomainID,
8954 self.ipfix_domain_id)
8955 if p.haslayer(Data):
8956 data = ipfix.decode_data_set(p.getlayer(Set))
8957 if scapy.compat.orb(data[0][230]) == 11:
8958 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
8959 elif scapy.compat.orb(data[0][230]) == 7:
8960 self.verify_ipfix_nat64_ses(data,
8962 self.pg0.remote_ip6n,
8963 self.pg1.remote_ip4,
8966 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8968 def test_syslog_sess(self):
8969 """ Test syslog session creation and deletion """
8970 self.tcp_port_in = random.randint(1025, 65535)
8971 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8975 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8976 end_addr=self.nat_addr,
8979 flags = self.config_flags.NAT_IS_INSIDE
8980 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8981 sw_if_index=self.pg0.sw_if_index)
8982 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8983 sw_if_index=self.pg1.sw_if_index)
8984 self.vapi.syslog_set_filter(
8985 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
8986 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
8988 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8989 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8990 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
8991 self.pg0.add_stream(p)
8992 self.pg_enable_capture(self.pg_interfaces)
8994 p = self.pg1.get_capture(1)
8995 self.tcp_port_out = p[0][TCP].sport
8996 capture = self.pg3.get_capture(1)
8997 self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
8999 self.pg_enable_capture(self.pg_interfaces)
9001 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9002 end_addr=self.nat_addr,
9005 capture = self.pg3.get_capture(1)
9006 self.verify_syslog_sess(capture[0][Raw].load, False, True)
9008 def nat64_get_ses_num(self):
9010 Return number of active NAT64 sessions.
9012 st = self.vapi.nat64_st_dump(proto=255)
9015 def clear_nat64(self):
9017 Clear NAT64 configuration.
9019 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
9020 src_port=self.ipfix_src_port,
9022 self.ipfix_src_port = 4739
9023 self.ipfix_domain_id = 1
9025 self.vapi.syslog_set_filter(
9026 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_EMERG)
9028 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
9029 tcp_transitory=240, icmp=60)
9031 interfaces = self.vapi.nat64_interface_dump()
9032 for intf in interfaces:
9033 self.vapi.nat64_add_del_interface(is_add=0, flags=intf.flags,
9034 sw_if_index=intf.sw_if_index)
9036 bib = self.vapi.nat64_bib_dump(proto=255)
9038 if bibe.flags & self.config_flags.NAT_IS_STATIC:
9039 self.vapi.nat64_add_del_static_bib(i_addr=bibe.i_addr,
9047 adresses = self.vapi.nat64_pool_addr_dump()
9048 for addr in adresses:
9049 self.vapi.nat64_add_del_pool_addr_range(start_addr=addr.address,
9050 end_addr=addr.address,
9054 prefixes = self.vapi.nat64_prefix_dump()
9055 for prefix in prefixes:
9056 self.vapi.nat64_add_del_prefix(prefix=str(prefix.prefix),
9057 vrf_id=prefix.vrf_id, is_add=0)
9059 bibs = self.statistics.get_counter('/nat64/total-bibs')
9060 self.assertEqual(bibs[0][0], 0)
9061 sessions = self.statistics.get_counter('/nat64/total-sessions')
9062 self.assertEqual(sessions[0][0], 0)
9065 super(TestNAT64, self).tearDown()
9066 if not self.vpp_dead:
9069 def show_commands_at_teardown(self):
9070 self.logger.info(self.vapi.cli("show nat64 pool"))
9071 self.logger.info(self.vapi.cli("show nat64 interfaces"))
9072 self.logger.info(self.vapi.cli("show nat64 prefix"))
9073 self.logger.info(self.vapi.cli("show nat64 bib all"))
9074 self.logger.info(self.vapi.cli("show nat64 session table all"))
9077 class TestNAT66(MethodHolder):
9078 """ NAT66 Test Cases """
9081 def setUpClass(cls):
9082 super(TestNAT66, cls).setUpClass()
9084 cls.nat_addr = 'fd01:ff::2'
9086 cls.create_pg_interfaces(range(2))
9087 cls.interfaces = list(cls.pg_interfaces)
9089 for i in cls.interfaces:
9092 i.configure_ipv6_neighbors()
9095 def tearDownClass(cls):
9096 super(TestNAT66, cls).tearDownClass()
9098 def test_static(self):
9099 """ 1:1 NAT66 test """
9100 flags = self.config_flags.NAT_IS_INSIDE
9101 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9102 sw_if_index=self.pg0.sw_if_index)
9103 self.vapi.nat66_add_del_interface(is_add=1,
9104 sw_if_index=self.pg1.sw_if_index)
9105 self.vapi.nat66_add_del_static_mapping(
9106 local_ip_address=self.pg0.remote_ip6n,
9107 external_ip_address=self.nat_addr,
9112 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9113 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9116 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9117 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9120 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9121 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9122 ICMPv6EchoRequest())
9124 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9125 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9126 GRE() / IP() / TCP())
9128 self.pg0.add_stream(pkts)
9129 self.pg_enable_capture(self.pg_interfaces)
9131 capture = self.pg1.get_capture(len(pkts))
9133 for packet in capture:
9135 self.assertEqual(packet[IPv6].src, self.nat_addr)
9136 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9137 self.assert_packet_checksums_valid(packet)
9139 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9144 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9145 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9148 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9149 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9152 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9153 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9156 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9157 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9158 GRE() / IP() / TCP())
9160 self.pg1.add_stream(pkts)
9161 self.pg_enable_capture(self.pg_interfaces)
9163 capture = self.pg0.get_capture(len(pkts))
9164 for packet in capture:
9166 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
9167 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
9168 self.assert_packet_checksums_valid(packet)
9170 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9173 sm = self.vapi.nat66_static_mapping_dump()
9174 self.assertEqual(len(sm), 1)
9175 self.assertEqual(sm[0].total_pkts, 8)
9177 def test_check_no_translate(self):
9178 """ NAT66 translate only when egress interface is outside interface """
9179 flags = self.config_flags.NAT_IS_INSIDE
9180 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9181 sw_if_index=self.pg0.sw_if_index)
9182 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9183 sw_if_index=self.pg1.sw_if_index)
9184 self.vapi.nat66_add_del_static_mapping(
9185 local_ip_address=self.pg0.remote_ip6n,
9186 external_ip_address=self.nat_addr,
9190 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9191 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9193 self.pg0.add_stream([p])
9194 self.pg_enable_capture(self.pg_interfaces)
9196 capture = self.pg1.get_capture(1)
9199 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
9200 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9202 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9205 def clear_nat66(self):
9207 Clear NAT66 configuration.
9209 interfaces = self.vapi.nat66_interface_dump()
9210 for intf in interfaces:
9211 self.vapi.nat66_add_del_interface(is_add=0, flags=intf.flags,
9212 sw_if_index=intf.sw_if_index)
9214 static_mappings = self.vapi.nat66_static_mapping_dump()
9215 for sm in static_mappings:
9216 self.vapi.nat66_add_del_static_mapping(
9217 local_ip_address=sm.local_ip_address,
9218 external_ip_address=sm.external_ip_address, vrf_id=sm.vrf_id,
9222 super(TestNAT66, self).tearDown()
9225 def show_commands_at_teardown(self):
9226 self.logger.info(self.vapi.cli("show nat66 interfaces"))
9227 self.logger.info(self.vapi.cli("show nat66 static mappings"))
9230 if __name__ == '__main__':
9231 unittest.main(testRunner=VppTestRunner)