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 TestNAT44EndpointDependent2(MethodHolder):
4191 """ Endpoint-Dependent session test cases """
4196 def setUpConstants(cls):
4197 super(TestNAT44EndpointDependent2, cls).setUpConstants()
4198 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent",
4199 "translation", "hash", "buckets", "1",
4200 "icmp", "timeout", str(cls.icmp_timeout), "}"])
4203 def setUpClass(cls):
4204 super(TestNAT44EndpointDependent2, cls).setUpClass()
4205 translation_buckets = 1
4206 cls.max_translations = 10 * translation_buckets
4208 cls.create_pg_interfaces(range(2))
4209 cls.interfaces = list(cls.pg_interfaces[0:2])
4211 for i in cls.interfaces:
4216 cls.pg0.generate_remote_hosts(1)
4217 cls.pg0.configure_ipv4_neighbors()
4219 cls.pg1.generate_remote_hosts(1)
4220 cls.pg1.configure_ipv4_neighbors()
4223 def tearDownClass(cls):
4224 super(TestNAT44EndpointDependent2, cls).tearDownClass()
4226 def create_icmp_stream(self, in_if, out_if, count):
4228 Create ICMP packet stream for inside network
4230 :param in_if: Inside interface
4231 :param out_if: Outside interface
4232 :param count: Number of packets
4235 self.assertTrue(count > 0)
4236 icmp_id = random.randint(0, 65535 - (count - 1))
4239 for i in range(count):
4240 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4241 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=64) /
4242 ICMP(id=icmp_id + i, type='echo-request'))
4246 def send_pkts(self, pkts, expected=None):
4247 self.pg0.add_stream(pkts)
4248 self.pg_enable_capture(self.pg_interfaces)
4250 return self.pg1.get_capture(
4251 len(pkts) if expected is None else expected)
4253 def test_session_cleanup(self):
4254 """ NAT44 session cleanup test """
4256 self.nat44_add_address(self.pg1.local_ip4)
4257 flags = self.config_flags.NAT_IS_INSIDE
4258 self.vapi.nat44_interface_add_del_feature(
4259 sw_if_index=self.pg0.sw_if_index,
4260 flags=flags, is_add=1)
4261 self.vapi.nat44_interface_add_del_feature(
4262 sw_if_index=self.pg1.sw_if_index,
4265 nat_config = self.vapi.nat_show_config()
4266 self.assertEqual(1, nat_config.endpoint_dependent)
4268 pkts = self.create_icmp_stream(self.pg0, self.pg1,
4269 self.max_translations + 2)
4273 self.send_pkts(pkts[0:self.max_translations])
4275 # false positive test
4276 self.send_pkts(pkts[self.max_translations:sz - 1], 0)
4278 sleep(self.icmp_timeout)
4281 self.send_pkts(pkts[self.max_translations + 1:sz])
4284 class TestNAT44EndpointDependent(MethodHolder):
4285 """ Endpoint-Dependent mapping and filtering test cases """
4288 def setUpConstants(cls):
4289 super(TestNAT44EndpointDependent, cls).setUpConstants()
4290 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4293 def setUpClass(cls):
4294 super(TestNAT44EndpointDependent, cls).setUpClass()
4295 cls.vapi.cli("set log class nat level debug")
4297 cls.tcp_port_in = 6303
4298 cls.tcp_port_out = 6303
4299 cls.udp_port_in = 6304
4300 cls.udp_port_out = 6304
4301 cls.icmp_id_in = 6305
4302 cls.icmp_id_out = 6305
4303 cls.nat_addr = '10.0.0.3'
4304 cls.ipfix_src_port = 4739
4305 cls.ipfix_domain_id = 1
4306 cls.tcp_external_port = 80
4308 cls.create_pg_interfaces(range(9))
4309 cls.interfaces = list(cls.pg_interfaces[0:3])
4311 for i in cls.interfaces:
4316 cls.pg0.generate_remote_hosts(3)
4317 cls.pg0.configure_ipv4_neighbors()
4321 cls.pg4.generate_remote_hosts(2)
4322 cls.pg4.config_ip4()
4323 cls.vapi.sw_interface_add_del_address(
4324 sw_if_index=cls.pg4.sw_if_index,
4325 prefix="10.0.0.1/24")
4328 cls.pg4.resolve_arp()
4329 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4330 cls.pg4.resolve_arp()
4332 zero_ip4 = socket.inet_pton(socket.AF_INET, "0.0.0.0")
4333 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 1})
4335 cls.pg5._local_ip4 = "10.1.1.1"
4336 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4337 cls.pg5.set_table_ip4(1)
4338 cls.pg5.config_ip4()
4340 r1 = VppIpRoute(cls, cls.pg5.remote_ip4, 32,
4341 [VppRoutePath("0.0.0.0",
4342 cls.pg5.sw_if_index)],
4347 cls.pg6._local_ip4 = "10.1.2.1"
4348 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4349 cls.pg6.set_table_ip4(1)
4350 cls.pg6.config_ip4()
4353 r2 = VppIpRoute(cls, cls.pg6.remote_ip4, 32,
4354 [VppRoutePath("0.0.0.0",
4355 cls.pg6.sw_if_index)],
4358 r3 = VppIpRoute(cls, cls.pg6.remote_ip4, 16,
4359 [VppRoutePath("0.0.0.0",
4364 r4 = VppIpRoute(cls, "0.0.0.0", 0,
4365 [VppRoutePath("0.0.0.0", 0xffffffff,
4369 r5 = VppIpRoute(cls, "0.0.0.0", 0,
4370 [VppRoutePath(cls.pg1.local_ip4,
4371 cls.pg1.sw_if_index)],
4378 cls.pg5.resolve_arp()
4379 cls.pg6.resolve_arp()
4382 cls.pg7.config_ip4()
4383 cls.pg7.resolve_arp()
4384 cls.pg7.generate_remote_hosts(3)
4385 cls.pg7.configure_ipv4_neighbors()
4388 cls.pg8.config_ip4()
4389 cls.pg8.resolve_arp()
4392 super(TestNAT44EndpointDependent, self).setUp()
4393 self.vapi.nat_set_timeouts(
4394 udp=300, tcp_established=7440, tcp_transitory=240, icmp=60)
4397 def tearDownClass(cls):
4398 super(TestNAT44EndpointDependent, cls).tearDownClass()
4400 def test_frag_in_order(self):
4401 """ NAT44 translate fragments arriving in order """
4402 self.nat44_add_address(self.nat_addr)
4403 flags = self.config_flags.NAT_IS_INSIDE
4404 self.vapi.nat44_interface_add_del_feature(
4405 sw_if_index=self.pg0.sw_if_index,
4406 flags=flags, is_add=1)
4407 self.vapi.nat44_interface_add_del_feature(
4408 sw_if_index=self.pg1.sw_if_index,
4410 self.frag_in_order(proto=IP_PROTOS.tcp)
4411 self.frag_in_order(proto=IP_PROTOS.udp)
4412 self.frag_in_order(proto=IP_PROTOS.icmp)
4414 def test_frag_in_order_dont_translate(self):
4415 """ NAT44 don't translate fragments arriving in order """
4416 flags = self.config_flags.NAT_IS_INSIDE
4417 self.vapi.nat44_interface_add_del_feature(
4418 sw_if_index=self.pg0.sw_if_index,
4419 flags=flags, is_add=1)
4420 self.vapi.nat44_interface_add_del_feature(
4421 sw_if_index=self.pg1.sw_if_index,
4423 self.vapi.nat44_forwarding_enable_disable(enable=True)
4424 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4426 def test_frag_out_of_order(self):
4427 """ NAT44 translate fragments arriving out of order """
4428 self.nat44_add_address(self.nat_addr)
4429 flags = self.config_flags.NAT_IS_INSIDE
4430 self.vapi.nat44_interface_add_del_feature(
4431 sw_if_index=self.pg0.sw_if_index,
4432 flags=flags, is_add=1)
4433 self.vapi.nat44_interface_add_del_feature(
4434 sw_if_index=self.pg1.sw_if_index,
4436 self.frag_out_of_order(proto=IP_PROTOS.tcp)
4437 self.frag_out_of_order(proto=IP_PROTOS.udp)
4438 self.frag_out_of_order(proto=IP_PROTOS.icmp)
4440 def test_frag_out_of_order_dont_translate(self):
4441 """ NAT44 don't translate fragments arriving out of order """
4442 flags = self.config_flags.NAT_IS_INSIDE
4443 self.vapi.nat44_interface_add_del_feature(
4444 sw_if_index=self.pg0.sw_if_index,
4445 flags=flags, is_add=1)
4446 self.vapi.nat44_interface_add_del_feature(
4447 sw_if_index=self.pg1.sw_if_index,
4449 self.vapi.nat44_forwarding_enable_disable(enable=True)
4450 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4452 def test_frag_in_order_in_plus_out(self):
4453 """ in+out interface fragments in order """
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,
4458 self.vapi.nat44_interface_add_del_feature(
4459 sw_if_index=self.pg0.sw_if_index,
4460 flags=flags, is_add=1)
4461 self.vapi.nat44_interface_add_del_feature(
4462 sw_if_index=self.pg1.sw_if_index,
4464 self.vapi.nat44_interface_add_del_feature(
4465 sw_if_index=self.pg1.sw_if_index,
4466 flags=flags, is_add=1)
4468 self.server = self.pg1.remote_hosts[0]
4470 self.server_in_addr = self.server.ip4
4471 self.server_out_addr = '11.11.11.11'
4472 self.server_in_port = random.randint(1025, 65535)
4473 self.server_out_port = random.randint(1025, 65535)
4475 self.nat44_add_address(self.server_out_addr)
4477 # add static mappings for server
4478 self.nat44_add_static_mapping(self.server_in_addr,
4479 self.server_out_addr,
4480 self.server_in_port,
4481 self.server_out_port,
4482 proto=IP_PROTOS.tcp)
4483 self.nat44_add_static_mapping(self.server_in_addr,
4484 self.server_out_addr,
4485 self.server_in_port,
4486 self.server_out_port,
4487 proto=IP_PROTOS.udp)
4488 self.nat44_add_static_mapping(self.server_in_addr,
4489 self.server_out_addr,
4490 proto=IP_PROTOS.icmp)
4492 self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4493 self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4494 self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4496 def test_frag_out_of_order_in_plus_out(self):
4497 """ in+out interface fragments out of order """
4498 flags = self.config_flags.NAT_IS_INSIDE
4499 self.vapi.nat44_interface_add_del_feature(
4500 sw_if_index=self.pg0.sw_if_index,
4502 self.vapi.nat44_interface_add_del_feature(
4503 sw_if_index=self.pg0.sw_if_index,
4504 flags=flags, is_add=1)
4505 self.vapi.nat44_interface_add_del_feature(
4506 sw_if_index=self.pg1.sw_if_index,
4508 self.vapi.nat44_interface_add_del_feature(
4509 sw_if_index=self.pg1.sw_if_index,
4510 flags=flags, is_add=1)
4512 self.server = self.pg1.remote_hosts[0]
4514 self.server_in_addr = self.server.ip4
4515 self.server_out_addr = '11.11.11.11'
4516 self.server_in_port = random.randint(1025, 65535)
4517 self.server_out_port = random.randint(1025, 65535)
4519 self.nat44_add_address(self.server_out_addr)
4521 # add static mappings for server
4522 self.nat44_add_static_mapping(self.server_in_addr,
4523 self.server_out_addr,
4524 self.server_in_port,
4525 self.server_out_port,
4526 proto=IP_PROTOS.tcp)
4527 self.nat44_add_static_mapping(self.server_in_addr,
4528 self.server_out_addr,
4529 self.server_in_port,
4530 self.server_out_port,
4531 proto=IP_PROTOS.udp)
4532 self.nat44_add_static_mapping(self.server_in_addr,
4533 self.server_out_addr,
4534 proto=IP_PROTOS.icmp)
4536 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4537 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4538 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4540 def test_reass_hairpinning(self):
4541 """ NAT44 fragments hairpinning """
4542 self.server = self.pg0.remote_hosts[1]
4543 self.host_in_port = random.randint(1025, 65535)
4544 self.server_in_port = random.randint(1025, 65535)
4545 self.server_out_port = random.randint(1025, 65535)
4547 self.nat44_add_address(self.nat_addr)
4548 flags = self.config_flags.NAT_IS_INSIDE
4549 self.vapi.nat44_interface_add_del_feature(
4550 sw_if_index=self.pg0.sw_if_index,
4551 flags=flags, is_add=1)
4552 self.vapi.nat44_interface_add_del_feature(
4553 sw_if_index=self.pg1.sw_if_index,
4555 # add static mapping for server
4556 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4557 self.server_in_port,
4558 self.server_out_port,
4559 proto=IP_PROTOS.tcp)
4560 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4561 self.server_in_port,
4562 self.server_out_port,
4563 proto=IP_PROTOS.udp)
4564 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
4566 self.reass_hairpinning(proto=IP_PROTOS.tcp)
4567 self.reass_hairpinning(proto=IP_PROTOS.udp)
4568 self.reass_hairpinning(proto=IP_PROTOS.icmp)
4570 def test_dynamic(self):
4571 """ NAT44 dynamic translation test """
4573 self.nat44_add_address(self.nat_addr)
4574 flags = self.config_flags.NAT_IS_INSIDE
4575 self.vapi.nat44_interface_add_del_feature(
4576 sw_if_index=self.pg0.sw_if_index,
4577 flags=flags, is_add=1)
4578 self.vapi.nat44_interface_add_del_feature(
4579 sw_if_index=self.pg1.sw_if_index,
4582 nat_config = self.vapi.nat_show_config()
4583 self.assertEqual(1, nat_config.endpoint_dependent)
4586 tcpn = self.statistics.get_err_counter(
4587 '/err/nat44-ed-in2out-slowpath/TCP packets')
4588 udpn = self.statistics.get_err_counter(
4589 '/err/nat44-ed-in2out-slowpath/UDP packets')
4590 icmpn = self.statistics.get_err_counter(
4591 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4592 totaln = self.statistics.get_err_counter(
4593 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4595 pkts = self.create_stream_in(self.pg0, self.pg1)
4596 self.pg0.add_stream(pkts)
4597 self.pg_enable_capture(self.pg_interfaces)
4599 capture = self.pg1.get_capture(len(pkts))
4600 self.verify_capture_out(capture)
4602 err = self.statistics.get_err_counter(
4603 '/err/nat44-ed-in2out-slowpath/TCP packets')
4604 self.assertEqual(err - tcpn, 2)
4605 err = self.statistics.get_err_counter(
4606 '/err/nat44-ed-in2out-slowpath/UDP packets')
4607 self.assertEqual(err - udpn, 1)
4608 err = self.statistics.get_err_counter(
4609 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4610 self.assertEqual(err - icmpn, 1)
4611 err = self.statistics.get_err_counter(
4612 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4613 self.assertEqual(err - totaln, 4)
4616 tcpn = self.statistics.get_err_counter(
4617 '/err/nat44-ed-out2in/TCP packets')
4618 udpn = self.statistics.get_err_counter(
4619 '/err/nat44-ed-out2in/UDP packets')
4620 icmpn = self.statistics.get_err_counter(
4621 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4622 totaln = self.statistics.get_err_counter(
4623 '/err/nat44-ed-out2in/good out2in packets processed')
4625 pkts = self.create_stream_out(self.pg1)
4626 self.pg1.add_stream(pkts)
4627 self.pg_enable_capture(self.pg_interfaces)
4629 capture = self.pg0.get_capture(len(pkts))
4630 self.verify_capture_in(capture, self.pg0)
4632 err = self.statistics.get_err_counter(
4633 '/err/nat44-ed-out2in/TCP packets')
4634 self.assertEqual(err - tcpn, 2)
4635 err = self.statistics.get_err_counter(
4636 '/err/nat44-ed-out2in/UDP packets')
4637 self.assertEqual(err - udpn, 1)
4638 err = self.statistics.get_err_counter(
4639 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4640 self.assertEqual(err - icmpn, 1)
4641 err = self.statistics.get_err_counter(
4642 '/err/nat44-ed-out2in/good out2in packets processed')
4643 self.assertEqual(err - totaln, 3)
4645 users = self.statistics.get_counter('/nat44/total-users')
4646 self.assertEqual(users[0][0], 1)
4647 sessions = self.statistics.get_counter('/nat44/total-sessions')
4648 self.assertEqual(sessions[0][0], 3)
4650 def test_dynamic_output_feature_vrf(self):
4651 """ NAT44 dynamic translation test: output-feature, VRF"""
4653 # other then default (0)
4656 self.nat44_add_address(self.nat_addr)
4657 flags = self.config_flags.NAT_IS_INSIDE
4658 self.vapi.nat44_interface_add_del_output_feature(
4659 sw_if_index=self.pg7.sw_if_index,
4660 flags=flags, is_add=1)
4661 self.vapi.nat44_interface_add_del_output_feature(
4662 sw_if_index=self.pg8.sw_if_index,
4666 self.vapi.ip_table_add_del(is_add=1,
4667 table={'table_id': new_vrf_id})
4669 self.pg7.unconfig_ip4()
4670 self.pg7.set_table_ip4(new_vrf_id)
4671 self.pg7.config_ip4()
4672 self.pg7.resolve_arp()
4674 self.pg8.unconfig_ip4()
4675 self.pg8.set_table_ip4(new_vrf_id)
4676 self.pg8.config_ip4()
4677 self.pg8.resolve_arp()
4679 nat_config = self.vapi.nat_show_config()
4680 self.assertEqual(1, nat_config.endpoint_dependent)
4683 tcpn = self.statistics.get_err_counter(
4684 '/err/nat44-ed-in2out-slowpath/TCP packets')
4685 udpn = self.statistics.get_err_counter(
4686 '/err/nat44-ed-in2out-slowpath/UDP packets')
4687 icmpn = self.statistics.get_err_counter(
4688 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4689 totaln = self.statistics.get_err_counter(
4690 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4692 pkts = self.create_stream_in(self.pg7, self.pg8)
4693 self.pg7.add_stream(pkts)
4694 self.pg_enable_capture(self.pg_interfaces)
4696 capture = self.pg8.get_capture(len(pkts))
4697 self.verify_capture_out(capture)
4699 err = self.statistics.get_err_counter(
4700 '/err/nat44-ed-in2out-slowpath/TCP packets')
4701 self.assertEqual(err - tcpn, 2)
4702 err = self.statistics.get_err_counter(
4703 '/err/nat44-ed-in2out-slowpath/UDP packets')
4704 self.assertEqual(err - udpn, 1)
4705 err = self.statistics.get_err_counter(
4706 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4707 self.assertEqual(err - icmpn, 1)
4708 err = self.statistics.get_err_counter(
4709 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4710 self.assertEqual(err - totaln, 4)
4713 tcpn = self.statistics.get_err_counter(
4714 '/err/nat44-ed-out2in/TCP packets')
4715 udpn = self.statistics.get_err_counter(
4716 '/err/nat44-ed-out2in/UDP packets')
4717 icmpn = self.statistics.get_err_counter(
4718 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4719 totaln = self.statistics.get_err_counter(
4720 '/err/nat44-ed-out2in/good out2in packets processed')
4722 pkts = self.create_stream_out(self.pg8)
4723 self.pg8.add_stream(pkts)
4724 self.pg_enable_capture(self.pg_interfaces)
4726 capture = self.pg7.get_capture(len(pkts))
4727 self.verify_capture_in(capture, self.pg7)
4729 err = self.statistics.get_err_counter(
4730 '/err/nat44-ed-out2in/TCP packets')
4731 self.assertEqual(err - tcpn, 2)
4732 err = self.statistics.get_err_counter(
4733 '/err/nat44-ed-out2in/UDP packets')
4734 self.assertEqual(err - udpn, 1)
4735 err = self.statistics.get_err_counter(
4736 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4737 self.assertEqual(err - icmpn, 1)
4738 err = self.statistics.get_err_counter(
4739 '/err/nat44-ed-out2in/good out2in packets processed')
4740 self.assertEqual(err - totaln, 3)
4742 users = self.statistics.get_counter('/nat44/total-users')
4743 self.assertEqual(users[0][0], 1)
4744 sessions = self.statistics.get_counter('/nat44/total-sessions')
4745 self.assertEqual(sessions[0][0], 3)
4748 self.pg7.unconfig_ip4()
4749 self.pg7.set_table_ip4(1)
4750 self.pg7.config_ip4()
4751 self.pg7.resolve_arp()
4753 self.pg8.unconfig_ip4()
4754 self.pg8.set_table_ip4(1)
4755 self.pg8.config_ip4()
4756 self.pg8.resolve_arp()
4758 self.vapi.ip_table_add_del(is_add=0,
4759 table={'table_id': new_vrf_id})
4761 def test_forwarding(self):
4762 """ NAT44 forwarding test """
4764 flags = self.config_flags.NAT_IS_INSIDE
4765 self.vapi.nat44_interface_add_del_feature(
4766 sw_if_index=self.pg0.sw_if_index,
4767 flags=flags, is_add=1)
4768 self.vapi.nat44_interface_add_del_feature(
4769 sw_if_index=self.pg1.sw_if_index,
4771 self.vapi.nat44_forwarding_enable_disable(enable=1)
4773 real_ip = self.pg0.remote_ip4
4774 alias_ip = self.nat_addr
4775 flags = self.config_flags.NAT_IS_ADDR_ONLY
4776 self.vapi.nat44_add_del_static_mapping(is_add=1,
4777 local_ip_address=real_ip,
4778 external_ip_address=alias_ip,
4779 external_sw_if_index=0xFFFFFFFF,
4783 # in2out - static mapping match
4785 pkts = self.create_stream_out(self.pg1)
4786 self.pg1.add_stream(pkts)
4787 self.pg_enable_capture(self.pg_interfaces)
4789 capture = self.pg0.get_capture(len(pkts))
4790 self.verify_capture_in(capture, self.pg0)
4792 pkts = self.create_stream_in(self.pg0, self.pg1)
4793 self.pg0.add_stream(pkts)
4794 self.pg_enable_capture(self.pg_interfaces)
4796 capture = self.pg1.get_capture(len(pkts))
4797 self.verify_capture_out(capture, same_port=True)
4799 # in2out - no static mapping match
4801 host0 = self.pg0.remote_hosts[0]
4802 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4804 pkts = self.create_stream_out(self.pg1,
4805 dst_ip=self.pg0.remote_ip4,
4806 use_inside_ports=True)
4807 self.pg1.add_stream(pkts)
4808 self.pg_enable_capture(self.pg_interfaces)
4810 capture = self.pg0.get_capture(len(pkts))
4811 self.verify_capture_in(capture, self.pg0)
4813 pkts = self.create_stream_in(self.pg0, self.pg1)
4814 self.pg0.add_stream(pkts)
4815 self.pg_enable_capture(self.pg_interfaces)
4817 capture = self.pg1.get_capture(len(pkts))
4818 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4821 self.pg0.remote_hosts[0] = host0
4823 user = self.pg0.remote_hosts[1]
4824 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4825 self.assertEqual(len(sessions), 3)
4826 self.assertTrue(sessions[0].flags &
4827 self.config_flags.NAT_IS_EXT_HOST_VALID)
4828 self.vapi.nat44_del_session(
4829 address=sessions[0].inside_ip_address,
4830 port=sessions[0].inside_port,
4831 protocol=sessions[0].protocol,
4832 flags=(self.config_flags.NAT_IS_INSIDE |
4833 self.config_flags.NAT_IS_EXT_HOST_VALID),
4834 ext_host_address=sessions[0].ext_host_address,
4835 ext_host_port=sessions[0].ext_host_port)
4836 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4837 self.assertEqual(len(sessions), 2)
4840 self.vapi.nat44_forwarding_enable_disable(enable=0)
4841 flags = self.config_flags.NAT_IS_ADDR_ONLY
4842 self.vapi.nat44_add_del_static_mapping(
4844 local_ip_address=real_ip,
4845 external_ip_address=alias_ip,
4846 external_sw_if_index=0xFFFFFFFF,
4849 def test_static_lb(self):
4850 """ NAT44 local service load balancing """
4851 external_addr_n = self.nat_addr
4854 server1 = self.pg0.remote_hosts[0]
4855 server2 = self.pg0.remote_hosts[1]
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(
4869 external_addr=external_addr_n,
4870 external_port=external_port,
4871 protocol=IP_PROTOS.tcp,
4872 local_num=len(locals),
4874 flags = self.config_flags.NAT_IS_INSIDE
4875 self.vapi.nat44_interface_add_del_feature(
4876 sw_if_index=self.pg0.sw_if_index,
4877 flags=flags, is_add=1)
4878 self.vapi.nat44_interface_add_del_feature(
4879 sw_if_index=self.pg1.sw_if_index,
4882 # from client to service
4883 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4884 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4885 TCP(sport=12345, dport=external_port))
4886 self.pg1.add_stream(p)
4887 self.pg_enable_capture(self.pg_interfaces)
4889 capture = self.pg0.get_capture(1)
4895 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4896 if ip.dst == server1.ip4:
4900 self.assertEqual(tcp.dport, local_port)
4901 self.assert_packet_checksums_valid(p)
4903 self.logger.error(ppp("Unexpected or invalid packet:", p))
4906 # from service back to client
4907 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4908 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4909 TCP(sport=local_port, dport=12345))
4910 self.pg0.add_stream(p)
4911 self.pg_enable_capture(self.pg_interfaces)
4913 capture = self.pg1.get_capture(1)
4918 self.assertEqual(ip.src, self.nat_addr)
4919 self.assertEqual(tcp.sport, external_port)
4920 self.assert_packet_checksums_valid(p)
4922 self.logger.error(ppp("Unexpected or invalid packet:", p))
4925 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
4926 self.assertEqual(len(sessions), 1)
4927 self.assertTrue(sessions[0].flags &
4928 self.config_flags.NAT_IS_EXT_HOST_VALID)
4929 self.vapi.nat44_del_session(
4930 address=sessions[0].inside_ip_address,
4931 port=sessions[0].inside_port,
4932 protocol=sessions[0].protocol,
4933 flags=(self.config_flags.NAT_IS_INSIDE |
4934 self.config_flags.NAT_IS_EXT_HOST_VALID),
4935 ext_host_address=sessions[0].ext_host_address,
4936 ext_host_port=sessions[0].ext_host_port)
4937 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
4938 self.assertEqual(len(sessions), 0)
4940 @unittest.skipUnless(running_extended_tests, "part of extended tests")
4941 def test_static_lb_multi_clients(self):
4942 """ NAT44 local service load balancing - multiple clients"""
4944 external_addr = self.nat_addr
4947 server1 = self.pg0.remote_hosts[0]
4948 server2 = self.pg0.remote_hosts[1]
4949 server3 = self.pg0.remote_hosts[2]
4951 locals = [{'addr': server1.ip4,
4955 {'addr': server2.ip4,
4960 self.nat44_add_address(self.nat_addr)
4961 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
4962 external_addr=external_addr,
4963 external_port=external_port,
4964 protocol=IP_PROTOS.tcp,
4965 local_num=len(locals),
4967 flags = self.config_flags.NAT_IS_INSIDE
4968 self.vapi.nat44_interface_add_del_feature(
4969 sw_if_index=self.pg0.sw_if_index,
4970 flags=flags, is_add=1)
4971 self.vapi.nat44_interface_add_del_feature(
4972 sw_if_index=self.pg1.sw_if_index,
4977 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4979 for client in clients:
4980 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4981 IP(src=client, dst=self.nat_addr) /
4982 TCP(sport=12345, dport=external_port))
4984 self.pg1.add_stream(pkts)
4985 self.pg_enable_capture(self.pg_interfaces)
4987 capture = self.pg0.get_capture(len(pkts))
4989 if p[IP].dst == server1.ip4:
4993 self.assertGreater(server1_n, server2_n)
4996 'addr': server3.ip4,
5003 self.vapi.nat44_lb_static_mapping_add_del_local(
5005 external_addr=external_addr,
5006 external_port=external_port,
5008 protocol=IP_PROTOS.tcp)
5012 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
5014 for client in clients:
5015 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5016 IP(src=client, dst=self.nat_addr) /
5017 TCP(sport=12346, dport=external_port))
5019 self.assertGreater(len(pkts), 0)
5020 self.pg1.add_stream(pkts)
5021 self.pg_enable_capture(self.pg_interfaces)
5023 capture = self.pg0.get_capture(len(pkts))
5025 if p[IP].dst == server1.ip4:
5027 elif p[IP].dst == server2.ip4:
5031 self.assertGreater(server1_n, 0)
5032 self.assertGreater(server2_n, 0)
5033 self.assertGreater(server3_n, 0)
5036 'addr': server2.ip4,
5042 # remove one back-end
5043 self.vapi.nat44_lb_static_mapping_add_del_local(
5045 external_addr=external_addr,
5046 external_port=external_port,
5048 protocol=IP_PROTOS.tcp)
5052 self.pg1.add_stream(pkts)
5053 self.pg_enable_capture(self.pg_interfaces)
5055 capture = self.pg0.get_capture(len(pkts))
5057 if p[IP].dst == server1.ip4:
5059 elif p[IP].dst == server2.ip4:
5063 self.assertGreater(server1_n, 0)
5064 self.assertEqual(server2_n, 0)
5065 self.assertGreater(server3_n, 0)
5067 def test_static_lb_2(self):
5068 """ NAT44 local service load balancing (asymmetrical rule) """
5069 external_addr = self.nat_addr
5072 server1 = self.pg0.remote_hosts[0]
5073 server2 = self.pg0.remote_hosts[1]
5075 locals = [{'addr': server1.ip4,
5079 {'addr': server2.ip4,
5084 self.vapi.nat44_forwarding_enable_disable(enable=1)
5085 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5086 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5087 external_addr=external_addr,
5088 external_port=external_port,
5089 protocol=IP_PROTOS.tcp,
5090 local_num=len(locals),
5092 flags = self.config_flags.NAT_IS_INSIDE
5093 self.vapi.nat44_interface_add_del_feature(
5094 sw_if_index=self.pg0.sw_if_index,
5095 flags=flags, is_add=1)
5096 self.vapi.nat44_interface_add_del_feature(
5097 sw_if_index=self.pg1.sw_if_index,
5100 # from client to service
5101 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5102 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5103 TCP(sport=12345, dport=external_port))
5104 self.pg1.add_stream(p)
5105 self.pg_enable_capture(self.pg_interfaces)
5107 capture = self.pg0.get_capture(1)
5113 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
5114 if ip.dst == server1.ip4:
5118 self.assertEqual(tcp.dport, local_port)
5119 self.assert_packet_checksums_valid(p)
5121 self.logger.error(ppp("Unexpected or invalid packet:", p))
5124 # from service back to client
5125 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
5126 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
5127 TCP(sport=local_port, dport=12345))
5128 self.pg0.add_stream(p)
5129 self.pg_enable_capture(self.pg_interfaces)
5131 capture = self.pg1.get_capture(1)
5136 self.assertEqual(ip.src, self.nat_addr)
5137 self.assertEqual(tcp.sport, external_port)
5138 self.assert_packet_checksums_valid(p)
5140 self.logger.error(ppp("Unexpected or invalid packet:", p))
5143 # from client to server (no translation)
5144 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5145 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
5146 TCP(sport=12346, dport=local_port))
5147 self.pg1.add_stream(p)
5148 self.pg_enable_capture(self.pg_interfaces)
5150 capture = self.pg0.get_capture(1)
5156 self.assertEqual(ip.dst, server1.ip4)
5157 self.assertEqual(tcp.dport, local_port)
5158 self.assert_packet_checksums_valid(p)
5160 self.logger.error(ppp("Unexpected or invalid packet:", p))
5163 # from service back to client (no translation)
5164 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
5165 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
5166 TCP(sport=local_port, dport=12346))
5167 self.pg0.add_stream(p)
5168 self.pg_enable_capture(self.pg_interfaces)
5170 capture = self.pg1.get_capture(1)
5175 self.assertEqual(ip.src, server1.ip4)
5176 self.assertEqual(tcp.sport, local_port)
5177 self.assert_packet_checksums_valid(p)
5179 self.logger.error(ppp("Unexpected or invalid packet:", p))
5182 def test_lb_affinity(self):
5183 """ NAT44 local service load balancing affinity """
5184 external_addr = self.nat_addr
5187 server1 = self.pg0.remote_hosts[0]
5188 server2 = self.pg0.remote_hosts[1]
5190 locals = [{'addr': server1.ip4,
5194 {'addr': server2.ip4,
5199 self.nat44_add_address(self.nat_addr)
5200 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
5201 external_addr=external_addr,
5202 external_port=external_port,
5203 protocol=IP_PROTOS.tcp,
5205 local_num=len(locals),
5207 flags = self.config_flags.NAT_IS_INSIDE
5208 self.vapi.nat44_interface_add_del_feature(
5209 sw_if_index=self.pg0.sw_if_index,
5210 flags=flags, is_add=1)
5211 self.vapi.nat44_interface_add_del_feature(
5212 sw_if_index=self.pg1.sw_if_index,
5215 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5216 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5217 TCP(sport=1025, dport=external_port))
5218 self.pg1.add_stream(p)
5219 self.pg_enable_capture(self.pg_interfaces)
5221 capture = self.pg0.get_capture(1)
5222 backend = capture[0][IP].dst
5224 sessions = self.vapi.nat44_user_session_dump(backend, 0)
5225 self.assertEqual(len(sessions), 1)
5226 self.assertTrue(sessions[0].flags &
5227 self.config_flags.NAT_IS_EXT_HOST_VALID)
5228 self.vapi.nat44_del_session(
5229 address=sessions[0].inside_ip_address,
5230 port=sessions[0].inside_port,
5231 protocol=sessions[0].protocol,
5232 flags=(self.config_flags.NAT_IS_INSIDE |
5233 self.config_flags.NAT_IS_EXT_HOST_VALID),
5234 ext_host_address=sessions[0].ext_host_address,
5235 ext_host_port=sessions[0].ext_host_port)
5238 for port in range(1030, 1100):
5239 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5240 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5241 TCP(sport=port, dport=external_port))
5243 self.pg1.add_stream(pkts)
5244 self.pg_enable_capture(self.pg_interfaces)
5246 capture = self.pg0.get_capture(len(pkts))
5248 self.assertEqual(p[IP].dst, backend)
5250 def test_unknown_proto(self):
5251 """ NAT44 translate packet with unknown protocol """
5252 self.nat44_add_address(self.nat_addr)
5253 flags = self.config_flags.NAT_IS_INSIDE
5254 self.vapi.nat44_interface_add_del_feature(
5255 sw_if_index=self.pg0.sw_if_index,
5256 flags=flags, is_add=1)
5257 self.vapi.nat44_interface_add_del_feature(
5258 sw_if_index=self.pg1.sw_if_index,
5262 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5263 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5264 TCP(sport=self.tcp_port_in, dport=20))
5265 self.pg0.add_stream(p)
5266 self.pg_enable_capture(self.pg_interfaces)
5268 p = self.pg1.get_capture(1)
5270 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5271 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5273 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5274 TCP(sport=1234, dport=1234))
5275 self.pg0.add_stream(p)
5276 self.pg_enable_capture(self.pg_interfaces)
5278 p = self.pg1.get_capture(1)
5281 self.assertEqual(packet[IP].src, self.nat_addr)
5282 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5283 self.assertEqual(packet.haslayer(GRE), 1)
5284 self.assert_packet_checksums_valid(packet)
5286 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5290 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5291 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5293 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5294 TCP(sport=1234, dport=1234))
5295 self.pg1.add_stream(p)
5296 self.pg_enable_capture(self.pg_interfaces)
5298 p = self.pg0.get_capture(1)
5301 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
5302 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
5303 self.assertEqual(packet.haslayer(GRE), 1)
5304 self.assert_packet_checksums_valid(packet)
5306 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5309 def test_hairpinning_unknown_proto(self):
5310 """ NAT44 translate packet with unknown protocol - hairpinning """
5311 host = self.pg0.remote_hosts[0]
5312 server = self.pg0.remote_hosts[1]
5314 server_out_port = 8765
5315 server_nat_ip = "10.0.0.11"
5317 self.nat44_add_address(self.nat_addr)
5318 flags = self.config_flags.NAT_IS_INSIDE
5319 self.vapi.nat44_interface_add_del_feature(
5320 sw_if_index=self.pg0.sw_if_index,
5321 flags=flags, is_add=1)
5322 self.vapi.nat44_interface_add_del_feature(
5323 sw_if_index=self.pg1.sw_if_index,
5326 # add static mapping for server
5327 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
5330 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
5331 IP(src=host.ip4, dst=server_nat_ip) /
5332 TCP(sport=host_in_port, dport=server_out_port))
5333 self.pg0.add_stream(p)
5334 self.pg_enable_capture(self.pg_interfaces)
5336 self.pg0.get_capture(1)
5338 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5339 IP(src=host.ip4, dst=server_nat_ip) /
5341 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5342 TCP(sport=1234, dport=1234))
5343 self.pg0.add_stream(p)
5344 self.pg_enable_capture(self.pg_interfaces)
5346 p = self.pg0.get_capture(1)
5349 self.assertEqual(packet[IP].src, self.nat_addr)
5350 self.assertEqual(packet[IP].dst, server.ip4)
5351 self.assertEqual(packet.haslayer(GRE), 1)
5352 self.assert_packet_checksums_valid(packet)
5354 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5358 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5359 IP(src=server.ip4, dst=self.nat_addr) /
5361 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5362 TCP(sport=1234, dport=1234))
5363 self.pg0.add_stream(p)
5364 self.pg_enable_capture(self.pg_interfaces)
5366 p = self.pg0.get_capture(1)
5369 self.assertEqual(packet[IP].src, server_nat_ip)
5370 self.assertEqual(packet[IP].dst, host.ip4)
5371 self.assertEqual(packet.haslayer(GRE), 1)
5372 self.assert_packet_checksums_valid(packet)
5374 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5377 def test_output_feature_and_service(self):
5378 """ NAT44 interface output feature and services """
5379 external_addr = '1.2.3.4'
5383 self.vapi.nat44_forwarding_enable_disable(enable=1)
5384 self.nat44_add_address(self.nat_addr)
5385 flags = self.config_flags.NAT_IS_ADDR_ONLY
5386 self.vapi.nat44_add_del_identity_mapping(
5387 ip_address=self.pg1.remote_ip4, sw_if_index=0xFFFFFFFF,
5388 flags=flags, is_add=1)
5389 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5390 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5391 local_port, external_port,
5392 proto=IP_PROTOS.tcp, flags=flags)
5393 flags = self.config_flags.NAT_IS_INSIDE
5394 self.vapi.nat44_interface_add_del_feature(
5395 sw_if_index=self.pg0.sw_if_index,
5397 self.vapi.nat44_interface_add_del_feature(
5398 sw_if_index=self.pg0.sw_if_index,
5399 flags=flags, is_add=1)
5400 self.vapi.nat44_interface_add_del_output_feature(
5402 sw_if_index=self.pg1.sw_if_index)
5404 # from client to service
5405 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5406 IP(src=self.pg1.remote_ip4, dst=external_addr) /
5407 TCP(sport=12345, dport=external_port))
5408 self.pg1.add_stream(p)
5409 self.pg_enable_capture(self.pg_interfaces)
5411 capture = self.pg0.get_capture(1)
5416 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5417 self.assertEqual(tcp.dport, local_port)
5418 self.assert_packet_checksums_valid(p)
5420 self.logger.error(ppp("Unexpected or invalid packet:", p))
5423 # from service back to client
5424 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5425 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5426 TCP(sport=local_port, dport=12345))
5427 self.pg0.add_stream(p)
5428 self.pg_enable_capture(self.pg_interfaces)
5430 capture = self.pg1.get_capture(1)
5435 self.assertEqual(ip.src, external_addr)
5436 self.assertEqual(tcp.sport, external_port)
5437 self.assert_packet_checksums_valid(p)
5439 self.logger.error(ppp("Unexpected or invalid packet:", p))
5442 # from local network host to external network
5443 pkts = self.create_stream_in(self.pg0, self.pg1)
5444 self.pg0.add_stream(pkts)
5445 self.pg_enable_capture(self.pg_interfaces)
5447 capture = self.pg1.get_capture(len(pkts))
5448 self.verify_capture_out(capture)
5449 pkts = self.create_stream_in(self.pg0, self.pg1)
5450 self.pg0.add_stream(pkts)
5451 self.pg_enable_capture(self.pg_interfaces)
5453 capture = self.pg1.get_capture(len(pkts))
5454 self.verify_capture_out(capture)
5456 # from external network back to local network host
5457 pkts = self.create_stream_out(self.pg1)
5458 self.pg1.add_stream(pkts)
5459 self.pg_enable_capture(self.pg_interfaces)
5461 capture = self.pg0.get_capture(len(pkts))
5462 self.verify_capture_in(capture, self.pg0)
5464 def test_output_feature_and_service2(self):
5465 """ NAT44 interface output feature and service host direct access """
5466 self.vapi.nat44_forwarding_enable_disable(enable=1)
5467 self.nat44_add_address(self.nat_addr)
5468 self.vapi.nat44_interface_add_del_output_feature(
5470 sw_if_index=self.pg1.sw_if_index)
5472 # session initiated from service host - translate
5473 pkts = self.create_stream_in(self.pg0, self.pg1)
5474 self.pg0.add_stream(pkts)
5475 self.pg_enable_capture(self.pg_interfaces)
5477 capture = self.pg1.get_capture(len(pkts))
5478 self.verify_capture_out(capture)
5480 pkts = self.create_stream_out(self.pg1)
5481 self.pg1.add_stream(pkts)
5482 self.pg_enable_capture(self.pg_interfaces)
5484 capture = self.pg0.get_capture(len(pkts))
5485 self.verify_capture_in(capture, self.pg0)
5487 # session initiated from remote host - do not translate
5488 self.tcp_port_in = 60303
5489 self.udp_port_in = 60304
5490 self.icmp_id_in = 60305
5491 pkts = self.create_stream_out(self.pg1,
5492 self.pg0.remote_ip4,
5493 use_inside_ports=True)
5494 self.pg1.add_stream(pkts)
5495 self.pg_enable_capture(self.pg_interfaces)
5497 capture = self.pg0.get_capture(len(pkts))
5498 self.verify_capture_in(capture, self.pg0)
5500 pkts = self.create_stream_in(self.pg0, self.pg1)
5501 self.pg0.add_stream(pkts)
5502 self.pg_enable_capture(self.pg_interfaces)
5504 capture = self.pg1.get_capture(len(pkts))
5505 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5508 def test_output_feature_and_service3(self):
5509 """ NAT44 interface output feature and DST NAT """
5510 external_addr = '1.2.3.4'
5514 self.vapi.nat44_forwarding_enable_disable(enable=1)
5515 self.nat44_add_address(self.nat_addr)
5516 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5517 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5518 local_port, external_port,
5519 proto=IP_PROTOS.tcp, flags=flags)
5520 flags = self.config_flags.NAT_IS_INSIDE
5521 self.vapi.nat44_interface_add_del_feature(
5522 sw_if_index=self.pg0.sw_if_index,
5524 self.vapi.nat44_interface_add_del_feature(
5525 sw_if_index=self.pg0.sw_if_index,
5526 flags=flags, is_add=1)
5527 self.vapi.nat44_interface_add_del_output_feature(
5529 sw_if_index=self.pg1.sw_if_index)
5531 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5532 IP(src=self.pg0.remote_ip4, dst=external_addr) /
5533 TCP(sport=12345, dport=external_port))
5534 self.pg0.add_stream(p)
5535 self.pg_enable_capture(self.pg_interfaces)
5537 capture = self.pg1.get_capture(1)
5542 self.assertEqual(ip.src, self.pg0.remote_ip4)
5543 self.assertEqual(tcp.sport, 12345)
5544 self.assertEqual(ip.dst, self.pg1.remote_ip4)
5545 self.assertEqual(tcp.dport, local_port)
5546 self.assert_packet_checksums_valid(p)
5548 self.logger.error(ppp("Unexpected or invalid packet:", p))
5551 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5552 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5553 TCP(sport=local_port, dport=12345))
5554 self.pg1.add_stream(p)
5555 self.pg_enable_capture(self.pg_interfaces)
5557 capture = self.pg0.get_capture(1)
5562 self.assertEqual(ip.src, external_addr)
5563 self.assertEqual(tcp.sport, external_port)
5564 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5565 self.assertEqual(tcp.dport, 12345)
5566 self.assert_packet_checksums_valid(p)
5568 self.logger.error(ppp("Unexpected or invalid packet:", p))
5571 def test_next_src_nat(self):
5572 """ On way back forward packet to nat44-in2out node. """
5573 twice_nat_addr = '10.0.1.3'
5576 post_twice_nat_port = 0
5578 self.vapi.nat44_forwarding_enable_disable(enable=1)
5579 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5580 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5581 self.config_flags.NAT_IS_SELF_TWICE_NAT)
5582 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5583 local_port, external_port,
5584 proto=IP_PROTOS.tcp, vrf_id=1,
5586 self.vapi.nat44_interface_add_del_feature(
5587 sw_if_index=self.pg6.sw_if_index,
5590 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5591 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5592 TCP(sport=12345, dport=external_port))
5593 self.pg6.add_stream(p)
5594 self.pg_enable_capture(self.pg_interfaces)
5596 capture = self.pg6.get_capture(1)
5601 self.assertEqual(ip.src, twice_nat_addr)
5602 self.assertNotEqual(tcp.sport, 12345)
5603 post_twice_nat_port = tcp.sport
5604 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5605 self.assertEqual(tcp.dport, local_port)
5606 self.assert_packet_checksums_valid(p)
5608 self.logger.error(ppp("Unexpected or invalid packet:", p))
5611 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5612 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5613 TCP(sport=local_port, dport=post_twice_nat_port))
5614 self.pg6.add_stream(p)
5615 self.pg_enable_capture(self.pg_interfaces)
5617 capture = self.pg6.get_capture(1)
5622 self.assertEqual(ip.src, self.pg1.remote_ip4)
5623 self.assertEqual(tcp.sport, external_port)
5624 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5625 self.assertEqual(tcp.dport, 12345)
5626 self.assert_packet_checksums_valid(p)
5628 self.logger.error(ppp("Unexpected or invalid packet:", p))
5631 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5633 twice_nat_addr = '10.0.1.3'
5641 port_in1 = port_in + 1
5642 port_in2 = port_in + 2
5647 server1 = self.pg0.remote_hosts[0]
5648 server2 = self.pg0.remote_hosts[1]
5660 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5663 self.nat44_add_address(self.nat_addr)
5664 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5668 flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
5670 flags |= self.config_flags.NAT_IS_TWICE_NAT
5673 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5675 proto=IP_PROTOS.tcp,
5678 locals = [{'addr': server1.ip4,
5682 {'addr': server2.ip4,
5686 out_addr = self.nat_addr
5688 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5689 external_addr=out_addr,
5690 external_port=port_out,
5691 protocol=IP_PROTOS.tcp,
5692 local_num=len(locals),
5694 flags = self.config_flags.NAT_IS_INSIDE
5695 self.vapi.nat44_interface_add_del_feature(
5696 sw_if_index=pg0.sw_if_index,
5697 flags=flags, is_add=1)
5698 self.vapi.nat44_interface_add_del_feature(
5699 sw_if_index=pg1.sw_if_index,
5706 assert client_id is not None
5708 client = self.pg0.remote_hosts[0]
5709 elif client_id == 2:
5710 client = self.pg0.remote_hosts[1]
5712 client = pg1.remote_hosts[0]
5713 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5714 IP(src=client.ip4, dst=self.nat_addr) /
5715 TCP(sport=eh_port_out, dport=port_out))
5717 self.pg_enable_capture(self.pg_interfaces)
5719 capture = pg0.get_capture(1)
5725 if ip.dst == server1.ip4:
5731 self.assertEqual(ip.dst, server.ip4)
5733 self.assertIn(tcp.dport, [port_in1, port_in2])
5735 self.assertEqual(tcp.dport, port_in)
5737 self.assertEqual(ip.src, twice_nat_addr)
5738 self.assertNotEqual(tcp.sport, eh_port_out)
5740 self.assertEqual(ip.src, client.ip4)
5741 self.assertEqual(tcp.sport, eh_port_out)
5743 eh_port_in = tcp.sport
5744 saved_port_in = tcp.dport
5745 self.assert_packet_checksums_valid(p)
5747 self.logger.error(ppp("Unexpected or invalid packet:", p))
5750 p = (Ether(src=server.mac, dst=pg0.local_mac) /
5751 IP(src=server.ip4, dst=eh_addr_in) /
5752 TCP(sport=saved_port_in, dport=eh_port_in))
5754 self.pg_enable_capture(self.pg_interfaces)
5756 capture = pg1.get_capture(1)
5761 self.assertEqual(ip.dst, client.ip4)
5762 self.assertEqual(ip.src, self.nat_addr)
5763 self.assertEqual(tcp.dport, eh_port_out)
5764 self.assertEqual(tcp.sport, port_out)
5765 self.assert_packet_checksums_valid(p)
5767 self.logger.error(ppp("Unexpected or invalid packet:", p))
5771 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5772 self.assertEqual(len(sessions), 1)
5773 self.assertTrue(sessions[0].flags &
5774 self.config_flags.NAT_IS_EXT_HOST_VALID)
5775 self.assertTrue(sessions[0].flags &
5776 self.config_flags.NAT_IS_TWICE_NAT)
5777 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
5778 self.vapi.nat44_del_session(
5779 address=sessions[0].inside_ip_address,
5780 port=sessions[0].inside_port,
5781 protocol=sessions[0].protocol,
5782 flags=(self.config_flags.NAT_IS_INSIDE |
5783 self.config_flags.NAT_IS_EXT_HOST_VALID),
5784 ext_host_address=sessions[0].ext_host_nat_address,
5785 ext_host_port=sessions[0].ext_host_nat_port)
5786 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5787 self.assertEqual(len(sessions), 0)
5789 def test_twice_nat(self):
5791 self.twice_nat_common()
5793 def test_self_twice_nat_positive(self):
5794 """ Self Twice NAT44 (positive test) """
5795 self.twice_nat_common(self_twice_nat=True, same_pg=True)
5797 def test_self_twice_nat_negative(self):
5798 """ Self Twice NAT44 (negative test) """
5799 self.twice_nat_common(self_twice_nat=True)
5801 def test_twice_nat_lb(self):
5802 """ Twice NAT44 local service load balancing """
5803 self.twice_nat_common(lb=True)
5805 def test_self_twice_nat_lb_positive(self):
5806 """ Self Twice NAT44 local service load balancing (positive test) """
5807 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5810 def test_self_twice_nat_lb_negative(self):
5811 """ Self Twice NAT44 local service load balancing (negative test) """
5812 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5815 def test_twice_nat_interface_addr(self):
5816 """ Acquire twice NAT44 addresses from interface """
5817 flags = self.config_flags.NAT_IS_TWICE_NAT
5818 self.vapi.nat44_add_del_interface_addr(
5820 sw_if_index=self.pg3.sw_if_index,
5823 # no address in NAT pool
5824 adresses = self.vapi.nat44_address_dump()
5825 self.assertEqual(0, len(adresses))
5827 # configure interface address and check NAT address pool
5828 self.pg3.config_ip4()
5829 adresses = self.vapi.nat44_address_dump()
5830 self.assertEqual(1, len(adresses))
5831 self.assertEqual(str(adresses[0].ip_address),
5833 self.assertEqual(adresses[0].flags, flags)
5835 # remove interface address and check NAT address pool
5836 self.pg3.unconfig_ip4()
5837 adresses = self.vapi.nat44_address_dump()
5838 self.assertEqual(0, len(adresses))
5840 def test_tcp_close(self):
5841 """ Close TCP session from inside network - output feature """
5842 self.vapi.nat44_forwarding_enable_disable(enable=1)
5843 self.nat44_add_address(self.pg1.local_ip4)
5844 twice_nat_addr = '10.0.1.3'
5845 service_ip = '192.168.16.150'
5846 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5847 flags = self.config_flags.NAT_IS_INSIDE
5848 self.vapi.nat44_interface_add_del_feature(
5849 sw_if_index=self.pg0.sw_if_index,
5851 self.vapi.nat44_interface_add_del_feature(
5852 sw_if_index=self.pg0.sw_if_index,
5853 flags=flags, is_add=1)
5854 self.vapi.nat44_interface_add_del_output_feature(
5856 sw_if_index=self.pg1.sw_if_index)
5857 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5858 self.config_flags.NAT_IS_TWICE_NAT)
5859 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5863 proto=IP_PROTOS.tcp,
5865 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5866 start_sessnum = len(sessions)
5868 # SYN packet out->in
5869 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5870 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5871 TCP(sport=33898, dport=80, flags="S"))
5872 self.pg1.add_stream(p)
5873 self.pg_enable_capture(self.pg_interfaces)
5875 capture = self.pg0.get_capture(1)
5877 tcp_port = p[TCP].sport
5879 # SYN + ACK packet in->out
5880 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5881 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5882 TCP(sport=80, dport=tcp_port, flags="SA"))
5883 self.pg0.add_stream(p)
5884 self.pg_enable_capture(self.pg_interfaces)
5886 self.pg1.get_capture(1)
5888 # ACK packet out->in
5889 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5890 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5891 TCP(sport=33898, dport=80, flags="A"))
5892 self.pg1.add_stream(p)
5893 self.pg_enable_capture(self.pg_interfaces)
5895 self.pg0.get_capture(1)
5897 # FIN packet in -> out
5898 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5899 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5900 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5901 self.pg0.add_stream(p)
5902 self.pg_enable_capture(self.pg_interfaces)
5904 self.pg1.get_capture(1)
5906 # FIN+ACK packet out -> in
5907 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5908 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5909 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5910 self.pg1.add_stream(p)
5911 self.pg_enable_capture(self.pg_interfaces)
5913 self.pg0.get_capture(1)
5915 # ACK packet in -> out
5916 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5917 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5918 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5919 self.pg0.add_stream(p)
5920 self.pg_enable_capture(self.pg_interfaces)
5922 self.pg1.get_capture(1)
5924 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4,
5926 self.assertEqual(len(sessions) - start_sessnum, 0)
5928 def test_tcp_session_close_in(self):
5929 """ Close TCP session from inside network """
5930 self.tcp_port_out = 10505
5931 self.nat44_add_address(self.nat_addr)
5932 flags = self.config_flags.NAT_IS_TWICE_NAT
5933 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5937 proto=IP_PROTOS.tcp,
5939 flags = self.config_flags.NAT_IS_INSIDE
5940 self.vapi.nat44_interface_add_del_feature(
5941 sw_if_index=self.pg0.sw_if_index,
5942 flags=flags, is_add=1)
5943 self.vapi.nat44_interface_add_del_feature(
5944 sw_if_index=self.pg1.sw_if_index,
5947 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5948 start_sessnum = len(sessions)
5950 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
5951 tcp_transitory=2, icmp=5)
5953 self.initiate_tcp_session(self.pg0, self.pg1)
5955 # FIN packet in -> out
5956 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5957 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5958 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5959 flags="FA", seq=100, ack=300))
5960 self.pg0.add_stream(p)
5961 self.pg_enable_capture(self.pg_interfaces)
5963 self.pg1.get_capture(1)
5967 # ACK packet out -> in
5968 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5969 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5970 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5971 flags="A", seq=300, ack=101))
5974 # FIN packet out -> in
5975 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5976 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5977 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5978 flags="FA", seq=300, ack=101))
5981 self.pg1.add_stream(pkts)
5982 self.pg_enable_capture(self.pg_interfaces)
5984 self.pg0.get_capture(2)
5986 # ACK packet in -> out
5987 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5988 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5989 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5990 flags="A", seq=101, ack=301))
5991 self.pg0.add_stream(p)
5992 self.pg_enable_capture(self.pg_interfaces)
5994 self.pg1.get_capture(1)
5996 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5997 self.assertEqual(len(sessions) - start_sessnum, 1)
5999 stats = self.statistics.get_counter(
6000 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6001 out2in_drops = stats[0]
6002 stats = self.statistics.get_counter(
6003 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6004 in2out_drops = stats[0]
6006 # extra FIN packet out -> in - this should be dropped
6007 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6008 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6009 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6010 flags="FA", seq=300, ack=101))
6012 self.pg1.add_stream(p)
6013 self.pg_enable_capture(self.pg_interfaces)
6015 self.pg0.assert_nothing_captured()
6017 # extra ACK packet in -> out - this should be dropped
6018 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6019 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6020 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6021 flags="A", seq=101, ack=301))
6022 self.pg0.add_stream(p)
6023 self.pg_enable_capture(self.pg_interfaces)
6025 self.pg1.assert_nothing_captured()
6027 stats = self.statistics.get_counter(
6028 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6029 self.assertEqual(stats[0] - out2in_drops, 1)
6030 stats = self.statistics.get_counter(
6031 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6032 self.assertEqual(stats[0] - in2out_drops, 1)
6035 # extra ACK packet in -> out - this will cause session to be wiped
6036 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6037 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6038 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6039 flags="A", seq=101, ack=301))
6040 self.pg0.add_stream(p)
6041 self.pg_enable_capture(self.pg_interfaces)
6043 self.pg1.assert_nothing_captured()
6044 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6045 self.assertEqual(len(sessions) - start_sessnum, 0)
6047 def test_tcp_session_close_out(self):
6048 """ Close TCP session from outside network """
6049 self.tcp_port_out = 10505
6050 self.nat44_add_address(self.nat_addr)
6051 flags = self.config_flags.NAT_IS_TWICE_NAT
6052 self.nat44_add_static_mapping(self.pg0.remote_ip4,
6056 proto=IP_PROTOS.tcp,
6058 flags = self.config_flags.NAT_IS_INSIDE
6059 self.vapi.nat44_interface_add_del_feature(
6060 sw_if_index=self.pg0.sw_if_index,
6061 flags=flags, is_add=1)
6062 self.vapi.nat44_interface_add_del_feature(
6063 sw_if_index=self.pg1.sw_if_index,
6066 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6067 start_sessnum = len(sessions)
6069 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6070 tcp_transitory=2, icmp=5)
6072 self.initiate_tcp_session(self.pg0, self.pg1)
6074 # FIN packet out -> in
6075 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6076 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6077 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6078 flags="FA", seq=100, ack=300))
6079 self.pg1.add_stream(p)
6080 self.pg_enable_capture(self.pg_interfaces)
6082 self.pg0.get_capture(1)
6084 # FIN+ACK packet in -> out
6085 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6086 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6087 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6088 flags="FA", seq=300, ack=101))
6090 self.pg0.add_stream(p)
6091 self.pg_enable_capture(self.pg_interfaces)
6093 self.pg1.get_capture(1)
6095 # ACK packet out -> in
6096 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6097 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6098 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6099 flags="A", seq=101, ack=301))
6100 self.pg1.add_stream(p)
6101 self.pg_enable_capture(self.pg_interfaces)
6103 self.pg0.get_capture(1)
6105 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6106 self.assertEqual(len(sessions) - start_sessnum, 1)
6108 stats = self.statistics.get_counter(
6109 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6110 out2in_drops = stats[0]
6111 stats = self.statistics.get_counter(
6112 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6113 in2out_drops = stats[0]
6115 # extra FIN packet out -> in - this should be dropped
6116 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6117 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6118 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6119 flags="FA", seq=300, ack=101))
6121 self.pg1.add_stream(p)
6122 self.pg_enable_capture(self.pg_interfaces)
6124 self.pg0.assert_nothing_captured()
6126 # extra ACK packet in -> out - this should be dropped
6127 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6128 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6129 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6130 flags="A", seq=101, ack=301))
6131 self.pg0.add_stream(p)
6132 self.pg_enable_capture(self.pg_interfaces)
6134 self.pg1.assert_nothing_captured()
6136 stats = self.statistics.get_counter(
6137 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6138 self.assertEqual(stats[0] - out2in_drops, 1)
6139 stats = self.statistics.get_counter(
6140 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6141 self.assertEqual(stats[0] - in2out_drops, 1)
6144 # extra ACK packet in -> out - this will cause session to be wiped
6145 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6146 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6147 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6148 flags="A", seq=101, ack=301))
6149 self.pg0.add_stream(p)
6150 self.pg_enable_capture(self.pg_interfaces)
6152 self.pg1.assert_nothing_captured()
6153 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6154 self.assertEqual(len(sessions) - start_sessnum, 0)
6156 def test_tcp_session_close_simultaneous(self):
6157 """ Close TCP session from inside network """
6158 self.tcp_port_out = 10505
6159 self.nat44_add_address(self.nat_addr)
6160 flags = self.config_flags.NAT_IS_TWICE_NAT
6161 self.nat44_add_static_mapping(self.pg0.remote_ip4,
6165 proto=IP_PROTOS.tcp,
6167 flags = self.config_flags.NAT_IS_INSIDE
6168 self.vapi.nat44_interface_add_del_feature(
6169 sw_if_index=self.pg0.sw_if_index,
6170 flags=flags, is_add=1)
6171 self.vapi.nat44_interface_add_del_feature(
6172 sw_if_index=self.pg1.sw_if_index,
6175 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6176 start_sessnum = len(sessions)
6178 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6179 tcp_transitory=2, icmp=5)
6181 self.initiate_tcp_session(self.pg0, self.pg1)
6183 # FIN packet in -> out
6184 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6185 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6186 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6187 flags="FA", seq=100, ack=300))
6188 self.pg0.add_stream(p)
6189 self.pg_enable_capture(self.pg_interfaces)
6191 self.pg1.get_capture(1)
6193 # FIN packet out -> in
6194 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6195 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6196 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6197 flags="FA", seq=300, ack=100))
6198 self.pg1.add_stream(p)
6199 self.pg_enable_capture(self.pg_interfaces)
6201 self.pg0.get_capture(1)
6203 # ACK packet in -> out
6204 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6205 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6206 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6207 flags="A", seq=101, ack=301))
6208 self.pg0.add_stream(p)
6209 self.pg_enable_capture(self.pg_interfaces)
6211 self.pg1.get_capture(1)
6213 # ACK packet out -> in
6214 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6215 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6216 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6217 flags="A", seq=301, ack=101))
6218 self.pg1.add_stream(p)
6219 self.pg_enable_capture(self.pg_interfaces)
6221 self.pg0.get_capture(1)
6223 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6224 self.assertEqual(len(sessions) - start_sessnum, 1)
6226 stats = self.statistics.get_counter(
6227 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6228 out2in_drops = stats[0]
6229 stats = self.statistics.get_counter(
6230 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6231 in2out_drops = stats[0]
6233 # extra FIN packet out -> in - this should be dropped
6234 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6235 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6236 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6237 flags="FA", seq=300, ack=101))
6239 self.pg1.add_stream(p)
6240 self.pg_enable_capture(self.pg_interfaces)
6242 self.pg0.assert_nothing_captured()
6244 # extra ACK packet in -> out - this should be dropped
6245 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6246 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6247 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6248 flags="A", seq=101, ack=301))
6249 self.pg0.add_stream(p)
6250 self.pg_enable_capture(self.pg_interfaces)
6252 self.pg1.assert_nothing_captured()
6254 stats = self.statistics.get_counter(
6255 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6256 self.assertEqual(stats[0] - out2in_drops, 1)
6257 stats = self.statistics.get_counter(
6258 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6259 self.assertEqual(stats[0] - in2out_drops, 1)
6262 # extra ACK packet in -> out - this will cause session to be wiped
6263 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6264 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6265 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6266 flags="A", seq=101, ack=301))
6267 self.pg0.add_stream(p)
6268 self.pg_enable_capture(self.pg_interfaces)
6270 self.pg1.assert_nothing_captured()
6271 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6272 self.assertEqual(len(sessions) - start_sessnum, 0)
6274 def test_one_armed_nat44_static(self):
6275 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
6276 remote_host = self.pg4.remote_hosts[0]
6277 local_host = self.pg4.remote_hosts[1]
6282 self.vapi.nat44_forwarding_enable_disable(enable=1)
6283 self.nat44_add_address(self.nat_addr, twice_nat=1)
6284 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
6285 self.config_flags.NAT_IS_TWICE_NAT)
6286 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
6287 local_port, external_port,
6288 proto=IP_PROTOS.tcp, flags=flags)
6289 flags = self.config_flags.NAT_IS_INSIDE
6290 self.vapi.nat44_interface_add_del_feature(
6291 sw_if_index=self.pg4.sw_if_index,
6293 self.vapi.nat44_interface_add_del_feature(
6294 sw_if_index=self.pg4.sw_if_index,
6295 flags=flags, is_add=1)
6297 # from client to service
6298 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6299 IP(src=remote_host.ip4, dst=self.nat_addr) /
6300 TCP(sport=12345, dport=external_port))
6301 self.pg4.add_stream(p)
6302 self.pg_enable_capture(self.pg_interfaces)
6304 capture = self.pg4.get_capture(1)
6309 self.assertEqual(ip.dst, local_host.ip4)
6310 self.assertEqual(ip.src, self.nat_addr)
6311 self.assertEqual(tcp.dport, local_port)
6312 self.assertNotEqual(tcp.sport, 12345)
6313 eh_port_in = tcp.sport
6314 self.assert_packet_checksums_valid(p)
6316 self.logger.error(ppp("Unexpected or invalid packet:", p))
6319 # from service back to client
6320 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6321 IP(src=local_host.ip4, dst=self.nat_addr) /
6322 TCP(sport=local_port, dport=eh_port_in))
6323 self.pg4.add_stream(p)
6324 self.pg_enable_capture(self.pg_interfaces)
6326 capture = self.pg4.get_capture(1)
6331 self.assertEqual(ip.src, self.nat_addr)
6332 self.assertEqual(ip.dst, remote_host.ip4)
6333 self.assertEqual(tcp.sport, external_port)
6334 self.assertEqual(tcp.dport, 12345)
6335 self.assert_packet_checksums_valid(p)
6337 self.logger.error(ppp("Unexpected or invalid packet:", p))
6340 def test_static_with_port_out2(self):
6341 """ 1:1 NAPT asymmetrical rule """
6346 self.vapi.nat44_forwarding_enable_disable(enable=1)
6347 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6348 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
6349 local_port, external_port,
6350 proto=IP_PROTOS.tcp, flags=flags)
6351 flags = self.config_flags.NAT_IS_INSIDE
6352 self.vapi.nat44_interface_add_del_feature(
6353 sw_if_index=self.pg0.sw_if_index,
6354 flags=flags, is_add=1)
6355 self.vapi.nat44_interface_add_del_feature(
6356 sw_if_index=self.pg1.sw_if_index,
6359 # from client to service
6360 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6361 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6362 TCP(sport=12345, dport=external_port))
6363 self.pg1.add_stream(p)
6364 self.pg_enable_capture(self.pg_interfaces)
6366 capture = self.pg0.get_capture(1)
6371 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6372 self.assertEqual(tcp.dport, local_port)
6373 self.assert_packet_checksums_valid(p)
6375 self.logger.error(ppp("Unexpected or invalid packet:", p))
6379 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6380 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6381 ICMP(type=11) / capture[0][IP])
6382 self.pg0.add_stream(p)
6383 self.pg_enable_capture(self.pg_interfaces)
6385 capture = self.pg1.get_capture(1)
6388 self.assertEqual(p[IP].src, self.nat_addr)
6390 self.assertEqual(inner.dst, self.nat_addr)
6391 self.assertEqual(inner[TCPerror].dport, external_port)
6393 self.logger.error(ppp("Unexpected or invalid packet:", p))
6396 # from service back to client
6397 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6398 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6399 TCP(sport=local_port, dport=12345))
6400 self.pg0.add_stream(p)
6401 self.pg_enable_capture(self.pg_interfaces)
6403 capture = self.pg1.get_capture(1)
6408 self.assertEqual(ip.src, self.nat_addr)
6409 self.assertEqual(tcp.sport, external_port)
6410 self.assert_packet_checksums_valid(p)
6412 self.logger.error(ppp("Unexpected or invalid packet:", p))
6416 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6417 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6418 ICMP(type=11) / capture[0][IP])
6419 self.pg1.add_stream(p)
6420 self.pg_enable_capture(self.pg_interfaces)
6422 capture = self.pg0.get_capture(1)
6425 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
6427 self.assertEqual(inner.src, self.pg0.remote_ip4)
6428 self.assertEqual(inner[TCPerror].sport, local_port)
6430 self.logger.error(ppp("Unexpected or invalid packet:", p))
6433 # from client to server (no translation)
6434 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6435 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
6436 TCP(sport=12346, dport=local_port))
6437 self.pg1.add_stream(p)
6438 self.pg_enable_capture(self.pg_interfaces)
6440 capture = self.pg0.get_capture(1)
6445 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6446 self.assertEqual(tcp.dport, local_port)
6447 self.assert_packet_checksums_valid(p)
6449 self.logger.error(ppp("Unexpected or invalid packet:", p))
6452 # from service back to client (no translation)
6453 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6454 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6455 TCP(sport=local_port, dport=12346))
6456 self.pg0.add_stream(p)
6457 self.pg_enable_capture(self.pg_interfaces)
6459 capture = self.pg1.get_capture(1)
6464 self.assertEqual(ip.src, self.pg0.remote_ip4)
6465 self.assertEqual(tcp.sport, local_port)
6466 self.assert_packet_checksums_valid(p)
6468 self.logger.error(ppp("Unexpected or invalid packet:", p))
6471 def test_output_feature(self):
6472 """ NAT44 interface output feature (in2out postrouting) """
6473 self.vapi.nat44_forwarding_enable_disable(enable=1)
6474 self.nat44_add_address(self.nat_addr)
6475 self.vapi.nat44_interface_add_del_feature(
6476 sw_if_index=self.pg0.sw_if_index,
6478 self.vapi.nat44_interface_add_del_output_feature(
6480 sw_if_index=self.pg1.sw_if_index)
6483 pkts = self.create_stream_in(self.pg0, self.pg1)
6484 self.pg0.add_stream(pkts)
6485 self.pg_enable_capture(self.pg_interfaces)
6487 capture = self.pg1.get_capture(len(pkts))
6488 self.verify_capture_out(capture)
6491 pkts = self.create_stream_out(self.pg1)
6492 self.pg1.add_stream(pkts)
6493 self.pg_enable_capture(self.pg_interfaces)
6495 capture = self.pg0.get_capture(len(pkts))
6496 self.verify_capture_in(capture, self.pg0)
6498 def test_output_feature_stateful_acl(self):
6499 """ NAT44 endpoint-dependent output feature works with stateful ACL """
6500 self.nat44_add_address(self.nat_addr)
6501 self.vapi.nat44_interface_add_del_output_feature(
6502 sw_if_index=self.pg0.sw_if_index,
6503 flags=self.config_flags.NAT_IS_INSIDE,
6505 self.vapi.nat44_interface_add_del_output_feature(
6506 sw_if_index=self.pg1.sw_if_index,
6507 flags=self.config_flags.NAT_IS_OUTSIDE,
6510 # First ensure that the NAT is working sans ACL
6512 # send packets out2in, no sessions yet so packets should drop
6513 pkts_out2in = self.create_stream_out(self.pg1)
6514 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
6516 # send packets into inside intf, ensure received via outside intf
6517 pkts_in2out = self.create_stream_in(self.pg0, self.pg1)
6518 capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
6520 self.verify_capture_out(capture)
6522 # send out2in again, with sessions created it should work now
6523 pkts_out2in = self.create_stream_out(self.pg1)
6524 capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
6526 self.verify_capture_in(capture, self.pg0)
6528 # Create an ACL blocking everything
6529 out2in_deny_rule = AclRule(is_permit=0)
6530 out2in_acl = VppAcl(self, rules=[out2in_deny_rule])
6531 out2in_acl.add_vpp_config()
6533 # create an ACL to permit/reflect everything
6534 in2out_reflect_rule = AclRule(is_permit=2)
6535 in2out_acl = VppAcl(self, rules=[in2out_reflect_rule])
6536 in2out_acl.add_vpp_config()
6538 # apply as input acl on interface and confirm it blocks everything
6539 acl_if = VppAclInterface(self, sw_if_index=self.pg1.sw_if_index,
6540 n_input=1, acls=[out2in_acl])
6541 acl_if.add_vpp_config()
6542 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
6545 acl_if.acls = [out2in_acl, in2out_acl]
6546 acl_if.add_vpp_config()
6547 # send in2out to generate ACL state (NAT state was created earlier)
6548 capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
6550 self.verify_capture_out(capture)
6552 # send out2in again. ACL state exists so it should work now.
6553 # TCP packets with the syn flag set also need the ack flag
6554 for p in pkts_out2in:
6555 if p.haslayer(TCP) and p[TCP].flags & 0x02:
6556 p[TCP].flags |= 0x10
6557 capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
6559 self.verify_capture_in(capture, self.pg0)
6560 self.logger.info(self.vapi.cli("show trace"))
6562 def test_multiple_vrf(self):
6563 """ Multiple VRF setup """
6564 external_addr = '1.2.3.4'
6569 self.vapi.nat44_forwarding_enable_disable(enable=1)
6570 self.nat44_add_address(self.nat_addr)
6571 flags = self.config_flags.NAT_IS_INSIDE
6572 self.vapi.nat44_interface_add_del_feature(
6573 sw_if_index=self.pg0.sw_if_index,
6575 self.vapi.nat44_interface_add_del_feature(
6576 sw_if_index=self.pg0.sw_if_index,
6577 flags=flags, is_add=1)
6578 self.vapi.nat44_interface_add_del_output_feature(
6580 sw_if_index=self.pg1.sw_if_index)
6581 self.vapi.nat44_interface_add_del_feature(
6582 sw_if_index=self.pg5.sw_if_index,
6584 self.vapi.nat44_interface_add_del_feature(
6585 sw_if_index=self.pg5.sw_if_index,
6586 flags=flags, is_add=1)
6587 self.vapi.nat44_interface_add_del_feature(
6588 sw_if_index=self.pg6.sw_if_index,
6590 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6591 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
6592 local_port, external_port, vrf_id=1,
6593 proto=IP_PROTOS.tcp, flags=flags)
6594 self.nat44_add_static_mapping(
6595 self.pg0.remote_ip4,
6596 external_sw_if_index=self.pg0.sw_if_index,
6597 local_port=local_port,
6599 external_port=external_port,
6600 proto=IP_PROTOS.tcp,
6604 # from client to service (both VRF1)
6605 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6606 IP(src=self.pg6.remote_ip4, dst=external_addr) /
6607 TCP(sport=12345, dport=external_port))
6608 self.pg6.add_stream(p)
6609 self.pg_enable_capture(self.pg_interfaces)
6611 capture = self.pg5.get_capture(1)
6616 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6617 self.assertEqual(tcp.dport, local_port)
6618 self.assert_packet_checksums_valid(p)
6620 self.logger.error(ppp("Unexpected or invalid packet:", p))
6623 # from service back to client (both VRF1)
6624 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6625 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6626 TCP(sport=local_port, dport=12345))
6627 self.pg5.add_stream(p)
6628 self.pg_enable_capture(self.pg_interfaces)
6630 capture = self.pg6.get_capture(1)
6635 self.assertEqual(ip.src, external_addr)
6636 self.assertEqual(tcp.sport, external_port)
6637 self.assert_packet_checksums_valid(p)
6639 self.logger.error(ppp("Unexpected or invalid packet:", p))
6642 # dynamic NAT from VRF1 to VRF0 (output-feature)
6643 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6644 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6645 TCP(sport=2345, dport=22))
6646 self.pg5.add_stream(p)
6647 self.pg_enable_capture(self.pg_interfaces)
6649 capture = self.pg1.get_capture(1)
6654 self.assertEqual(ip.src, self.nat_addr)
6655 self.assertNotEqual(tcp.sport, 2345)
6656 self.assert_packet_checksums_valid(p)
6659 self.logger.error(ppp("Unexpected or invalid packet:", p))
6662 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6663 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6664 TCP(sport=22, dport=port))
6665 self.pg1.add_stream(p)
6666 self.pg_enable_capture(self.pg_interfaces)
6668 capture = self.pg5.get_capture(1)
6673 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6674 self.assertEqual(tcp.dport, 2345)
6675 self.assert_packet_checksums_valid(p)
6677 self.logger.error(ppp("Unexpected or invalid packet:", p))
6680 # from client VRF1 to service VRF0
6681 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6682 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6683 TCP(sport=12346, dport=external_port))
6684 self.pg6.add_stream(p)
6685 self.pg_enable_capture(self.pg_interfaces)
6687 capture = self.pg0.get_capture(1)
6692 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6693 self.assertEqual(tcp.dport, local_port)
6694 self.assert_packet_checksums_valid(p)
6696 self.logger.error(ppp("Unexpected or invalid packet:", p))
6699 # from service VRF0 back to client VRF1
6700 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6701 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6702 TCP(sport=local_port, dport=12346))
6703 self.pg0.add_stream(p)
6704 self.pg_enable_capture(self.pg_interfaces)
6706 capture = self.pg6.get_capture(1)
6711 self.assertEqual(ip.src, self.pg0.local_ip4)
6712 self.assertEqual(tcp.sport, external_port)
6713 self.assert_packet_checksums_valid(p)
6715 self.logger.error(ppp("Unexpected or invalid packet:", p))
6718 # from client VRF0 to service VRF1
6719 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6720 IP(src=self.pg0.remote_ip4, dst=external_addr) /
6721 TCP(sport=12347, dport=external_port))
6722 self.pg0.add_stream(p)
6723 self.pg_enable_capture(self.pg_interfaces)
6725 capture = self.pg5.get_capture(1)
6730 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6731 self.assertEqual(tcp.dport, local_port)
6732 self.assert_packet_checksums_valid(p)
6734 self.logger.error(ppp("Unexpected or invalid packet:", p))
6737 # from service VRF1 back to client VRF0
6738 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6739 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6740 TCP(sport=local_port, dport=12347))
6741 self.pg5.add_stream(p)
6742 self.pg_enable_capture(self.pg_interfaces)
6744 capture = self.pg0.get_capture(1)
6749 self.assertEqual(ip.src, external_addr)
6750 self.assertEqual(tcp.sport, external_port)
6751 self.assert_packet_checksums_valid(p)
6753 self.logger.error(ppp("Unexpected or invalid packet:", p))
6756 # from client to server (both VRF1, no translation)
6757 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6758 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6759 TCP(sport=12348, dport=local_port))
6760 self.pg6.add_stream(p)
6761 self.pg_enable_capture(self.pg_interfaces)
6763 capture = self.pg5.get_capture(1)
6768 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6769 self.assertEqual(tcp.dport, local_port)
6770 self.assert_packet_checksums_valid(p)
6772 self.logger.error(ppp("Unexpected or invalid packet:", p))
6775 # from server back to client (both VRF1, no translation)
6776 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6777 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6778 TCP(sport=local_port, dport=12348))
6779 self.pg5.add_stream(p)
6780 self.pg_enable_capture(self.pg_interfaces)
6782 capture = self.pg6.get_capture(1)
6787 self.assertEqual(ip.src, self.pg5.remote_ip4)
6788 self.assertEqual(tcp.sport, local_port)
6789 self.assert_packet_checksums_valid(p)
6791 self.logger.error(ppp("Unexpected or invalid packet:", p))
6794 # from client VRF1 to server VRF0 (no translation)
6795 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6796 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6797 TCP(sport=local_port, dport=12349))
6798 self.pg0.add_stream(p)
6799 self.pg_enable_capture(self.pg_interfaces)
6801 capture = self.pg6.get_capture(1)
6806 self.assertEqual(ip.src, self.pg0.remote_ip4)
6807 self.assertEqual(tcp.sport, local_port)
6808 self.assert_packet_checksums_valid(p)
6810 self.logger.error(ppp("Unexpected or invalid packet:", p))
6813 # from server VRF0 back to client VRF1 (no translation)
6814 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6815 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6816 TCP(sport=local_port, dport=12349))
6817 self.pg0.add_stream(p)
6818 self.pg_enable_capture(self.pg_interfaces)
6820 capture = self.pg6.get_capture(1)
6825 self.assertEqual(ip.src, self.pg0.remote_ip4)
6826 self.assertEqual(tcp.sport, local_port)
6827 self.assert_packet_checksums_valid(p)
6829 self.logger.error(ppp("Unexpected or invalid packet:", p))
6832 # from client VRF0 to server VRF1 (no translation)
6833 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6834 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6835 TCP(sport=12344, dport=local_port))
6836 self.pg0.add_stream(p)
6837 self.pg_enable_capture(self.pg_interfaces)
6839 capture = self.pg5.get_capture(1)
6844 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6845 self.assertEqual(tcp.dport, local_port)
6846 self.assert_packet_checksums_valid(p)
6848 self.logger.error(ppp("Unexpected or invalid packet:", p))
6851 # from server VRF1 back to client VRF0 (no translation)
6852 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6853 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6854 TCP(sport=local_port, dport=12344))
6855 self.pg5.add_stream(p)
6856 self.pg_enable_capture(self.pg_interfaces)
6858 capture = self.pg0.get_capture(1)
6863 self.assertEqual(ip.src, self.pg5.remote_ip4)
6864 self.assertEqual(tcp.sport, local_port)
6865 self.assert_packet_checksums_valid(p)
6867 self.logger.error(ppp("Unexpected or invalid packet:", p))
6870 @unittest.skipUnless(running_extended_tests, "part of extended tests")
6871 def test_session_timeout(self):
6872 """ NAT44 session timeouts """
6873 self.nat44_add_address(self.nat_addr)
6874 flags = self.config_flags.NAT_IS_INSIDE
6875 self.vapi.nat44_interface_add_del_feature(
6876 sw_if_index=self.pg0.sw_if_index,
6877 flags=flags, is_add=1)
6878 self.vapi.nat44_interface_add_del_feature(
6879 sw_if_index=self.pg1.sw_if_index,
6881 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6882 tcp_transitory=240, icmp=5)
6886 for i in range(0, max_sessions):
6887 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6888 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6889 IP(src=src, dst=self.pg1.remote_ip4) /
6890 ICMP(id=1025, type='echo-request'))
6892 self.pg0.add_stream(pkts)
6893 self.pg_enable_capture(self.pg_interfaces)
6895 self.pg1.get_capture(max_sessions)
6900 for i in range(0, max_sessions):
6901 src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6902 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6903 IP(src=src, dst=self.pg1.remote_ip4) /
6904 ICMP(id=1026, type='echo-request'))
6906 self.pg0.add_stream(pkts)
6907 self.pg_enable_capture(self.pg_interfaces)
6909 self.pg1.get_capture(max_sessions)
6912 users = self.vapi.nat44_user_dump()
6914 nsessions = nsessions + user.nsessions
6915 self.assertLess(nsessions, 2 * max_sessions)
6917 @unittest.skipUnless(running_extended_tests, "part of extended tests")
6918 def test_session_rst_timeout(self):
6919 """ NAT44 session RST timeouts """
6920 self.nat44_add_address(self.nat_addr)
6921 flags = self.config_flags.NAT_IS_INSIDE
6922 self.vapi.nat44_interface_add_del_feature(
6923 sw_if_index=self.pg0.sw_if_index,
6924 flags=flags, is_add=1)
6925 self.vapi.nat44_interface_add_del_feature(
6926 sw_if_index=self.pg1.sw_if_index,
6928 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6929 tcp_transitory=5, icmp=60)
6931 self.initiate_tcp_session(self.pg0, self.pg1)
6932 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6933 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6934 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6936 self.pg0.add_stream(p)
6937 self.pg_enable_capture(self.pg_interfaces)
6939 self.pg1.get_capture(1)
6943 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6944 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6945 TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6947 self.pg0.add_stream(p)
6948 self.pg_enable_capture(self.pg_interfaces)
6950 self.pg1.get_capture(1)
6953 users = self.vapi.nat44_user_dump()
6954 self.assertEqual(len(users), 1)
6955 self.assertEqual(str(users[0].ip_address),
6956 self.pg0.remote_ip4)
6957 self.assertEqual(users[0].nsessions, 1)
6959 def test_syslog_sess(self):
6960 """ Test syslog session creation and deletion """
6961 self.vapi.syslog_set_filter(
6962 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
6963 self.vapi.syslog_set_sender(self.pg2.local_ip4, self.pg2.remote_ip4)
6964 self.nat44_add_address(self.nat_addr)
6965 flags = self.config_flags.NAT_IS_INSIDE
6966 self.vapi.nat44_interface_add_del_feature(
6967 sw_if_index=self.pg0.sw_if_index,
6968 flags=flags, is_add=1)
6969 self.vapi.nat44_interface_add_del_feature(
6970 sw_if_index=self.pg1.sw_if_index,
6973 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6974 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6975 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6976 self.pg0.add_stream(p)
6977 self.pg_enable_capture(self.pg_interfaces)
6979 capture = self.pg1.get_capture(1)
6980 self.tcp_port_out = capture[0][TCP].sport
6981 capture = self.pg2.get_capture(1)
6982 self.verify_syslog_sess(capture[0][Raw].load)
6984 self.pg_enable_capture(self.pg_interfaces)
6986 self.nat44_add_address(self.nat_addr, is_add=0)
6987 capture = self.pg2.get_capture(1)
6988 self.verify_syslog_sess(capture[0][Raw].load, False)
6991 super(TestNAT44EndpointDependent, self).tearDown()
6992 if not self.vpp_dead:
6994 self.vapi.cli("clear logging")
6996 def show_commands_at_teardown(self):
6997 self.logger.info(self.vapi.cli("show nat44 addresses"))
6998 self.logger.info(self.vapi.cli("show nat44 interfaces"))
6999 self.logger.info(self.vapi.cli("show nat44 static mappings"))
7000 self.logger.info(self.vapi.cli("show nat44 interface address"))
7001 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
7002 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
7003 self.logger.info(self.vapi.cli("show nat timeouts"))
7006 class TestNAT44Out2InDPO(MethodHolder):
7007 """ NAT44 Test Cases using out2in DPO """
7010 def setUpConstants(cls):
7011 super(TestNAT44Out2InDPO, cls).setUpConstants()
7012 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
7015 def setUpClass(cls):
7016 super(TestNAT44Out2InDPO, cls).setUpClass()
7017 cls.vapi.cli("set log class nat level debug")
7019 cls.tcp_port_in = 6303
7020 cls.tcp_port_out = 6303
7021 cls.udp_port_in = 6304
7022 cls.udp_port_out = 6304
7023 cls.icmp_id_in = 6305
7024 cls.icmp_id_out = 6305
7025 cls.nat_addr = '10.0.0.3'
7026 cls.dst_ip4 = '192.168.70.1'
7028 cls.create_pg_interfaces(range(2))
7031 cls.pg0.config_ip4()
7032 cls.pg0.resolve_arp()
7035 cls.pg1.config_ip6()
7036 cls.pg1.resolve_ndp()
7038 r1 = VppIpRoute(cls, "::", 0,
7039 [VppRoutePath(cls.pg1.remote_ip6,
7040 cls.pg1.sw_if_index)],
7045 def tearDownClass(cls):
7046 super(TestNAT44Out2InDPO, cls).tearDownClass()
7048 def configure_xlat(self):
7049 self.dst_ip6_pfx = '1:2:3::'
7050 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
7052 self.dst_ip6_pfx_len = 96
7053 self.src_ip6_pfx = '4:5:6::'
7054 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
7056 self.src_ip6_pfx_len = 96
7057 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
7058 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
7059 '\x00\x00\x00\x00', 0)
7061 @unittest.skip('Temporary disabled')
7062 def test_464xlat_ce(self):
7063 """ Test 464XLAT CE with NAT44 """
7065 nat_config = self.vapi.nat_show_config()
7066 self.assertEqual(1, nat_config.out2in_dpo)
7068 self.configure_xlat()
7070 flags = self.config_flags.NAT_IS_INSIDE
7071 self.vapi.nat44_interface_add_del_feature(
7072 sw_if_index=self.pg0.sw_if_index,
7073 flags=flags, is_add=1)
7074 self.vapi.nat44_add_del_address_range(first_ip_address=self.nat_addr_n,
7075 last_ip_address=self.nat_addr_n,
7076 vrf_id=0xFFFFFFFF, is_add=1)
7078 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7079 self.dst_ip6_pfx_len)
7080 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
7081 self.src_ip6_pfx_len)
7084 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7085 self.pg0.add_stream(pkts)
7086 self.pg_enable_capture(self.pg_interfaces)
7088 capture = self.pg1.get_capture(len(pkts))
7089 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
7092 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
7094 self.pg1.add_stream(pkts)
7095 self.pg_enable_capture(self.pg_interfaces)
7097 capture = self.pg0.get_capture(len(pkts))
7098 self.verify_capture_in(capture, self.pg0)
7100 self.vapi.nat44_interface_add_del_feature(
7101 sw_if_index=self.pg0.sw_if_index,
7103 self.vapi.nat44_add_del_address_range(
7104 first_ip_address=self.nat_addr_n,
7105 last_ip_address=self.nat_addr_n,
7108 @unittest.skip('Temporary disabled')
7109 def test_464xlat_ce_no_nat(self):
7110 """ Test 464XLAT CE without NAT44 """
7112 self.configure_xlat()
7114 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7115 self.dst_ip6_pfx_len)
7116 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
7117 self.src_ip6_pfx_len)
7119 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7120 self.pg0.add_stream(pkts)
7121 self.pg_enable_capture(self.pg_interfaces)
7123 capture = self.pg1.get_capture(len(pkts))
7124 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
7125 nat_ip=out_dst_ip6, same_port=True)
7127 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
7128 self.pg1.add_stream(pkts)
7129 self.pg_enable_capture(self.pg_interfaces)
7131 capture = self.pg0.get_capture(len(pkts))
7132 self.verify_capture_in(capture, self.pg0)
7135 class TestDeterministicNAT(MethodHolder):
7136 """ Deterministic NAT Test Cases """
7139 def setUpConstants(cls):
7140 super(TestDeterministicNAT, cls).setUpConstants()
7141 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
7144 def setUpClass(cls):
7145 super(TestDeterministicNAT, cls).setUpClass()
7146 cls.vapi.cli("set log class nat level debug")
7148 cls.tcp_port_in = 6303
7149 cls.tcp_external_port = 6303
7150 cls.udp_port_in = 6304
7151 cls.udp_external_port = 6304
7152 cls.icmp_id_in = 6305
7153 cls.nat_addr = '10.0.0.3'
7155 cls.create_pg_interfaces(range(3))
7156 cls.interfaces = list(cls.pg_interfaces)
7158 for i in cls.interfaces:
7163 cls.pg0.generate_remote_hosts(2)
7164 cls.pg0.configure_ipv4_neighbors()
7167 def tearDownClass(cls):
7168 super(TestDeterministicNAT, cls).tearDownClass()
7170 def create_stream_in(self, in_if, out_if, ttl=64):
7172 Create packet stream for inside network
7174 :param in_if: Inside interface
7175 :param out_if: Outside interface
7176 :param ttl: TTL of generated packets
7180 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7181 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7182 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
7186 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7187 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7188 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
7192 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7193 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7194 ICMP(id=self.icmp_id_in, type='echo-request'))
7199 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
7201 Create packet stream for outside network
7203 :param out_if: Outside interface
7204 :param dst_ip: Destination IP address (Default use global NAT address)
7205 :param ttl: TTL of generated packets
7208 dst_ip = self.nat_addr
7211 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7212 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7213 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
7217 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7218 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7219 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
7223 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7224 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7225 ICMP(id=self.icmp_external_id, type='echo-reply'))
7230 def verify_capture_out(self, capture, nat_ip=None):
7232 Verify captured packets on outside network
7234 :param capture: Captured packets
7235 :param nat_ip: Translated IP address (Default use global NAT address)
7236 :param same_port: Source port number is not translated (Default False)
7239 nat_ip = self.nat_addr
7240 for packet in capture:
7242 self.assertEqual(packet[IP].src, nat_ip)
7243 if packet.haslayer(TCP):
7244 self.tcp_port_out = packet[TCP].sport
7245 elif packet.haslayer(UDP):
7246 self.udp_port_out = packet[UDP].sport
7248 self.icmp_external_id = packet[ICMP].id
7250 self.logger.error(ppp("Unexpected or invalid packet "
7251 "(outside network):", packet))
7254 def test_deterministic_mode(self):
7255 """ NAT plugin run deterministic mode """
7256 in_addr = '172.16.255.0'
7257 out_addr = '172.17.255.50'
7258 in_addr_t = '172.16.255.20'
7262 nat_config = self.vapi.nat_show_config()
7263 self.assertEqual(1, nat_config.deterministic)
7265 self.vapi.nat_det_add_del_map(is_add=1, in_addr=in_addr,
7266 in_plen=in_plen, out_addr=out_addr,
7269 rep1 = self.vapi.nat_det_forward(in_addr_t)
7270 self.assertEqual(str(rep1.out_addr), out_addr)
7271 rep2 = self.vapi.nat_det_reverse(rep1.out_port_hi, out_addr)
7273 self.assertEqual(str(rep2.in_addr), in_addr_t)
7275 deterministic_mappings = self.vapi.nat_det_map_dump()
7276 self.assertEqual(len(deterministic_mappings), 1)
7277 dsm = deterministic_mappings[0]
7278 self.assertEqual(in_addr, str(dsm.in_addr))
7279 self.assertEqual(in_plen, dsm.in_plen)
7280 self.assertEqual(out_addr, str(dsm.out_addr))
7281 self.assertEqual(out_plen, dsm.out_plen)
7283 self.clear_nat_det()
7284 deterministic_mappings = self.vapi.nat_det_map_dump()
7285 self.assertEqual(len(deterministic_mappings), 0)
7287 def test_set_timeouts(self):
7288 """ Set deterministic NAT timeouts """
7289 timeouts_before = self.vapi.nat_get_timeouts()
7291 self.vapi.nat_set_timeouts(
7292 udp=timeouts_before.udp + 10,
7293 tcp_established=timeouts_before.tcp_established + 10,
7294 tcp_transitory=timeouts_before.tcp_transitory + 10,
7295 icmp=timeouts_before.icmp + 10)
7297 timeouts_after = self.vapi.nat_get_timeouts()
7299 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
7300 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
7301 self.assertNotEqual(timeouts_before.tcp_established,
7302 timeouts_after.tcp_established)
7303 self.assertNotEqual(timeouts_before.tcp_transitory,
7304 timeouts_after.tcp_transitory)
7306 def test_det_in(self):
7307 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
7309 nat_ip = "10.0.0.10"
7311 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7313 out_addr=socket.inet_aton(nat_ip),
7316 flags = self.config_flags.NAT_IS_INSIDE
7317 self.vapi.nat44_interface_add_del_feature(
7318 sw_if_index=self.pg0.sw_if_index,
7319 flags=flags, is_add=1)
7320 self.vapi.nat44_interface_add_del_feature(
7321 sw_if_index=self.pg1.sw_if_index,
7325 pkts = self.create_stream_in(self.pg0, self.pg1)
7326 self.pg0.add_stream(pkts)
7327 self.pg_enable_capture(self.pg_interfaces)
7329 capture = self.pg1.get_capture(len(pkts))
7330 self.verify_capture_out(capture, nat_ip)
7333 pkts = self.create_stream_out(self.pg1, nat_ip)
7334 self.pg1.add_stream(pkts)
7335 self.pg_enable_capture(self.pg_interfaces)
7337 capture = self.pg0.get_capture(len(pkts))
7338 self.verify_capture_in(capture, self.pg0)
7341 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4)
7342 self.assertEqual(len(sessions), 3)
7346 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7347 self.assertEqual(s.in_port, self.tcp_port_in)
7348 self.assertEqual(s.out_port, self.tcp_port_out)
7349 self.assertEqual(s.ext_port, self.tcp_external_port)
7353 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7354 self.assertEqual(s.in_port, self.udp_port_in)
7355 self.assertEqual(s.out_port, self.udp_port_out)
7356 self.assertEqual(s.ext_port, self.udp_external_port)
7360 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7361 self.assertEqual(s.in_port, self.icmp_id_in)
7362 self.assertEqual(s.out_port, self.icmp_external_id)
7364 def test_multiple_users(self):
7365 """ Deterministic NAT multiple users """
7367 nat_ip = "10.0.0.10"
7369 external_port = 6303
7371 host0 = self.pg0.remote_hosts[0]
7372 host1 = self.pg0.remote_hosts[1]
7374 self.vapi.nat_det_add_del_map(is_add=1, in_addr=host0.ip4, in_plen=24,
7375 out_addr=socket.inet_aton(nat_ip),
7377 flags = self.config_flags.NAT_IS_INSIDE
7378 self.vapi.nat44_interface_add_del_feature(
7379 sw_if_index=self.pg0.sw_if_index,
7380 flags=flags, is_add=1)
7381 self.vapi.nat44_interface_add_del_feature(
7382 sw_if_index=self.pg1.sw_if_index,
7386 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
7387 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
7388 TCP(sport=port_in, dport=external_port))
7389 self.pg0.add_stream(p)
7390 self.pg_enable_capture(self.pg_interfaces)
7392 capture = self.pg1.get_capture(1)
7397 self.assertEqual(ip.src, nat_ip)
7398 self.assertEqual(ip.dst, self.pg1.remote_ip4)
7399 self.assertEqual(tcp.dport, external_port)
7400 port_out0 = tcp.sport
7402 self.logger.error(ppp("Unexpected or invalid packet:", p))
7406 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
7407 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
7408 TCP(sport=port_in, dport=external_port))
7409 self.pg0.add_stream(p)
7410 self.pg_enable_capture(self.pg_interfaces)
7412 capture = self.pg1.get_capture(1)
7417 self.assertEqual(ip.src, nat_ip)
7418 self.assertEqual(ip.dst, self.pg1.remote_ip4)
7419 self.assertEqual(tcp.dport, external_port)
7420 port_out1 = tcp.sport
7422 self.logger.error(ppp("Unexpected or invalid packet:", p))
7425 dms = self.vapi.nat_det_map_dump()
7426 self.assertEqual(1, len(dms))
7427 self.assertEqual(2, dms[0].ses_num)
7430 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7431 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
7432 TCP(sport=external_port, dport=port_out0))
7433 self.pg1.add_stream(p)
7434 self.pg_enable_capture(self.pg_interfaces)
7436 capture = self.pg0.get_capture(1)
7441 self.assertEqual(ip.src, self.pg1.remote_ip4)
7442 self.assertEqual(ip.dst, host0.ip4)
7443 self.assertEqual(tcp.dport, port_in)
7444 self.assertEqual(tcp.sport, external_port)
7446 self.logger.error(ppp("Unexpected or invalid packet:", p))
7450 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7451 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
7452 TCP(sport=external_port, dport=port_out1))
7453 self.pg1.add_stream(p)
7454 self.pg_enable_capture(self.pg_interfaces)
7456 capture = self.pg0.get_capture(1)
7461 self.assertEqual(ip.src, self.pg1.remote_ip4)
7462 self.assertEqual(ip.dst, host1.ip4)
7463 self.assertEqual(tcp.dport, port_in)
7464 self.assertEqual(tcp.sport, external_port)
7466 self.logger.error(ppp("Unexpected or invalid packet", p))
7469 # session close api test
7470 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
7472 self.pg1.remote_ip4,
7474 dms = self.vapi.nat_det_map_dump()
7475 self.assertEqual(dms[0].ses_num, 1)
7477 self.vapi.nat_det_close_session_in(host0.ip4,
7479 self.pg1.remote_ip4,
7481 dms = self.vapi.nat_det_map_dump()
7482 self.assertEqual(dms[0].ses_num, 0)
7484 def test_tcp_session_close_detection_in(self):
7485 """ Deterministic NAT TCP session close from inside network """
7486 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7488 out_addr=socket.inet_aton(self.nat_addr),
7490 flags = self.config_flags.NAT_IS_INSIDE
7491 self.vapi.nat44_interface_add_del_feature(
7492 sw_if_index=self.pg0.sw_if_index,
7493 flags=flags, is_add=1)
7494 self.vapi.nat44_interface_add_del_feature(
7495 sw_if_index=self.pg1.sw_if_index,
7498 self.initiate_tcp_session(self.pg0, self.pg1)
7500 # close the session from inside
7502 # FIN packet in -> out
7503 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7504 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7505 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7507 self.pg0.add_stream(p)
7508 self.pg_enable_capture(self.pg_interfaces)
7510 self.pg1.get_capture(1)
7514 # ACK packet out -> in
7515 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7516 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7517 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7521 # FIN packet out -> in
7522 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7523 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7524 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7528 self.pg1.add_stream(pkts)
7529 self.pg_enable_capture(self.pg_interfaces)
7531 self.pg0.get_capture(2)
7533 # ACK packet in -> out
7534 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7535 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7536 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7538 self.pg0.add_stream(p)
7539 self.pg_enable_capture(self.pg_interfaces)
7541 self.pg1.get_capture(1)
7543 # Check if deterministic NAT44 closed the session
7544 dms = self.vapi.nat_det_map_dump()
7545 self.assertEqual(0, dms[0].ses_num)
7547 self.logger.error("TCP session termination failed")
7550 def test_tcp_session_close_detection_out(self):
7551 """ Deterministic NAT TCP session close from outside network """
7552 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7554 out_addr=socket.inet_aton(self.nat_addr),
7556 flags = self.config_flags.NAT_IS_INSIDE
7557 self.vapi.nat44_interface_add_del_feature(
7558 sw_if_index=self.pg0.sw_if_index,
7559 flags=flags, is_add=1)
7560 self.vapi.nat44_interface_add_del_feature(
7561 sw_if_index=self.pg1.sw_if_index,
7564 self.initiate_tcp_session(self.pg0, self.pg1)
7566 # close the session from outside
7568 # FIN packet out -> in
7569 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7570 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7571 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7573 self.pg1.add_stream(p)
7574 self.pg_enable_capture(self.pg_interfaces)
7576 self.pg0.get_capture(1)
7580 # ACK packet in -> out
7581 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7582 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7583 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7587 # ACK packet in -> out
7588 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7589 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7590 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7594 self.pg0.add_stream(pkts)
7595 self.pg_enable_capture(self.pg_interfaces)
7597 self.pg1.get_capture(2)
7599 # ACK packet out -> in
7600 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7601 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7602 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7604 self.pg1.add_stream(p)
7605 self.pg_enable_capture(self.pg_interfaces)
7607 self.pg0.get_capture(1)
7609 # Check if deterministic NAT44 closed the session
7610 dms = self.vapi.nat_det_map_dump()
7611 self.assertEqual(0, dms[0].ses_num)
7613 self.logger.error("TCP session termination failed")
7616 @unittest.skipUnless(running_extended_tests, "part of extended tests")
7617 def test_session_timeout(self):
7618 """ Deterministic NAT session timeouts """
7619 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7621 out_addr=socket.inet_aton(self.nat_addr),
7623 flags = self.config_flags.NAT_IS_INSIDE
7624 self.vapi.nat44_interface_add_del_feature(
7625 sw_if_index=self.pg0.sw_if_index,
7626 flags=flags, is_add=1)
7627 self.vapi.nat44_interface_add_del_feature(
7628 sw_if_index=self.pg1.sw_if_index,
7631 self.initiate_tcp_session(self.pg0, self.pg1)
7632 self.vapi.nat_set_timeouts(udp=5, tcp_established=5, tcp_transitory=5,
7634 pkts = self.create_stream_in(self.pg0, self.pg1)
7635 self.pg0.add_stream(pkts)
7636 self.pg_enable_capture(self.pg_interfaces)
7638 capture = self.pg1.get_capture(len(pkts))
7641 dms = self.vapi.nat_det_map_dump()
7642 self.assertEqual(0, dms[0].ses_num)
7644 @unittest.skipUnless(running_extended_tests, "part of extended tests")
7645 def test_session_limit_per_user(self):
7646 """ Deterministic NAT maximum sessions per user limit """
7647 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7649 out_addr=socket.inet_aton(self.nat_addr),
7651 flags = self.config_flags.NAT_IS_INSIDE
7652 self.vapi.nat44_interface_add_del_feature(
7653 sw_if_index=self.pg0.sw_if_index,
7654 flags=flags, is_add=1)
7655 self.vapi.nat44_interface_add_del_feature(
7656 sw_if_index=self.pg1.sw_if_index,
7658 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4,
7659 src_address=self.pg2.local_ip4,
7661 template_interval=10)
7662 self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7666 for port in range(1025, 2025):
7667 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7668 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7669 UDP(sport=port, dport=port))
7672 self.pg0.add_stream(pkts)
7673 self.pg_enable_capture(self.pg_interfaces)
7675 capture = self.pg1.get_capture(len(pkts))
7677 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7678 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7679 UDP(sport=3001, dport=3002))
7680 self.pg0.add_stream(p)
7681 self.pg_enable_capture(self.pg_interfaces)
7683 capture = self.pg1.assert_nothing_captured()
7685 # verify ICMP error packet
7686 capture = self.pg0.get_capture(1)
7688 self.assertTrue(p.haslayer(ICMP))
7690 self.assertEqual(icmp.type, 3)
7691 self.assertEqual(icmp.code, 1)
7692 self.assertTrue(icmp.haslayer(IPerror))
7693 inner_ip = icmp[IPerror]
7694 self.assertEqual(inner_ip[UDPerror].sport, 3001)
7695 self.assertEqual(inner_ip[UDPerror].dport, 3002)
7697 dms = self.vapi.nat_det_map_dump()
7699 self.assertEqual(1000, dms[0].ses_num)
7701 # verify IPFIX logging
7702 self.vapi.ipfix_flush()
7704 capture = self.pg2.get_capture(2)
7705 ipfix = IPFIXDecoder()
7706 # first load template
7708 self.assertTrue(p.haslayer(IPFIX))
7709 if p.haslayer(Template):
7710 ipfix.add_template(p.getlayer(Template))
7711 # verify events in data set
7713 if p.haslayer(Data):
7714 data = ipfix.decode_data_set(p.getlayer(Set))
7715 self.verify_ipfix_max_entries_per_user(data,
7717 self.pg0.remote_ip4)
7719 def clear_nat_det(self):
7721 Clear deterministic NAT configuration.
7723 self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7725 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
7726 tcp_transitory=240, icmp=60)
7727 deterministic_mappings = self.vapi.nat_det_map_dump()
7728 for dsm in deterministic_mappings:
7729 self.vapi.nat_det_add_del_map(is_add=0, in_addr=dsm.in_addr,
7730 in_plen=dsm.in_plen,
7731 out_addr=dsm.out_addr,
7732 out_plen=dsm.out_plen)
7734 interfaces = self.vapi.nat44_interface_dump()
7735 for intf in interfaces:
7736 self.vapi.nat44_interface_add_del_feature(
7737 sw_if_index=intf.sw_if_index,
7741 super(TestDeterministicNAT, self).tearDown()
7742 if not self.vpp_dead:
7743 self.clear_nat_det()
7745 def show_commands_at_teardown(self):
7746 self.logger.info(self.vapi.cli("show nat44 interfaces"))
7747 self.logger.info(self.vapi.cli("show nat timeouts"))
7749 self.vapi.cli("show nat44 deterministic mappings"))
7751 self.vapi.cli("show nat44 deterministic sessions"))
7754 class TestNAT64(MethodHolder):
7755 """ NAT64 Test Cases """
7758 def setUpConstants(cls):
7759 super(TestNAT64, cls).setUpConstants()
7760 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
7761 "nat64 st hash buckets 256", "}"])
7764 def setUpClass(cls):
7765 super(TestNAT64, cls).setUpClass()
7767 cls.tcp_port_in = 6303
7768 cls.tcp_port_out = 6303
7769 cls.udp_port_in = 6304
7770 cls.udp_port_out = 6304
7771 cls.icmp_id_in = 6305
7772 cls.icmp_id_out = 6305
7773 cls.tcp_external_port = 80
7774 cls.nat_addr = '10.0.0.3'
7775 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
7777 cls.vrf1_nat_addr = '10.0.10.3'
7778 cls.ipfix_src_port = 4739
7779 cls.ipfix_domain_id = 1
7781 cls.create_pg_interfaces(range(6))
7782 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
7783 cls.ip6_interfaces.append(cls.pg_interfaces[2])
7784 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
7786 cls.vapi.ip_table_add_del(is_add=1,
7787 table={'table_id': cls.vrf1_id,
7790 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
7792 cls.pg0.generate_remote_hosts(2)
7794 for i in cls.ip6_interfaces:
7797 i.configure_ipv6_neighbors()
7799 for i in cls.ip4_interfaces:
7805 cls.pg3.config_ip4()
7806 cls.pg3.resolve_arp()
7807 cls.pg3.config_ip6()
7808 cls.pg3.configure_ipv6_neighbors()
7811 cls.pg5.config_ip6()
7814 def tearDownClass(cls):
7815 super(TestNAT64, cls).tearDownClass()
7817 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
7818 """ NAT64 inside interface handles Neighbor Advertisement """
7820 flags = self.config_flags.NAT_IS_INSIDE
7821 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7822 sw_if_index=self.pg5.sw_if_index)
7825 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7826 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7827 ICMPv6EchoRequest())
7829 self.pg5.add_stream(pkts)
7830 self.pg_enable_capture(self.pg_interfaces)
7833 # Wait for Neighbor Solicitation
7834 capture = self.pg5.get_capture(len(pkts))
7837 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7838 self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
7839 tgt = packet[ICMPv6ND_NS].tgt
7841 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7844 # Send Neighbor Advertisement
7845 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7846 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7847 ICMPv6ND_NA(tgt=tgt) /
7848 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
7850 self.pg5.add_stream(pkts)
7851 self.pg_enable_capture(self.pg_interfaces)
7854 # Try to send ping again
7856 self.pg5.add_stream(pkts)
7857 self.pg_enable_capture(self.pg_interfaces)
7860 # Wait for ping reply
7861 capture = self.pg5.get_capture(len(pkts))
7864 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7865 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
7866 self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
7868 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7871 def test_pool(self):
7872 """ Add/delete address to NAT64 pool """
7873 nat_addr = '1.2.3.4'
7875 self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7877 vrf_id=0xFFFFFFFF, is_add=1)
7879 addresses = self.vapi.nat64_pool_addr_dump()
7880 self.assertEqual(len(addresses), 1)
7881 self.assertEqual(str(addresses[0].address), nat_addr)
7883 self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7885 vrf_id=0xFFFFFFFF, is_add=0)
7887 addresses = self.vapi.nat64_pool_addr_dump()
7888 self.assertEqual(len(addresses), 0)
7890 def test_interface(self):
7891 """ Enable/disable NAT64 feature on the interface """
7892 flags = self.config_flags.NAT_IS_INSIDE
7893 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7894 sw_if_index=self.pg0.sw_if_index)
7895 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7896 sw_if_index=self.pg1.sw_if_index)
7898 interfaces = self.vapi.nat64_interface_dump()
7899 self.assertEqual(len(interfaces), 2)
7902 for intf in interfaces:
7903 if intf.sw_if_index == self.pg0.sw_if_index:
7904 self.assertEqual(intf.flags, self.config_flags.NAT_IS_INSIDE)
7906 elif intf.sw_if_index == self.pg1.sw_if_index:
7907 self.assertEqual(intf.flags, self.config_flags.NAT_IS_OUTSIDE)
7909 self.assertTrue(pg0_found)
7910 self.assertTrue(pg1_found)
7912 features = self.vapi.cli("show interface features pg0")
7913 self.assertIn('nat64-in2out', features)
7914 features = self.vapi.cli("show interface features pg1")
7915 self.assertIn('nat64-out2in', features)
7917 self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7918 sw_if_index=self.pg0.sw_if_index)
7919 self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7920 sw_if_index=self.pg1.sw_if_index)
7922 interfaces = self.vapi.nat64_interface_dump()
7923 self.assertEqual(len(interfaces), 0)
7925 def test_static_bib(self):
7926 """ Add/delete static BIB entry """
7927 in_addr = '2001:db8:85a3::8a2e:370:7334'
7928 out_addr = '10.1.1.3'
7931 proto = IP_PROTOS.tcp
7933 self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7934 i_port=in_port, o_port=out_port,
7935 proto=proto, vrf_id=0, is_add=1)
7936 bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
7939 if bibe.flags & self.config_flags.NAT_IS_STATIC:
7941 self.assertEqual(str(bibe.i_addr), in_addr)
7942 self.assertEqual(str(bibe.o_addr), out_addr)
7943 self.assertEqual(bibe.i_port, in_port)
7944 self.assertEqual(bibe.o_port, out_port)
7945 self.assertEqual(static_bib_num, 1)
7946 bibs = self.statistics.get_counter('/nat64/total-bibs')
7947 self.assertEqual(bibs[0][0], 1)
7949 self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7950 i_port=in_port, o_port=out_port,
7951 proto=proto, vrf_id=0, is_add=0)
7952 bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
7955 if bibe.flags & self.config_flags.NAT_IS_STATIC:
7957 self.assertEqual(static_bib_num, 0)
7958 bibs = self.statistics.get_counter('/nat64/total-bibs')
7959 self.assertEqual(bibs[0][0], 0)
7961 def test_set_timeouts(self):
7962 """ Set NAT64 timeouts """
7963 # verify default values
7964 timeouts = self.vapi.nat_get_timeouts()
7965 self.assertEqual(timeouts.udp, 300)
7966 self.assertEqual(timeouts.icmp, 60)
7967 self.assertEqual(timeouts.tcp_transitory, 240)
7968 self.assertEqual(timeouts.tcp_established, 7440)
7970 # set and verify custom values
7971 self.vapi.nat_set_timeouts(udp=200, tcp_established=7450,
7972 tcp_transitory=250, icmp=30)
7973 timeouts = self.vapi.nat_get_timeouts()
7974 self.assertEqual(timeouts.udp, 200)
7975 self.assertEqual(timeouts.icmp, 30)
7976 self.assertEqual(timeouts.tcp_transitory, 250)
7977 self.assertEqual(timeouts.tcp_established, 7450)
7979 def test_dynamic(self):
7980 """ NAT64 dynamic translation test """
7981 self.tcp_port_in = 6303
7982 self.udp_port_in = 6304
7983 self.icmp_id_in = 6305
7985 ses_num_start = self.nat64_get_ses_num()
7987 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
7988 end_addr=self.nat_addr,
7991 flags = self.config_flags.NAT_IS_INSIDE
7992 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7993 sw_if_index=self.pg0.sw_if_index)
7994 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7995 sw_if_index=self.pg1.sw_if_index)
7998 tcpn = self.statistics.get_err_counter('/err/nat64-in2out/TCP packets')
7999 udpn = self.statistics.get_err_counter('/err/nat64-in2out/UDP packets')
8000 icmpn = self.statistics.get_err_counter(
8001 '/err/nat64-in2out/ICMP packets')
8002 totaln = self.statistics.get_err_counter(
8003 '/err/nat64-in2out/good in2out packets processed')
8005 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8006 self.pg0.add_stream(pkts)
8007 self.pg_enable_capture(self.pg_interfaces)
8009 capture = self.pg1.get_capture(len(pkts))
8010 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8011 dst_ip=self.pg1.remote_ip4)
8013 err = self.statistics.get_err_counter('/err/nat64-in2out/TCP packets')
8014 self.assertEqual(err - tcpn, 1)
8015 err = self.statistics.get_err_counter('/err/nat64-in2out/UDP packets')
8016 self.assertEqual(err - udpn, 1)
8017 err = self.statistics.get_err_counter('/err/nat64-in2out/ICMP packets')
8018 self.assertEqual(err - icmpn, 1)
8019 err = self.statistics.get_err_counter(
8020 '/err/nat64-in2out/good in2out packets processed')
8021 self.assertEqual(err - totaln, 3)
8024 tcpn = self.statistics.get_err_counter('/err/nat64-out2in/TCP packets')
8025 udpn = self.statistics.get_err_counter('/err/nat64-out2in/UDP packets')
8026 icmpn = self.statistics.get_err_counter(
8027 '/err/nat64-out2in/ICMP packets')
8028 totaln = self.statistics.get_err_counter(
8029 '/err/nat64-out2in/good out2in packets processed')
8031 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8032 self.pg1.add_stream(pkts)
8033 self.pg_enable_capture(self.pg_interfaces)
8035 capture = self.pg0.get_capture(len(pkts))
8036 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8037 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8039 err = self.statistics.get_err_counter('/err/nat64-out2in/TCP packets')
8040 self.assertEqual(err - tcpn, 2)
8041 err = self.statistics.get_err_counter('/err/nat64-out2in/UDP packets')
8042 self.assertEqual(err - udpn, 1)
8043 err = self.statistics.get_err_counter('/err/nat64-out2in/ICMP packets')
8044 self.assertEqual(err - icmpn, 1)
8045 err = self.statistics.get_err_counter(
8046 '/err/nat64-out2in/good out2in packets processed')
8047 self.assertEqual(err - totaln, 4)
8049 bibs = self.statistics.get_counter('/nat64/total-bibs')
8050 self.assertEqual(bibs[0][0], 3)
8051 sessions = self.statistics.get_counter('/nat64/total-sessions')
8052 self.assertEqual(sessions[0][0], 3)
8055 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8056 self.pg0.add_stream(pkts)
8057 self.pg_enable_capture(self.pg_interfaces)
8059 capture = self.pg1.get_capture(len(pkts))
8060 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8061 dst_ip=self.pg1.remote_ip4)
8064 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8065 self.pg1.add_stream(pkts)
8066 self.pg_enable_capture(self.pg_interfaces)
8068 capture = self.pg0.get_capture(len(pkts))
8069 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8071 ses_num_end = self.nat64_get_ses_num()
8073 self.assertEqual(ses_num_end - ses_num_start, 3)
8075 # tenant with specific VRF
8076 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
8077 end_addr=self.vrf1_nat_addr,
8078 vrf_id=self.vrf1_id, is_add=1)
8079 flags = self.config_flags.NAT_IS_INSIDE
8080 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8081 sw_if_index=self.pg2.sw_if_index)
8083 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
8084 self.pg2.add_stream(pkts)
8085 self.pg_enable_capture(self.pg_interfaces)
8087 capture = self.pg1.get_capture(len(pkts))
8088 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
8089 dst_ip=self.pg1.remote_ip4)
8091 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
8092 self.pg1.add_stream(pkts)
8093 self.pg_enable_capture(self.pg_interfaces)
8095 capture = self.pg2.get_capture(len(pkts))
8096 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
8098 def test_static(self):
8099 """ NAT64 static translation test """
8100 self.tcp_port_in = 60303
8101 self.udp_port_in = 60304
8102 self.icmp_id_in = 60305
8103 self.tcp_port_out = 60303
8104 self.udp_port_out = 60304
8105 self.icmp_id_out = 60305
8107 ses_num_start = self.nat64_get_ses_num()
8109 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8110 end_addr=self.nat_addr,
8113 flags = self.config_flags.NAT_IS_INSIDE
8114 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8115 sw_if_index=self.pg0.sw_if_index)
8116 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8117 sw_if_index=self.pg1.sw_if_index)
8119 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8120 o_addr=self.nat_addr,
8121 i_port=self.tcp_port_in,
8122 o_port=self.tcp_port_out,
8123 proto=IP_PROTOS.tcp, vrf_id=0,
8125 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8126 o_addr=self.nat_addr,
8127 i_port=self.udp_port_in,
8128 o_port=self.udp_port_out,
8129 proto=IP_PROTOS.udp, vrf_id=0,
8131 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8132 o_addr=self.nat_addr,
8133 i_port=self.icmp_id_in,
8134 o_port=self.icmp_id_out,
8135 proto=IP_PROTOS.icmp, vrf_id=0,
8139 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8140 self.pg0.add_stream(pkts)
8141 self.pg_enable_capture(self.pg_interfaces)
8143 capture = self.pg1.get_capture(len(pkts))
8144 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8145 dst_ip=self.pg1.remote_ip4, same_port=True)
8148 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8149 self.pg1.add_stream(pkts)
8150 self.pg_enable_capture(self.pg_interfaces)
8152 capture = self.pg0.get_capture(len(pkts))
8153 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8154 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8156 ses_num_end = self.nat64_get_ses_num()
8158 self.assertEqual(ses_num_end - ses_num_start, 3)
8160 @unittest.skipUnless(running_extended_tests, "part of extended tests")
8161 def test_session_timeout(self):
8162 """ NAT64 session timeout """
8163 self.icmp_id_in = 1234
8164 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8165 end_addr=self.nat_addr,
8168 flags = self.config_flags.NAT_IS_INSIDE
8169 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8170 sw_if_index=self.pg0.sw_if_index)
8171 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8172 sw_if_index=self.pg1.sw_if_index)
8173 self.vapi.nat_set_timeouts(udp=300, tcp_established=5,
8177 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8178 self.pg0.add_stream(pkts)
8179 self.pg_enable_capture(self.pg_interfaces)
8181 capture = self.pg1.get_capture(len(pkts))
8183 ses_num_before_timeout = self.nat64_get_ses_num()
8187 # ICMP and TCP session after timeout
8188 ses_num_after_timeout = self.nat64_get_ses_num()
8189 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
8191 def test_icmp_error(self):
8192 """ NAT64 ICMP Error message translation """
8193 self.tcp_port_in = 6303
8194 self.udp_port_in = 6304
8195 self.icmp_id_in = 6305
8197 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8198 end_addr=self.nat_addr,
8201 flags = self.config_flags.NAT_IS_INSIDE
8202 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8203 sw_if_index=self.pg0.sw_if_index)
8204 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8205 sw_if_index=self.pg1.sw_if_index)
8207 # send some packets to create sessions
8208 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8209 self.pg0.add_stream(pkts)
8210 self.pg_enable_capture(self.pg_interfaces)
8212 capture_ip4 = self.pg1.get_capture(len(pkts))
8213 self.verify_capture_out(capture_ip4,
8214 nat_ip=self.nat_addr,
8215 dst_ip=self.pg1.remote_ip4)
8217 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8218 self.pg1.add_stream(pkts)
8219 self.pg_enable_capture(self.pg_interfaces)
8221 capture_ip6 = self.pg0.get_capture(len(pkts))
8222 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8223 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
8224 self.pg0.remote_ip6)
8227 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8228 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
8229 ICMPv6DestUnreach(code=1) /
8230 packet[IPv6] for packet in capture_ip6]
8231 self.pg0.add_stream(pkts)
8232 self.pg_enable_capture(self.pg_interfaces)
8234 capture = self.pg1.get_capture(len(pkts))
8235 for packet in capture:
8237 self.assertEqual(packet[IP].src, self.nat_addr)
8238 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
8239 self.assertEqual(packet[ICMP].type, 3)
8240 self.assertEqual(packet[ICMP].code, 13)
8241 inner = packet[IPerror]
8242 self.assertEqual(inner.src, self.pg1.remote_ip4)
8243 self.assertEqual(inner.dst, self.nat_addr)
8244 self.assert_packet_checksums_valid(packet)
8245 if inner.haslayer(TCPerror):
8246 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
8247 elif inner.haslayer(UDPerror):
8248 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
8250 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
8252 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8256 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8257 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8258 ICMP(type=3, code=13) /
8259 packet[IP] for packet in capture_ip4]
8260 self.pg1.add_stream(pkts)
8261 self.pg_enable_capture(self.pg_interfaces)
8263 capture = self.pg0.get_capture(len(pkts))
8264 for packet in capture:
8266 self.assertEqual(packet[IPv6].src, ip.src)
8267 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8268 icmp = packet[ICMPv6DestUnreach]
8269 self.assertEqual(icmp.code, 1)
8270 inner = icmp[IPerror6]
8271 self.assertEqual(inner.src, self.pg0.remote_ip6)
8272 self.assertEqual(inner.dst, ip.src)
8273 self.assert_icmpv6_checksum_valid(packet)
8274 if inner.haslayer(TCPerror):
8275 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
8276 elif inner.haslayer(UDPerror):
8277 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
8279 self.assertEqual(inner[ICMPv6EchoRequest].id,
8282 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8285 def test_hairpinning(self):
8286 """ NAT64 hairpinning """
8288 client = self.pg0.remote_hosts[0]
8289 server = self.pg0.remote_hosts[1]
8290 server_tcp_in_port = 22
8291 server_tcp_out_port = 4022
8292 server_udp_in_port = 23
8293 server_udp_out_port = 4023
8294 client_tcp_in_port = 1234
8295 client_udp_in_port = 1235
8296 client_tcp_out_port = 0
8297 client_udp_out_port = 0
8298 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8299 nat_addr_ip6 = ip.src
8301 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8302 end_addr=self.nat_addr,
8305 flags = self.config_flags.NAT_IS_INSIDE
8306 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8307 sw_if_index=self.pg0.sw_if_index)
8308 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8309 sw_if_index=self.pg1.sw_if_index)
8311 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8312 o_addr=self.nat_addr,
8313 i_port=server_tcp_in_port,
8314 o_port=server_tcp_out_port,
8315 proto=IP_PROTOS.tcp, vrf_id=0,
8317 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8318 o_addr=self.nat_addr,
8319 i_port=server_udp_in_port,
8320 o_port=server_udp_out_port,
8321 proto=IP_PROTOS.udp, vrf_id=0,
8326 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8327 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8328 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8330 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8331 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8332 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
8334 self.pg0.add_stream(pkts)
8335 self.pg_enable_capture(self.pg_interfaces)
8337 capture = self.pg0.get_capture(len(pkts))
8338 for packet in capture:
8340 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8341 self.assertEqual(packet[IPv6].dst, server.ip6)
8342 self.assert_packet_checksums_valid(packet)
8343 if packet.haslayer(TCP):
8344 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
8345 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
8346 client_tcp_out_port = packet[TCP].sport
8348 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
8349 self.assertEqual(packet[UDP].dport, server_udp_in_port)
8350 client_udp_out_port = packet[UDP].sport
8352 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8357 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8358 IPv6(src=server.ip6, dst=nat_addr_ip6) /
8359 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
8361 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8362 IPv6(src=server.ip6, dst=nat_addr_ip6) /
8363 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
8365 self.pg0.add_stream(pkts)
8366 self.pg_enable_capture(self.pg_interfaces)
8368 capture = self.pg0.get_capture(len(pkts))
8369 for packet in capture:
8371 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8372 self.assertEqual(packet[IPv6].dst, client.ip6)
8373 self.assert_packet_checksums_valid(packet)
8374 if packet.haslayer(TCP):
8375 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
8376 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
8378 self.assertEqual(packet[UDP].sport, server_udp_out_port)
8379 self.assertEqual(packet[UDP].dport, client_udp_in_port)
8381 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8386 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8387 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8388 ICMPv6DestUnreach(code=1) /
8389 packet[IPv6] for packet in capture]
8390 self.pg0.add_stream(pkts)
8391 self.pg_enable_capture(self.pg_interfaces)
8393 capture = self.pg0.get_capture(len(pkts))
8394 for packet in capture:
8396 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8397 self.assertEqual(packet[IPv6].dst, server.ip6)
8398 icmp = packet[ICMPv6DestUnreach]
8399 self.assertEqual(icmp.code, 1)
8400 inner = icmp[IPerror6]
8401 self.assertEqual(inner.src, server.ip6)
8402 self.assertEqual(inner.dst, nat_addr_ip6)
8403 self.assert_packet_checksums_valid(packet)
8404 if inner.haslayer(TCPerror):
8405 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
8406 self.assertEqual(inner[TCPerror].dport,
8407 client_tcp_out_port)
8409 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
8410 self.assertEqual(inner[UDPerror].dport,
8411 client_udp_out_port)
8413 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8416 def test_prefix(self):
8417 """ NAT64 Network-Specific Prefix """
8419 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8420 end_addr=self.nat_addr,
8423 flags = self.config_flags.NAT_IS_INSIDE
8424 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8425 sw_if_index=self.pg0.sw_if_index)
8426 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8427 sw_if_index=self.pg1.sw_if_index)
8428 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
8429 end_addr=self.vrf1_nat_addr,
8430 vrf_id=self.vrf1_id, is_add=1)
8431 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8432 sw_if_index=self.pg2.sw_if_index)
8435 global_pref64 = "2001:db8::"
8436 global_pref64_len = 32
8437 global_pref64_str = "{}/{}".format(global_pref64, global_pref64_len)
8438 self.vapi.nat64_add_del_prefix(prefix=global_pref64_str, vrf_id=0,
8441 prefix = self.vapi.nat64_prefix_dump()
8442 self.assertEqual(len(prefix), 1)
8443 self.assertEqual(str(prefix[0].prefix), global_pref64_str)
8444 self.assertEqual(prefix[0].vrf_id, 0)
8446 # Add tenant specific prefix
8447 vrf1_pref64 = "2001:db8:122:300::"
8448 vrf1_pref64_len = 56
8449 vrf1_pref64_str = "{}/{}".format(vrf1_pref64, vrf1_pref64_len)
8450 self.vapi.nat64_add_del_prefix(prefix=vrf1_pref64_str,
8451 vrf_id=self.vrf1_id, is_add=1)
8453 prefix = self.vapi.nat64_prefix_dump()
8454 self.assertEqual(len(prefix), 2)
8457 pkts = self.create_stream_in_ip6(self.pg0,
8460 plen=global_pref64_len)
8461 self.pg0.add_stream(pkts)
8462 self.pg_enable_capture(self.pg_interfaces)
8464 capture = self.pg1.get_capture(len(pkts))
8465 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8466 dst_ip=self.pg1.remote_ip4)
8468 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8469 self.pg1.add_stream(pkts)
8470 self.pg_enable_capture(self.pg_interfaces)
8472 capture = self.pg0.get_capture(len(pkts))
8473 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8476 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
8478 # Tenant specific prefix
8479 pkts = self.create_stream_in_ip6(self.pg2,
8482 plen=vrf1_pref64_len)
8483 self.pg2.add_stream(pkts)
8484 self.pg_enable_capture(self.pg_interfaces)
8486 capture = self.pg1.get_capture(len(pkts))
8487 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
8488 dst_ip=self.pg1.remote_ip4)
8490 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
8491 self.pg1.add_stream(pkts)
8492 self.pg_enable_capture(self.pg_interfaces)
8494 capture = self.pg2.get_capture(len(pkts))
8495 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8498 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
8500 def test_unknown_proto(self):
8501 """ NAT64 translate packet with unknown protocol """
8503 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8504 end_addr=self.nat_addr,
8507 flags = self.config_flags.NAT_IS_INSIDE
8508 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8509 sw_if_index=self.pg0.sw_if_index)
8510 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8511 sw_if_index=self.pg1.sw_if_index)
8512 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8515 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8516 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
8517 TCP(sport=self.tcp_port_in, dport=20))
8518 self.pg0.add_stream(p)
8519 self.pg_enable_capture(self.pg_interfaces)
8521 p = self.pg1.get_capture(1)
8523 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8524 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
8526 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8527 TCP(sport=1234, dport=1234))
8528 self.pg0.add_stream(p)
8529 self.pg_enable_capture(self.pg_interfaces)
8531 p = self.pg1.get_capture(1)
8534 self.assertEqual(packet[IP].src, self.nat_addr)
8535 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
8536 self.assertEqual(packet.haslayer(GRE), 1)
8537 self.assert_packet_checksums_valid(packet)
8539 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8543 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8544 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8546 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8547 TCP(sport=1234, dport=1234))
8548 self.pg1.add_stream(p)
8549 self.pg_enable_capture(self.pg_interfaces)
8551 p = self.pg0.get_capture(1)
8554 self.assertEqual(packet[IPv6].src, remote_ip6)
8555 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8556 self.assertEqual(packet[IPv6].nh, 47)
8558 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8561 def test_hairpinning_unknown_proto(self):
8562 """ NAT64 translate packet with unknown protocol - hairpinning """
8564 client = self.pg0.remote_hosts[0]
8565 server = self.pg0.remote_hosts[1]
8566 server_tcp_in_port = 22
8567 server_tcp_out_port = 4022
8568 client_tcp_in_port = 1234
8569 client_tcp_out_port = 1235
8570 server_nat_ip = "10.0.0.100"
8571 client_nat_ip = "10.0.0.110"
8572 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
8573 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
8575 self.vapi.nat64_add_del_pool_addr_range(start_addr=server_nat_ip,
8576 end_addr=client_nat_ip,
8579 flags = self.config_flags.NAT_IS_INSIDE
8580 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8581 sw_if_index=self.pg0.sw_if_index)
8582 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8583 sw_if_index=self.pg1.sw_if_index)
8585 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8586 o_addr=server_nat_ip,
8587 i_port=server_tcp_in_port,
8588 o_port=server_tcp_out_port,
8589 proto=IP_PROTOS.tcp, vrf_id=0,
8592 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8593 o_addr=server_nat_ip, i_port=0,
8595 proto=IP_PROTOS.gre, vrf_id=0,
8598 self.vapi.nat64_add_del_static_bib(i_addr=client.ip6n,
8599 o_addr=client_nat_ip,
8600 i_port=client_tcp_in_port,
8601 o_port=client_tcp_out_port,
8602 proto=IP_PROTOS.tcp, vrf_id=0,
8606 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8607 IPv6(src=client.ip6, dst=server_nat_ip6) /
8608 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8609 self.pg0.add_stream(p)
8610 self.pg_enable_capture(self.pg_interfaces)
8612 p = self.pg0.get_capture(1)
8614 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8615 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
8617 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8618 TCP(sport=1234, dport=1234))
8619 self.pg0.add_stream(p)
8620 self.pg_enable_capture(self.pg_interfaces)
8622 p = self.pg0.get_capture(1)
8625 self.assertEqual(packet[IPv6].src, client_nat_ip6)
8626 self.assertEqual(packet[IPv6].dst, server.ip6)
8627 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
8629 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8633 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8634 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
8636 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8637 TCP(sport=1234, dport=1234))
8638 self.pg0.add_stream(p)
8639 self.pg_enable_capture(self.pg_interfaces)
8641 p = self.pg0.get_capture(1)
8644 self.assertEqual(packet[IPv6].src, server_nat_ip6)
8645 self.assertEqual(packet[IPv6].dst, client.ip6)
8646 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
8648 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8651 def test_one_armed_nat64(self):
8652 """ One armed NAT64 """
8654 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
8658 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8659 end_addr=self.nat_addr,
8662 flags = self.config_flags.NAT_IS_INSIDE
8663 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8664 sw_if_index=self.pg3.sw_if_index)
8665 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8666 sw_if_index=self.pg3.sw_if_index)
8669 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8670 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
8671 TCP(sport=12345, dport=80))
8672 self.pg3.add_stream(p)
8673 self.pg_enable_capture(self.pg_interfaces)
8675 capture = self.pg3.get_capture(1)
8680 self.assertEqual(ip.src, self.nat_addr)
8681 self.assertEqual(ip.dst, self.pg3.remote_ip4)
8682 self.assertNotEqual(tcp.sport, 12345)
8683 external_port = tcp.sport
8684 self.assertEqual(tcp.dport, 80)
8685 self.assert_packet_checksums_valid(p)
8687 self.logger.error(ppp("Unexpected or invalid packet:", p))
8691 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8692 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
8693 TCP(sport=80, dport=external_port))
8694 self.pg3.add_stream(p)
8695 self.pg_enable_capture(self.pg_interfaces)
8697 capture = self.pg3.get_capture(1)
8702 self.assertEqual(ip.src, remote_host_ip6)
8703 self.assertEqual(ip.dst, self.pg3.remote_ip6)
8704 self.assertEqual(tcp.sport, 80)
8705 self.assertEqual(tcp.dport, 12345)
8706 self.assert_packet_checksums_valid(p)
8708 self.logger.error(ppp("Unexpected or invalid packet:", p))
8711 def test_frag_in_order(self):
8712 """ NAT64 translate fragments arriving in order """
8713 self.tcp_port_in = random.randint(1025, 65535)
8715 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8716 end_addr=self.nat_addr,
8719 flags = self.config_flags.NAT_IS_INSIDE
8720 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8721 sw_if_index=self.pg0.sw_if_index)
8722 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8723 sw_if_index=self.pg1.sw_if_index)
8727 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8728 self.tcp_port_in, 20, data)
8729 self.pg0.add_stream(pkts)
8730 self.pg_enable_capture(self.pg_interfaces)
8732 frags = self.pg1.get_capture(len(pkts))
8733 p = self.reass_frags_and_verify(frags,
8735 self.pg1.remote_ip4)
8736 self.assertEqual(p[TCP].dport, 20)
8737 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8738 self.tcp_port_out = p[TCP].sport
8739 self.assertEqual(data, p[Raw].load)
8742 data = b"A" * 4 + b"b" * 16 + b"C" * 3
8743 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 self.logger.debug(ppc("Captured:", frags))
8753 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8754 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8755 self.assertEqual(p[TCP].sport, 20)
8756 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8757 self.assertEqual(data, p[Raw].load)
8759 def test_reass_hairpinning(self):
8760 """ NAT64 fragments hairpinning """
8762 server = self.pg0.remote_hosts[1]
8763 server_in_port = random.randint(1025, 65535)
8764 server_out_port = random.randint(1025, 65535)
8765 client_in_port = random.randint(1025, 65535)
8766 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8767 nat_addr_ip6 = ip.src
8769 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8770 end_addr=self.nat_addr,
8773 flags = self.config_flags.NAT_IS_INSIDE
8774 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8775 sw_if_index=self.pg0.sw_if_index)
8776 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8777 sw_if_index=self.pg1.sw_if_index)
8779 # add static BIB entry for server
8780 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8781 o_addr=self.nat_addr,
8782 i_port=server_in_port,
8783 o_port=server_out_port,
8784 proto=IP_PROTOS.tcp, vrf_id=0,
8787 # send packet from host to server
8788 pkts = self.create_stream_frag_ip6(self.pg0,
8793 self.pg0.add_stream(pkts)
8794 self.pg_enable_capture(self.pg_interfaces)
8796 frags = self.pg0.get_capture(len(pkts))
8797 self.logger.debug(ppc("Captured:", frags))
8798 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
8799 self.assertNotEqual(p[TCP].sport, client_in_port)
8800 self.assertEqual(p[TCP].dport, server_in_port)
8801 self.assertEqual(data, p[Raw].load)
8803 def test_frag_out_of_order(self):
8804 """ NAT64 translate fragments arriving out of order """
8805 self.tcp_port_in = random.randint(1025, 65535)
8807 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8808 end_addr=self.nat_addr,
8811 flags = self.config_flags.NAT_IS_INSIDE
8812 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8813 sw_if_index=self.pg0.sw_if_index)
8814 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8815 sw_if_index=self.pg1.sw_if_index)
8819 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8820 self.tcp_port_in, 20, data)
8822 self.pg0.add_stream(pkts)
8823 self.pg_enable_capture(self.pg_interfaces)
8825 frags = self.pg1.get_capture(len(pkts))
8826 p = self.reass_frags_and_verify(frags,
8828 self.pg1.remote_ip4)
8829 self.assertEqual(p[TCP].dport, 20)
8830 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8831 self.tcp_port_out = p[TCP].sport
8832 self.assertEqual(data, p[Raw].load)
8835 data = b"A" * 4 + b"B" * 16 + b"C" * 3
8836 pkts = self.create_stream_frag(self.pg1,
8842 self.pg1.add_stream(pkts)
8843 self.pg_enable_capture(self.pg_interfaces)
8845 frags = self.pg0.get_capture(len(pkts))
8846 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8847 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8848 self.assertEqual(p[TCP].sport, 20)
8849 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8850 self.assertEqual(data, p[Raw].load)
8852 def test_interface_addr(self):
8853 """ Acquire NAT64 pool addresses from interface """
8854 self.vapi.nat64_add_del_interface_addr(
8856 sw_if_index=self.pg4.sw_if_index)
8858 # no address in NAT64 pool
8859 addresses = self.vapi.nat44_address_dump()
8860 self.assertEqual(0, len(addresses))
8862 # configure interface address and check NAT64 address pool
8863 self.pg4.config_ip4()
8864 addresses = self.vapi.nat64_pool_addr_dump()
8865 self.assertEqual(len(addresses), 1)
8867 self.assertEqual(str(addresses[0].address),
8870 # remove interface address and check NAT64 address pool
8871 self.pg4.unconfig_ip4()
8872 addresses = self.vapi.nat64_pool_addr_dump()
8873 self.assertEqual(0, len(addresses))
8875 @unittest.skipUnless(running_extended_tests, "part of extended tests")
8876 def test_ipfix_max_bibs_sessions(self):
8877 """ IPFIX logging maximum session and BIB entries exceeded """
8880 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8884 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8885 end_addr=self.nat_addr,
8888 flags = self.config_flags.NAT_IS_INSIDE
8889 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8890 sw_if_index=self.pg0.sw_if_index)
8891 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8892 sw_if_index=self.pg1.sw_if_index)
8896 for i in range(0, max_bibs):
8897 src = "fd01:aa::%x" % (i)
8898 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8899 IPv6(src=src, dst=remote_host_ip6) /
8900 TCP(sport=12345, dport=80))
8902 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8903 IPv6(src=src, dst=remote_host_ip6) /
8904 TCP(sport=12345, dport=22))
8906 self.pg0.add_stream(pkts)
8907 self.pg_enable_capture(self.pg_interfaces)
8909 self.pg1.get_capture(max_sessions)
8911 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
8912 src_address=self.pg3.local_ip4,
8914 template_interval=10)
8915 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8916 src_port=self.ipfix_src_port,
8919 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8920 IPv6(src=src, dst=remote_host_ip6) /
8921 TCP(sport=12345, dport=25))
8922 self.pg0.add_stream(p)
8923 self.pg_enable_capture(self.pg_interfaces)
8925 self.pg1.assert_nothing_captured()
8927 self.vapi.ipfix_flush()
8928 capture = self.pg3.get_capture(9)
8929 ipfix = IPFIXDecoder()
8930 # first load template
8932 self.assertTrue(p.haslayer(IPFIX))
8933 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8934 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8935 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8936 self.assertEqual(p[UDP].dport, 4739)
8937 self.assertEqual(p[IPFIX].observationDomainID,
8938 self.ipfix_domain_id)
8939 if p.haslayer(Template):
8940 ipfix.add_template(p.getlayer(Template))
8941 # verify events in data set
8943 if p.haslayer(Data):
8944 data = ipfix.decode_data_set(p.getlayer(Set))
8945 self.verify_ipfix_max_sessions(data, max_sessions)
8947 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8948 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8949 TCP(sport=12345, dport=80))
8950 self.pg0.add_stream(p)
8951 self.pg_enable_capture(self.pg_interfaces)
8953 self.pg1.assert_nothing_captured()
8955 self.vapi.ipfix_flush()
8956 capture = self.pg3.get_capture(1)
8957 # verify events in data set
8959 self.assertTrue(p.haslayer(IPFIX))
8960 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8961 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8962 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8963 self.assertEqual(p[UDP].dport, 4739)
8964 self.assertEqual(p[IPFIX].observationDomainID,
8965 self.ipfix_domain_id)
8966 if p.haslayer(Data):
8967 data = ipfix.decode_data_set(p.getlayer(Set))
8968 self.verify_ipfix_max_bibs(data, max_bibs)
8970 def test_ipfix_bib_ses(self):
8971 """ IPFIX logging NAT64 BIB/session create and delete events """
8972 self.tcp_port_in = random.randint(1025, 65535)
8973 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8977 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8978 end_addr=self.nat_addr,
8981 flags = self.config_flags.NAT_IS_INSIDE
8982 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8983 sw_if_index=self.pg0.sw_if_index)
8984 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8985 sw_if_index=self.pg1.sw_if_index)
8986 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
8987 src_address=self.pg3.local_ip4,
8989 template_interval=10)
8990 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8991 src_port=self.ipfix_src_port,
8995 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8996 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8997 TCP(sport=self.tcp_port_in, dport=25))
8998 self.pg0.add_stream(p)
8999 self.pg_enable_capture(self.pg_interfaces)
9001 p = self.pg1.get_capture(1)
9002 self.tcp_port_out = p[0][TCP].sport
9003 self.vapi.ipfix_flush()
9004 capture = self.pg3.get_capture(10)
9005 ipfix = IPFIXDecoder()
9006 # first load template
9008 self.assertTrue(p.haslayer(IPFIX))
9009 self.assertEqual(p[IP].src, self.pg3.local_ip4)
9010 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
9011 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
9012 self.assertEqual(p[UDP].dport, 4739)
9013 self.assertEqual(p[IPFIX].observationDomainID,
9014 self.ipfix_domain_id)
9015 if p.haslayer(Template):
9016 ipfix.add_template(p.getlayer(Template))
9017 # verify events in data set
9019 if p.haslayer(Data):
9020 data = ipfix.decode_data_set(p.getlayer(Set))
9021 if scapy.compat.orb(data[0][230]) == 10:
9022 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
9023 elif scapy.compat.orb(data[0][230]) == 6:
9024 self.verify_ipfix_nat64_ses(data,
9026 self.pg0.remote_ip6n,
9027 self.pg1.remote_ip4,
9030 self.logger.error(ppp("Unexpected or invalid packet: ", p))
9033 self.pg_enable_capture(self.pg_interfaces)
9034 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9035 end_addr=self.nat_addr,
9038 self.vapi.ipfix_flush()
9039 capture = self.pg3.get_capture(2)
9040 # verify events in data set
9042 self.assertTrue(p.haslayer(IPFIX))
9043 self.assertEqual(p[IP].src, self.pg3.local_ip4)
9044 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
9045 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
9046 self.assertEqual(p[UDP].dport, 4739)
9047 self.assertEqual(p[IPFIX].observationDomainID,
9048 self.ipfix_domain_id)
9049 if p.haslayer(Data):
9050 data = ipfix.decode_data_set(p.getlayer(Set))
9051 if scapy.compat.orb(data[0][230]) == 11:
9052 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
9053 elif scapy.compat.orb(data[0][230]) == 7:
9054 self.verify_ipfix_nat64_ses(data,
9056 self.pg0.remote_ip6n,
9057 self.pg1.remote_ip4,
9060 self.logger.error(ppp("Unexpected or invalid packet: ", p))
9062 def test_syslog_sess(self):
9063 """ Test syslog session creation and deletion """
9064 self.tcp_port_in = random.randint(1025, 65535)
9065 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
9069 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9070 end_addr=self.nat_addr,
9073 flags = self.config_flags.NAT_IS_INSIDE
9074 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
9075 sw_if_index=self.pg0.sw_if_index)
9076 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
9077 sw_if_index=self.pg1.sw_if_index)
9078 self.vapi.syslog_set_filter(
9079 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
9080 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
9082 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
9083 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
9084 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
9085 self.pg0.add_stream(p)
9086 self.pg_enable_capture(self.pg_interfaces)
9088 p = self.pg1.get_capture(1)
9089 self.tcp_port_out = p[0][TCP].sport
9090 capture = self.pg3.get_capture(1)
9091 self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
9093 self.pg_enable_capture(self.pg_interfaces)
9095 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9096 end_addr=self.nat_addr,
9099 capture = self.pg3.get_capture(1)
9100 self.verify_syslog_sess(capture[0][Raw].load, False, True)
9102 def nat64_get_ses_num(self):
9104 Return number of active NAT64 sessions.
9106 st = self.vapi.nat64_st_dump(proto=255)
9109 def clear_nat64(self):
9111 Clear NAT64 configuration.
9113 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
9114 src_port=self.ipfix_src_port,
9116 self.ipfix_src_port = 4739
9117 self.ipfix_domain_id = 1
9119 self.vapi.syslog_set_filter(
9120 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_EMERG)
9122 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
9123 tcp_transitory=240, icmp=60)
9125 interfaces = self.vapi.nat64_interface_dump()
9126 for intf in interfaces:
9127 self.vapi.nat64_add_del_interface(is_add=0, flags=intf.flags,
9128 sw_if_index=intf.sw_if_index)
9130 bib = self.vapi.nat64_bib_dump(proto=255)
9132 if bibe.flags & self.config_flags.NAT_IS_STATIC:
9133 self.vapi.nat64_add_del_static_bib(i_addr=bibe.i_addr,
9141 adresses = self.vapi.nat64_pool_addr_dump()
9142 for addr in adresses:
9143 self.vapi.nat64_add_del_pool_addr_range(start_addr=addr.address,
9144 end_addr=addr.address,
9148 prefixes = self.vapi.nat64_prefix_dump()
9149 for prefix in prefixes:
9150 self.vapi.nat64_add_del_prefix(prefix=str(prefix.prefix),
9151 vrf_id=prefix.vrf_id, is_add=0)
9153 bibs = self.statistics.get_counter('/nat64/total-bibs')
9154 self.assertEqual(bibs[0][0], 0)
9155 sessions = self.statistics.get_counter('/nat64/total-sessions')
9156 self.assertEqual(sessions[0][0], 0)
9159 super(TestNAT64, self).tearDown()
9160 if not self.vpp_dead:
9163 def show_commands_at_teardown(self):
9164 self.logger.info(self.vapi.cli("show nat64 pool"))
9165 self.logger.info(self.vapi.cli("show nat64 interfaces"))
9166 self.logger.info(self.vapi.cli("show nat64 prefix"))
9167 self.logger.info(self.vapi.cli("show nat64 bib all"))
9168 self.logger.info(self.vapi.cli("show nat64 session table all"))
9171 class TestNAT66(MethodHolder):
9172 """ NAT66 Test Cases """
9175 def setUpClass(cls):
9176 super(TestNAT66, cls).setUpClass()
9178 cls.nat_addr = 'fd01:ff::2'
9180 cls.create_pg_interfaces(range(2))
9181 cls.interfaces = list(cls.pg_interfaces)
9183 for i in cls.interfaces:
9186 i.configure_ipv6_neighbors()
9189 def tearDownClass(cls):
9190 super(TestNAT66, cls).tearDownClass()
9192 def test_static(self):
9193 """ 1:1 NAT66 test """
9194 flags = self.config_flags.NAT_IS_INSIDE
9195 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9196 sw_if_index=self.pg0.sw_if_index)
9197 self.vapi.nat66_add_del_interface(is_add=1,
9198 sw_if_index=self.pg1.sw_if_index)
9199 self.vapi.nat66_add_del_static_mapping(
9200 local_ip_address=self.pg0.remote_ip6n,
9201 external_ip_address=self.nat_addr,
9206 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9207 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9210 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9211 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9214 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9215 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9216 ICMPv6EchoRequest())
9218 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9219 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9220 GRE() / IP() / TCP())
9222 self.pg0.add_stream(pkts)
9223 self.pg_enable_capture(self.pg_interfaces)
9225 capture = self.pg1.get_capture(len(pkts))
9227 for packet in capture:
9229 self.assertEqual(packet[IPv6].src, self.nat_addr)
9230 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9231 self.assert_packet_checksums_valid(packet)
9233 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9238 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9239 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9242 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9243 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9246 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9247 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9250 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9251 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9252 GRE() / IP() / TCP())
9254 self.pg1.add_stream(pkts)
9255 self.pg_enable_capture(self.pg_interfaces)
9257 capture = self.pg0.get_capture(len(pkts))
9258 for packet in capture:
9260 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
9261 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
9262 self.assert_packet_checksums_valid(packet)
9264 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9267 sm = self.vapi.nat66_static_mapping_dump()
9268 self.assertEqual(len(sm), 1)
9269 self.assertEqual(sm[0].total_pkts, 8)
9271 def test_check_no_translate(self):
9272 """ NAT66 translate only when egress interface is outside interface """
9273 flags = self.config_flags.NAT_IS_INSIDE
9274 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9275 sw_if_index=self.pg0.sw_if_index)
9276 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9277 sw_if_index=self.pg1.sw_if_index)
9278 self.vapi.nat66_add_del_static_mapping(
9279 local_ip_address=self.pg0.remote_ip6n,
9280 external_ip_address=self.nat_addr,
9284 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9285 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9287 self.pg0.add_stream([p])
9288 self.pg_enable_capture(self.pg_interfaces)
9290 capture = self.pg1.get_capture(1)
9293 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
9294 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9296 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9299 def clear_nat66(self):
9301 Clear NAT66 configuration.
9303 interfaces = self.vapi.nat66_interface_dump()
9304 for intf in interfaces:
9305 self.vapi.nat66_add_del_interface(is_add=0, flags=intf.flags,
9306 sw_if_index=intf.sw_if_index)
9308 static_mappings = self.vapi.nat66_static_mapping_dump()
9309 for sm in static_mappings:
9310 self.vapi.nat66_add_del_static_mapping(
9311 local_ip_address=sm.local_ip_address,
9312 external_ip_address=sm.external_ip_address, vrf_id=sm.vrf_id,
9316 super(TestNAT66, self).tearDown()
9319 def show_commands_at_teardown(self):
9320 self.logger.info(self.vapi.cli("show nat66 interfaces"))
9321 self.logger.info(self.vapi.cli("show nat66 static mappings"))
9324 if __name__ == '__main__':
9325 unittest.main(testRunner=VppTestRunner)