12 from framework import VppTestCase, VppTestRunner, running_extended_tests
13 from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
14 from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \
15 IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \
17 from scapy.data import IP_PROTOS
18 from scapy.layers.inet import IP, TCP, UDP, ICMP
19 from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
20 from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
21 from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply, \
22 ICMPv6ND_NS, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr, fragment6
23 from scapy.layers.l2 import Ether, ARP, GRE
24 from scapy.packet import Raw
25 from syslog_rfc5424_parser import SyslogMessage, ParseError
26 from syslog_rfc5424_parser.constants import SyslogSeverity
27 from util import ip4_range
28 from util import ppc, ppp
29 from vpp_acl import AclRule, VppAcl, VppAclInterface
30 from vpp_ip_route import VppIpRoute, VppRoutePath
31 from vpp_neighbor import VppNeighbor
32 from vpp_papi import VppEnum
35 # NAT HA protocol event data
38 fields_desc = [ByteEnumField("event_type", None,
39 {1: "add", 2: "del", 3: "refresh"}),
40 ByteEnumField("protocol", None,
41 {0: "udp", 1: "tcp", 2: "icmp"}),
42 ShortField("flags", 0),
43 IPField("in_addr", None),
44 IPField("out_addr", None),
45 ShortField("in_port", None),
46 ShortField("out_port", None),
47 IPField("eh_addr", None),
48 IPField("ehn_addr", None),
49 ShortField("eh_port", None),
50 ShortField("ehn_port", None),
51 IntField("fib_index", None),
52 IntField("total_pkts", 0),
53 LongField("total_bytes", 0)]
55 def extract_padding(self, s):
59 # NAT HA protocol header
60 class HANATStateSync(Packet):
61 name = "HA NAT state sync"
62 fields_desc = [XByteField("version", 1),
63 FlagsField("flags", 0, 8, ['ACK']),
64 FieldLenField("count", None, count_of="events"),
65 IntField("sequence_number", 1),
66 IntField("thread_index", 0),
67 PacketListField("events", [], Event,
68 count_from=lambda pkt: pkt.count)]
71 class MethodHolder(VppTestCase):
72 """ NAT create capture and verify method holder """
75 def config_flags(self):
76 return VppEnum.vl_api_nat_config_flags_t
79 def SYSLOG_SEVERITY(self):
80 return VppEnum.vl_api_syslog_severity_t
82 def clear_nat44(self):
84 Clear NAT44 configuration.
86 if hasattr(self, 'pg7') and hasattr(self, 'pg8'):
87 if self.pg7.has_ip4_config:
88 self.pg7.unconfig_ip4()
90 self.vapi.nat44_forwarding_enable_disable(enable=0)
92 interfaces = self.vapi.nat44_interface_addr_dump()
93 for intf in interfaces:
94 self.vapi.nat44_add_del_interface_addr(
96 sw_if_index=intf.sw_if_index,
99 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
100 src_port=self.ipfix_src_port,
102 self.ipfix_src_port = 4739
103 self.ipfix_domain_id = 1
105 self.vapi.syslog_set_filter(
106 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_EMERG)
108 self.vapi.nat_ha_set_listener(ip_address='0.0.0.0', port=0,
110 self.vapi.nat_ha_set_failover(ip_address='0.0.0.0', port=0,
111 session_refresh_interval=10)
113 interfaces = self.vapi.nat44_interface_dump()
114 for intf in interfaces:
115 if intf.flags & self.config_flags.NAT_IS_INSIDE and \
116 intf.flags & self.config_flags.NAT_IS_OUTSIDE:
117 self.vapi.nat44_interface_add_del_feature(
118 sw_if_index=intf.sw_if_index)
119 self.vapi.nat44_interface_add_del_feature(
120 sw_if_index=intf.sw_if_index,
123 interfaces = self.vapi.nat44_interface_output_feature_dump()
124 for intf in interfaces:
125 self.vapi.nat44_interface_add_del_output_feature(
128 sw_if_index=intf.sw_if_index)
129 static_mappings = self.vapi.nat44_static_mapping_dump()
130 for sm in static_mappings:
131 self.vapi.nat44_add_del_static_mapping(
133 local_ip_address=sm.local_ip_address,
134 external_ip_address=sm.external_ip_address,
135 external_sw_if_index=sm.external_sw_if_index,
136 local_port=sm.local_port,
137 external_port=sm.external_port,
139 protocol=sm.protocol,
140 flags=sm.flags, tag=sm.tag)
142 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
143 for lb_sm in lb_static_mappings:
144 self.vapi.nat44_add_del_lb_static_mapping(
147 external_addr=lb_sm.external_addr,
148 external_port=lb_sm.external_port,
149 protocol=lb_sm.protocol,
150 local_num=0, locals=[],
153 identity_mappings = self.vapi.nat44_identity_mapping_dump()
154 for id_m in identity_mappings:
155 self.vapi.nat44_add_del_identity_mapping(
156 ip_address=id_m.ip_address,
157 sw_if_index=id_m.sw_if_index,
161 protocol=id_m.protocol)
163 addresses = self.vapi.nat44_address_dump()
164 for addr in addresses:
165 self.vapi.nat44_add_del_address_range(
166 first_ip_address=addr.ip_address,
167 last_ip_address=addr.ip_address,
168 vrf_id=0xFFFFFFFF, flags=addr.flags)
170 self.verify_no_nat44_user()
171 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
172 tcp_transitory=240, icmp=60)
173 self.vapi.nat_set_addr_and_port_alloc_alg()
174 self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
176 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
177 local_port=0, external_port=0, vrf_id=0,
178 is_add=1, external_sw_if_index=0xFFFFFFFF,
179 proto=0, tag="", flags=0):
181 Add/delete NAT44 static mapping
183 :param local_ip: Local IP address
184 :param external_ip: External IP address
185 :param local_port: Local port number (Optional)
186 :param external_port: External port number (Optional)
187 :param vrf_id: VRF ID (Default 0)
188 :param is_add: 1 if add, 0 if delete (Default add)
189 :param external_sw_if_index: External interface instead of IP address
190 :param proto: IP protocol (Mandatory if port specified)
191 :param tag: Opaque string tag
192 :param flags: NAT configuration flags
195 if not (local_port and external_port):
196 flags |= self.config_flags.NAT_IS_ADDR_ONLY
198 self.vapi.nat44_add_del_static_mapping(
200 local_ip_address=local_ip,
201 external_ip_address=external_ip,
202 external_sw_if_index=external_sw_if_index,
203 local_port=local_port,
204 external_port=external_port,
205 vrf_id=vrf_id, protocol=proto,
209 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
211 Add/delete NAT44 address
213 :param ip: IP address
214 :param is_add: 1 if add, 0 if delete (Default add)
215 :param twice_nat: twice NAT address for external hosts
217 flags = self.config_flags.NAT_IS_TWICE_NAT if twice_nat else 0
218 self.vapi.nat44_add_del_address_range(first_ip_address=ip,
224 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
226 Create packet stream for inside network
228 :param in_if: Inside interface
229 :param out_if: Outside interface
230 :param dst_ip: Destination address
231 :param ttl: TTL of generated packets
234 dst_ip = out_if.remote_ip4
238 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
239 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
240 TCP(sport=self.tcp_port_in, dport=20))
244 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
245 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
246 UDP(sport=self.udp_port_in, dport=20))
250 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
251 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
252 ICMP(id=self.icmp_id_in, type='echo-request'))
257 def compose_ip6(self, ip4, pref, plen):
259 Compose IPv4-embedded IPv6 addresses
261 :param ip4: IPv4 address
262 :param pref: IPv6 prefix
263 :param plen: IPv6 prefix length
264 :returns: IPv4-embedded IPv6 addresses
266 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
267 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
282 pref_n[10] = ip4_n[3]
286 pref_n[10] = ip4_n[2]
287 pref_n[11] = ip4_n[3]
290 pref_n[10] = ip4_n[1]
291 pref_n[11] = ip4_n[2]
292 pref_n[12] = ip4_n[3]
294 pref_n[12] = ip4_n[0]
295 pref_n[13] = ip4_n[1]
296 pref_n[14] = ip4_n[2]
297 pref_n[15] = ip4_n[3]
298 packed_pref_n = b''.join([scapy.compat.chb(x) for x in pref_n])
299 return socket.inet_ntop(socket.AF_INET6, packed_pref_n)
301 def extract_ip4(self, ip6, plen):
303 Extract IPv4 address embedded in IPv6 addresses
305 :param ip6: IPv6 address
306 :param plen: IPv6 prefix length
307 :returns: extracted IPv4 address
309 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
341 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
343 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
345 Create IPv6 packet stream for inside network
347 :param in_if: Inside interface
348 :param out_if: Outside interface
349 :param ttl: Hop Limit of generated packets
350 :param pref: NAT64 prefix
351 :param plen: NAT64 prefix length
355 dst = ''.join(['64:ff9b::', out_if.remote_ip4])
357 dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
360 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
361 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
362 TCP(sport=self.tcp_port_in, dport=20))
366 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
367 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
368 UDP(sport=self.udp_port_in, dport=20))
372 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
373 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
374 ICMPv6EchoRequest(id=self.icmp_id_in))
379 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
380 use_inside_ports=False):
382 Create packet stream for outside network
384 :param out_if: Outside interface
385 :param dst_ip: Destination IP address (Default use global NAT address)
386 :param ttl: TTL of generated packets
387 :param use_inside_ports: Use inside NAT ports as destination ports
388 instead of outside ports
391 dst_ip = self.nat_addr
392 if not use_inside_ports:
393 tcp_port = self.tcp_port_out
394 udp_port = self.udp_port_out
395 icmp_id = self.icmp_id_out
397 tcp_port = self.tcp_port_in
398 udp_port = self.udp_port_in
399 icmp_id = self.icmp_id_in
402 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
403 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
404 TCP(dport=tcp_port, sport=20))
408 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
409 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
410 UDP(dport=udp_port, sport=20))
414 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
415 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
416 ICMP(id=icmp_id, type='echo-reply'))
421 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
423 Create packet stream for outside network
425 :param out_if: Outside interface
426 :param dst_ip: Destination IP address (Default use global NAT address)
427 :param hl: HL of generated packets
431 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
432 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
433 TCP(dport=self.tcp_port_out, sport=20))
437 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
438 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
439 UDP(dport=self.udp_port_out, sport=20))
443 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
444 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
445 ICMPv6EchoReply(id=self.icmp_id_out))
450 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
451 dst_ip=None, is_ip6=False):
453 Verify captured packets on outside network
455 :param capture: Captured packets
456 :param nat_ip: Translated IP address (Default use global NAT address)
457 :param same_port: Source port number is not translated (Default False)
458 :param dst_ip: Destination IP address (Default do not verify)
459 :param is_ip6: If L3 protocol is IPv6 (Default False)
463 ICMP46 = ICMPv6EchoRequest
468 nat_ip = self.nat_addr
469 for packet in capture:
472 self.assert_packet_checksums_valid(packet)
473 self.assertEqual(packet[IP46].src, nat_ip)
474 if dst_ip is not None:
475 self.assertEqual(packet[IP46].dst, dst_ip)
476 if packet.haslayer(TCP):
478 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
481 packet[TCP].sport, self.tcp_port_in)
482 self.tcp_port_out = packet[TCP].sport
483 self.assert_packet_checksums_valid(packet)
484 elif packet.haslayer(UDP):
486 self.assertEqual(packet[UDP].sport, self.udp_port_in)
489 packet[UDP].sport, self.udp_port_in)
490 self.udp_port_out = packet[UDP].sport
493 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
495 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
496 self.icmp_id_out = packet[ICMP46].id
497 self.assert_packet_checksums_valid(packet)
499 self.logger.error(ppp("Unexpected or invalid packet "
500 "(outside network):", packet))
503 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
506 Verify captured packets on outside network
508 :param capture: Captured packets
509 :param nat_ip: Translated IP address
510 :param same_port: Source port number is not translated (Default False)
511 :param dst_ip: Destination IP address (Default do not verify)
513 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
516 def verify_capture_in(self, capture, in_if):
518 Verify captured packets on inside network
520 :param capture: Captured packets
521 :param in_if: Inside interface
523 for packet in capture:
525 self.assert_packet_checksums_valid(packet)
526 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
527 if packet.haslayer(TCP):
528 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
529 elif packet.haslayer(UDP):
530 self.assertEqual(packet[UDP].dport, self.udp_port_in)
532 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
534 self.logger.error(ppp("Unexpected or invalid packet "
535 "(inside network):", packet))
538 def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
540 Verify captured IPv6 packets on inside network
542 :param capture: Captured packets
543 :param src_ip: Source IP
544 :param dst_ip: Destination IP address
546 for packet in capture:
548 self.assertEqual(packet[IPv6].src, src_ip)
549 self.assertEqual(packet[IPv6].dst, dst_ip)
550 self.assert_packet_checksums_valid(packet)
551 if packet.haslayer(TCP):
552 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
553 elif packet.haslayer(UDP):
554 self.assertEqual(packet[UDP].dport, self.udp_port_in)
556 self.assertEqual(packet[ICMPv6EchoReply].id,
559 self.logger.error(ppp("Unexpected or invalid packet "
560 "(inside network):", packet))
563 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
565 Verify captured packet that don't have to be translated
567 :param capture: Captured packets
568 :param ingress_if: Ingress interface
569 :param egress_if: Egress interface
571 for packet in capture:
573 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
574 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
575 if packet.haslayer(TCP):
576 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
577 elif packet.haslayer(UDP):
578 self.assertEqual(packet[UDP].sport, self.udp_port_in)
580 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
582 self.logger.error(ppp("Unexpected or invalid packet "
583 "(inside network):", packet))
586 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
589 Verify captured packets with ICMP errors on outside network
591 :param capture: Captured packets
592 :param src_ip: Translated IP address or IP address of VPP
593 (Default use global NAT address)
594 :param icmp_type: Type of error ICMP packet
595 we are expecting (Default 11)
598 src_ip = self.nat_addr
599 for packet in capture:
601 self.assertEqual(packet[IP].src, src_ip)
602 self.assertEqual(packet.haslayer(ICMP), 1)
604 self.assertEqual(icmp.type, icmp_type)
605 self.assertTrue(icmp.haslayer(IPerror))
606 inner_ip = icmp[IPerror]
607 if inner_ip.haslayer(TCPerror):
608 self.assertEqual(inner_ip[TCPerror].dport,
610 elif inner_ip.haslayer(UDPerror):
611 self.assertEqual(inner_ip[UDPerror].dport,
614 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
616 self.logger.error(ppp("Unexpected or invalid packet "
617 "(outside network):", packet))
620 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
622 Verify captured packets with ICMP errors on inside network
624 :param capture: Captured packets
625 :param in_if: Inside interface
626 :param icmp_type: Type of error ICMP packet
627 we are expecting (Default 11)
629 for packet in capture:
631 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
632 self.assertEqual(packet.haslayer(ICMP), 1)
634 self.assertEqual(icmp.type, icmp_type)
635 self.assertTrue(icmp.haslayer(IPerror))
636 inner_ip = icmp[IPerror]
637 if inner_ip.haslayer(TCPerror):
638 self.assertEqual(inner_ip[TCPerror].sport,
640 elif inner_ip.haslayer(UDPerror):
641 self.assertEqual(inner_ip[UDPerror].sport,
644 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
646 self.logger.error(ppp("Unexpected or invalid packet "
647 "(inside network):", packet))
650 def create_stream_frag(self, src_if, dst, sport, dport, data,
651 proto=IP_PROTOS.tcp, echo_reply=False):
653 Create fragmented packet stream
655 :param src_if: Source interface
656 :param dst: Destination IPv4 address
657 :param sport: Source port
658 :param dport: Destination port
659 :param data: Payload data
660 :param proto: protocol (TCP, UDP, ICMP)
661 :param echo_reply: use echo_reply if protocol is ICMP
664 if proto == IP_PROTOS.tcp:
665 p = (IP(src=src_if.remote_ip4, dst=dst) /
666 TCP(sport=sport, dport=dport) /
668 p = p.__class__(scapy.compat.raw(p))
669 chksum = p[TCP].chksum
670 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
671 elif proto == IP_PROTOS.udp:
672 proto_header = UDP(sport=sport, dport=dport)
673 elif proto == IP_PROTOS.icmp:
675 proto_header = ICMP(id=sport, type='echo-request')
677 proto_header = ICMP(id=sport, type='echo-reply')
679 raise Exception("Unsupported protocol")
680 id = random.randint(0, 65535)
682 if proto == IP_PROTOS.tcp:
685 raw = Raw(data[0:16])
686 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
687 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
691 if proto == IP_PROTOS.tcp:
692 raw = Raw(data[4:20])
694 raw = Raw(data[16:32])
695 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
696 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
700 if proto == IP_PROTOS.tcp:
704 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
705 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
711 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
712 pref=None, plen=0, frag_size=128):
714 Create fragmented packet stream
716 :param src_if: Source interface
717 :param dst: Destination IPv4 address
718 :param sport: Source TCP port
719 :param dport: Destination TCP port
720 :param data: Payload data
721 :param pref: NAT64 prefix
722 :param plen: NAT64 prefix length
723 :param fragsize: size of fragments
727 dst_ip6 = ''.join(['64:ff9b::', dst])
729 dst_ip6 = self.compose_ip6(dst, pref, plen)
731 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
732 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
733 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
734 TCP(sport=sport, dport=dport) /
737 return fragment6(p, frag_size)
739 def reass_frags_and_verify(self, frags, src, dst):
741 Reassemble and verify fragmented packet
743 :param frags: Captured fragments
744 :param src: Source IPv4 address to verify
745 :param dst: Destination IPv4 address to verify
747 :returns: Reassembled IPv4 packet
751 self.assertEqual(p[IP].src, src)
752 self.assertEqual(p[IP].dst, dst)
753 self.assert_ip_checksum_valid(p)
754 buffer.seek(p[IP].frag * 8)
755 buffer.write(bytes(p[IP].payload))
756 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
757 proto=frags[0][IP].proto)
758 if ip.proto == IP_PROTOS.tcp:
759 p = (ip / TCP(buffer.getvalue()))
760 self.logger.debug(ppp("Reassembled:", p))
761 self.assert_tcp_checksum_valid(p)
762 elif ip.proto == IP_PROTOS.udp:
763 p = (ip / UDP(buffer.getvalue()[:8]) /
764 Raw(buffer.getvalue()[8:]))
765 elif ip.proto == IP_PROTOS.icmp:
766 p = (ip / ICMP(buffer.getvalue()))
769 def reass_frags_and_verify_ip6(self, frags, src, dst):
771 Reassemble and verify fragmented packet
773 :param frags: Captured fragments
774 :param src: Source IPv6 address to verify
775 :param dst: Destination IPv6 address to verify
777 :returns: Reassembled IPv6 packet
781 self.assertEqual(p[IPv6].src, src)
782 self.assertEqual(p[IPv6].dst, dst)
783 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
784 buffer.write(bytes(p[IPv6ExtHdrFragment].payload))
785 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
786 nh=frags[0][IPv6ExtHdrFragment].nh)
787 if ip.nh == IP_PROTOS.tcp:
788 p = (ip / TCP(buffer.getvalue()))
789 elif ip.nh == IP_PROTOS.udp:
790 p = (ip / UDP(buffer.getvalue()))
791 self.logger.debug(ppp("Reassembled:", p))
792 self.assert_packet_checksums_valid(p)
795 def initiate_tcp_session(self, in_if, out_if):
797 Initiates TCP session
799 :param in_if: Inside interface
800 :param out_if: Outside interface
804 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
805 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
806 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
809 self.pg_enable_capture(self.pg_interfaces)
811 capture = out_if.get_capture(1)
813 self.tcp_port_out = p[TCP].sport
815 # SYN + ACK packet out->in
816 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
817 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
818 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
821 self.pg_enable_capture(self.pg_interfaces)
826 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
827 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
828 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
831 self.pg_enable_capture(self.pg_interfaces)
833 out_if.get_capture(1)
836 self.logger.error("TCP 3 way handshake failed")
839 def verify_ipfix_nat44_ses(self, data):
841 Verify IPFIX NAT44 session create/delete event
843 :param data: Decoded IPFIX data records
845 nat44_ses_create_num = 0
846 nat44_ses_delete_num = 0
847 self.assertEqual(6, len(data))
850 self.assertIn(scapy.compat.orb(record[230]), [4, 5])
851 if scapy.compat.orb(record[230]) == 4:
852 nat44_ses_create_num += 1
854 nat44_ses_delete_num += 1
856 self.assertEqual(self.pg0.remote_ip4,
857 str(ipaddress.IPv4Address(record[8])))
858 # postNATSourceIPv4Address
859 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
862 self.assertEqual(struct.pack("!I", 0), record[234])
863 # protocolIdentifier/sourceTransportPort
864 # /postNAPTSourceTransportPort
865 if IP_PROTOS.icmp == scapy.compat.orb(record[4]):
866 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
867 self.assertEqual(struct.pack("!H", self.icmp_id_out),
869 elif IP_PROTOS.tcp == scapy.compat.orb(record[4]):
870 self.assertEqual(struct.pack("!H", self.tcp_port_in),
872 self.assertEqual(struct.pack("!H", self.tcp_port_out),
874 elif IP_PROTOS.udp == scapy.compat.orb(record[4]):
875 self.assertEqual(struct.pack("!H", self.udp_port_in),
877 self.assertEqual(struct.pack("!H", self.udp_port_out),
880 self.fail("Invalid protocol")
881 self.assertEqual(3, nat44_ses_create_num)
882 self.assertEqual(3, nat44_ses_delete_num)
884 def verify_ipfix_addr_exhausted(self, data):
886 Verify IPFIX NAT addresses event
888 :param data: Decoded IPFIX data records
890 self.assertEqual(1, len(data))
893 self.assertEqual(scapy.compat.orb(record[230]), 3)
895 self.assertEqual(struct.pack("!I", 0), record[283])
897 def verify_ipfix_max_sessions(self, data, limit):
899 Verify IPFIX maximum session entries exceeded event
901 :param data: Decoded IPFIX data records
902 :param limit: Number of maximum session entries that can be created.
904 self.assertEqual(1, len(data))
907 self.assertEqual(scapy.compat.orb(record[230]), 13)
908 # natQuotaExceededEvent
909 self.assertEqual(struct.pack("I", 1), record[466])
911 self.assertEqual(struct.pack("I", limit), record[471])
913 def verify_ipfix_max_bibs(self, data, limit):
915 Verify IPFIX maximum BIB entries exceeded event
917 :param data: Decoded IPFIX data records
918 :param limit: Number of maximum BIB entries that can be created.
920 self.assertEqual(1, len(data))
923 self.assertEqual(scapy.compat.orb(record[230]), 13)
924 # natQuotaExceededEvent
925 self.assertEqual(struct.pack("I", 2), record[466])
927 self.assertEqual(struct.pack("I", limit), record[472])
929 def verify_ipfix_bib(self, data, is_create, src_addr):
931 Verify IPFIX NAT64 BIB create and delete events
933 :param data: Decoded IPFIX data records
934 :param is_create: Create event if nonzero value otherwise delete event
935 :param src_addr: IPv6 source address
937 self.assertEqual(1, len(data))
941 self.assertEqual(scapy.compat.orb(record[230]), 10)
943 self.assertEqual(scapy.compat.orb(record[230]), 11)
945 self.assertEqual(src_addr, str(ipaddress.IPv6Address(record[27])))
946 # postNATSourceIPv4Address
947 self.assertEqual(self.nat_addr_n, record[225])
949 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
951 self.assertEqual(struct.pack("!I", 0), record[234])
952 # sourceTransportPort
953 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
954 # postNAPTSourceTransportPort
955 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
957 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
960 Verify IPFIX NAT64 session create and delete events
962 :param data: Decoded IPFIX data records
963 :param is_create: Create event if nonzero value otherwise delete event
964 :param src_addr: IPv6 source address
965 :param dst_addr: IPv4 destination address
966 :param dst_port: destination TCP port
968 self.assertEqual(1, len(data))
972 self.assertEqual(scapy.compat.orb(record[230]), 6)
974 self.assertEqual(scapy.compat.orb(record[230]), 7)
976 self.assertEqual(src_addr, str(ipaddress.IPv6Address(record[27])))
977 # destinationIPv6Address
978 self.assertEqual(socket.inet_pton(socket.AF_INET6,
979 self.compose_ip6(dst_addr,
983 # postNATSourceIPv4Address
984 self.assertEqual(self.nat_addr_n, record[225])
985 # postNATDestinationIPv4Address
986 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
989 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
991 self.assertEqual(struct.pack("!I", 0), record[234])
992 # sourceTransportPort
993 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
994 # postNAPTSourceTransportPort
995 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
996 # destinationTransportPort
997 self.assertEqual(struct.pack("!H", dst_port), record[11])
998 # postNAPTDestinationTransportPort
999 self.assertEqual(struct.pack("!H", dst_port), record[228])
1001 def verify_no_nat44_user(self):
1002 """ Verify that there is no NAT44 user """
1003 users = self.vapi.nat44_user_dump()
1004 self.assertEqual(len(users), 0)
1005 users = self.statistics.get_counter('/nat44/total-users')
1006 self.assertEqual(users[0][0], 0)
1007 sessions = self.statistics.get_counter('/nat44/total-sessions')
1008 self.assertEqual(sessions[0][0], 0)
1010 def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
1012 Verify IPFIX maximum entries per user exceeded event
1014 :param data: Decoded IPFIX data records
1015 :param limit: Number of maximum entries per user
1016 :param src_addr: IPv4 source address
1018 self.assertEqual(1, len(data))
1021 self.assertEqual(scapy.compat.orb(record[230]), 13)
1022 # natQuotaExceededEvent
1023 self.assertEqual(struct.pack("I", 3), record[466])
1025 self.assertEqual(struct.pack("I", limit), record[473])
1027 self.assertEqual(socket.inet_pton(socket.AF_INET, src_addr), record[8])
1029 def verify_syslog_apmap(self, data, is_add=True):
1030 message = data.decode('utf-8')
1032 message = SyslogMessage.parse(message)
1033 except ParseError as e:
1034 self.logger.error(e)
1037 self.assertEqual(message.severity, SyslogSeverity.info)
1038 self.assertEqual(message.appname, 'NAT')
1039 self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
1040 sd_params = message.sd.get('napmap')
1041 self.assertTrue(sd_params is not None)
1042 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1043 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1044 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1045 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1046 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1047 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1048 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1049 self.assertTrue(sd_params.get('SSUBIX') is not None)
1050 self.assertEqual(sd_params.get('SVLAN'), '0')
1052 def verify_syslog_sess(self, data, is_add=True, is_ip6=False):
1053 message = data.decode('utf-8')
1055 message = SyslogMessage.parse(message)
1056 except ParseError as e:
1057 self.logger.error(e)
1060 self.assertEqual(message.severity, SyslogSeverity.info)
1061 self.assertEqual(message.appname, 'NAT')
1062 self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL')
1063 sd_params = message.sd.get('nsess')
1064 self.assertTrue(sd_params is not None)
1066 self.assertEqual(sd_params.get('IATYP'), 'IPv6')
1067 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
1069 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1070 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1071 self.assertTrue(sd_params.get('SSUBIX') is not None)
1072 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1073 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1074 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1075 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1076 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1077 self.assertEqual(sd_params.get('SVLAN'), '0')
1078 self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
1079 self.assertEqual(sd_params.get('XDPORT'),
1080 "%d" % self.tcp_external_port)
1082 def verify_mss_value(self, pkt, mss):
1084 Verify TCP MSS value
1089 if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
1090 raise TypeError("Not a TCP/IP packet")
1092 for option in pkt[TCP].options:
1093 if option[0] == 'MSS':
1094 self.assertEqual(option[1], mss)
1095 self.assert_tcp_checksum_valid(pkt)
1098 def proto2layer(proto):
1099 if proto == IP_PROTOS.tcp:
1101 elif proto == IP_PROTOS.udp:
1103 elif proto == IP_PROTOS.icmp:
1106 raise Exception("Unsupported protocol")
1108 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1109 layer = self.proto2layer(proto)
1111 if proto == IP_PROTOS.tcp:
1112 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1114 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1115 self.port_in = random.randint(1025, 65535)
1118 pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
1119 self.port_in, 20, data, proto)
1120 self.pg0.add_stream(pkts)
1121 self.pg_enable_capture(self.pg_interfaces)
1123 frags = self.pg1.get_capture(len(pkts))
1124 if not dont_translate:
1125 p = self.reass_frags_and_verify(frags,
1127 self.pg1.remote_ip4)
1129 p = self.reass_frags_and_verify(frags,
1130 self.pg0.remote_ip4,
1131 self.pg1.remote_ip4)
1132 if proto != IP_PROTOS.icmp:
1133 if not dont_translate:
1134 self.assertEqual(p[layer].dport, 20)
1135 self.assertNotEqual(p[layer].sport, self.port_in)
1137 self.assertEqual(p[layer].sport, self.port_in)
1139 if not dont_translate:
1140 self.assertNotEqual(p[layer].id, self.port_in)
1142 self.assertEqual(p[layer].id, self.port_in)
1143 self.assertEqual(data, p[Raw].load)
1146 if not dont_translate:
1147 dst_addr = self.nat_addr
1149 dst_addr = self.pg0.remote_ip4
1150 if proto != IP_PROTOS.icmp:
1152 dport = p[layer].sport
1156 pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport, data,
1157 proto, echo_reply=True)
1158 self.pg1.add_stream(pkts)
1159 self.pg_enable_capture(self.pg_interfaces)
1161 frags = self.pg0.get_capture(len(pkts))
1162 p = self.reass_frags_and_verify(frags,
1163 self.pg1.remote_ip4,
1164 self.pg0.remote_ip4)
1165 if proto != IP_PROTOS.icmp:
1166 self.assertEqual(p[layer].sport, 20)
1167 self.assertEqual(p[layer].dport, self.port_in)
1169 self.assertEqual(p[layer].id, self.port_in)
1170 self.assertEqual(data, p[Raw].load)
1172 def frag_in_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1173 layer = self.proto2layer(proto)
1175 if proto == IP_PROTOS.tcp:
1176 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1178 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1179 self.port_in = random.randint(1025, 65535)
1183 pkts = self.create_stream_frag(self.pg0, self.server_out_addr,
1184 self.port_in, self.server_out_port,
1186 self.pg0.add_stream(pkts)
1187 self.pg_enable_capture(self.pg_interfaces)
1189 frags = self.pg1.get_capture(len(pkts))
1190 p = self.reass_frags_and_verify(frags,
1191 self.pg0.remote_ip4,
1192 self.server_in_addr)
1193 if proto != IP_PROTOS.icmp:
1194 self.assertEqual(p[layer].sport, self.port_in)
1195 self.assertEqual(p[layer].dport, self.server_in_port)
1197 self.assertEqual(p[layer].id, self.port_in)
1198 self.assertEqual(data, p[Raw].load)
1201 if proto != IP_PROTOS.icmp:
1202 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1203 self.server_in_port,
1204 p[layer].sport, data, proto)
1206 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1207 p[layer].id, 0, data, proto,
1209 self.pg1.add_stream(pkts)
1210 self.pg_enable_capture(self.pg_interfaces)
1212 frags = self.pg0.get_capture(len(pkts))
1213 p = self.reass_frags_and_verify(frags,
1214 self.server_out_addr,
1215 self.pg0.remote_ip4)
1216 if proto != IP_PROTOS.icmp:
1217 self.assertEqual(p[layer].sport, self.server_out_port)
1218 self.assertEqual(p[layer].dport, self.port_in)
1220 self.assertEqual(p[layer].id, self.port_in)
1221 self.assertEqual(data, p[Raw].load)
1223 def reass_hairpinning(self, proto=IP_PROTOS.tcp):
1224 layer = self.proto2layer(proto)
1226 if proto == IP_PROTOS.tcp:
1227 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1229 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1231 # send packet from host to server
1232 pkts = self.create_stream_frag(self.pg0,
1235 self.server_out_port,
1238 self.pg0.add_stream(pkts)
1239 self.pg_enable_capture(self.pg_interfaces)
1241 frags = self.pg0.get_capture(len(pkts))
1242 p = self.reass_frags_and_verify(frags,
1245 if proto != IP_PROTOS.icmp:
1246 self.assertNotEqual(p[layer].sport, self.host_in_port)
1247 self.assertEqual(p[layer].dport, self.server_in_port)
1249 self.assertNotEqual(p[layer].id, self.host_in_port)
1250 self.assertEqual(data, p[Raw].load)
1252 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1253 layer = self.proto2layer(proto)
1255 if proto == IP_PROTOS.tcp:
1256 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1258 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1259 self.port_in = random.randint(1025, 65535)
1263 pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
1264 self.port_in, 20, data, proto)
1266 self.pg0.add_stream(pkts)
1267 self.pg_enable_capture(self.pg_interfaces)
1269 frags = self.pg1.get_capture(len(pkts))
1270 if not dont_translate:
1271 p = self.reass_frags_and_verify(frags,
1273 self.pg1.remote_ip4)
1275 p = self.reass_frags_and_verify(frags,
1276 self.pg0.remote_ip4,
1277 self.pg1.remote_ip4)
1278 if proto != IP_PROTOS.icmp:
1279 if not dont_translate:
1280 self.assertEqual(p[layer].dport, 20)
1281 self.assertNotEqual(p[layer].sport, self.port_in)
1283 self.assertEqual(p[layer].sport, self.port_in)
1285 if not dont_translate:
1286 self.assertNotEqual(p[layer].id, self.port_in)
1288 self.assertEqual(p[layer].id, self.port_in)
1289 self.assertEqual(data, p[Raw].load)
1292 if not dont_translate:
1293 dst_addr = self.nat_addr
1295 dst_addr = self.pg0.remote_ip4
1296 if proto != IP_PROTOS.icmp:
1298 dport = p[layer].sport
1302 pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport,
1303 data, proto, echo_reply=True)
1305 self.pg1.add_stream(pkts)
1306 self.pg_enable_capture(self.pg_interfaces)
1308 frags = self.pg0.get_capture(len(pkts))
1309 p = self.reass_frags_and_verify(frags,
1310 self.pg1.remote_ip4,
1311 self.pg0.remote_ip4)
1312 if proto != IP_PROTOS.icmp:
1313 self.assertEqual(p[layer].sport, 20)
1314 self.assertEqual(p[layer].dport, self.port_in)
1316 self.assertEqual(p[layer].id, self.port_in)
1317 self.assertEqual(data, p[Raw].load)
1319 def frag_out_of_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1320 layer = self.proto2layer(proto)
1322 if proto == IP_PROTOS.tcp:
1323 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1325 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1326 self.port_in = random.randint(1025, 65535)
1330 pkts = self.create_stream_frag(self.pg0, self.server_out_addr,
1331 self.port_in, self.server_out_port,
1334 self.pg0.add_stream(pkts)
1335 self.pg_enable_capture(self.pg_interfaces)
1337 frags = self.pg1.get_capture(len(pkts))
1338 p = self.reass_frags_and_verify(frags,
1339 self.pg0.remote_ip4,
1340 self.server_in_addr)
1341 if proto != IP_PROTOS.icmp:
1342 self.assertEqual(p[layer].dport, self.server_in_port)
1343 self.assertEqual(p[layer].sport, self.port_in)
1344 self.assertEqual(p[layer].dport, self.server_in_port)
1346 self.assertEqual(p[layer].id, self.port_in)
1347 self.assertEqual(data, p[Raw].load)
1350 if proto != IP_PROTOS.icmp:
1351 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1352 self.server_in_port,
1353 p[layer].sport, data, proto)
1355 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1356 p[layer].id, 0, data, proto,
1359 self.pg1.add_stream(pkts)
1360 self.pg_enable_capture(self.pg_interfaces)
1362 frags = self.pg0.get_capture(len(pkts))
1363 p = self.reass_frags_and_verify(frags,
1364 self.server_out_addr,
1365 self.pg0.remote_ip4)
1366 if proto != IP_PROTOS.icmp:
1367 self.assertEqual(p[layer].sport, self.server_out_port)
1368 self.assertEqual(p[layer].dport, self.port_in)
1370 self.assertEqual(p[layer].id, self.port_in)
1371 self.assertEqual(data, p[Raw].load)
1374 class TestNAT44(MethodHolder):
1375 """ NAT44 Test Cases """
1378 def setUpClass(cls):
1379 super(TestNAT44, cls).setUpClass()
1380 cls.vapi.cli("set log class nat level debug")
1382 cls.tcp_port_in = 6303
1383 cls.tcp_port_out = 6303
1384 cls.udp_port_in = 6304
1385 cls.udp_port_out = 6304
1386 cls.icmp_id_in = 6305
1387 cls.icmp_id_out = 6305
1388 cls.nat_addr = '10.0.0.3'
1389 cls.ipfix_src_port = 4739
1390 cls.ipfix_domain_id = 1
1391 cls.tcp_external_port = 80
1392 cls.udp_external_port = 69
1394 cls.create_pg_interfaces(range(10))
1395 cls.interfaces = list(cls.pg_interfaces[0:4])
1397 for i in cls.interfaces:
1402 cls.pg0.generate_remote_hosts(3)
1403 cls.pg0.configure_ipv4_neighbors()
1405 cls.pg1.generate_remote_hosts(1)
1406 cls.pg1.configure_ipv4_neighbors()
1408 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
1409 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 10})
1410 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 20})
1412 cls.pg4._local_ip4 = "172.16.255.1"
1413 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1414 cls.pg4.set_table_ip4(10)
1415 cls.pg5._local_ip4 = "172.17.255.3"
1416 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
1417 cls.pg5.set_table_ip4(10)
1418 cls.pg6._local_ip4 = "172.16.255.1"
1419 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1420 cls.pg6.set_table_ip4(20)
1421 for i in cls.overlapping_interfaces:
1429 cls.pg9.generate_remote_hosts(2)
1430 cls.pg9.config_ip4()
1431 cls.vapi.sw_interface_add_del_address(
1432 sw_if_index=cls.pg9.sw_if_index,
1433 prefix="10.0.0.1/24")
1436 cls.pg9.resolve_arp()
1437 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1438 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1439 cls.pg9.resolve_arp()
1442 def tearDownClass(cls):
1443 super(TestNAT44, cls).tearDownClass()
1445 def test_dynamic(self):
1446 """ NAT44 dynamic translation test """
1447 self.nat44_add_address(self.nat_addr)
1448 flags = self.config_flags.NAT_IS_INSIDE
1449 self.vapi.nat44_interface_add_del_feature(
1450 sw_if_index=self.pg0.sw_if_index,
1451 flags=flags, is_add=1)
1452 self.vapi.nat44_interface_add_del_feature(
1453 sw_if_index=self.pg1.sw_if_index,
1457 tcpn = self.statistics.get_err_counter(
1458 '/err/nat44-in2out-slowpath/TCP packets')
1459 udpn = self.statistics.get_err_counter(
1460 '/err/nat44-in2out-slowpath/UDP packets')
1461 icmpn = self.statistics.get_err_counter(
1462 '/err/nat44-in2out-slowpath/ICMP packets')
1463 totaln = self.statistics.get_err_counter(
1464 '/err/nat44-in2out-slowpath/good in2out packets processed')
1466 pkts = self.create_stream_in(self.pg0, self.pg1)
1467 self.pg0.add_stream(pkts)
1468 self.pg_enable_capture(self.pg_interfaces)
1470 capture = self.pg1.get_capture(len(pkts))
1471 self.verify_capture_out(capture)
1473 err = self.statistics.get_err_counter(
1474 '/err/nat44-in2out-slowpath/TCP packets')
1475 self.assertEqual(err - tcpn, 2)
1476 err = self.statistics.get_err_counter(
1477 '/err/nat44-in2out-slowpath/UDP packets')
1478 self.assertEqual(err - udpn, 1)
1479 err = self.statistics.get_err_counter(
1480 '/err/nat44-in2out-slowpath/ICMP packets')
1481 self.assertEqual(err - icmpn, 1)
1482 err = self.statistics.get_err_counter(
1483 '/err/nat44-in2out-slowpath/good in2out packets processed')
1484 self.assertEqual(err - totaln, 4)
1487 tcpn = self.statistics.get_err_counter('/err/nat44-out2in/TCP packets')
1488 udpn = self.statistics.get_err_counter('/err/nat44-out2in/UDP packets')
1489 icmpn = self.statistics.get_err_counter(
1490 '/err/nat44-out2in/ICMP packets')
1491 totaln = self.statistics.get_err_counter(
1492 '/err/nat44-out2in/good out2in packets processed')
1494 pkts = self.create_stream_out(self.pg1)
1495 self.pg1.add_stream(pkts)
1496 self.pg_enable_capture(self.pg_interfaces)
1498 capture = self.pg0.get_capture(len(pkts))
1499 self.verify_capture_in(capture, self.pg0)
1501 err = self.statistics.get_err_counter('/err/nat44-out2in/TCP packets')
1502 self.assertEqual(err - tcpn, 2)
1503 err = self.statistics.get_err_counter('/err/nat44-out2in/UDP packets')
1504 self.assertEqual(err - udpn, 1)
1505 err = self.statistics.get_err_counter('/err/nat44-out2in/ICMP packets')
1506 self.assertEqual(err - icmpn, 1)
1507 err = self.statistics.get_err_counter(
1508 '/err/nat44-out2in/good out2in packets processed')
1509 self.assertEqual(err - totaln, 4)
1511 users = self.statistics.get_counter('/nat44/total-users')
1512 self.assertEqual(users[0][0], 1)
1513 sessions = self.statistics.get_counter('/nat44/total-sessions')
1514 self.assertEqual(sessions[0][0], 3)
1516 def test_dynamic_icmp_errors_in2out_ttl_1(self):
1517 """ NAT44 handling of client packets with TTL=1 """
1519 self.nat44_add_address(self.nat_addr)
1520 flags = self.config_flags.NAT_IS_INSIDE
1521 self.vapi.nat44_interface_add_del_feature(
1522 sw_if_index=self.pg0.sw_if_index,
1523 flags=flags, is_add=1)
1524 self.vapi.nat44_interface_add_del_feature(
1525 sw_if_index=self.pg1.sw_if_index,
1528 # Client side - generate traffic
1529 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1530 self.pg0.add_stream(pkts)
1531 self.pg_enable_capture(self.pg_interfaces)
1534 # Client side - verify ICMP type 11 packets
1535 capture = self.pg0.get_capture(len(pkts))
1536 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1538 def test_dynamic_icmp_errors_out2in_ttl_1(self):
1539 """ NAT44 handling of server packets with TTL=1 """
1541 self.nat44_add_address(self.nat_addr)
1542 flags = self.config_flags.NAT_IS_INSIDE
1543 self.vapi.nat44_interface_add_del_feature(
1544 sw_if_index=self.pg0.sw_if_index,
1545 flags=flags, is_add=1)
1546 self.vapi.nat44_interface_add_del_feature(
1547 sw_if_index=self.pg1.sw_if_index,
1550 # Client side - create sessions
1551 pkts = self.create_stream_in(self.pg0, self.pg1)
1552 self.pg0.add_stream(pkts)
1553 self.pg_enable_capture(self.pg_interfaces)
1556 # Server side - generate traffic
1557 capture = self.pg1.get_capture(len(pkts))
1558 self.verify_capture_out(capture)
1559 pkts = self.create_stream_out(self.pg1, ttl=1)
1560 self.pg1.add_stream(pkts)
1561 self.pg_enable_capture(self.pg_interfaces)
1564 # Server side - verify ICMP type 11 packets
1565 capture = self.pg1.get_capture(len(pkts))
1566 self.verify_capture_out_with_icmp_errors(capture,
1567 src_ip=self.pg1.local_ip4)
1569 def test_dynamic_icmp_errors_in2out_ttl_2(self):
1570 """ NAT44 handling of error responses to client packets with TTL=2 """
1572 self.nat44_add_address(self.nat_addr)
1573 flags = self.config_flags.NAT_IS_INSIDE
1574 self.vapi.nat44_interface_add_del_feature(
1575 sw_if_index=self.pg0.sw_if_index,
1576 flags=flags, is_add=1)
1577 self.vapi.nat44_interface_add_del_feature(
1578 sw_if_index=self.pg1.sw_if_index,
1581 # Client side - generate traffic
1582 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1583 self.pg0.add_stream(pkts)
1584 self.pg_enable_capture(self.pg_interfaces)
1587 # Server side - simulate ICMP type 11 response
1588 capture = self.pg1.get_capture(len(pkts))
1589 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1590 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1591 ICMP(type=11) / packet[IP] for packet in capture]
1592 self.pg1.add_stream(pkts)
1593 self.pg_enable_capture(self.pg_interfaces)
1596 # Client side - verify ICMP type 11 packets
1597 capture = self.pg0.get_capture(len(pkts))
1598 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1600 def test_dynamic_icmp_errors_out2in_ttl_2(self):
1601 """ NAT44 handling of error responses to server packets with TTL=2 """
1603 self.nat44_add_address(self.nat_addr)
1604 flags = self.config_flags.NAT_IS_INSIDE
1605 self.vapi.nat44_interface_add_del_feature(
1606 sw_if_index=self.pg0.sw_if_index,
1607 flags=flags, is_add=1)
1608 self.vapi.nat44_interface_add_del_feature(
1609 sw_if_index=self.pg1.sw_if_index,
1612 # Client side - create sessions
1613 pkts = self.create_stream_in(self.pg0, self.pg1)
1614 self.pg0.add_stream(pkts)
1615 self.pg_enable_capture(self.pg_interfaces)
1618 # Server side - generate traffic
1619 capture = self.pg1.get_capture(len(pkts))
1620 self.verify_capture_out(capture)
1621 pkts = self.create_stream_out(self.pg1, ttl=2)
1622 self.pg1.add_stream(pkts)
1623 self.pg_enable_capture(self.pg_interfaces)
1626 # Client side - simulate ICMP type 11 response
1627 capture = self.pg0.get_capture(len(pkts))
1628 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1629 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1630 ICMP(type=11) / packet[IP] for packet in capture]
1631 self.pg0.add_stream(pkts)
1632 self.pg_enable_capture(self.pg_interfaces)
1635 # Server side - verify ICMP type 11 packets
1636 capture = self.pg1.get_capture(len(pkts))
1637 self.verify_capture_out_with_icmp_errors(capture)
1639 def test_ping_out_interface_from_outside(self):
1640 """ Ping NAT44 out interface from outside network """
1642 self.nat44_add_address(self.nat_addr)
1643 flags = self.config_flags.NAT_IS_INSIDE
1644 self.vapi.nat44_interface_add_del_feature(
1645 sw_if_index=self.pg0.sw_if_index,
1646 flags=flags, is_add=1)
1647 self.vapi.nat44_interface_add_del_feature(
1648 sw_if_index=self.pg1.sw_if_index,
1651 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1652 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1653 ICMP(id=self.icmp_id_out, type='echo-request'))
1655 self.pg1.add_stream(pkts)
1656 self.pg_enable_capture(self.pg_interfaces)
1658 capture = self.pg1.get_capture(len(pkts))
1661 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1662 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1663 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1664 self.assertEqual(packet[ICMP].type, 0) # echo reply
1666 self.logger.error(ppp("Unexpected or invalid packet "
1667 "(outside network):", packet))
1670 def test_ping_internal_host_from_outside(self):
1671 """ Ping internal host from outside network """
1673 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1674 flags = self.config_flags.NAT_IS_INSIDE
1675 self.vapi.nat44_interface_add_del_feature(
1676 sw_if_index=self.pg0.sw_if_index,
1677 flags=flags, is_add=1)
1678 self.vapi.nat44_interface_add_del_feature(
1679 sw_if_index=self.pg1.sw_if_index,
1683 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1684 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
1685 ICMP(id=self.icmp_id_out, type='echo-request'))
1686 self.pg1.add_stream(pkt)
1687 self.pg_enable_capture(self.pg_interfaces)
1689 capture = self.pg0.get_capture(1)
1690 self.verify_capture_in(capture, self.pg0)
1691 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1694 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1695 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1696 ICMP(id=self.icmp_id_in, type='echo-reply'))
1697 self.pg0.add_stream(pkt)
1698 self.pg_enable_capture(self.pg_interfaces)
1700 capture = self.pg1.get_capture(1)
1701 self.verify_capture_out(capture, same_port=True)
1702 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1704 def test_forwarding(self):
1705 """ NAT44 forwarding test """
1707 flags = self.config_flags.NAT_IS_INSIDE
1708 self.vapi.nat44_interface_add_del_feature(
1709 sw_if_index=self.pg0.sw_if_index,
1710 flags=flags, is_add=1)
1711 self.vapi.nat44_interface_add_del_feature(
1712 sw_if_index=self.pg1.sw_if_index,
1714 self.vapi.nat44_forwarding_enable_disable(enable=1)
1716 real_ip = self.pg0.remote_ip4
1717 alias_ip = self.nat_addr
1718 flags = self.config_flags.NAT_IS_ADDR_ONLY
1719 self.vapi.nat44_add_del_static_mapping(is_add=1,
1720 local_ip_address=real_ip,
1721 external_ip_address=alias_ip,
1722 external_sw_if_index=0xFFFFFFFF,
1726 # static mapping match
1728 pkts = self.create_stream_out(self.pg1)
1729 self.pg1.add_stream(pkts)
1730 self.pg_enable_capture(self.pg_interfaces)
1732 capture = self.pg0.get_capture(len(pkts))
1733 self.verify_capture_in(capture, self.pg0)
1735 pkts = self.create_stream_in(self.pg0, self.pg1)
1736 self.pg0.add_stream(pkts)
1737 self.pg_enable_capture(self.pg_interfaces)
1739 capture = self.pg1.get_capture(len(pkts))
1740 self.verify_capture_out(capture, same_port=True)
1742 # no static mapping match
1744 host0 = self.pg0.remote_hosts[0]
1745 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1747 pkts = self.create_stream_out(self.pg1,
1748 dst_ip=self.pg0.remote_ip4,
1749 use_inside_ports=True)
1750 self.pg1.add_stream(pkts)
1751 self.pg_enable_capture(self.pg_interfaces)
1753 capture = self.pg0.get_capture(len(pkts))
1754 self.verify_capture_in(capture, self.pg0)
1756 pkts = self.create_stream_in(self.pg0, self.pg1)
1757 self.pg0.add_stream(pkts)
1758 self.pg_enable_capture(self.pg_interfaces)
1760 capture = self.pg1.get_capture(len(pkts))
1761 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1764 self.pg0.remote_hosts[0] = host0
1767 self.vapi.nat44_forwarding_enable_disable(enable=0)
1768 flags = self.config_flags.NAT_IS_ADDR_ONLY
1769 self.vapi.nat44_add_del_static_mapping(
1771 local_ip_address=real_ip,
1772 external_ip_address=alias_ip,
1773 external_sw_if_index=0xFFFFFFFF,
1776 def test_static_in(self):
1777 """ 1:1 NAT initialized from inside network """
1779 nat_ip = "10.0.0.10"
1780 self.tcp_port_out = 6303
1781 self.udp_port_out = 6304
1782 self.icmp_id_out = 6305
1784 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1785 flags = self.config_flags.NAT_IS_INSIDE
1786 self.vapi.nat44_interface_add_del_feature(
1787 sw_if_index=self.pg0.sw_if_index,
1788 flags=flags, is_add=1)
1789 self.vapi.nat44_interface_add_del_feature(
1790 sw_if_index=self.pg1.sw_if_index,
1792 sm = self.vapi.nat44_static_mapping_dump()
1793 self.assertEqual(len(sm), 1)
1794 self.assertEqual(sm[0].tag, '')
1795 self.assertEqual(sm[0].protocol, 0)
1796 self.assertEqual(sm[0].local_port, 0)
1797 self.assertEqual(sm[0].external_port, 0)
1800 pkts = self.create_stream_in(self.pg0, self.pg1)
1801 self.pg0.add_stream(pkts)
1802 self.pg_enable_capture(self.pg_interfaces)
1804 capture = self.pg1.get_capture(len(pkts))
1805 self.verify_capture_out(capture, nat_ip, True)
1808 pkts = self.create_stream_out(self.pg1, nat_ip)
1809 self.pg1.add_stream(pkts)
1810 self.pg_enable_capture(self.pg_interfaces)
1812 capture = self.pg0.get_capture(len(pkts))
1813 self.verify_capture_in(capture, self.pg0)
1815 def test_static_out(self):
1816 """ 1:1 NAT initialized from outside network """
1818 nat_ip = "10.0.0.20"
1819 self.tcp_port_out = 6303
1820 self.udp_port_out = 6304
1821 self.icmp_id_out = 6305
1824 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
1825 flags = self.config_flags.NAT_IS_INSIDE
1826 self.vapi.nat44_interface_add_del_feature(
1827 sw_if_index=self.pg0.sw_if_index,
1828 flags=flags, is_add=1)
1829 self.vapi.nat44_interface_add_del_feature(
1830 sw_if_index=self.pg1.sw_if_index,
1832 sm = self.vapi.nat44_static_mapping_dump()
1833 self.assertEqual(len(sm), 1)
1834 self.assertEqual(sm[0].tag, tag)
1837 pkts = self.create_stream_out(self.pg1, nat_ip)
1838 self.pg1.add_stream(pkts)
1839 self.pg_enable_capture(self.pg_interfaces)
1841 capture = self.pg0.get_capture(len(pkts))
1842 self.verify_capture_in(capture, self.pg0)
1845 pkts = self.create_stream_in(self.pg0, self.pg1)
1846 self.pg0.add_stream(pkts)
1847 self.pg_enable_capture(self.pg_interfaces)
1849 capture = self.pg1.get_capture(len(pkts))
1850 self.verify_capture_out(capture, nat_ip, True)
1852 def test_static_with_port_in(self):
1853 """ 1:1 NAPT initialized from inside network """
1855 self.tcp_port_out = 3606
1856 self.udp_port_out = 3607
1857 self.icmp_id_out = 3608
1859 self.nat44_add_address(self.nat_addr)
1860 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1861 self.tcp_port_in, self.tcp_port_out,
1862 proto=IP_PROTOS.tcp)
1863 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1864 self.udp_port_in, self.udp_port_out,
1865 proto=IP_PROTOS.udp)
1866 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1867 self.icmp_id_in, self.icmp_id_out,
1868 proto=IP_PROTOS.icmp)
1869 flags = self.config_flags.NAT_IS_INSIDE
1870 self.vapi.nat44_interface_add_del_feature(
1871 sw_if_index=self.pg0.sw_if_index,
1872 flags=flags, is_add=1)
1873 self.vapi.nat44_interface_add_del_feature(
1874 sw_if_index=self.pg1.sw_if_index,
1878 pkts = self.create_stream_in(self.pg0, self.pg1)
1879 self.pg0.add_stream(pkts)
1880 self.pg_enable_capture(self.pg_interfaces)
1882 capture = self.pg1.get_capture(len(pkts))
1883 self.verify_capture_out(capture)
1886 pkts = self.create_stream_out(self.pg1)
1887 self.pg1.add_stream(pkts)
1888 self.pg_enable_capture(self.pg_interfaces)
1890 capture = self.pg0.get_capture(len(pkts))
1891 self.verify_capture_in(capture, self.pg0)
1893 def test_static_with_port_out(self):
1894 """ 1:1 NAPT initialized from outside network """
1896 self.tcp_port_out = 30606
1897 self.udp_port_out = 30607
1898 self.icmp_id_out = 30608
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_out(self.pg1)
1920 self.pg1.add_stream(pkts)
1921 self.pg_enable_capture(self.pg_interfaces)
1923 capture = self.pg0.get_capture(len(pkts))
1924 self.verify_capture_in(capture, self.pg0)
1927 pkts = self.create_stream_in(self.pg0, self.pg1)
1928 self.pg0.add_stream(pkts)
1929 self.pg_enable_capture(self.pg_interfaces)
1931 capture = self.pg1.get_capture(len(pkts))
1932 self.verify_capture_out(capture)
1934 def test_static_vrf_aware(self):
1935 """ 1:1 NAT VRF awareness """
1937 nat_ip1 = "10.0.0.30"
1938 nat_ip2 = "10.0.0.40"
1939 self.tcp_port_out = 6303
1940 self.udp_port_out = 6304
1941 self.icmp_id_out = 6305
1943 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1945 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1947 flags = self.config_flags.NAT_IS_INSIDE
1948 self.vapi.nat44_interface_add_del_feature(
1949 sw_if_index=self.pg3.sw_if_index,
1951 self.vapi.nat44_interface_add_del_feature(
1952 sw_if_index=self.pg0.sw_if_index,
1953 flags=flags, is_add=1)
1954 self.vapi.nat44_interface_add_del_feature(
1955 sw_if_index=self.pg4.sw_if_index,
1956 flags=flags, is_add=1)
1958 # inside interface VRF match NAT44 static mapping VRF
1959 pkts = self.create_stream_in(self.pg4, self.pg3)
1960 self.pg4.add_stream(pkts)
1961 self.pg_enable_capture(self.pg_interfaces)
1963 capture = self.pg3.get_capture(len(pkts))
1964 self.verify_capture_out(capture, nat_ip1, True)
1966 # inside interface VRF don't match NAT44 static mapping VRF (packets
1968 pkts = self.create_stream_in(self.pg0, self.pg3)
1969 self.pg0.add_stream(pkts)
1970 self.pg_enable_capture(self.pg_interfaces)
1972 self.pg3.assert_nothing_captured()
1974 def test_dynamic_to_static(self):
1975 """ Switch from dynamic translation to 1:1NAT """
1976 nat_ip = "10.0.0.10"
1977 self.tcp_port_out = 6303
1978 self.udp_port_out = 6304
1979 self.icmp_id_out = 6305
1981 self.nat44_add_address(self.nat_addr)
1982 flags = self.config_flags.NAT_IS_INSIDE
1983 self.vapi.nat44_interface_add_del_feature(
1984 sw_if_index=self.pg0.sw_if_index,
1985 flags=flags, is_add=1)
1986 self.vapi.nat44_interface_add_del_feature(
1987 sw_if_index=self.pg1.sw_if_index,
1991 pkts = self.create_stream_in(self.pg0, self.pg1)
1992 self.pg0.add_stream(pkts)
1993 self.pg_enable_capture(self.pg_interfaces)
1995 capture = self.pg1.get_capture(len(pkts))
1996 self.verify_capture_out(capture)
1999 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2000 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
2001 self.assertEqual(len(sessions), 0)
2002 pkts = self.create_stream_in(self.pg0, self.pg1)
2003 self.pg0.add_stream(pkts)
2004 self.pg_enable_capture(self.pg_interfaces)
2006 capture = self.pg1.get_capture(len(pkts))
2007 self.verify_capture_out(capture, nat_ip, True)
2009 def test_identity_nat(self):
2010 """ Identity NAT """
2011 flags = self.config_flags.NAT_IS_ADDR_ONLY
2012 self.vapi.nat44_add_del_identity_mapping(
2013 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
2014 flags=flags, is_add=1)
2015 flags = self.config_flags.NAT_IS_INSIDE
2016 self.vapi.nat44_interface_add_del_feature(
2017 sw_if_index=self.pg0.sw_if_index,
2018 flags=flags, is_add=1)
2019 self.vapi.nat44_interface_add_del_feature(
2020 sw_if_index=self.pg1.sw_if_index,
2023 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2024 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2025 TCP(sport=12345, dport=56789))
2026 self.pg1.add_stream(p)
2027 self.pg_enable_capture(self.pg_interfaces)
2029 capture = self.pg0.get_capture(1)
2034 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2035 self.assertEqual(ip.src, self.pg1.remote_ip4)
2036 self.assertEqual(tcp.dport, 56789)
2037 self.assertEqual(tcp.sport, 12345)
2038 self.assert_packet_checksums_valid(p)
2040 self.logger.error(ppp("Unexpected or invalid packet:", p))
2043 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
2044 self.assertEqual(len(sessions), 0)
2045 flags = self.config_flags.NAT_IS_ADDR_ONLY
2046 self.vapi.nat44_add_del_identity_mapping(
2047 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
2048 flags=flags, vrf_id=1, is_add=1)
2049 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2050 self.assertEqual(len(identity_mappings), 2)
2052 def test_multiple_inside_interfaces(self):
2053 """ NAT44 multiple non-overlapping address space inside interfaces """
2055 self.nat44_add_address(self.nat_addr)
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,
2062 flags=flags, is_add=1)
2063 self.vapi.nat44_interface_add_del_feature(
2064 sw_if_index=self.pg3.sw_if_index,
2067 # between two NAT44 inside interfaces (no translation)
2068 pkts = self.create_stream_in(self.pg0, self.pg1)
2069 self.pg0.add_stream(pkts)
2070 self.pg_enable_capture(self.pg_interfaces)
2072 capture = self.pg1.get_capture(len(pkts))
2073 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
2075 # from NAT44 inside to interface without NAT44 feature (no translation)
2076 pkts = self.create_stream_in(self.pg0, self.pg2)
2077 self.pg0.add_stream(pkts)
2078 self.pg_enable_capture(self.pg_interfaces)
2080 capture = self.pg2.get_capture(len(pkts))
2081 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2083 # in2out 1st interface
2084 pkts = self.create_stream_in(self.pg0, self.pg3)
2085 self.pg0.add_stream(pkts)
2086 self.pg_enable_capture(self.pg_interfaces)
2088 capture = self.pg3.get_capture(len(pkts))
2089 self.verify_capture_out(capture)
2091 # out2in 1st interface
2092 pkts = self.create_stream_out(self.pg3)
2093 self.pg3.add_stream(pkts)
2094 self.pg_enable_capture(self.pg_interfaces)
2096 capture = self.pg0.get_capture(len(pkts))
2097 self.verify_capture_in(capture, self.pg0)
2099 # in2out 2nd interface
2100 pkts = self.create_stream_in(self.pg1, self.pg3)
2101 self.pg1.add_stream(pkts)
2102 self.pg_enable_capture(self.pg_interfaces)
2104 capture = self.pg3.get_capture(len(pkts))
2105 self.verify_capture_out(capture)
2107 # out2in 2nd interface
2108 pkts = self.create_stream_out(self.pg3)
2109 self.pg3.add_stream(pkts)
2110 self.pg_enable_capture(self.pg_interfaces)
2112 capture = self.pg1.get_capture(len(pkts))
2113 self.verify_capture_in(capture, self.pg1)
2115 def test_inside_overlapping_interfaces(self):
2116 """ NAT44 multiple inside interfaces with overlapping address space """
2118 static_nat_ip = "10.0.0.10"
2119 self.nat44_add_address(self.nat_addr)
2120 flags = self.config_flags.NAT_IS_INSIDE
2121 self.vapi.nat44_interface_add_del_feature(
2122 sw_if_index=self.pg3.sw_if_index,
2124 self.vapi.nat44_interface_add_del_feature(
2125 sw_if_index=self.pg4.sw_if_index,
2126 flags=flags, is_add=1)
2127 self.vapi.nat44_interface_add_del_feature(
2128 sw_if_index=self.pg5.sw_if_index,
2129 flags=flags, is_add=1)
2130 self.vapi.nat44_interface_add_del_feature(
2131 sw_if_index=self.pg6.sw_if_index,
2132 flags=flags, is_add=1)
2133 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2136 # between NAT44 inside interfaces with same VRF (no translation)
2137 pkts = self.create_stream_in(self.pg4, self.pg5)
2138 self.pg4.add_stream(pkts)
2139 self.pg_enable_capture(self.pg_interfaces)
2141 capture = self.pg5.get_capture(len(pkts))
2142 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2144 # between NAT44 inside interfaces with different VRF (hairpinning)
2145 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2146 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2147 TCP(sport=1234, dport=5678))
2148 self.pg4.add_stream(p)
2149 self.pg_enable_capture(self.pg_interfaces)
2151 capture = self.pg6.get_capture(1)
2156 self.assertEqual(ip.src, self.nat_addr)
2157 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2158 self.assertNotEqual(tcp.sport, 1234)
2159 self.assertEqual(tcp.dport, 5678)
2161 self.logger.error(ppp("Unexpected or invalid packet:", p))
2164 # in2out 1st interface
2165 pkts = self.create_stream_in(self.pg4, self.pg3)
2166 self.pg4.add_stream(pkts)
2167 self.pg_enable_capture(self.pg_interfaces)
2169 capture = self.pg3.get_capture(len(pkts))
2170 self.verify_capture_out(capture)
2172 # out2in 1st interface
2173 pkts = self.create_stream_out(self.pg3)
2174 self.pg3.add_stream(pkts)
2175 self.pg_enable_capture(self.pg_interfaces)
2177 capture = self.pg4.get_capture(len(pkts))
2178 self.verify_capture_in(capture, self.pg4)
2180 # in2out 2nd interface
2181 pkts = self.create_stream_in(self.pg5, self.pg3)
2182 self.pg5.add_stream(pkts)
2183 self.pg_enable_capture(self.pg_interfaces)
2185 capture = self.pg3.get_capture(len(pkts))
2186 self.verify_capture_out(capture)
2188 # out2in 2nd interface
2189 pkts = self.create_stream_out(self.pg3)
2190 self.pg3.add_stream(pkts)
2191 self.pg_enable_capture(self.pg_interfaces)
2193 capture = self.pg5.get_capture(len(pkts))
2194 self.verify_capture_in(capture, self.pg5)
2197 addresses = self.vapi.nat44_address_dump()
2198 self.assertEqual(len(addresses), 1)
2199 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4, 10)
2200 self.assertEqual(len(sessions), 3)
2201 for session in sessions:
2202 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2203 self.assertEqual(str(session.inside_ip_address),
2204 self.pg5.remote_ip4)
2205 self.assertEqual(session.outside_ip_address,
2206 addresses[0].ip_address)
2207 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2208 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2209 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2210 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2211 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2212 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2213 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2214 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2215 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2217 # in2out 3rd interface
2218 pkts = self.create_stream_in(self.pg6, self.pg3)
2219 self.pg6.add_stream(pkts)
2220 self.pg_enable_capture(self.pg_interfaces)
2222 capture = self.pg3.get_capture(len(pkts))
2223 self.verify_capture_out(capture, static_nat_ip, True)
2225 # out2in 3rd interface
2226 pkts = self.create_stream_out(self.pg3, static_nat_ip)
2227 self.pg3.add_stream(pkts)
2228 self.pg_enable_capture(self.pg_interfaces)
2230 capture = self.pg6.get_capture(len(pkts))
2231 self.verify_capture_in(capture, self.pg6)
2233 # general user and session dump verifications
2234 users = self.vapi.nat44_user_dump()
2235 self.assertGreaterEqual(len(users), 3)
2236 addresses = self.vapi.nat44_address_dump()
2237 self.assertEqual(len(addresses), 1)
2239 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2241 for session in sessions:
2242 self.assertEqual(user.ip_address, session.inside_ip_address)
2243 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2244 self.assertTrue(session.protocol in
2245 [IP_PROTOS.tcp, IP_PROTOS.udp,
2247 self.assertFalse(session.flags &
2248 self.config_flags.NAT_IS_EXT_HOST_VALID)
2251 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4, 10)
2252 self.assertGreaterEqual(len(sessions), 4)
2253 for session in sessions:
2254 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2255 self.assertEqual(str(session.inside_ip_address),
2256 self.pg4.remote_ip4)
2257 self.assertEqual(session.outside_ip_address,
2258 addresses[0].ip_address)
2261 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4, 20)
2262 self.assertGreaterEqual(len(sessions), 3)
2263 for session in sessions:
2264 self.assertTrue(session.flags & self.config_flags.NAT_IS_STATIC)
2265 self.assertEqual(str(session.inside_ip_address),
2266 self.pg6.remote_ip4)
2267 self.assertEqual(str(session.outside_ip_address),
2269 self.assertTrue(session.inside_port in
2270 [self.tcp_port_in, self.udp_port_in,
2273 def test_hairpinning(self):
2274 """ NAT44 hairpinning - 1:1 NAPT """
2276 host = self.pg0.remote_hosts[0]
2277 server = self.pg0.remote_hosts[1]
2280 server_in_port = 5678
2281 server_out_port = 8765
2283 self.nat44_add_address(self.nat_addr)
2284 flags = self.config_flags.NAT_IS_INSIDE
2285 self.vapi.nat44_interface_add_del_feature(
2286 sw_if_index=self.pg0.sw_if_index,
2287 flags=flags, is_add=1)
2288 self.vapi.nat44_interface_add_del_feature(
2289 sw_if_index=self.pg1.sw_if_index,
2292 # add static mapping for server
2293 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2294 server_in_port, server_out_port,
2295 proto=IP_PROTOS.tcp)
2297 # send packet from host to server
2298 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2299 IP(src=host.ip4, dst=self.nat_addr) /
2300 TCP(sport=host_in_port, dport=server_out_port))
2301 self.pg0.add_stream(p)
2302 self.pg_enable_capture(self.pg_interfaces)
2304 capture = self.pg0.get_capture(1)
2309 self.assertEqual(ip.src, self.nat_addr)
2310 self.assertEqual(ip.dst, server.ip4)
2311 self.assertNotEqual(tcp.sport, host_in_port)
2312 self.assertEqual(tcp.dport, server_in_port)
2313 self.assert_packet_checksums_valid(p)
2314 host_out_port = tcp.sport
2316 self.logger.error(ppp("Unexpected or invalid packet:", p))
2319 # send reply from server to host
2320 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2321 IP(src=server.ip4, dst=self.nat_addr) /
2322 TCP(sport=server_in_port, dport=host_out_port))
2323 self.pg0.add_stream(p)
2324 self.pg_enable_capture(self.pg_interfaces)
2326 capture = self.pg0.get_capture(1)
2331 self.assertEqual(ip.src, self.nat_addr)
2332 self.assertEqual(ip.dst, host.ip4)
2333 self.assertEqual(tcp.sport, server_out_port)
2334 self.assertEqual(tcp.dport, host_in_port)
2335 self.assert_packet_checksums_valid(p)
2337 self.logger.error(ppp("Unexpected or invalid packet:", p))
2340 def test_hairpinning2(self):
2341 """ NAT44 hairpinning - 1:1 NAT"""
2343 server1_nat_ip = "10.0.0.10"
2344 server2_nat_ip = "10.0.0.11"
2345 host = self.pg0.remote_hosts[0]
2346 server1 = self.pg0.remote_hosts[1]
2347 server2 = self.pg0.remote_hosts[2]
2348 server_tcp_port = 22
2349 server_udp_port = 20
2351 self.nat44_add_address(self.nat_addr)
2352 flags = self.config_flags.NAT_IS_INSIDE
2353 self.vapi.nat44_interface_add_del_feature(
2354 sw_if_index=self.pg0.sw_if_index,
2355 flags=flags, is_add=1)
2356 self.vapi.nat44_interface_add_del_feature(
2357 sw_if_index=self.pg1.sw_if_index,
2360 # add static mapping for servers
2361 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2362 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
2366 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2367 IP(src=host.ip4, dst=server1_nat_ip) /
2368 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2370 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2371 IP(src=host.ip4, dst=server1_nat_ip) /
2372 UDP(sport=self.udp_port_in, dport=server_udp_port))
2374 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2375 IP(src=host.ip4, dst=server1_nat_ip) /
2376 ICMP(id=self.icmp_id_in, type='echo-request'))
2378 self.pg0.add_stream(pkts)
2379 self.pg_enable_capture(self.pg_interfaces)
2381 capture = self.pg0.get_capture(len(pkts))
2382 for packet in capture:
2384 self.assertEqual(packet[IP].src, self.nat_addr)
2385 self.assertEqual(packet[IP].dst, server1.ip4)
2386 if packet.haslayer(TCP):
2387 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2388 self.assertEqual(packet[TCP].dport, server_tcp_port)
2389 self.tcp_port_out = packet[TCP].sport
2390 self.assert_packet_checksums_valid(packet)
2391 elif packet.haslayer(UDP):
2392 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2393 self.assertEqual(packet[UDP].dport, server_udp_port)
2394 self.udp_port_out = packet[UDP].sport
2396 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2397 self.icmp_id_out = packet[ICMP].id
2399 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2404 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2405 IP(src=server1.ip4, dst=self.nat_addr) /
2406 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2408 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2409 IP(src=server1.ip4, dst=self.nat_addr) /
2410 UDP(sport=server_udp_port, dport=self.udp_port_out))
2412 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2413 IP(src=server1.ip4, dst=self.nat_addr) /
2414 ICMP(id=self.icmp_id_out, type='echo-reply'))
2416 self.pg0.add_stream(pkts)
2417 self.pg_enable_capture(self.pg_interfaces)
2419 capture = self.pg0.get_capture(len(pkts))
2420 for packet in capture:
2422 self.assertEqual(packet[IP].src, server1_nat_ip)
2423 self.assertEqual(packet[IP].dst, host.ip4)
2424 if packet.haslayer(TCP):
2425 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2426 self.assertEqual(packet[TCP].sport, server_tcp_port)
2427 self.assert_packet_checksums_valid(packet)
2428 elif packet.haslayer(UDP):
2429 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2430 self.assertEqual(packet[UDP].sport, server_udp_port)
2432 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2434 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2437 # server2 to server1
2439 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2440 IP(src=server2.ip4, dst=server1_nat_ip) /
2441 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2443 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2444 IP(src=server2.ip4, dst=server1_nat_ip) /
2445 UDP(sport=self.udp_port_in, dport=server_udp_port))
2447 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2448 IP(src=server2.ip4, dst=server1_nat_ip) /
2449 ICMP(id=self.icmp_id_in, type='echo-request'))
2451 self.pg0.add_stream(pkts)
2452 self.pg_enable_capture(self.pg_interfaces)
2454 capture = self.pg0.get_capture(len(pkts))
2455 for packet in capture:
2457 self.assertEqual(packet[IP].src, server2_nat_ip)
2458 self.assertEqual(packet[IP].dst, server1.ip4)
2459 if packet.haslayer(TCP):
2460 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2461 self.assertEqual(packet[TCP].dport, server_tcp_port)
2462 self.tcp_port_out = packet[TCP].sport
2463 self.assert_packet_checksums_valid(packet)
2464 elif packet.haslayer(UDP):
2465 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2466 self.assertEqual(packet[UDP].dport, server_udp_port)
2467 self.udp_port_out = packet[UDP].sport
2469 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2470 self.icmp_id_out = packet[ICMP].id
2472 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2475 # server1 to server2
2477 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2478 IP(src=server1.ip4, dst=server2_nat_ip) /
2479 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2481 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2482 IP(src=server1.ip4, dst=server2_nat_ip) /
2483 UDP(sport=server_udp_port, dport=self.udp_port_out))
2485 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2486 IP(src=server1.ip4, dst=server2_nat_ip) /
2487 ICMP(id=self.icmp_id_out, type='echo-reply'))
2489 self.pg0.add_stream(pkts)
2490 self.pg_enable_capture(self.pg_interfaces)
2492 capture = self.pg0.get_capture(len(pkts))
2493 for packet in capture:
2495 self.assertEqual(packet[IP].src, server1_nat_ip)
2496 self.assertEqual(packet[IP].dst, server2.ip4)
2497 if packet.haslayer(TCP):
2498 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2499 self.assertEqual(packet[TCP].sport, server_tcp_port)
2500 self.assert_packet_checksums_valid(packet)
2501 elif packet.haslayer(UDP):
2502 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2503 self.assertEqual(packet[UDP].sport, server_udp_port)
2505 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2507 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2510 def test_interface_addr(self):
2511 """ Acquire NAT44 addresses from interface """
2512 self.vapi.nat44_add_del_interface_addr(
2514 sw_if_index=self.pg7.sw_if_index)
2516 # no address in NAT pool
2517 addresses = self.vapi.nat44_address_dump()
2518 self.assertEqual(0, len(addresses))
2520 # configure interface address and check NAT address pool
2521 self.pg7.config_ip4()
2522 addresses = self.vapi.nat44_address_dump()
2523 self.assertEqual(1, len(addresses))
2524 self.assertEqual(str(addresses[0].ip_address), self.pg7.local_ip4)
2526 # remove interface address and check NAT address pool
2527 self.pg7.unconfig_ip4()
2528 addresses = self.vapi.nat44_address_dump()
2529 self.assertEqual(0, len(addresses))
2531 def test_interface_addr_static_mapping(self):
2532 """ Static mapping with addresses from interface """
2535 self.vapi.nat44_add_del_interface_addr(
2537 sw_if_index=self.pg7.sw_if_index)
2538 self.nat44_add_static_mapping(
2540 external_sw_if_index=self.pg7.sw_if_index,
2543 # static mappings with external interface
2544 static_mappings = self.vapi.nat44_static_mapping_dump()
2545 self.assertEqual(1, len(static_mappings))
2546 self.assertEqual(self.pg7.sw_if_index,
2547 static_mappings[0].external_sw_if_index)
2548 self.assertEqual(static_mappings[0].tag, tag)
2550 # configure interface address and check static mappings
2551 self.pg7.config_ip4()
2552 static_mappings = self.vapi.nat44_static_mapping_dump()
2553 self.assertEqual(2, len(static_mappings))
2555 for sm in static_mappings:
2556 if sm.external_sw_if_index == 0xFFFFFFFF:
2557 self.assertEqual(str(sm.external_ip_address),
2559 self.assertEqual(sm.tag, tag)
2561 self.assertTrue(resolved)
2563 # remove interface address and check static mappings
2564 self.pg7.unconfig_ip4()
2565 static_mappings = self.vapi.nat44_static_mapping_dump()
2566 self.assertEqual(1, len(static_mappings))
2567 self.assertEqual(self.pg7.sw_if_index,
2568 static_mappings[0].external_sw_if_index)
2569 self.assertEqual(static_mappings[0].tag, tag)
2571 # configure interface address again and check static mappings
2572 self.pg7.config_ip4()
2573 static_mappings = self.vapi.nat44_static_mapping_dump()
2574 self.assertEqual(2, len(static_mappings))
2576 for sm in static_mappings:
2577 if sm.external_sw_if_index == 0xFFFFFFFF:
2578 self.assertEqual(str(sm.external_ip_address),
2580 self.assertEqual(sm.tag, tag)
2582 self.assertTrue(resolved)
2584 # remove static mapping
2585 self.nat44_add_static_mapping(
2587 external_sw_if_index=self.pg7.sw_if_index,
2590 static_mappings = self.vapi.nat44_static_mapping_dump()
2591 self.assertEqual(0, len(static_mappings))
2593 def test_interface_addr_identity_nat(self):
2594 """ Identity NAT with addresses from interface """
2597 self.vapi.nat44_add_del_interface_addr(
2599 sw_if_index=self.pg7.sw_if_index)
2600 self.vapi.nat44_add_del_identity_mapping(
2602 sw_if_index=self.pg7.sw_if_index,
2604 protocol=IP_PROTOS.tcp,
2607 # identity mappings with external interface
2608 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2609 self.assertEqual(1, len(identity_mappings))
2610 self.assertEqual(self.pg7.sw_if_index,
2611 identity_mappings[0].sw_if_index)
2613 # configure interface address and check identity mappings
2614 self.pg7.config_ip4()
2615 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2617 self.assertEqual(2, len(identity_mappings))
2618 for sm in identity_mappings:
2619 if sm.sw_if_index == 0xFFFFFFFF:
2620 self.assertEqual(str(identity_mappings[0].ip_address),
2622 self.assertEqual(port, identity_mappings[0].port)
2623 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2625 self.assertTrue(resolved)
2627 # remove interface address and check identity mappings
2628 self.pg7.unconfig_ip4()
2629 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2630 self.assertEqual(1, len(identity_mappings))
2631 self.assertEqual(self.pg7.sw_if_index,
2632 identity_mappings[0].sw_if_index)
2634 def test_ipfix_nat44_sess(self):
2635 """ IPFIX logging NAT44 session created/deleted """
2636 self.ipfix_domain_id = 10
2637 self.ipfix_src_port = 20202
2638 collector_port = 30303
2639 bind_layers(UDP, IPFIX, dport=30303)
2640 self.nat44_add_address(self.nat_addr)
2641 flags = self.config_flags.NAT_IS_INSIDE
2642 self.vapi.nat44_interface_add_del_feature(
2643 sw_if_index=self.pg0.sw_if_index,
2644 flags=flags, is_add=1)
2645 self.vapi.nat44_interface_add_del_feature(
2646 sw_if_index=self.pg1.sw_if_index,
2648 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2649 src_address=self.pg3.local_ip4,
2651 template_interval=10,
2652 collector_port=collector_port)
2653 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2654 src_port=self.ipfix_src_port,
2657 pkts = self.create_stream_in(self.pg0, self.pg1)
2658 self.pg0.add_stream(pkts)
2659 self.pg_enable_capture(self.pg_interfaces)
2661 capture = self.pg1.get_capture(len(pkts))
2662 self.verify_capture_out(capture)
2663 self.nat44_add_address(self.nat_addr, is_add=0)
2664 self.vapi.ipfix_flush()
2665 capture = self.pg3.get_capture(7)
2666 ipfix = IPFIXDecoder()
2667 # first load template
2669 self.assertTrue(p.haslayer(IPFIX))
2670 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2671 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2672 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2673 self.assertEqual(p[UDP].dport, collector_port)
2674 self.assertEqual(p[IPFIX].observationDomainID,
2675 self.ipfix_domain_id)
2676 if p.haslayer(Template):
2677 ipfix.add_template(p.getlayer(Template))
2678 # verify events in data set
2680 if p.haslayer(Data):
2681 data = ipfix.decode_data_set(p.getlayer(Set))
2682 self.verify_ipfix_nat44_ses(data)
2684 def test_ipfix_addr_exhausted(self):
2685 """ IPFIX logging NAT addresses exhausted """
2686 flags = self.config_flags.NAT_IS_INSIDE
2687 self.vapi.nat44_interface_add_del_feature(
2688 sw_if_index=self.pg0.sw_if_index,
2689 flags=flags, is_add=1)
2690 self.vapi.nat44_interface_add_del_feature(
2691 sw_if_index=self.pg1.sw_if_index,
2693 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2694 src_address=self.pg3.local_ip4,
2696 template_interval=10)
2697 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2698 src_port=self.ipfix_src_port,
2701 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2702 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2704 self.pg0.add_stream(p)
2705 self.pg_enable_capture(self.pg_interfaces)
2707 self.pg1.assert_nothing_captured()
2709 self.vapi.ipfix_flush()
2710 capture = self.pg3.get_capture(7)
2711 ipfix = IPFIXDecoder()
2712 # first load template
2714 self.assertTrue(p.haslayer(IPFIX))
2715 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2716 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2717 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2718 self.assertEqual(p[UDP].dport, 4739)
2719 self.assertEqual(p[IPFIX].observationDomainID,
2720 self.ipfix_domain_id)
2721 if p.haslayer(Template):
2722 ipfix.add_template(p.getlayer(Template))
2723 # verify events in data set
2725 if p.haslayer(Data):
2726 data = ipfix.decode_data_set(p.getlayer(Set))
2727 self.verify_ipfix_addr_exhausted(data)
2729 @unittest.skipUnless(running_extended_tests, "part of extended tests")
2730 def test_ipfix_max_sessions(self):
2731 """ IPFIX logging maximum session entries exceeded """
2732 self.nat44_add_address(self.nat_addr)
2733 flags = self.config_flags.NAT_IS_INSIDE
2734 self.vapi.nat44_interface_add_del_feature(
2735 sw_if_index=self.pg0.sw_if_index,
2736 flags=flags, is_add=1)
2737 self.vapi.nat44_interface_add_del_feature(
2738 sw_if_index=self.pg1.sw_if_index,
2741 nat44_config = self.vapi.nat_show_config()
2742 max_sessions = 10 * nat44_config.translation_buckets
2745 for i in range(0, max_sessions):
2746 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2747 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2748 IP(src=src, dst=self.pg1.remote_ip4) /
2751 self.pg0.add_stream(pkts)
2752 self.pg_enable_capture(self.pg_interfaces)
2755 self.pg1.get_capture(max_sessions)
2756 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2757 src_address=self.pg3.local_ip4,
2759 template_interval=10)
2760 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2761 src_port=self.ipfix_src_port,
2764 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2765 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2767 self.pg0.add_stream(p)
2768 self.pg_enable_capture(self.pg_interfaces)
2770 self.pg1.assert_nothing_captured()
2772 self.vapi.ipfix_flush()
2773 capture = self.pg3.get_capture(7)
2774 ipfix = IPFIXDecoder()
2775 # first load template
2777 self.assertTrue(p.haslayer(IPFIX))
2778 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2779 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2780 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2781 self.assertEqual(p[UDP].dport, 4739)
2782 self.assertEqual(p[IPFIX].observationDomainID,
2783 self.ipfix_domain_id)
2784 if p.haslayer(Template):
2785 ipfix.add_template(p.getlayer(Template))
2786 # verify events in data set
2788 if p.haslayer(Data):
2789 data = ipfix.decode_data_set(p.getlayer(Set))
2790 self.verify_ipfix_max_sessions(data, max_sessions)
2792 def test_syslog_apmap(self):
2793 """ Test syslog address and port mapping creation and deletion """
2794 self.vapi.syslog_set_filter(
2795 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
2796 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
2797 self.nat44_add_address(self.nat_addr)
2798 flags = self.config_flags.NAT_IS_INSIDE
2799 self.vapi.nat44_interface_add_del_feature(
2800 sw_if_index=self.pg0.sw_if_index,
2801 flags=flags, is_add=1)
2802 self.vapi.nat44_interface_add_del_feature(
2803 sw_if_index=self.pg1.sw_if_index,
2806 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2807 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2808 TCP(sport=self.tcp_port_in, dport=20))
2809 self.pg0.add_stream(p)
2810 self.pg_enable_capture(self.pg_interfaces)
2812 capture = self.pg1.get_capture(1)
2813 self.tcp_port_out = capture[0][TCP].sport
2814 capture = self.pg3.get_capture(1)
2815 self.verify_syslog_apmap(capture[0][Raw].load)
2817 self.pg_enable_capture(self.pg_interfaces)
2819 self.nat44_add_address(self.nat_addr, is_add=0)
2820 capture = self.pg3.get_capture(1)
2821 self.verify_syslog_apmap(capture[0][Raw].load, False)
2823 def test_pool_addr_fib(self):
2824 """ NAT44 add pool addresses to FIB """
2825 static_addr = '10.0.0.10'
2826 self.nat44_add_address(self.nat_addr)
2827 flags = self.config_flags.NAT_IS_INSIDE
2828 self.vapi.nat44_interface_add_del_feature(
2829 sw_if_index=self.pg0.sw_if_index,
2830 flags=flags, is_add=1)
2831 self.vapi.nat44_interface_add_del_feature(
2832 sw_if_index=self.pg1.sw_if_index,
2834 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
2837 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2838 ARP(op=ARP.who_has, pdst=self.nat_addr,
2839 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2840 self.pg1.add_stream(p)
2841 self.pg_enable_capture(self.pg_interfaces)
2843 capture = self.pg1.get_capture(1)
2844 self.assertTrue(capture[0].haslayer(ARP))
2845 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2848 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2849 ARP(op=ARP.who_has, pdst=static_addr,
2850 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2851 self.pg1.add_stream(p)
2852 self.pg_enable_capture(self.pg_interfaces)
2854 capture = self.pg1.get_capture(1)
2855 self.assertTrue(capture[0].haslayer(ARP))
2856 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2858 # send ARP to non-NAT44 interface
2859 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2860 ARP(op=ARP.who_has, pdst=self.nat_addr,
2861 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2862 self.pg2.add_stream(p)
2863 self.pg_enable_capture(self.pg_interfaces)
2865 self.pg1.assert_nothing_captured()
2867 # remove addresses and verify
2868 self.nat44_add_address(self.nat_addr, is_add=0)
2869 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2872 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2873 ARP(op=ARP.who_has, pdst=self.nat_addr,
2874 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2875 self.pg1.add_stream(p)
2876 self.pg_enable_capture(self.pg_interfaces)
2878 self.pg1.assert_nothing_captured()
2880 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2881 ARP(op=ARP.who_has, pdst=static_addr,
2882 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2883 self.pg1.add_stream(p)
2884 self.pg_enable_capture(self.pg_interfaces)
2886 self.pg1.assert_nothing_captured()
2888 def test_vrf_mode(self):
2889 """ NAT44 tenant VRF aware address pool mode """
2893 nat_ip1 = "10.0.0.10"
2894 nat_ip2 = "10.0.0.11"
2896 self.pg0.unconfig_ip4()
2897 self.pg1.unconfig_ip4()
2898 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
2899 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
2900 self.pg0.set_table_ip4(vrf_id1)
2901 self.pg1.set_table_ip4(vrf_id2)
2902 self.pg0.config_ip4()
2903 self.pg1.config_ip4()
2904 self.pg0.resolve_arp()
2905 self.pg1.resolve_arp()
2907 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2908 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2909 flags = self.config_flags.NAT_IS_INSIDE
2910 self.vapi.nat44_interface_add_del_feature(
2911 sw_if_index=self.pg0.sw_if_index,
2912 flags=flags, is_add=1)
2913 self.vapi.nat44_interface_add_del_feature(
2914 sw_if_index=self.pg1.sw_if_index,
2915 flags=flags, is_add=1)
2916 self.vapi.nat44_interface_add_del_feature(
2917 sw_if_index=self.pg2.sw_if_index,
2922 pkts = self.create_stream_in(self.pg0, self.pg2)
2923 self.pg0.add_stream(pkts)
2924 self.pg_enable_capture(self.pg_interfaces)
2926 capture = self.pg2.get_capture(len(pkts))
2927 self.verify_capture_out(capture, nat_ip1)
2930 pkts = self.create_stream_in(self.pg1, self.pg2)
2931 self.pg1.add_stream(pkts)
2932 self.pg_enable_capture(self.pg_interfaces)
2934 capture = self.pg2.get_capture(len(pkts))
2935 self.verify_capture_out(capture, nat_ip2)
2938 self.pg0.unconfig_ip4()
2939 self.pg1.unconfig_ip4()
2940 self.pg0.set_table_ip4(0)
2941 self.pg1.set_table_ip4(0)
2942 self.pg0.config_ip4()
2943 self.pg1.config_ip4()
2944 self.pg0.resolve_arp()
2945 self.pg1.resolve_arp()
2946 self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id1})
2947 self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id2})
2949 def test_vrf_feature_independent(self):
2950 """ NAT44 tenant VRF independent address pool mode """
2952 nat_ip1 = "10.0.0.10"
2953 nat_ip2 = "10.0.0.11"
2955 self.nat44_add_address(nat_ip1)
2956 self.nat44_add_address(nat_ip2, vrf_id=99)
2957 flags = self.config_flags.NAT_IS_INSIDE
2958 self.vapi.nat44_interface_add_del_feature(
2959 sw_if_index=self.pg0.sw_if_index,
2960 flags=flags, is_add=1)
2961 self.vapi.nat44_interface_add_del_feature(
2962 sw_if_index=self.pg1.sw_if_index,
2963 flags=flags, is_add=1)
2964 self.vapi.nat44_interface_add_del_feature(
2965 sw_if_index=self.pg2.sw_if_index,
2969 pkts = self.create_stream_in(self.pg0, self.pg2)
2970 self.pg0.add_stream(pkts)
2971 self.pg_enable_capture(self.pg_interfaces)
2973 capture = self.pg2.get_capture(len(pkts))
2974 self.verify_capture_out(capture, nat_ip1)
2977 pkts = self.create_stream_in(self.pg1, self.pg2)
2978 self.pg1.add_stream(pkts)
2979 self.pg_enable_capture(self.pg_interfaces)
2981 capture = self.pg2.get_capture(len(pkts))
2982 self.verify_capture_out(capture, nat_ip1)
2984 def create_routes_and_neigbors(self):
2985 r1 = VppIpRoute(self, self.pg7.remote_ip4, 32,
2986 [VppRoutePath(self.pg7.remote_ip4,
2987 self.pg7.sw_if_index)])
2988 r2 = VppIpRoute(self, self.pg8.remote_ip4, 32,
2989 [VppRoutePath(self.pg8.remote_ip4,
2990 self.pg8.sw_if_index)])
2994 n1 = VppNeighbor(self,
2995 self.pg7.sw_if_index,
2996 self.pg7.remote_mac,
2997 self.pg7.remote_ip4,
2999 n2 = VppNeighbor(self,
3000 self.pg8.sw_if_index,
3001 self.pg8.remote_mac,
3002 self.pg8.remote_ip4,
3007 def test_dynamic_ipless_interfaces(self):
3008 """ NAT44 interfaces without configured IP address """
3009 self.create_routes_and_neigbors()
3010 self.nat44_add_address(self.nat_addr)
3011 flags = self.config_flags.NAT_IS_INSIDE
3012 self.vapi.nat44_interface_add_del_feature(
3013 sw_if_index=self.pg7.sw_if_index,
3014 flags=flags, is_add=1)
3015 self.vapi.nat44_interface_add_del_feature(
3016 sw_if_index=self.pg8.sw_if_index,
3020 pkts = self.create_stream_in(self.pg7, self.pg8)
3021 self.pg7.add_stream(pkts)
3022 self.pg_enable_capture(self.pg_interfaces)
3024 capture = self.pg8.get_capture(len(pkts))
3025 self.verify_capture_out(capture)
3028 pkts = self.create_stream_out(self.pg8, self.nat_addr)
3029 self.pg8.add_stream(pkts)
3030 self.pg_enable_capture(self.pg_interfaces)
3032 capture = self.pg7.get_capture(len(pkts))
3033 self.verify_capture_in(capture, self.pg7)
3035 def test_static_ipless_interfaces(self):
3036 """ NAT44 interfaces without configured IP address - 1:1 NAT """
3038 self.create_routes_and_neigbors()
3039 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
3040 flags = self.config_flags.NAT_IS_INSIDE
3041 self.vapi.nat44_interface_add_del_feature(
3042 sw_if_index=self.pg7.sw_if_index,
3043 flags=flags, is_add=1)
3044 self.vapi.nat44_interface_add_del_feature(
3045 sw_if_index=self.pg8.sw_if_index,
3049 pkts = self.create_stream_out(self.pg8)
3050 self.pg8.add_stream(pkts)
3051 self.pg_enable_capture(self.pg_interfaces)
3053 capture = self.pg7.get_capture(len(pkts))
3054 self.verify_capture_in(capture, self.pg7)
3057 pkts = self.create_stream_in(self.pg7, self.pg8)
3058 self.pg7.add_stream(pkts)
3059 self.pg_enable_capture(self.pg_interfaces)
3061 capture = self.pg8.get_capture(len(pkts))
3062 self.verify_capture_out(capture, self.nat_addr, True)
3064 def test_static_with_port_ipless_interfaces(self):
3065 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
3067 self.tcp_port_out = 30606
3068 self.udp_port_out = 30607
3069 self.icmp_id_out = 30608
3071 self.create_routes_and_neigbors()
3072 self.nat44_add_address(self.nat_addr)
3073 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3074 self.tcp_port_in, self.tcp_port_out,
3075 proto=IP_PROTOS.tcp)
3076 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3077 self.udp_port_in, self.udp_port_out,
3078 proto=IP_PROTOS.udp)
3079 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3080 self.icmp_id_in, self.icmp_id_out,
3081 proto=IP_PROTOS.icmp)
3082 flags = self.config_flags.NAT_IS_INSIDE
3083 self.vapi.nat44_interface_add_del_feature(
3084 sw_if_index=self.pg7.sw_if_index,
3085 flags=flags, is_add=1)
3086 self.vapi.nat44_interface_add_del_feature(
3087 sw_if_index=self.pg8.sw_if_index,
3091 pkts = self.create_stream_out(self.pg8)
3092 self.pg8.add_stream(pkts)
3093 self.pg_enable_capture(self.pg_interfaces)
3095 capture = self.pg7.get_capture(len(pkts))
3096 self.verify_capture_in(capture, self.pg7)
3099 pkts = self.create_stream_in(self.pg7, self.pg8)
3100 self.pg7.add_stream(pkts)
3101 self.pg_enable_capture(self.pg_interfaces)
3103 capture = self.pg8.get_capture(len(pkts))
3104 self.verify_capture_out(capture)
3106 def test_static_unknown_proto(self):
3107 """ 1:1 NAT translate packet with unknown protocol """
3108 nat_ip = "10.0.0.10"
3109 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
3110 flags = self.config_flags.NAT_IS_INSIDE
3111 self.vapi.nat44_interface_add_del_feature(
3112 sw_if_index=self.pg0.sw_if_index,
3113 flags=flags, is_add=1)
3114 self.vapi.nat44_interface_add_del_feature(
3115 sw_if_index=self.pg1.sw_if_index,
3119 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3120 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3122 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3123 TCP(sport=1234, dport=1234))
3124 self.pg0.add_stream(p)
3125 self.pg_enable_capture(self.pg_interfaces)
3127 p = self.pg1.get_capture(1)
3130 self.assertEqual(packet[IP].src, nat_ip)
3131 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3132 self.assertEqual(packet.haslayer(GRE), 1)
3133 self.assert_packet_checksums_valid(packet)
3135 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3139 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3140 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3142 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3143 TCP(sport=1234, dport=1234))
3144 self.pg1.add_stream(p)
3145 self.pg_enable_capture(self.pg_interfaces)
3147 p = self.pg0.get_capture(1)
3150 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3151 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3152 self.assertEqual(packet.haslayer(GRE), 1)
3153 self.assert_packet_checksums_valid(packet)
3155 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3158 def test_hairpinning_static_unknown_proto(self):
3159 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3161 host = self.pg0.remote_hosts[0]
3162 server = self.pg0.remote_hosts[1]
3164 host_nat_ip = "10.0.0.10"
3165 server_nat_ip = "10.0.0.11"
3167 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3168 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3169 flags = self.config_flags.NAT_IS_INSIDE
3170 self.vapi.nat44_interface_add_del_feature(
3171 sw_if_index=self.pg0.sw_if_index,
3172 flags=flags, is_add=1)
3173 self.vapi.nat44_interface_add_del_feature(
3174 sw_if_index=self.pg1.sw_if_index,
3178 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3179 IP(src=host.ip4, dst=server_nat_ip) /
3181 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3182 TCP(sport=1234, dport=1234))
3183 self.pg0.add_stream(p)
3184 self.pg_enable_capture(self.pg_interfaces)
3186 p = self.pg0.get_capture(1)
3189 self.assertEqual(packet[IP].src, host_nat_ip)
3190 self.assertEqual(packet[IP].dst, server.ip4)
3191 self.assertEqual(packet.haslayer(GRE), 1)
3192 self.assert_packet_checksums_valid(packet)
3194 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3198 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3199 IP(src=server.ip4, dst=host_nat_ip) /
3201 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3202 TCP(sport=1234, dport=1234))
3203 self.pg0.add_stream(p)
3204 self.pg_enable_capture(self.pg_interfaces)
3206 p = self.pg0.get_capture(1)
3209 self.assertEqual(packet[IP].src, server_nat_ip)
3210 self.assertEqual(packet[IP].dst, host.ip4)
3211 self.assertEqual(packet.haslayer(GRE), 1)
3212 self.assert_packet_checksums_valid(packet)
3214 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3217 def test_output_feature(self):
3218 """ NAT44 interface output feature (in2out postrouting) """
3219 self.nat44_add_address(self.nat_addr)
3220 flags = self.config_flags.NAT_IS_INSIDE
3221 self.vapi.nat44_interface_add_del_output_feature(
3222 is_add=1, flags=flags,
3223 sw_if_index=self.pg0.sw_if_index)
3224 self.vapi.nat44_interface_add_del_output_feature(
3225 is_add=1, flags=flags,
3226 sw_if_index=self.pg1.sw_if_index)
3227 self.vapi.nat44_interface_add_del_output_feature(
3229 sw_if_index=self.pg3.sw_if_index)
3232 pkts = self.create_stream_in(self.pg0, self.pg3)
3233 self.pg0.add_stream(pkts)
3234 self.pg_enable_capture(self.pg_interfaces)
3236 capture = self.pg3.get_capture(len(pkts))
3237 self.verify_capture_out(capture)
3240 pkts = self.create_stream_out(self.pg3)
3241 self.pg3.add_stream(pkts)
3242 self.pg_enable_capture(self.pg_interfaces)
3244 capture = self.pg0.get_capture(len(pkts))
3245 self.verify_capture_in(capture, self.pg0)
3247 # from non-NAT interface to NAT inside interface
3248 pkts = self.create_stream_in(self.pg2, self.pg0)
3249 self.pg2.add_stream(pkts)
3250 self.pg_enable_capture(self.pg_interfaces)
3252 capture = self.pg0.get_capture(len(pkts))
3253 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3255 def test_output_feature_vrf_aware(self):
3256 """ NAT44 interface output feature VRF aware (in2out postrouting) """
3257 nat_ip_vrf10 = "10.0.0.10"
3258 nat_ip_vrf20 = "10.0.0.20"
3260 r1 = VppIpRoute(self, self.pg3.remote_ip4, 32,
3261 [VppRoutePath(self.pg3.remote_ip4,
3262 self.pg3.sw_if_index)],
3264 r2 = VppIpRoute(self, self.pg3.remote_ip4, 32,
3265 [VppRoutePath(self.pg3.remote_ip4,
3266 self.pg3.sw_if_index)],
3271 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3272 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3273 flags = self.config_flags.NAT_IS_INSIDE
3274 self.vapi.nat44_interface_add_del_output_feature(
3275 is_add=1, flags=flags,
3276 sw_if_index=self.pg4.sw_if_index)
3277 self.vapi.nat44_interface_add_del_output_feature(
3278 is_add=1, flags=flags,
3279 sw_if_index=self.pg6.sw_if_index)
3280 self.vapi.nat44_interface_add_del_output_feature(
3282 sw_if_index=self.pg3.sw_if_index)
3285 pkts = self.create_stream_in(self.pg4, self.pg3)
3286 self.pg4.add_stream(pkts)
3287 self.pg_enable_capture(self.pg_interfaces)
3289 capture = self.pg3.get_capture(len(pkts))
3290 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3293 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3294 self.pg3.add_stream(pkts)
3295 self.pg_enable_capture(self.pg_interfaces)
3297 capture = self.pg4.get_capture(len(pkts))
3298 self.verify_capture_in(capture, self.pg4)
3301 pkts = self.create_stream_in(self.pg6, self.pg3)
3302 self.pg6.add_stream(pkts)
3303 self.pg_enable_capture(self.pg_interfaces)
3305 capture = self.pg3.get_capture(len(pkts))
3306 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3309 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3310 self.pg3.add_stream(pkts)
3311 self.pg_enable_capture(self.pg_interfaces)
3313 capture = self.pg6.get_capture(len(pkts))
3314 self.verify_capture_in(capture, self.pg6)
3316 def test_output_feature_hairpinning(self):
3317 """ NAT44 interface output feature hairpinning (in2out postrouting) """
3318 host = self.pg0.remote_hosts[0]
3319 server = self.pg0.remote_hosts[1]
3322 server_in_port = 5678
3323 server_out_port = 8765
3325 self.nat44_add_address(self.nat_addr)
3326 flags = self.config_flags.NAT_IS_INSIDE
3327 self.vapi.nat44_interface_add_del_output_feature(
3328 is_add=1, flags=flags,
3329 sw_if_index=self.pg0.sw_if_index)
3330 self.vapi.nat44_interface_add_del_output_feature(
3332 sw_if_index=self.pg1.sw_if_index)
3334 # add static mapping for server
3335 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3336 server_in_port, server_out_port,
3337 proto=IP_PROTOS.tcp)
3339 # send packet from host to server
3340 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3341 IP(src=host.ip4, dst=self.nat_addr) /
3342 TCP(sport=host_in_port, dport=server_out_port))
3343 self.pg0.add_stream(p)
3344 self.pg_enable_capture(self.pg_interfaces)
3346 capture = self.pg0.get_capture(1)
3351 self.assertEqual(ip.src, self.nat_addr)
3352 self.assertEqual(ip.dst, server.ip4)
3353 self.assertNotEqual(tcp.sport, host_in_port)
3354 self.assertEqual(tcp.dport, server_in_port)
3355 self.assert_packet_checksums_valid(p)
3356 host_out_port = tcp.sport
3358 self.logger.error(ppp("Unexpected or invalid packet:", p))
3361 # send reply from server to host
3362 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3363 IP(src=server.ip4, dst=self.nat_addr) /
3364 TCP(sport=server_in_port, dport=host_out_port))
3365 self.pg0.add_stream(p)
3366 self.pg_enable_capture(self.pg_interfaces)
3368 capture = self.pg0.get_capture(1)
3373 self.assertEqual(ip.src, self.nat_addr)
3374 self.assertEqual(ip.dst, host.ip4)
3375 self.assertEqual(tcp.sport, server_out_port)
3376 self.assertEqual(tcp.dport, host_in_port)
3377 self.assert_packet_checksums_valid(p)
3379 self.logger.error(ppp("Unexpected or invalid packet:", p))
3382 def test_one_armed_nat44(self):
3383 """ One armed NAT44 """
3384 remote_host = self.pg9.remote_hosts[0]
3385 local_host = self.pg9.remote_hosts[1]
3388 self.nat44_add_address(self.nat_addr)
3389 flags = self.config_flags.NAT_IS_INSIDE
3390 self.vapi.nat44_interface_add_del_feature(
3391 sw_if_index=self.pg9.sw_if_index,
3393 self.vapi.nat44_interface_add_del_feature(
3394 sw_if_index=self.pg9.sw_if_index,
3395 flags=flags, is_add=1)
3398 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3399 IP(src=local_host.ip4, dst=remote_host.ip4) /
3400 TCP(sport=12345, dport=80))
3401 self.pg9.add_stream(p)
3402 self.pg_enable_capture(self.pg_interfaces)
3404 capture = self.pg9.get_capture(1)
3409 self.assertEqual(ip.src, self.nat_addr)
3410 self.assertEqual(ip.dst, remote_host.ip4)
3411 self.assertNotEqual(tcp.sport, 12345)
3412 external_port = tcp.sport
3413 self.assertEqual(tcp.dport, 80)
3414 self.assert_packet_checksums_valid(p)
3416 self.logger.error(ppp("Unexpected or invalid packet:", p))
3420 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3421 IP(src=remote_host.ip4, dst=self.nat_addr) /
3422 TCP(sport=80, dport=external_port))
3423 self.pg9.add_stream(p)
3424 self.pg_enable_capture(self.pg_interfaces)
3426 capture = self.pg9.get_capture(1)
3431 self.assertEqual(ip.src, remote_host.ip4)
3432 self.assertEqual(ip.dst, local_host.ip4)
3433 self.assertEqual(tcp.sport, 80)
3434 self.assertEqual(tcp.dport, 12345)
3435 self.assert_packet_checksums_valid(p)
3437 self.logger.error(ppp("Unexpected or invalid packet:", p))
3440 err = self.statistics.get_err_counter(
3441 '/err/nat44-classify/next in2out')
3442 self.assertEqual(err, 1)
3443 err = self.statistics.get_err_counter(
3444 '/err/nat44-classify/next out2in')
3445 self.assertEqual(err, 1)
3447 def test_del_session(self):
3448 """ Delete NAT44 session """
3449 self.nat44_add_address(self.nat_addr)
3450 flags = self.config_flags.NAT_IS_INSIDE
3451 self.vapi.nat44_interface_add_del_feature(
3452 sw_if_index=self.pg0.sw_if_index,
3453 flags=flags, is_add=1)
3454 self.vapi.nat44_interface_add_del_feature(
3455 sw_if_index=self.pg1.sw_if_index,
3458 pkts = self.create_stream_in(self.pg0, self.pg1)
3459 self.pg0.add_stream(pkts)
3460 self.pg_enable_capture(self.pg_interfaces)
3462 self.pg1.get_capture(len(pkts))
3464 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3465 nsessions = len(sessions)
3467 self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3468 port=sessions[0].inside_port,
3469 protocol=sessions[0].protocol,
3470 flags=self.config_flags.NAT_IS_INSIDE)
3471 self.vapi.nat44_del_session(address=sessions[1].outside_ip_address,
3472 port=sessions[1].outside_port,
3473 protocol=sessions[1].protocol)
3475 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3476 self.assertEqual(nsessions - len(sessions), 2)
3478 self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3479 port=sessions[0].inside_port,
3480 protocol=sessions[0].protocol,
3481 flags=self.config_flags.NAT_IS_INSIDE)
3483 self.verify_no_nat44_user()
3485 def test_frag_in_order(self):
3486 """ NAT44 translate fragments arriving in order """
3488 self.nat44_add_address(self.nat_addr)
3489 flags = self.config_flags.NAT_IS_INSIDE
3490 self.vapi.nat44_interface_add_del_feature(
3491 sw_if_index=self.pg0.sw_if_index,
3492 flags=flags, is_add=1)
3493 self.vapi.nat44_interface_add_del_feature(
3494 sw_if_index=self.pg1.sw_if_index,
3497 self.frag_in_order(proto=IP_PROTOS.tcp)
3498 self.frag_in_order(proto=IP_PROTOS.udp)
3499 self.frag_in_order(proto=IP_PROTOS.icmp)
3501 def test_frag_forwarding(self):
3502 """ NAT44 forwarding fragment test """
3503 self.vapi.nat44_add_del_interface_addr(
3505 sw_if_index=self.pg1.sw_if_index)
3506 flags = self.config_flags.NAT_IS_INSIDE
3507 self.vapi.nat44_interface_add_del_feature(
3508 sw_if_index=self.pg0.sw_if_index,
3509 flags=flags, is_add=1)
3510 self.vapi.nat44_interface_add_del_feature(
3511 sw_if_index=self.pg1.sw_if_index,
3513 self.vapi.nat44_forwarding_enable_disable(enable=1)
3515 data = b"A" * 16 + b"B" * 16 + b"C" * 3
3516 pkts = self.create_stream_frag(self.pg1,
3517 self.pg0.remote_ip4,
3521 proto=IP_PROTOS.udp)
3522 self.pg1.add_stream(pkts)
3523 self.pg_enable_capture(self.pg_interfaces)
3525 frags = self.pg0.get_capture(len(pkts))
3526 p = self.reass_frags_and_verify(frags,
3527 self.pg1.remote_ip4,
3528 self.pg0.remote_ip4)
3529 self.assertEqual(p[UDP].sport, 4789)
3530 self.assertEqual(p[UDP].dport, 4789)
3531 self.assertEqual(data, p[Raw].load)
3533 def test_reass_hairpinning(self):
3534 """ NAT44 fragments hairpinning """
3536 self.server = self.pg0.remote_hosts[1]
3537 self.host_in_port = random.randint(1025, 65535)
3538 self.server_in_port = random.randint(1025, 65535)
3539 self.server_out_port = random.randint(1025, 65535)
3541 self.nat44_add_address(self.nat_addr)
3542 flags = self.config_flags.NAT_IS_INSIDE
3543 self.vapi.nat44_interface_add_del_feature(
3544 sw_if_index=self.pg0.sw_if_index,
3545 flags=flags, is_add=1)
3546 self.vapi.nat44_interface_add_del_feature(
3547 sw_if_index=self.pg1.sw_if_index,
3549 # add static mapping for server
3550 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3551 self.server_in_port,
3552 self.server_out_port,
3553 proto=IP_PROTOS.tcp)
3554 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3555 self.server_in_port,
3556 self.server_out_port,
3557 proto=IP_PROTOS.udp)
3558 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
3560 self.reass_hairpinning(proto=IP_PROTOS.tcp)
3561 self.reass_hairpinning(proto=IP_PROTOS.udp)
3562 self.reass_hairpinning(proto=IP_PROTOS.icmp)
3564 def test_frag_out_of_order(self):
3565 """ NAT44 translate fragments arriving out of order """
3567 self.nat44_add_address(self.nat_addr)
3568 flags = self.config_flags.NAT_IS_INSIDE
3569 self.vapi.nat44_interface_add_del_feature(
3570 sw_if_index=self.pg0.sw_if_index,
3571 flags=flags, is_add=1)
3572 self.vapi.nat44_interface_add_del_feature(
3573 sw_if_index=self.pg1.sw_if_index,
3576 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3577 self.frag_out_of_order(proto=IP_PROTOS.udp)
3578 self.frag_out_of_order(proto=IP_PROTOS.icmp)
3580 def test_port_restricted(self):
3581 """ Port restricted NAT44 (MAP-E CE) """
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 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3595 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3596 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3597 TCP(sport=4567, dport=22))
3598 self.pg0.add_stream(p)
3599 self.pg_enable_capture(self.pg_interfaces)
3601 capture = self.pg1.get_capture(1)
3606 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3607 self.assertEqual(ip.src, self.nat_addr)
3608 self.assertEqual(tcp.dport, 22)
3609 self.assertNotEqual(tcp.sport, 4567)
3610 self.assertEqual((tcp.sport >> 6) & 63, 10)
3611 self.assert_packet_checksums_valid(p)
3613 self.logger.error(ppp("Unexpected or invalid packet:", p))
3616 def test_port_range(self):
3617 """ External address port range """
3618 self.nat44_add_address(self.nat_addr)
3619 flags = self.config_flags.NAT_IS_INSIDE
3620 self.vapi.nat44_interface_add_del_feature(
3621 sw_if_index=self.pg0.sw_if_index,
3622 flags=flags, is_add=1)
3623 self.vapi.nat44_interface_add_del_feature(
3624 sw_if_index=self.pg1.sw_if_index,
3626 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3631 for port in range(0, 5):
3632 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3633 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3634 TCP(sport=1125 + port))
3636 self.pg0.add_stream(pkts)
3637 self.pg_enable_capture(self.pg_interfaces)
3639 capture = self.pg1.get_capture(3)
3642 self.assertGreaterEqual(tcp.sport, 1025)
3643 self.assertLessEqual(tcp.sport, 1027)
3645 def test_multiple_outside_vrf(self):
3646 """ Multiple outside VRF """
3650 self.pg1.unconfig_ip4()
3651 self.pg2.unconfig_ip4()
3652 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
3653 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
3654 self.pg1.set_table_ip4(vrf_id1)
3655 self.pg2.set_table_ip4(vrf_id2)
3656 self.pg1.config_ip4()
3657 self.pg2.config_ip4()
3658 self.pg1.resolve_arp()
3659 self.pg2.resolve_arp()
3661 self.nat44_add_address(self.nat_addr)
3662 flags = self.config_flags.NAT_IS_INSIDE
3663 self.vapi.nat44_interface_add_del_feature(
3664 sw_if_index=self.pg0.sw_if_index,
3665 flags=flags, is_add=1)
3666 self.vapi.nat44_interface_add_del_feature(
3667 sw_if_index=self.pg1.sw_if_index,
3669 self.vapi.nat44_interface_add_del_feature(
3670 sw_if_index=self.pg2.sw_if_index,
3675 pkts = self.create_stream_in(self.pg0, self.pg1)
3676 self.pg0.add_stream(pkts)
3677 self.pg_enable_capture(self.pg_interfaces)
3679 capture = self.pg1.get_capture(len(pkts))
3680 self.verify_capture_out(capture, self.nat_addr)
3682 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3683 self.pg1.add_stream(pkts)
3684 self.pg_enable_capture(self.pg_interfaces)
3686 capture = self.pg0.get_capture(len(pkts))
3687 self.verify_capture_in(capture, self.pg0)
3689 self.tcp_port_in = 60303
3690 self.udp_port_in = 60304
3691 self.icmp_id_in = 60305
3694 pkts = self.create_stream_in(self.pg0, self.pg2)
3695 self.pg0.add_stream(pkts)
3696 self.pg_enable_capture(self.pg_interfaces)
3698 capture = self.pg2.get_capture(len(pkts))
3699 self.verify_capture_out(capture, self.nat_addr)
3701 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3702 self.pg2.add_stream(pkts)
3703 self.pg_enable_capture(self.pg_interfaces)
3705 capture = self.pg0.get_capture(len(pkts))
3706 self.verify_capture_in(capture, self.pg0)
3709 self.nat44_add_address(self.nat_addr, is_add=0)
3710 self.pg1.unconfig_ip4()
3711 self.pg2.unconfig_ip4()
3712 self.pg1.set_table_ip4(0)
3713 self.pg2.set_table_ip4(0)
3714 self.pg1.config_ip4()
3715 self.pg2.config_ip4()
3716 self.pg1.resolve_arp()
3717 self.pg2.resolve_arp()
3719 @unittest.skipUnless(running_extended_tests, "part of extended tests")
3720 def test_session_timeout(self):
3721 """ NAT44 session timeouts """
3722 self.nat44_add_address(self.nat_addr)
3723 flags = self.config_flags.NAT_IS_INSIDE
3724 self.vapi.nat44_interface_add_del_feature(
3725 sw_if_index=self.pg0.sw_if_index,
3726 flags=flags, is_add=1)
3727 self.vapi.nat44_interface_add_del_feature(
3728 sw_if_index=self.pg1.sw_if_index,
3730 self.vapi.nat_set_timeouts(udp=5, tcp_established=7440,
3731 tcp_transitory=240, icmp=60)
3735 for i in range(0, max_sessions):
3736 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3737 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3738 IP(src=src, dst=self.pg1.remote_ip4) /
3739 UDP(sport=1025, dport=53))
3741 self.pg0.add_stream(pkts)
3742 self.pg_enable_capture(self.pg_interfaces)
3744 self.pg1.get_capture(max_sessions)
3749 for i in range(0, max_sessions):
3750 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3751 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3752 IP(src=src, dst=self.pg1.remote_ip4) /
3753 UDP(sport=1026, dport=53))
3755 self.pg0.add_stream(pkts)
3756 self.pg_enable_capture(self.pg_interfaces)
3758 self.pg1.get_capture(max_sessions)
3761 users = self.vapi.nat44_user_dump()
3763 nsessions = nsessions + user.nsessions
3764 self.assertLess(nsessions, 2 * max_sessions)
3766 def test_mss_clamping(self):
3767 """ TCP MSS clamping """
3768 self.nat44_add_address(self.nat_addr)
3769 flags = self.config_flags.NAT_IS_INSIDE
3770 self.vapi.nat44_interface_add_del_feature(
3771 sw_if_index=self.pg0.sw_if_index,
3772 flags=flags, is_add=1)
3773 self.vapi.nat44_interface_add_del_feature(
3774 sw_if_index=self.pg1.sw_if_index,
3777 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3778 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3779 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3780 flags="S", options=[('MSS', 1400)]))
3782 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3783 self.pg0.add_stream(p)
3784 self.pg_enable_capture(self.pg_interfaces)
3786 capture = self.pg1.get_capture(1)
3787 # Negotiated MSS value greater than configured - changed
3788 self.verify_mss_value(capture[0], 1000)
3790 self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
3791 self.pg0.add_stream(p)
3792 self.pg_enable_capture(self.pg_interfaces)
3794 capture = self.pg1.get_capture(1)
3795 # MSS clamping disabled - negotiated MSS unchanged
3796 self.verify_mss_value(capture[0], 1400)
3798 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3799 self.pg0.add_stream(p)
3800 self.pg_enable_capture(self.pg_interfaces)
3802 capture = self.pg1.get_capture(1)
3803 # Negotiated MSS value smaller than configured - unchanged
3804 self.verify_mss_value(capture[0], 1400)
3806 @unittest.skipUnless(running_extended_tests, "part of extended tests")
3807 def test_ha_send(self):
3808 """ Send HA session synchronization events (active) """
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,
3817 self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
3820 self.vapi.nat_ha_set_failover(ip_address=self.pg3.remote_ip4,
3821 port=12346, session_refresh_interval=10)
3822 bind_layers(UDP, HANATStateSync, sport=12345)
3825 pkts = self.create_stream_in(self.pg0, self.pg1)
3826 self.pg0.add_stream(pkts)
3827 self.pg_enable_capture(self.pg_interfaces)
3829 capture = self.pg1.get_capture(len(pkts))
3830 self.verify_capture_out(capture)
3831 # active send HA events
3832 self.vapi.nat_ha_flush()
3833 stats = self.statistics.get_counter('/nat44/ha/add-event-send')
3834 self.assertEqual(stats[0][0], 3)
3835 capture = self.pg3.get_capture(1)
3837 self.assert_packet_checksums_valid(p)
3841 hanat = p[HANATStateSync]
3843 self.logger.error(ppp("Invalid packet:", p))
3846 self.assertEqual(ip.src, self.pg3.local_ip4)
3847 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3848 self.assertEqual(udp.sport, 12345)
3849 self.assertEqual(udp.dport, 12346)
3850 self.assertEqual(hanat.version, 1)
3851 self.assertEqual(hanat.thread_index, 0)
3852 self.assertEqual(hanat.count, 3)
3853 seq = hanat.sequence_number
3854 for event in hanat.events:
3855 self.assertEqual(event.event_type, 1)
3856 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
3857 self.assertEqual(event.out_addr, self.nat_addr)
3858 self.assertEqual(event.fib_index, 0)
3860 # ACK received events
3861 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3862 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3863 UDP(sport=12346, dport=12345) /
3864 HANATStateSync(sequence_number=seq, flags='ACK'))
3865 self.pg3.add_stream(ack)
3867 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3868 self.assertEqual(stats[0][0], 1)
3870 # delete one session
3871 self.pg_enable_capture(self.pg_interfaces)
3872 self.vapi.nat44_del_session(address=self.pg0.remote_ip4,
3873 port=self.tcp_port_in,
3874 protocol=IP_PROTOS.tcp,
3875 flags=self.config_flags.NAT_IS_INSIDE)
3876 self.vapi.nat_ha_flush()
3877 stats = self.statistics.get_counter('/nat44/ha/del-event-send')
3878 self.assertEqual(stats[0][0], 1)
3879 capture = self.pg3.get_capture(1)
3882 hanat = p[HANATStateSync]
3884 self.logger.error(ppp("Invalid packet:", p))
3887 self.assertGreater(hanat.sequence_number, seq)
3889 # do not send ACK, active retry send HA event again
3890 self.pg_enable_capture(self.pg_interfaces)
3892 stats = self.statistics.get_counter('/nat44/ha/retry-count')
3893 self.assertEqual(stats[0][0], 3)
3894 stats = self.statistics.get_counter('/nat44/ha/missed-count')
3895 self.assertEqual(stats[0][0], 1)
3896 capture = self.pg3.get_capture(3)
3897 for packet in capture:
3898 self.assertEqual(packet, p)
3900 # session counters refresh
3901 pkts = self.create_stream_out(self.pg1)
3902 self.pg1.add_stream(pkts)
3903 self.pg_enable_capture(self.pg_interfaces)
3905 self.pg0.get_capture(2)
3906 self.vapi.nat_ha_flush()
3907 stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
3908 self.assertEqual(stats[0][0], 2)
3909 capture = self.pg3.get_capture(1)
3911 self.assert_packet_checksums_valid(p)
3915 hanat = p[HANATStateSync]
3917 self.logger.error(ppp("Invalid packet:", p))
3920 self.assertEqual(ip.src, self.pg3.local_ip4)
3921 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3922 self.assertEqual(udp.sport, 12345)
3923 self.assertEqual(udp.dport, 12346)
3924 self.assertEqual(hanat.version, 1)
3925 self.assertEqual(hanat.count, 2)
3926 seq = hanat.sequence_number
3927 for event in hanat.events:
3928 self.assertEqual(event.event_type, 3)
3929 self.assertEqual(event.out_addr, self.nat_addr)
3930 self.assertEqual(event.fib_index, 0)
3931 self.assertEqual(event.total_pkts, 2)
3932 self.assertGreater(event.total_bytes, 0)
3934 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3935 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3936 UDP(sport=12346, dport=12345) /
3937 HANATStateSync(sequence_number=seq, flags='ACK'))
3938 self.pg3.add_stream(ack)
3940 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3941 self.assertEqual(stats[0][0], 2)
3943 def test_ha_recv(self):
3944 """ Receive HA session synchronization events (passive) """
3945 self.nat44_add_address(self.nat_addr)
3946 flags = self.config_flags.NAT_IS_INSIDE
3947 self.vapi.nat44_interface_add_del_feature(
3948 sw_if_index=self.pg0.sw_if_index,
3949 flags=flags, is_add=1)
3950 self.vapi.nat44_interface_add_del_feature(
3951 sw_if_index=self.pg1.sw_if_index,
3953 self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
3956 bind_layers(UDP, HANATStateSync, sport=12345)
3958 self.tcp_port_out = random.randint(1025, 65535)
3959 self.udp_port_out = random.randint(1025, 65535)
3961 # send HA session add events to failover/passive
3962 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3963 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3964 UDP(sport=12346, dport=12345) /
3965 HANATStateSync(sequence_number=1, events=[
3966 Event(event_type='add', protocol='tcp',
3967 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3968 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
3969 eh_addr=self.pg1.remote_ip4,
3970 ehn_addr=self.pg1.remote_ip4,
3971 eh_port=self.tcp_external_port,
3972 ehn_port=self.tcp_external_port, fib_index=0),
3973 Event(event_type='add', protocol='udp',
3974 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
3975 in_port=self.udp_port_in, out_port=self.udp_port_out,
3976 eh_addr=self.pg1.remote_ip4,
3977 ehn_addr=self.pg1.remote_ip4,
3978 eh_port=self.udp_external_port,
3979 ehn_port=self.udp_external_port, fib_index=0)]))
3981 self.pg3.add_stream(p)
3982 self.pg_enable_capture(self.pg_interfaces)
3985 capture = self.pg3.get_capture(1)
3988 hanat = p[HANATStateSync]
3990 self.logger.error(ppp("Invalid packet:", p))
3993 self.assertEqual(hanat.sequence_number, 1)
3994 self.assertEqual(hanat.flags, 'ACK')
3995 self.assertEqual(hanat.version, 1)
3996 self.assertEqual(hanat.thread_index, 0)
3997 stats = self.statistics.get_counter('/nat44/ha/ack-send')
3998 self.assertEqual(stats[0][0], 1)
3999 stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
4000 self.assertEqual(stats[0][0], 2)
4001 users = self.statistics.get_counter('/nat44/total-users')
4002 self.assertEqual(users[0][0], 1)
4003 sessions = self.statistics.get_counter('/nat44/total-sessions')
4004 self.assertEqual(sessions[0][0], 2)
4005 users = self.vapi.nat44_user_dump()
4006 self.assertEqual(len(users), 1)
4007 self.assertEqual(str(users[0].ip_address),
4008 self.pg0.remote_ip4)
4009 # there should be 2 sessions created by HA
4010 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4012 self.assertEqual(len(sessions), 2)
4013 for session in sessions:
4014 self.assertEqual(str(session.inside_ip_address),
4015 self.pg0.remote_ip4)
4016 self.assertEqual(str(session.outside_ip_address),
4018 self.assertIn(session.inside_port,
4019 [self.tcp_port_in, self.udp_port_in])
4020 self.assertIn(session.outside_port,
4021 [self.tcp_port_out, self.udp_port_out])
4022 self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
4024 # send HA session delete event to failover/passive
4025 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4026 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4027 UDP(sport=12346, dport=12345) /
4028 HANATStateSync(sequence_number=2, events=[
4029 Event(event_type='del', protocol='udp',
4030 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4031 in_port=self.udp_port_in, out_port=self.udp_port_out,
4032 eh_addr=self.pg1.remote_ip4,
4033 ehn_addr=self.pg1.remote_ip4,
4034 eh_port=self.udp_external_port,
4035 ehn_port=self.udp_external_port, fib_index=0)]))
4037 self.pg3.add_stream(p)
4038 self.pg_enable_capture(self.pg_interfaces)
4041 capture = self.pg3.get_capture(1)
4044 hanat = p[HANATStateSync]
4046 self.logger.error(ppp("Invalid packet:", p))
4049 self.assertEqual(hanat.sequence_number, 2)
4050 self.assertEqual(hanat.flags, 'ACK')
4051 self.assertEqual(hanat.version, 1)
4052 users = self.vapi.nat44_user_dump()
4053 self.assertEqual(len(users), 1)
4054 self.assertEqual(str(users[0].ip_address),
4055 self.pg0.remote_ip4)
4056 # now we should have only 1 session, 1 deleted by HA
4057 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4059 self.assertEqual(len(sessions), 1)
4060 stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
4061 self.assertEqual(stats[0][0], 1)
4063 stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
4064 self.assertEqual(stats, 2)
4066 # send HA session refresh event to failover/passive
4067 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4068 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4069 UDP(sport=12346, dport=12345) /
4070 HANATStateSync(sequence_number=3, events=[
4071 Event(event_type='refresh', protocol='tcp',
4072 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4073 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4074 eh_addr=self.pg1.remote_ip4,
4075 ehn_addr=self.pg1.remote_ip4,
4076 eh_port=self.tcp_external_port,
4077 ehn_port=self.tcp_external_port, fib_index=0,
4078 total_bytes=1024, total_pkts=2)]))
4079 self.pg3.add_stream(p)
4080 self.pg_enable_capture(self.pg_interfaces)
4083 capture = self.pg3.get_capture(1)
4086 hanat = p[HANATStateSync]
4088 self.logger.error(ppp("Invalid packet:", p))
4091 self.assertEqual(hanat.sequence_number, 3)
4092 self.assertEqual(hanat.flags, 'ACK')
4093 self.assertEqual(hanat.version, 1)
4094 users = self.vapi.nat44_user_dump()
4095 self.assertEqual(len(users), 1)
4096 self.assertEqual(str(users[0].ip_address),
4097 self.pg0.remote_ip4)
4098 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4100 self.assertEqual(len(sessions), 1)
4101 session = sessions[0]
4102 self.assertEqual(session.total_bytes, 1024)
4103 self.assertEqual(session.total_pkts, 2)
4104 stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
4105 self.assertEqual(stats[0][0], 1)
4107 stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
4108 self.assertEqual(stats, 3)
4110 # send packet to test session created by HA
4111 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4112 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4113 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
4114 self.pg1.add_stream(p)
4115 self.pg_enable_capture(self.pg_interfaces)
4117 capture = self.pg0.get_capture(1)
4123 self.logger.error(ppp("Invalid packet:", p))
4126 self.assertEqual(ip.src, self.pg1.remote_ip4)
4127 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4128 self.assertEqual(tcp.sport, self.tcp_external_port)
4129 self.assertEqual(tcp.dport, self.tcp_port_in)
4132 super(TestNAT44, self).tearDown()
4134 self.vapi.cli("clear logging")
4136 def show_commands_at_teardown(self):
4137 self.logger.info(self.vapi.cli("show nat44 addresses"))
4138 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4139 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4140 self.logger.info(self.vapi.cli("show nat44 interface address"))
4141 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
4142 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
4143 self.logger.info(self.vapi.cli("show nat timeouts"))
4145 self.vapi.cli("show nat addr-port-assignment-alg"))
4146 self.logger.info(self.vapi.cli("show nat ha"))
4149 class TestNAT44EndpointDependent2(MethodHolder):
4150 """ Endpoint-Dependent mapping and filtering test cases """
4153 def setUpConstants(cls):
4154 super(TestNAT44EndpointDependent2, cls).setUpConstants()
4155 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4158 def tearDownClass(cls):
4159 super(TestNAT44EndpointDependent2, cls).tearDownClass()
4162 super(TestNAT44EndpointDependent2, self).tearDown()
4165 def create_and_add_ip4_table(cls, i, table_id):
4166 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': table_id})
4167 i.set_table_ip4(table_id)
4170 def setUpClass(cls):
4171 super(TestNAT44EndpointDependent2, cls).setUpClass()
4173 cls.create_pg_interfaces(range(3))
4174 cls.interfaces = list(cls.pg_interfaces)
4176 cls.create_and_add_ip4_table(cls.pg1, 10)
4178 for i in cls.interfaces:
4183 i.generate_remote_hosts(1)
4184 i.configure_ipv4_neighbors()
4187 super(TestNAT44EndpointDependent2, self).setUp()
4189 nat_config = self.vapi.nat_show_config()
4190 self.assertEqual(1, nat_config.endpoint_dependent)
4192 def nat_add_inside_interface(self, i):
4193 self.vapi.nat44_interface_add_del_feature(
4194 flags=self.config_flags.NAT_IS_INSIDE,
4195 sw_if_index=i.sw_if_index, is_add=1)
4197 def nat_add_outside_interface(self, i):
4198 self.vapi.nat44_interface_add_del_feature(
4199 flags=self.config_flags.NAT_IS_OUTSIDE,
4200 sw_if_index=i.sw_if_index, is_add=1)
4202 def nat_add_interface_address(self, i):
4203 self.nat_addr = i.local_ip4
4204 self.vapi.nat44_add_del_interface_addr(
4205 sw_if_index=i.sw_if_index, is_add=1)
4207 def nat_add_address(self, address, vrf_id=0xFFFFFFFF):
4208 self.nat_addr = address
4209 self.nat44_add_address(address, vrf_id=vrf_id)
4211 def cli(self, command):
4212 result = self.vapi.cli(command)
4213 self.logger.info(result)
4216 def show_configuration(self):
4217 self.cli("show interface")
4218 self.cli("show interface address")
4219 self.cli("show nat44 addresses")
4220 self.cli("show nat44 interfaces")
4222 def create_tcp_stream(self, in_if, out_if, count):
4224 Create tcp packet stream
4226 :param in_if: Inside interface
4227 :param out_if: Outside interface
4228 :param count: count of packets to generate
4233 for i in range(count):
4234 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4235 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=64) /
4236 TCP(sport=port + i, dport=20))
4241 def test_session_limit_per_vrf(self):
4244 inside_vrf10 = self.pg1
4249 # 2 interfaces pg0, pg1 (vrf10, limit 1 tcp session)
4250 # non existing vrf_id makes process core dump
4251 self.vapi.nat44_set_session_limit(session_limit=limit, vrf_id=10)
4253 self.nat_add_inside_interface(inside)
4254 self.nat_add_inside_interface(inside_vrf10)
4255 self.nat_add_outside_interface(outside)
4258 self.nat_add_interface_address(outside)
4260 # BUG: causing core dump - when bad vrf_id is specified
4261 # self.nat44_add_address(outside.local_ip4, vrf_id=20)
4263 self.show_configuration()
4265 stream = self.create_tcp_stream(inside_vrf10, outside, limit * 2)
4266 inside_vrf10.add_stream(stream)
4268 self.pg_enable_capture(self.pg_interfaces)
4271 capture = outside.get_capture(limit)
4273 stream = self.create_tcp_stream(inside, outside, limit * 2)
4274 inside.add_stream(stream)
4276 self.pg_enable_capture(self.pg_interfaces)
4279 capture = outside.get_capture(len(stream))
4282 class TestNAT44EndpointDependent(MethodHolder):
4283 """ Endpoint-Dependent mapping and filtering test cases """
4286 def setUpConstants(cls):
4287 super(TestNAT44EndpointDependent, cls).setUpConstants()
4288 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4291 def setUpClass(cls):
4292 super(TestNAT44EndpointDependent, cls).setUpClass()
4293 cls.vapi.cli("set log class nat level debug")
4295 cls.tcp_port_in = 6303
4296 cls.tcp_port_out = 6303
4297 cls.udp_port_in = 6304
4298 cls.udp_port_out = 6304
4299 cls.icmp_id_in = 6305
4300 cls.icmp_id_out = 6305
4301 cls.nat_addr = '10.0.0.3'
4302 cls.ipfix_src_port = 4739
4303 cls.ipfix_domain_id = 1
4304 cls.tcp_external_port = 80
4306 cls.create_pg_interfaces(range(9))
4307 cls.interfaces = list(cls.pg_interfaces[0:3])
4309 for i in cls.interfaces:
4314 cls.pg0.generate_remote_hosts(3)
4315 cls.pg0.configure_ipv4_neighbors()
4319 cls.pg4.generate_remote_hosts(2)
4320 cls.pg4.config_ip4()
4321 cls.vapi.sw_interface_add_del_address(
4322 sw_if_index=cls.pg4.sw_if_index,
4323 prefix="10.0.0.1/24")
4326 cls.pg4.resolve_arp()
4327 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4328 cls.pg4.resolve_arp()
4330 zero_ip4 = socket.inet_pton(socket.AF_INET, "0.0.0.0")
4331 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 1})
4333 cls.pg5._local_ip4 = "10.1.1.1"
4334 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4335 cls.pg5.set_table_ip4(1)
4336 cls.pg5.config_ip4()
4338 r1 = VppIpRoute(cls, cls.pg5.remote_ip4, 32,
4339 [VppRoutePath("0.0.0.0",
4340 cls.pg5.sw_if_index)],
4345 cls.pg6._local_ip4 = "10.1.2.1"
4346 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4347 cls.pg6.set_table_ip4(1)
4348 cls.pg6.config_ip4()
4351 r2 = VppIpRoute(cls, cls.pg6.remote_ip4, 32,
4352 [VppRoutePath("0.0.0.0",
4353 cls.pg6.sw_if_index)],
4356 r3 = VppIpRoute(cls, cls.pg6.remote_ip4, 16,
4357 [VppRoutePath("0.0.0.0",
4362 r4 = VppIpRoute(cls, "0.0.0.0", 0,
4363 [VppRoutePath("0.0.0.0", 0xffffffff,
4367 r5 = VppIpRoute(cls, "0.0.0.0", 0,
4368 [VppRoutePath(cls.pg1.local_ip4,
4369 cls.pg1.sw_if_index)],
4376 cls.pg5.resolve_arp()
4377 cls.pg6.resolve_arp()
4380 cls.pg7.config_ip4()
4381 cls.pg7.resolve_arp()
4382 cls.pg7.generate_remote_hosts(3)
4383 cls.pg7.configure_ipv4_neighbors()
4386 cls.pg8.config_ip4()
4387 cls.pg8.resolve_arp()
4390 super(TestNAT44EndpointDependent, self).setUp()
4391 self.vapi.nat_set_timeouts(
4392 udp=300, tcp_established=7440, tcp_transitory=240, icmp=60)
4395 def tearDownClass(cls):
4396 super(TestNAT44EndpointDependent, cls).tearDownClass()
4398 def test_frag_in_order(self):
4399 """ NAT44 translate fragments arriving in order """
4400 self.nat44_add_address(self.nat_addr)
4401 flags = self.config_flags.NAT_IS_INSIDE
4402 self.vapi.nat44_interface_add_del_feature(
4403 sw_if_index=self.pg0.sw_if_index,
4404 flags=flags, is_add=1)
4405 self.vapi.nat44_interface_add_del_feature(
4406 sw_if_index=self.pg1.sw_if_index,
4408 self.frag_in_order(proto=IP_PROTOS.tcp)
4409 self.frag_in_order(proto=IP_PROTOS.udp)
4410 self.frag_in_order(proto=IP_PROTOS.icmp)
4412 def test_frag_in_order_dont_translate(self):
4413 """ NAT44 don't translate fragments arriving in order """
4414 flags = self.config_flags.NAT_IS_INSIDE
4415 self.vapi.nat44_interface_add_del_feature(
4416 sw_if_index=self.pg0.sw_if_index,
4417 flags=flags, is_add=1)
4418 self.vapi.nat44_interface_add_del_feature(
4419 sw_if_index=self.pg1.sw_if_index,
4421 self.vapi.nat44_forwarding_enable_disable(enable=True)
4422 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4424 def test_frag_out_of_order(self):
4425 """ NAT44 translate fragments arriving out of order """
4426 self.nat44_add_address(self.nat_addr)
4427 flags = self.config_flags.NAT_IS_INSIDE
4428 self.vapi.nat44_interface_add_del_feature(
4429 sw_if_index=self.pg0.sw_if_index,
4430 flags=flags, is_add=1)
4431 self.vapi.nat44_interface_add_del_feature(
4432 sw_if_index=self.pg1.sw_if_index,
4434 self.frag_out_of_order(proto=IP_PROTOS.tcp)
4435 self.frag_out_of_order(proto=IP_PROTOS.udp)
4436 self.frag_out_of_order(proto=IP_PROTOS.icmp)
4438 def test_frag_out_of_order_dont_translate(self):
4439 """ NAT44 don't translate fragments arriving out of order """
4440 flags = self.config_flags.NAT_IS_INSIDE
4441 self.vapi.nat44_interface_add_del_feature(
4442 sw_if_index=self.pg0.sw_if_index,
4443 flags=flags, is_add=1)
4444 self.vapi.nat44_interface_add_del_feature(
4445 sw_if_index=self.pg1.sw_if_index,
4447 self.vapi.nat44_forwarding_enable_disable(enable=True)
4448 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4450 def test_frag_in_order_in_plus_out(self):
4451 """ in+out interface fragments in order """
4452 flags = self.config_flags.NAT_IS_INSIDE
4453 self.vapi.nat44_interface_add_del_feature(
4454 sw_if_index=self.pg0.sw_if_index,
4456 self.vapi.nat44_interface_add_del_feature(
4457 sw_if_index=self.pg0.sw_if_index,
4458 flags=flags, is_add=1)
4459 self.vapi.nat44_interface_add_del_feature(
4460 sw_if_index=self.pg1.sw_if_index,
4462 self.vapi.nat44_interface_add_del_feature(
4463 sw_if_index=self.pg1.sw_if_index,
4464 flags=flags, is_add=1)
4466 self.server = self.pg1.remote_hosts[0]
4468 self.server_in_addr = self.server.ip4
4469 self.server_out_addr = '11.11.11.11'
4470 self.server_in_port = random.randint(1025, 65535)
4471 self.server_out_port = random.randint(1025, 65535)
4473 self.nat44_add_address(self.server_out_addr)
4475 # add static mappings for server
4476 self.nat44_add_static_mapping(self.server_in_addr,
4477 self.server_out_addr,
4478 self.server_in_port,
4479 self.server_out_port,
4480 proto=IP_PROTOS.tcp)
4481 self.nat44_add_static_mapping(self.server_in_addr,
4482 self.server_out_addr,
4483 self.server_in_port,
4484 self.server_out_port,
4485 proto=IP_PROTOS.udp)
4486 self.nat44_add_static_mapping(self.server_in_addr,
4487 self.server_out_addr,
4488 proto=IP_PROTOS.icmp)
4490 self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4491 self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4492 self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4494 def test_frag_out_of_order_in_plus_out(self):
4495 """ in+out interface fragments out of order """
4496 flags = self.config_flags.NAT_IS_INSIDE
4497 self.vapi.nat44_interface_add_del_feature(
4498 sw_if_index=self.pg0.sw_if_index,
4500 self.vapi.nat44_interface_add_del_feature(
4501 sw_if_index=self.pg0.sw_if_index,
4502 flags=flags, is_add=1)
4503 self.vapi.nat44_interface_add_del_feature(
4504 sw_if_index=self.pg1.sw_if_index,
4506 self.vapi.nat44_interface_add_del_feature(
4507 sw_if_index=self.pg1.sw_if_index,
4508 flags=flags, is_add=1)
4510 self.server = self.pg1.remote_hosts[0]
4512 self.server_in_addr = self.server.ip4
4513 self.server_out_addr = '11.11.11.11'
4514 self.server_in_port = random.randint(1025, 65535)
4515 self.server_out_port = random.randint(1025, 65535)
4517 self.nat44_add_address(self.server_out_addr)
4519 # add static mappings for server
4520 self.nat44_add_static_mapping(self.server_in_addr,
4521 self.server_out_addr,
4522 self.server_in_port,
4523 self.server_out_port,
4524 proto=IP_PROTOS.tcp)
4525 self.nat44_add_static_mapping(self.server_in_addr,
4526 self.server_out_addr,
4527 self.server_in_port,
4528 self.server_out_port,
4529 proto=IP_PROTOS.udp)
4530 self.nat44_add_static_mapping(self.server_in_addr,
4531 self.server_out_addr,
4532 proto=IP_PROTOS.icmp)
4534 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4535 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4536 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4538 def test_reass_hairpinning(self):
4539 """ NAT44 fragments hairpinning """
4540 self.server = self.pg0.remote_hosts[1]
4541 self.host_in_port = random.randint(1025, 65535)
4542 self.server_in_port = random.randint(1025, 65535)
4543 self.server_out_port = random.randint(1025, 65535)
4545 self.nat44_add_address(self.nat_addr)
4546 flags = self.config_flags.NAT_IS_INSIDE
4547 self.vapi.nat44_interface_add_del_feature(
4548 sw_if_index=self.pg0.sw_if_index,
4549 flags=flags, is_add=1)
4550 self.vapi.nat44_interface_add_del_feature(
4551 sw_if_index=self.pg1.sw_if_index,
4553 # add static mapping for server
4554 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4555 self.server_in_port,
4556 self.server_out_port,
4557 proto=IP_PROTOS.tcp)
4558 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4559 self.server_in_port,
4560 self.server_out_port,
4561 proto=IP_PROTOS.udp)
4562 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
4564 self.reass_hairpinning(proto=IP_PROTOS.tcp)
4565 self.reass_hairpinning(proto=IP_PROTOS.udp)
4566 self.reass_hairpinning(proto=IP_PROTOS.icmp)
4568 def test_dynamic(self):
4569 """ NAT44 dynamic translation test """
4571 self.nat44_add_address(self.nat_addr)
4572 flags = self.config_flags.NAT_IS_INSIDE
4573 self.vapi.nat44_interface_add_del_feature(
4574 sw_if_index=self.pg0.sw_if_index,
4575 flags=flags, is_add=1)
4576 self.vapi.nat44_interface_add_del_feature(
4577 sw_if_index=self.pg1.sw_if_index,
4580 nat_config = self.vapi.nat_show_config()
4581 self.assertEqual(1, nat_config.endpoint_dependent)
4584 tcpn = self.statistics.get_err_counter(
4585 '/err/nat44-ed-in2out-slowpath/TCP packets')
4586 udpn = self.statistics.get_err_counter(
4587 '/err/nat44-ed-in2out-slowpath/UDP packets')
4588 icmpn = self.statistics.get_err_counter(
4589 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4590 totaln = self.statistics.get_err_counter(
4591 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4593 pkts = self.create_stream_in(self.pg0, self.pg1)
4594 self.pg0.add_stream(pkts)
4595 self.pg_enable_capture(self.pg_interfaces)
4597 capture = self.pg1.get_capture(len(pkts))
4598 self.verify_capture_out(capture)
4600 err = self.statistics.get_err_counter(
4601 '/err/nat44-ed-in2out-slowpath/TCP packets')
4602 self.assertEqual(err - tcpn, 2)
4603 err = self.statistics.get_err_counter(
4604 '/err/nat44-ed-in2out-slowpath/UDP packets')
4605 self.assertEqual(err - udpn, 1)
4606 err = self.statistics.get_err_counter(
4607 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4608 self.assertEqual(err - icmpn, 1)
4609 err = self.statistics.get_err_counter(
4610 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4611 self.assertEqual(err - totaln, 4)
4614 tcpn = self.statistics.get_err_counter(
4615 '/err/nat44-ed-out2in/TCP packets')
4616 udpn = self.statistics.get_err_counter(
4617 '/err/nat44-ed-out2in/UDP packets')
4618 icmpn = self.statistics.get_err_counter(
4619 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4620 totaln = self.statistics.get_err_counter(
4621 '/err/nat44-ed-out2in/good out2in packets processed')
4623 pkts = self.create_stream_out(self.pg1)
4624 self.pg1.add_stream(pkts)
4625 self.pg_enable_capture(self.pg_interfaces)
4627 capture = self.pg0.get_capture(len(pkts))
4628 self.verify_capture_in(capture, self.pg0)
4630 err = self.statistics.get_err_counter(
4631 '/err/nat44-ed-out2in/TCP packets')
4632 self.assertEqual(err - tcpn, 2)
4633 err = self.statistics.get_err_counter(
4634 '/err/nat44-ed-out2in/UDP packets')
4635 self.assertEqual(err - udpn, 1)
4636 err = self.statistics.get_err_counter(
4637 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4638 self.assertEqual(err - icmpn, 1)
4639 err = self.statistics.get_err_counter(
4640 '/err/nat44-ed-out2in/good out2in packets processed')
4641 self.assertEqual(err - totaln, 3)
4643 sessions = self.statistics.get_counter('/nat44/total-sessions')
4644 self.assertEqual(sessions[0][0], 3)
4646 def test_dynamic_output_feature_vrf(self):
4647 """ NAT44 dynamic translation test: output-feature, VRF"""
4649 # other then default (0)
4652 self.nat44_add_address(self.nat_addr)
4653 flags = self.config_flags.NAT_IS_INSIDE
4654 self.vapi.nat44_interface_add_del_output_feature(
4655 sw_if_index=self.pg7.sw_if_index,
4656 flags=flags, is_add=1)
4657 self.vapi.nat44_interface_add_del_output_feature(
4658 sw_if_index=self.pg8.sw_if_index,
4662 self.vapi.ip_table_add_del(is_add=1,
4663 table={'table_id': new_vrf_id})
4665 self.pg7.unconfig_ip4()
4666 self.pg7.set_table_ip4(new_vrf_id)
4667 self.pg7.config_ip4()
4668 self.pg7.resolve_arp()
4670 self.pg8.unconfig_ip4()
4671 self.pg8.set_table_ip4(new_vrf_id)
4672 self.pg8.config_ip4()
4673 self.pg8.resolve_arp()
4675 nat_config = self.vapi.nat_show_config()
4676 self.assertEqual(1, nat_config.endpoint_dependent)
4679 tcpn = self.statistics.get_err_counter(
4680 '/err/nat44-ed-in2out-slowpath/TCP packets')
4681 udpn = self.statistics.get_err_counter(
4682 '/err/nat44-ed-in2out-slowpath/UDP packets')
4683 icmpn = self.statistics.get_err_counter(
4684 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4685 totaln = self.statistics.get_err_counter(
4686 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4688 pkts = self.create_stream_in(self.pg7, self.pg8)
4689 self.pg7.add_stream(pkts)
4690 self.pg_enable_capture(self.pg_interfaces)
4692 capture = self.pg8.get_capture(len(pkts))
4693 self.verify_capture_out(capture)
4695 err = self.statistics.get_err_counter(
4696 '/err/nat44-ed-in2out-slowpath/TCP packets')
4697 self.assertEqual(err - tcpn, 2)
4698 err = self.statistics.get_err_counter(
4699 '/err/nat44-ed-in2out-slowpath/UDP packets')
4700 self.assertEqual(err - udpn, 1)
4701 err = self.statistics.get_err_counter(
4702 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4703 self.assertEqual(err - icmpn, 1)
4704 err = self.statistics.get_err_counter(
4705 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4706 self.assertEqual(err - totaln, 4)
4709 tcpn = self.statistics.get_err_counter(
4710 '/err/nat44-ed-out2in/TCP packets')
4711 udpn = self.statistics.get_err_counter(
4712 '/err/nat44-ed-out2in/UDP packets')
4713 icmpn = self.statistics.get_err_counter(
4714 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4715 totaln = self.statistics.get_err_counter(
4716 '/err/nat44-ed-out2in/good out2in packets processed')
4718 pkts = self.create_stream_out(self.pg8)
4719 self.pg8.add_stream(pkts)
4720 self.pg_enable_capture(self.pg_interfaces)
4722 capture = self.pg7.get_capture(len(pkts))
4723 self.verify_capture_in(capture, self.pg7)
4725 err = self.statistics.get_err_counter(
4726 '/err/nat44-ed-out2in/TCP packets')
4727 self.assertEqual(err - tcpn, 2)
4728 err = self.statistics.get_err_counter(
4729 '/err/nat44-ed-out2in/UDP packets')
4730 self.assertEqual(err - udpn, 1)
4731 err = self.statistics.get_err_counter(
4732 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4733 self.assertEqual(err - icmpn, 1)
4734 err = self.statistics.get_err_counter(
4735 '/err/nat44-ed-out2in/good out2in packets processed')
4736 self.assertEqual(err - totaln, 3)
4738 sessions = self.statistics.get_counter('/nat44/total-sessions')
4739 self.assertEqual(sessions[0][0], 3)
4742 self.pg7.unconfig_ip4()
4743 self.pg7.set_table_ip4(1)
4744 self.pg7.config_ip4()
4745 self.pg7.resolve_arp()
4747 self.pg8.unconfig_ip4()
4748 self.pg8.set_table_ip4(1)
4749 self.pg8.config_ip4()
4750 self.pg8.resolve_arp()
4752 self.vapi.ip_table_add_del(is_add=0,
4753 table={'table_id': new_vrf_id})
4755 def test_forwarding(self):
4756 """ NAT44 forwarding test """
4758 flags = self.config_flags.NAT_IS_INSIDE
4759 self.vapi.nat44_interface_add_del_feature(
4760 sw_if_index=self.pg0.sw_if_index,
4761 flags=flags, is_add=1)
4762 self.vapi.nat44_interface_add_del_feature(
4763 sw_if_index=self.pg1.sw_if_index,
4765 self.vapi.nat44_forwarding_enable_disable(enable=1)
4767 real_ip = self.pg0.remote_ip4
4768 alias_ip = self.nat_addr
4769 flags = self.config_flags.NAT_IS_ADDR_ONLY
4770 self.vapi.nat44_add_del_static_mapping(is_add=1,
4771 local_ip_address=real_ip,
4772 external_ip_address=alias_ip,
4773 external_sw_if_index=0xFFFFFFFF,
4777 # in2out - static mapping match
4779 pkts = self.create_stream_out(self.pg1)
4780 self.pg1.add_stream(pkts)
4781 self.pg_enable_capture(self.pg_interfaces)
4783 capture = self.pg0.get_capture(len(pkts))
4784 self.verify_capture_in(capture, self.pg0)
4786 pkts = self.create_stream_in(self.pg0, self.pg1)
4787 self.pg0.add_stream(pkts)
4788 self.pg_enable_capture(self.pg_interfaces)
4790 capture = self.pg1.get_capture(len(pkts))
4791 self.verify_capture_out(capture, same_port=True)
4793 # in2out - no static mapping match
4795 host0 = self.pg0.remote_hosts[0]
4796 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4798 pkts = self.create_stream_out(self.pg1,
4799 dst_ip=self.pg0.remote_ip4,
4800 use_inside_ports=True)
4801 self.pg1.add_stream(pkts)
4802 self.pg_enable_capture(self.pg_interfaces)
4804 capture = self.pg0.get_capture(len(pkts))
4805 self.verify_capture_in(capture, self.pg0)
4807 pkts = self.create_stream_in(self.pg0, self.pg1)
4808 self.pg0.add_stream(pkts)
4809 self.pg_enable_capture(self.pg_interfaces)
4811 capture = self.pg1.get_capture(len(pkts))
4812 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4815 self.pg0.remote_hosts[0] = host0
4817 user = self.pg0.remote_hosts[1]
4818 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4819 self.assertEqual(len(sessions), 3)
4820 self.assertTrue(sessions[0].flags &
4821 self.config_flags.NAT_IS_EXT_HOST_VALID)
4822 self.vapi.nat44_del_session(
4823 address=sessions[0].inside_ip_address,
4824 port=sessions[0].inside_port,
4825 protocol=sessions[0].protocol,
4826 flags=(self.config_flags.NAT_IS_INSIDE |
4827 self.config_flags.NAT_IS_EXT_HOST_VALID),
4828 ext_host_address=sessions[0].ext_host_address,
4829 ext_host_port=sessions[0].ext_host_port)
4830 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4831 self.assertEqual(len(sessions), 2)
4834 self.vapi.nat44_forwarding_enable_disable(enable=0)
4835 flags = self.config_flags.NAT_IS_ADDR_ONLY
4836 self.vapi.nat44_add_del_static_mapping(
4838 local_ip_address=real_ip,
4839 external_ip_address=alias_ip,
4840 external_sw_if_index=0xFFFFFFFF,
4843 def test_static_lb(self):
4844 """ NAT44 local service load balancing """
4845 external_addr_n = self.nat_addr
4848 server1 = self.pg0.remote_hosts[0]
4849 server2 = self.pg0.remote_hosts[1]
4851 locals = [{'addr': server1.ip4,
4855 {'addr': server2.ip4,
4860 self.nat44_add_address(self.nat_addr)
4861 self.vapi.nat44_add_del_lb_static_mapping(
4863 external_addr=external_addr_n,
4864 external_port=external_port,
4865 protocol=IP_PROTOS.tcp,
4866 local_num=len(locals),
4868 flags = self.config_flags.NAT_IS_INSIDE
4869 self.vapi.nat44_interface_add_del_feature(
4870 sw_if_index=self.pg0.sw_if_index,
4871 flags=flags, is_add=1)
4872 self.vapi.nat44_interface_add_del_feature(
4873 sw_if_index=self.pg1.sw_if_index,
4876 # from client to service
4877 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4878 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4879 TCP(sport=12345, dport=external_port))
4880 self.pg1.add_stream(p)
4881 self.pg_enable_capture(self.pg_interfaces)
4883 capture = self.pg0.get_capture(1)
4889 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4890 if ip.dst == server1.ip4:
4894 self.assertEqual(tcp.dport, local_port)
4895 self.assert_packet_checksums_valid(p)
4897 self.logger.error(ppp("Unexpected or invalid packet:", p))
4900 # from service back to client
4901 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4902 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4903 TCP(sport=local_port, dport=12345))
4904 self.pg0.add_stream(p)
4905 self.pg_enable_capture(self.pg_interfaces)
4907 capture = self.pg1.get_capture(1)
4912 self.assertEqual(ip.src, self.nat_addr)
4913 self.assertEqual(tcp.sport, external_port)
4914 self.assert_packet_checksums_valid(p)
4916 self.logger.error(ppp("Unexpected or invalid packet:", p))
4919 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
4920 self.assertEqual(len(sessions), 1)
4921 self.assertTrue(sessions[0].flags &
4922 self.config_flags.NAT_IS_EXT_HOST_VALID)
4923 self.vapi.nat44_del_session(
4924 address=sessions[0].inside_ip_address,
4925 port=sessions[0].inside_port,
4926 protocol=sessions[0].protocol,
4927 flags=(self.config_flags.NAT_IS_INSIDE |
4928 self.config_flags.NAT_IS_EXT_HOST_VALID),
4929 ext_host_address=sessions[0].ext_host_address,
4930 ext_host_port=sessions[0].ext_host_port)
4931 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
4932 self.assertEqual(len(sessions), 0)
4934 @unittest.skipUnless(running_extended_tests, "part of extended tests")
4935 def test_static_lb_multi_clients(self):
4936 """ NAT44 local service load balancing - multiple clients"""
4938 external_addr = self.nat_addr
4941 server1 = self.pg0.remote_hosts[0]
4942 server2 = self.pg0.remote_hosts[1]
4943 server3 = self.pg0.remote_hosts[2]
4945 locals = [{'addr': server1.ip4,
4949 {'addr': server2.ip4,
4954 self.nat44_add_address(self.nat_addr)
4955 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
4956 external_addr=external_addr,
4957 external_port=external_port,
4958 protocol=IP_PROTOS.tcp,
4959 local_num=len(locals),
4961 flags = self.config_flags.NAT_IS_INSIDE
4962 self.vapi.nat44_interface_add_del_feature(
4963 sw_if_index=self.pg0.sw_if_index,
4964 flags=flags, is_add=1)
4965 self.vapi.nat44_interface_add_del_feature(
4966 sw_if_index=self.pg1.sw_if_index,
4971 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4973 for client in clients:
4974 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4975 IP(src=client, dst=self.nat_addr) /
4976 TCP(sport=12345, dport=external_port))
4978 self.pg1.add_stream(pkts)
4979 self.pg_enable_capture(self.pg_interfaces)
4981 capture = self.pg0.get_capture(len(pkts))
4983 if p[IP].dst == server1.ip4:
4987 self.assertGreater(server1_n, server2_n)
4990 'addr': server3.ip4,
4997 self.vapi.nat44_lb_static_mapping_add_del_local(
4999 external_addr=external_addr,
5000 external_port=external_port,
5002 protocol=IP_PROTOS.tcp)
5006 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
5008 for client in clients:
5009 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5010 IP(src=client, dst=self.nat_addr) /
5011 TCP(sport=12346, dport=external_port))
5013 self.assertGreater(len(pkts), 0)
5014 self.pg1.add_stream(pkts)
5015 self.pg_enable_capture(self.pg_interfaces)
5017 capture = self.pg0.get_capture(len(pkts))
5019 if p[IP].dst == server1.ip4:
5021 elif p[IP].dst == server2.ip4:
5025 self.assertGreater(server1_n, 0)
5026 self.assertGreater(server2_n, 0)
5027 self.assertGreater(server3_n, 0)
5030 'addr': server2.ip4,
5036 # remove one back-end
5037 self.vapi.nat44_lb_static_mapping_add_del_local(
5039 external_addr=external_addr,
5040 external_port=external_port,
5042 protocol=IP_PROTOS.tcp)
5046 self.pg1.add_stream(pkts)
5047 self.pg_enable_capture(self.pg_interfaces)
5049 capture = self.pg0.get_capture(len(pkts))
5051 if p[IP].dst == server1.ip4:
5053 elif p[IP].dst == server2.ip4:
5057 self.assertGreater(server1_n, 0)
5058 self.assertEqual(server2_n, 0)
5059 self.assertGreater(server3_n, 0)
5061 def test_static_lb_2(self):
5062 """ NAT44 local service load balancing (asymmetrical rule) """
5063 external_addr = self.nat_addr
5066 server1 = self.pg0.remote_hosts[0]
5067 server2 = self.pg0.remote_hosts[1]
5069 locals = [{'addr': server1.ip4,
5073 {'addr': server2.ip4,
5078 self.vapi.nat44_forwarding_enable_disable(enable=1)
5079 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5080 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5081 external_addr=external_addr,
5082 external_port=external_port,
5083 protocol=IP_PROTOS.tcp,
5084 local_num=len(locals),
5086 flags = self.config_flags.NAT_IS_INSIDE
5087 self.vapi.nat44_interface_add_del_feature(
5088 sw_if_index=self.pg0.sw_if_index,
5089 flags=flags, is_add=1)
5090 self.vapi.nat44_interface_add_del_feature(
5091 sw_if_index=self.pg1.sw_if_index,
5094 # from client to service
5095 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5096 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5097 TCP(sport=12345, dport=external_port))
5098 self.pg1.add_stream(p)
5099 self.pg_enable_capture(self.pg_interfaces)
5101 capture = self.pg0.get_capture(1)
5107 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
5108 if ip.dst == server1.ip4:
5112 self.assertEqual(tcp.dport, local_port)
5113 self.assert_packet_checksums_valid(p)
5115 self.logger.error(ppp("Unexpected or invalid packet:", p))
5118 # from service back to client
5119 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
5120 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
5121 TCP(sport=local_port, dport=12345))
5122 self.pg0.add_stream(p)
5123 self.pg_enable_capture(self.pg_interfaces)
5125 capture = self.pg1.get_capture(1)
5130 self.assertEqual(ip.src, self.nat_addr)
5131 self.assertEqual(tcp.sport, external_port)
5132 self.assert_packet_checksums_valid(p)
5134 self.logger.error(ppp("Unexpected or invalid packet:", p))
5137 # from client to server (no translation)
5138 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5139 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
5140 TCP(sport=12346, dport=local_port))
5141 self.pg1.add_stream(p)
5142 self.pg_enable_capture(self.pg_interfaces)
5144 capture = self.pg0.get_capture(1)
5150 self.assertEqual(ip.dst, server1.ip4)
5151 self.assertEqual(tcp.dport, local_port)
5152 self.assert_packet_checksums_valid(p)
5154 self.logger.error(ppp("Unexpected or invalid packet:", p))
5157 # from service back to client (no translation)
5158 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
5159 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
5160 TCP(sport=local_port, dport=12346))
5161 self.pg0.add_stream(p)
5162 self.pg_enable_capture(self.pg_interfaces)
5164 capture = self.pg1.get_capture(1)
5169 self.assertEqual(ip.src, server1.ip4)
5170 self.assertEqual(tcp.sport, local_port)
5171 self.assert_packet_checksums_valid(p)
5173 self.logger.error(ppp("Unexpected or invalid packet:", p))
5176 def test_lb_affinity(self):
5177 """ NAT44 local service load balancing affinity """
5178 external_addr = self.nat_addr
5181 server1 = self.pg0.remote_hosts[0]
5182 server2 = self.pg0.remote_hosts[1]
5184 locals = [{'addr': server1.ip4,
5188 {'addr': server2.ip4,
5193 self.nat44_add_address(self.nat_addr)
5194 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
5195 external_addr=external_addr,
5196 external_port=external_port,
5197 protocol=IP_PROTOS.tcp,
5199 local_num=len(locals),
5201 flags = self.config_flags.NAT_IS_INSIDE
5202 self.vapi.nat44_interface_add_del_feature(
5203 sw_if_index=self.pg0.sw_if_index,
5204 flags=flags, is_add=1)
5205 self.vapi.nat44_interface_add_del_feature(
5206 sw_if_index=self.pg1.sw_if_index,
5209 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5210 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5211 TCP(sport=1025, dport=external_port))
5212 self.pg1.add_stream(p)
5213 self.pg_enable_capture(self.pg_interfaces)
5215 capture = self.pg0.get_capture(1)
5216 backend = capture[0][IP].dst
5218 sessions = self.vapi.nat44_user_session_dump(backend, 0)
5219 self.assertEqual(len(sessions), 1)
5220 self.assertTrue(sessions[0].flags &
5221 self.config_flags.NAT_IS_EXT_HOST_VALID)
5222 self.vapi.nat44_del_session(
5223 address=sessions[0].inside_ip_address,
5224 port=sessions[0].inside_port,
5225 protocol=sessions[0].protocol,
5226 flags=(self.config_flags.NAT_IS_INSIDE |
5227 self.config_flags.NAT_IS_EXT_HOST_VALID),
5228 ext_host_address=sessions[0].ext_host_address,
5229 ext_host_port=sessions[0].ext_host_port)
5232 for port in range(1030, 1100):
5233 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5234 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5235 TCP(sport=port, dport=external_port))
5237 self.pg1.add_stream(pkts)
5238 self.pg_enable_capture(self.pg_interfaces)
5240 capture = self.pg0.get_capture(len(pkts))
5242 self.assertEqual(p[IP].dst, backend)
5244 def test_unknown_proto(self):
5245 """ NAT44 translate packet with unknown protocol """
5246 self.nat44_add_address(self.nat_addr)
5247 flags = self.config_flags.NAT_IS_INSIDE
5248 self.vapi.nat44_interface_add_del_feature(
5249 sw_if_index=self.pg0.sw_if_index,
5250 flags=flags, is_add=1)
5251 self.vapi.nat44_interface_add_del_feature(
5252 sw_if_index=self.pg1.sw_if_index,
5256 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5257 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5258 TCP(sport=self.tcp_port_in, dport=20))
5259 self.pg0.add_stream(p)
5260 self.pg_enable_capture(self.pg_interfaces)
5262 p = self.pg1.get_capture(1)
5264 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5265 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5267 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5268 TCP(sport=1234, dport=1234))
5269 self.pg0.add_stream(p)
5270 self.pg_enable_capture(self.pg_interfaces)
5272 p = self.pg1.get_capture(1)
5275 self.assertEqual(packet[IP].src, self.nat_addr)
5276 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5277 self.assertEqual(packet.haslayer(GRE), 1)
5278 self.assert_packet_checksums_valid(packet)
5280 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5284 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5285 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5287 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5288 TCP(sport=1234, dport=1234))
5289 self.pg1.add_stream(p)
5290 self.pg_enable_capture(self.pg_interfaces)
5292 p = self.pg0.get_capture(1)
5295 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
5296 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
5297 self.assertEqual(packet.haslayer(GRE), 1)
5298 self.assert_packet_checksums_valid(packet)
5300 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5303 def test_hairpinning_unknown_proto(self):
5304 """ NAT44 translate packet with unknown protocol - hairpinning """
5305 host = self.pg0.remote_hosts[0]
5306 server = self.pg0.remote_hosts[1]
5308 server_out_port = 8765
5309 server_nat_ip = "10.0.0.11"
5311 self.nat44_add_address(self.nat_addr)
5312 flags = self.config_flags.NAT_IS_INSIDE
5313 self.vapi.nat44_interface_add_del_feature(
5314 sw_if_index=self.pg0.sw_if_index,
5315 flags=flags, is_add=1)
5316 self.vapi.nat44_interface_add_del_feature(
5317 sw_if_index=self.pg1.sw_if_index,
5320 # add static mapping for server
5321 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
5324 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
5325 IP(src=host.ip4, dst=server_nat_ip) /
5326 TCP(sport=host_in_port, dport=server_out_port))
5327 self.pg0.add_stream(p)
5328 self.pg_enable_capture(self.pg_interfaces)
5330 self.pg0.get_capture(1)
5332 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5333 IP(src=host.ip4, dst=server_nat_ip) /
5335 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5336 TCP(sport=1234, dport=1234))
5337 self.pg0.add_stream(p)
5338 self.pg_enable_capture(self.pg_interfaces)
5340 p = self.pg0.get_capture(1)
5343 self.assertEqual(packet[IP].src, self.nat_addr)
5344 self.assertEqual(packet[IP].dst, server.ip4)
5345 self.assertEqual(packet.haslayer(GRE), 1)
5346 self.assert_packet_checksums_valid(packet)
5348 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5352 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5353 IP(src=server.ip4, dst=self.nat_addr) /
5355 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5356 TCP(sport=1234, dport=1234))
5357 self.pg0.add_stream(p)
5358 self.pg_enable_capture(self.pg_interfaces)
5360 p = self.pg0.get_capture(1)
5363 self.assertEqual(packet[IP].src, server_nat_ip)
5364 self.assertEqual(packet[IP].dst, host.ip4)
5365 self.assertEqual(packet.haslayer(GRE), 1)
5366 self.assert_packet_checksums_valid(packet)
5368 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5371 def test_output_feature_and_service(self):
5372 """ NAT44 interface output feature and services """
5373 external_addr = '1.2.3.4'
5377 self.vapi.nat44_forwarding_enable_disable(enable=1)
5378 self.nat44_add_address(self.nat_addr)
5379 flags = self.config_flags.NAT_IS_ADDR_ONLY
5380 self.vapi.nat44_add_del_identity_mapping(
5381 ip_address=self.pg1.remote_ip4, sw_if_index=0xFFFFFFFF,
5382 flags=flags, is_add=1)
5383 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5384 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5385 local_port, external_port,
5386 proto=IP_PROTOS.tcp, flags=flags)
5387 flags = self.config_flags.NAT_IS_INSIDE
5388 self.vapi.nat44_interface_add_del_feature(
5389 sw_if_index=self.pg0.sw_if_index,
5391 self.vapi.nat44_interface_add_del_feature(
5392 sw_if_index=self.pg0.sw_if_index,
5393 flags=flags, is_add=1)
5394 self.vapi.nat44_interface_add_del_output_feature(
5396 sw_if_index=self.pg1.sw_if_index)
5398 # from client to service
5399 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5400 IP(src=self.pg1.remote_ip4, dst=external_addr) /
5401 TCP(sport=12345, dport=external_port))
5402 self.pg1.add_stream(p)
5403 self.pg_enable_capture(self.pg_interfaces)
5405 capture = self.pg0.get_capture(1)
5410 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5411 self.assertEqual(tcp.dport, local_port)
5412 self.assert_packet_checksums_valid(p)
5414 self.logger.error(ppp("Unexpected or invalid packet:", p))
5417 # from service back to client
5418 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5419 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5420 TCP(sport=local_port, dport=12345))
5421 self.pg0.add_stream(p)
5422 self.pg_enable_capture(self.pg_interfaces)
5424 capture = self.pg1.get_capture(1)
5429 self.assertEqual(ip.src, external_addr)
5430 self.assertEqual(tcp.sport, external_port)
5431 self.assert_packet_checksums_valid(p)
5433 self.logger.error(ppp("Unexpected or invalid packet:", p))
5436 # from local network host to external network
5437 pkts = self.create_stream_in(self.pg0, self.pg1)
5438 self.pg0.add_stream(pkts)
5439 self.pg_enable_capture(self.pg_interfaces)
5441 capture = self.pg1.get_capture(len(pkts))
5442 self.verify_capture_out(capture)
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)
5450 # from external network back to local network host
5451 pkts = self.create_stream_out(self.pg1)
5452 self.pg1.add_stream(pkts)
5453 self.pg_enable_capture(self.pg_interfaces)
5455 capture = self.pg0.get_capture(len(pkts))
5456 self.verify_capture_in(capture, self.pg0)
5458 def test_output_feature_and_service2(self):
5459 """ NAT44 interface output feature and service host direct access """
5460 self.vapi.nat44_forwarding_enable_disable(enable=1)
5461 self.nat44_add_address(self.nat_addr)
5462 self.vapi.nat44_interface_add_del_output_feature(
5464 sw_if_index=self.pg1.sw_if_index)
5466 # session initiated from service host - translate
5467 pkts = self.create_stream_in(self.pg0, self.pg1)
5468 self.pg0.add_stream(pkts)
5469 self.pg_enable_capture(self.pg_interfaces)
5471 capture = self.pg1.get_capture(len(pkts))
5472 self.verify_capture_out(capture)
5474 pkts = self.create_stream_out(self.pg1)
5475 self.pg1.add_stream(pkts)
5476 self.pg_enable_capture(self.pg_interfaces)
5478 capture = self.pg0.get_capture(len(pkts))
5479 self.verify_capture_in(capture, self.pg0)
5481 # session initiated from remote host - do not translate
5482 self.tcp_port_in = 60303
5483 self.udp_port_in = 60304
5484 self.icmp_id_in = 60305
5485 pkts = self.create_stream_out(self.pg1,
5486 self.pg0.remote_ip4,
5487 use_inside_ports=True)
5488 self.pg1.add_stream(pkts)
5489 self.pg_enable_capture(self.pg_interfaces)
5491 capture = self.pg0.get_capture(len(pkts))
5492 self.verify_capture_in(capture, self.pg0)
5494 pkts = self.create_stream_in(self.pg0, self.pg1)
5495 self.pg0.add_stream(pkts)
5496 self.pg_enable_capture(self.pg_interfaces)
5498 capture = self.pg1.get_capture(len(pkts))
5499 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5502 def test_output_feature_and_service3(self):
5503 """ NAT44 interface output feature and DST NAT """
5504 external_addr = '1.2.3.4'
5508 self.vapi.nat44_forwarding_enable_disable(enable=1)
5509 self.nat44_add_address(self.nat_addr)
5510 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5511 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5512 local_port, external_port,
5513 proto=IP_PROTOS.tcp, flags=flags)
5514 flags = self.config_flags.NAT_IS_INSIDE
5515 self.vapi.nat44_interface_add_del_feature(
5516 sw_if_index=self.pg0.sw_if_index,
5518 self.vapi.nat44_interface_add_del_feature(
5519 sw_if_index=self.pg0.sw_if_index,
5520 flags=flags, is_add=1)
5521 self.vapi.nat44_interface_add_del_output_feature(
5523 sw_if_index=self.pg1.sw_if_index)
5525 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5526 IP(src=self.pg0.remote_ip4, dst=external_addr) /
5527 TCP(sport=12345, dport=external_port))
5528 self.pg0.add_stream(p)
5529 self.pg_enable_capture(self.pg_interfaces)
5531 capture = self.pg1.get_capture(1)
5536 self.assertEqual(ip.src, self.pg0.remote_ip4)
5537 self.assertEqual(tcp.sport, 12345)
5538 self.assertEqual(ip.dst, self.pg1.remote_ip4)
5539 self.assertEqual(tcp.dport, local_port)
5540 self.assert_packet_checksums_valid(p)
5542 self.logger.error(ppp("Unexpected or invalid packet:", p))
5545 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5546 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5547 TCP(sport=local_port, dport=12345))
5548 self.pg1.add_stream(p)
5549 self.pg_enable_capture(self.pg_interfaces)
5551 capture = self.pg0.get_capture(1)
5556 self.assertEqual(ip.src, external_addr)
5557 self.assertEqual(tcp.sport, external_port)
5558 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5559 self.assertEqual(tcp.dport, 12345)
5560 self.assert_packet_checksums_valid(p)
5562 self.logger.error(ppp("Unexpected or invalid packet:", p))
5565 def test_next_src_nat(self):
5566 """ On way back forward packet to nat44-in2out node. """
5567 twice_nat_addr = '10.0.1.3'
5570 post_twice_nat_port = 0
5572 self.vapi.nat44_forwarding_enable_disable(enable=1)
5573 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5574 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5575 self.config_flags.NAT_IS_SELF_TWICE_NAT)
5576 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5577 local_port, external_port,
5578 proto=IP_PROTOS.tcp, vrf_id=1,
5580 self.vapi.nat44_interface_add_del_feature(
5581 sw_if_index=self.pg6.sw_if_index,
5584 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5585 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5586 TCP(sport=12345, dport=external_port))
5587 self.pg6.add_stream(p)
5588 self.pg_enable_capture(self.pg_interfaces)
5590 capture = self.pg6.get_capture(1)
5595 self.assertEqual(ip.src, twice_nat_addr)
5596 self.assertNotEqual(tcp.sport, 12345)
5597 post_twice_nat_port = tcp.sport
5598 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5599 self.assertEqual(tcp.dport, local_port)
5600 self.assert_packet_checksums_valid(p)
5602 self.logger.error(ppp("Unexpected or invalid packet:", p))
5605 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5606 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5607 TCP(sport=local_port, dport=post_twice_nat_port))
5608 self.pg6.add_stream(p)
5609 self.pg_enable_capture(self.pg_interfaces)
5611 capture = self.pg6.get_capture(1)
5616 self.assertEqual(ip.src, self.pg1.remote_ip4)
5617 self.assertEqual(tcp.sport, external_port)
5618 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5619 self.assertEqual(tcp.dport, 12345)
5620 self.assert_packet_checksums_valid(p)
5622 self.logger.error(ppp("Unexpected or invalid packet:", p))
5625 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5627 twice_nat_addr = '10.0.1.3'
5635 port_in1 = port_in + 1
5636 port_in2 = port_in + 2
5641 server1 = self.pg0.remote_hosts[0]
5642 server2 = self.pg0.remote_hosts[1]
5654 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5657 self.nat44_add_address(self.nat_addr)
5658 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5662 flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
5664 flags |= self.config_flags.NAT_IS_TWICE_NAT
5667 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5669 proto=IP_PROTOS.tcp,
5672 locals = [{'addr': server1.ip4,
5676 {'addr': server2.ip4,
5680 out_addr = self.nat_addr
5682 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5683 external_addr=out_addr,
5684 external_port=port_out,
5685 protocol=IP_PROTOS.tcp,
5686 local_num=len(locals),
5688 flags = self.config_flags.NAT_IS_INSIDE
5689 self.vapi.nat44_interface_add_del_feature(
5690 sw_if_index=pg0.sw_if_index,
5691 flags=flags, is_add=1)
5692 self.vapi.nat44_interface_add_del_feature(
5693 sw_if_index=pg1.sw_if_index,
5700 assert client_id is not None
5702 client = self.pg0.remote_hosts[0]
5703 elif client_id == 2:
5704 client = self.pg0.remote_hosts[1]
5706 client = pg1.remote_hosts[0]
5707 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5708 IP(src=client.ip4, dst=self.nat_addr) /
5709 TCP(sport=eh_port_out, dport=port_out))
5711 self.pg_enable_capture(self.pg_interfaces)
5713 capture = pg0.get_capture(1)
5719 if ip.dst == server1.ip4:
5725 self.assertEqual(ip.dst, server.ip4)
5727 self.assertIn(tcp.dport, [port_in1, port_in2])
5729 self.assertEqual(tcp.dport, port_in)
5731 self.assertEqual(ip.src, twice_nat_addr)
5732 self.assertNotEqual(tcp.sport, eh_port_out)
5734 self.assertEqual(ip.src, client.ip4)
5735 self.assertEqual(tcp.sport, eh_port_out)
5737 eh_port_in = tcp.sport
5738 saved_port_in = tcp.dport
5739 self.assert_packet_checksums_valid(p)
5741 self.logger.error(ppp("Unexpected or invalid packet:", p))
5744 p = (Ether(src=server.mac, dst=pg0.local_mac) /
5745 IP(src=server.ip4, dst=eh_addr_in) /
5746 TCP(sport=saved_port_in, dport=eh_port_in))
5748 self.pg_enable_capture(self.pg_interfaces)
5750 capture = pg1.get_capture(1)
5755 self.assertEqual(ip.dst, client.ip4)
5756 self.assertEqual(ip.src, self.nat_addr)
5757 self.assertEqual(tcp.dport, eh_port_out)
5758 self.assertEqual(tcp.sport, port_out)
5759 self.assert_packet_checksums_valid(p)
5761 self.logger.error(ppp("Unexpected or invalid packet:", p))
5765 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5766 self.assertEqual(len(sessions), 1)
5767 self.assertTrue(sessions[0].flags &
5768 self.config_flags.NAT_IS_EXT_HOST_VALID)
5769 self.assertTrue(sessions[0].flags &
5770 self.config_flags.NAT_IS_TWICE_NAT)
5771 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
5772 self.vapi.nat44_del_session(
5773 address=sessions[0].inside_ip_address,
5774 port=sessions[0].inside_port,
5775 protocol=sessions[0].protocol,
5776 flags=(self.config_flags.NAT_IS_INSIDE |
5777 self.config_flags.NAT_IS_EXT_HOST_VALID),
5778 ext_host_address=sessions[0].ext_host_nat_address,
5779 ext_host_port=sessions[0].ext_host_nat_port)
5780 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5781 self.assertEqual(len(sessions), 0)
5783 def test_twice_nat(self):
5785 self.twice_nat_common()
5787 def test_self_twice_nat_positive(self):
5788 """ Self Twice NAT44 (positive test) """
5789 self.twice_nat_common(self_twice_nat=True, same_pg=True)
5791 def test_self_twice_nat_negative(self):
5792 """ Self Twice NAT44 (negative test) """
5793 self.twice_nat_common(self_twice_nat=True)
5795 def test_twice_nat_lb(self):
5796 """ Twice NAT44 local service load balancing """
5797 self.twice_nat_common(lb=True)
5799 def test_self_twice_nat_lb_positive(self):
5800 """ Self Twice NAT44 local service load balancing (positive test) """
5801 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5804 def test_self_twice_nat_lb_negative(self):
5805 """ Self Twice NAT44 local service load balancing (negative test) """
5806 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5809 def test_twice_nat_interface_addr(self):
5810 """ Acquire twice NAT44 addresses from interface """
5811 flags = self.config_flags.NAT_IS_TWICE_NAT
5812 self.vapi.nat44_add_del_interface_addr(
5814 sw_if_index=self.pg3.sw_if_index,
5817 # no address in NAT pool
5818 adresses = self.vapi.nat44_address_dump()
5819 self.assertEqual(0, len(adresses))
5821 # configure interface address and check NAT address pool
5822 self.pg3.config_ip4()
5823 adresses = self.vapi.nat44_address_dump()
5824 self.assertEqual(1, len(adresses))
5825 self.assertEqual(str(adresses[0].ip_address),
5827 self.assertEqual(adresses[0].flags, flags)
5829 # remove interface address and check NAT address pool
5830 self.pg3.unconfig_ip4()
5831 adresses = self.vapi.nat44_address_dump()
5832 self.assertEqual(0, len(adresses))
5834 def test_tcp_close(self):
5835 """ Close TCP session from inside network - output feature """
5836 self.vapi.nat44_forwarding_enable_disable(enable=1)
5837 self.nat44_add_address(self.pg1.local_ip4)
5838 twice_nat_addr = '10.0.1.3'
5839 service_ip = '192.168.16.150'
5840 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5841 flags = self.config_flags.NAT_IS_INSIDE
5842 self.vapi.nat44_interface_add_del_feature(
5843 sw_if_index=self.pg0.sw_if_index,
5845 self.vapi.nat44_interface_add_del_feature(
5846 sw_if_index=self.pg0.sw_if_index,
5847 flags=flags, is_add=1)
5848 self.vapi.nat44_interface_add_del_output_feature(
5850 sw_if_index=self.pg1.sw_if_index)
5851 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5852 self.config_flags.NAT_IS_TWICE_NAT)
5853 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5857 proto=IP_PROTOS.tcp,
5859 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5860 start_sessnum = len(sessions)
5862 # SYN packet out->in
5863 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5864 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5865 TCP(sport=33898, dport=80, flags="S"))
5866 self.pg1.add_stream(p)
5867 self.pg_enable_capture(self.pg_interfaces)
5869 capture = self.pg0.get_capture(1)
5871 tcp_port = p[TCP].sport
5873 # SYN + ACK packet in->out
5874 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5875 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5876 TCP(sport=80, dport=tcp_port, flags="SA"))
5877 self.pg0.add_stream(p)
5878 self.pg_enable_capture(self.pg_interfaces)
5880 self.pg1.get_capture(1)
5882 # ACK packet out->in
5883 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5884 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5885 TCP(sport=33898, dport=80, flags="A"))
5886 self.pg1.add_stream(p)
5887 self.pg_enable_capture(self.pg_interfaces)
5889 self.pg0.get_capture(1)
5891 # FIN packet in -> out
5892 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5893 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5894 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5895 self.pg0.add_stream(p)
5896 self.pg_enable_capture(self.pg_interfaces)
5898 self.pg1.get_capture(1)
5900 # FIN+ACK packet out -> in
5901 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5902 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5903 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5904 self.pg1.add_stream(p)
5905 self.pg_enable_capture(self.pg_interfaces)
5907 self.pg0.get_capture(1)
5909 # ACK packet in -> out
5910 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5911 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5912 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5913 self.pg0.add_stream(p)
5914 self.pg_enable_capture(self.pg_interfaces)
5916 self.pg1.get_capture(1)
5918 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4,
5920 self.assertEqual(len(sessions) - start_sessnum, 0)
5922 def test_tcp_session_close_in(self):
5923 """ Close TCP session from inside network """
5924 self.tcp_port_out = 10505
5925 self.nat44_add_address(self.nat_addr)
5926 flags = self.config_flags.NAT_IS_TWICE_NAT
5927 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5931 proto=IP_PROTOS.tcp,
5933 flags = self.config_flags.NAT_IS_INSIDE
5934 self.vapi.nat44_interface_add_del_feature(
5935 sw_if_index=self.pg0.sw_if_index,
5936 flags=flags, is_add=1)
5937 self.vapi.nat44_interface_add_del_feature(
5938 sw_if_index=self.pg1.sw_if_index,
5941 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5942 start_sessnum = len(sessions)
5944 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
5945 tcp_transitory=2, icmp=5)
5947 self.initiate_tcp_session(self.pg0, self.pg1)
5949 # FIN packet in -> out
5950 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5951 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5952 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5953 flags="FA", seq=100, ack=300))
5954 self.pg0.add_stream(p)
5955 self.pg_enable_capture(self.pg_interfaces)
5957 self.pg1.get_capture(1)
5961 # ACK packet out -> in
5962 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5963 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5964 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5965 flags="A", seq=300, ack=101))
5968 # FIN packet out -> in
5969 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5970 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5971 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5972 flags="FA", seq=300, ack=101))
5975 self.pg1.add_stream(pkts)
5976 self.pg_enable_capture(self.pg_interfaces)
5978 self.pg0.get_capture(2)
5980 # ACK packet in -> out
5981 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5982 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5983 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5984 flags="A", seq=101, ack=301))
5985 self.pg0.add_stream(p)
5986 self.pg_enable_capture(self.pg_interfaces)
5988 self.pg1.get_capture(1)
5990 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5991 self.assertEqual(len(sessions) - start_sessnum, 1)
5993 stats = self.statistics.get_counter(
5994 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
5995 out2in_drops = stats[0]
5996 stats = self.statistics.get_counter(
5997 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
5998 in2out_drops = stats[0]
6000 # extra FIN packet out -> in - this should be dropped
6001 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6002 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6003 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6004 flags="FA", seq=300, ack=101))
6006 self.pg1.add_stream(p)
6007 self.pg_enable_capture(self.pg_interfaces)
6009 self.pg0.assert_nothing_captured()
6011 # extra ACK packet in -> out - this should be dropped
6012 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6013 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6014 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6015 flags="A", seq=101, ack=301))
6016 self.pg0.add_stream(p)
6017 self.pg_enable_capture(self.pg_interfaces)
6019 self.pg1.assert_nothing_captured()
6021 stats = self.statistics.get_counter(
6022 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6023 self.assertEqual(stats[0] - out2in_drops, 1)
6024 stats = self.statistics.get_counter(
6025 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6026 self.assertEqual(stats[0] - in2out_drops, 1)
6029 # extra ACK packet in -> out - this will cause session to be wiped
6030 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6031 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6032 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6033 flags="A", seq=101, ack=301))
6034 self.pg0.add_stream(p)
6035 self.pg_enable_capture(self.pg_interfaces)
6037 self.pg1.assert_nothing_captured()
6038 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6039 self.assertEqual(len(sessions) - start_sessnum, 0)
6041 def test_tcp_session_close_out(self):
6042 """ Close TCP session from outside network """
6043 self.tcp_port_out = 10505
6044 self.nat44_add_address(self.nat_addr)
6045 flags = self.config_flags.NAT_IS_TWICE_NAT
6046 self.nat44_add_static_mapping(self.pg0.remote_ip4,
6050 proto=IP_PROTOS.tcp,
6052 flags = self.config_flags.NAT_IS_INSIDE
6053 self.vapi.nat44_interface_add_del_feature(
6054 sw_if_index=self.pg0.sw_if_index,
6055 flags=flags, is_add=1)
6056 self.vapi.nat44_interface_add_del_feature(
6057 sw_if_index=self.pg1.sw_if_index,
6060 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6061 start_sessnum = len(sessions)
6063 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6064 tcp_transitory=2, icmp=5)
6066 self.initiate_tcp_session(self.pg0, self.pg1)
6068 # FIN packet out -> in
6069 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6070 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6071 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6072 flags="FA", seq=100, ack=300))
6073 self.pg1.add_stream(p)
6074 self.pg_enable_capture(self.pg_interfaces)
6076 self.pg0.get_capture(1)
6078 # FIN+ACK packet in -> out
6079 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6080 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6081 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6082 flags="FA", seq=300, ack=101))
6084 self.pg0.add_stream(p)
6085 self.pg_enable_capture(self.pg_interfaces)
6087 self.pg1.get_capture(1)
6089 # ACK packet out -> in
6090 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6091 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6092 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6093 flags="A", seq=101, ack=301))
6094 self.pg1.add_stream(p)
6095 self.pg_enable_capture(self.pg_interfaces)
6097 self.pg0.get_capture(1)
6099 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6100 self.assertEqual(len(sessions) - start_sessnum, 1)
6102 stats = self.statistics.get_counter(
6103 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6104 out2in_drops = stats[0]
6105 stats = self.statistics.get_counter(
6106 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6107 in2out_drops = stats[0]
6109 # extra FIN packet out -> in - this should be dropped
6110 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6111 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6112 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6113 flags="FA", seq=300, ack=101))
6115 self.pg1.add_stream(p)
6116 self.pg_enable_capture(self.pg_interfaces)
6118 self.pg0.assert_nothing_captured()
6120 # extra ACK packet in -> out - this should be dropped
6121 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6122 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6123 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6124 flags="A", seq=101, ack=301))
6125 self.pg0.add_stream(p)
6126 self.pg_enable_capture(self.pg_interfaces)
6128 self.pg1.assert_nothing_captured()
6130 stats = self.statistics.get_counter(
6131 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6132 self.assertEqual(stats[0] - out2in_drops, 1)
6133 stats = self.statistics.get_counter(
6134 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6135 self.assertEqual(stats[0] - in2out_drops, 1)
6138 # extra ACK packet in -> out - this will cause session to be wiped
6139 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6140 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6141 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6142 flags="A", seq=101, ack=301))
6143 self.pg0.add_stream(p)
6144 self.pg_enable_capture(self.pg_interfaces)
6146 self.pg1.assert_nothing_captured()
6147 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6148 self.assertEqual(len(sessions) - start_sessnum, 0)
6150 def test_tcp_session_close_simultaneous(self):
6151 """ Close TCP session from inside network """
6152 self.tcp_port_out = 10505
6153 self.nat44_add_address(self.nat_addr)
6154 flags = self.config_flags.NAT_IS_TWICE_NAT
6155 self.nat44_add_static_mapping(self.pg0.remote_ip4,
6159 proto=IP_PROTOS.tcp,
6161 flags = self.config_flags.NAT_IS_INSIDE
6162 self.vapi.nat44_interface_add_del_feature(
6163 sw_if_index=self.pg0.sw_if_index,
6164 flags=flags, is_add=1)
6165 self.vapi.nat44_interface_add_del_feature(
6166 sw_if_index=self.pg1.sw_if_index,
6169 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6170 start_sessnum = len(sessions)
6172 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6173 tcp_transitory=2, icmp=5)
6175 self.initiate_tcp_session(self.pg0, self.pg1)
6177 # FIN packet in -> out
6178 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6179 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6180 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6181 flags="FA", seq=100, ack=300))
6182 self.pg0.add_stream(p)
6183 self.pg_enable_capture(self.pg_interfaces)
6185 self.pg1.get_capture(1)
6187 # FIN packet out -> in
6188 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6189 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6190 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6191 flags="FA", seq=300, ack=100))
6192 self.pg1.add_stream(p)
6193 self.pg_enable_capture(self.pg_interfaces)
6195 self.pg0.get_capture(1)
6197 # ACK packet in -> out
6198 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6199 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6200 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6201 flags="A", seq=101, ack=301))
6202 self.pg0.add_stream(p)
6203 self.pg_enable_capture(self.pg_interfaces)
6205 self.pg1.get_capture(1)
6207 # ACK packet out -> in
6208 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6209 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6210 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6211 flags="A", seq=301, ack=101))
6212 self.pg1.add_stream(p)
6213 self.pg_enable_capture(self.pg_interfaces)
6215 self.pg0.get_capture(1)
6217 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6218 self.assertEqual(len(sessions) - start_sessnum, 1)
6220 stats = self.statistics.get_counter(
6221 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6222 out2in_drops = stats[0]
6223 stats = self.statistics.get_counter(
6224 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6225 in2out_drops = stats[0]
6227 # extra FIN packet out -> in - this should be dropped
6228 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6229 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6230 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6231 flags="FA", seq=300, ack=101))
6233 self.pg1.add_stream(p)
6234 self.pg_enable_capture(self.pg_interfaces)
6236 self.pg0.assert_nothing_captured()
6238 # extra ACK packet in -> out - this should be dropped
6239 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6240 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6241 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6242 flags="A", seq=101, ack=301))
6243 self.pg0.add_stream(p)
6244 self.pg_enable_capture(self.pg_interfaces)
6246 self.pg1.assert_nothing_captured()
6248 stats = self.statistics.get_counter(
6249 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6250 self.assertEqual(stats[0] - out2in_drops, 1)
6251 stats = self.statistics.get_counter(
6252 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6253 self.assertEqual(stats[0] - in2out_drops, 1)
6256 # extra ACK packet in -> out - this will cause session to be wiped
6257 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6258 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6259 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6260 flags="A", seq=101, ack=301))
6261 self.pg0.add_stream(p)
6262 self.pg_enable_capture(self.pg_interfaces)
6264 self.pg1.assert_nothing_captured()
6265 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6266 self.assertEqual(len(sessions) - start_sessnum, 0)
6268 def test_one_armed_nat44_static(self):
6269 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
6270 remote_host = self.pg4.remote_hosts[0]
6271 local_host = self.pg4.remote_hosts[1]
6276 self.vapi.nat44_forwarding_enable_disable(enable=1)
6277 self.nat44_add_address(self.nat_addr, twice_nat=1)
6278 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
6279 self.config_flags.NAT_IS_TWICE_NAT)
6280 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
6281 local_port, external_port,
6282 proto=IP_PROTOS.tcp, flags=flags)
6283 flags = self.config_flags.NAT_IS_INSIDE
6284 self.vapi.nat44_interface_add_del_feature(
6285 sw_if_index=self.pg4.sw_if_index,
6287 self.vapi.nat44_interface_add_del_feature(
6288 sw_if_index=self.pg4.sw_if_index,
6289 flags=flags, is_add=1)
6291 # from client to service
6292 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6293 IP(src=remote_host.ip4, dst=self.nat_addr) /
6294 TCP(sport=12345, dport=external_port))
6295 self.pg4.add_stream(p)
6296 self.pg_enable_capture(self.pg_interfaces)
6298 capture = self.pg4.get_capture(1)
6303 self.assertEqual(ip.dst, local_host.ip4)
6304 self.assertEqual(ip.src, self.nat_addr)
6305 self.assertEqual(tcp.dport, local_port)
6306 self.assertNotEqual(tcp.sport, 12345)
6307 eh_port_in = tcp.sport
6308 self.assert_packet_checksums_valid(p)
6310 self.logger.error(ppp("Unexpected or invalid packet:", p))
6313 # from service back to client
6314 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6315 IP(src=local_host.ip4, dst=self.nat_addr) /
6316 TCP(sport=local_port, dport=eh_port_in))
6317 self.pg4.add_stream(p)
6318 self.pg_enable_capture(self.pg_interfaces)
6320 capture = self.pg4.get_capture(1)
6325 self.assertEqual(ip.src, self.nat_addr)
6326 self.assertEqual(ip.dst, remote_host.ip4)
6327 self.assertEqual(tcp.sport, external_port)
6328 self.assertEqual(tcp.dport, 12345)
6329 self.assert_packet_checksums_valid(p)
6331 self.logger.error(ppp("Unexpected or invalid packet:", p))
6334 def test_static_with_port_out2(self):
6335 """ 1:1 NAPT asymmetrical rule """
6340 self.vapi.nat44_forwarding_enable_disable(enable=1)
6341 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6342 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
6343 local_port, external_port,
6344 proto=IP_PROTOS.tcp, flags=flags)
6345 flags = self.config_flags.NAT_IS_INSIDE
6346 self.vapi.nat44_interface_add_del_feature(
6347 sw_if_index=self.pg0.sw_if_index,
6348 flags=flags, is_add=1)
6349 self.vapi.nat44_interface_add_del_feature(
6350 sw_if_index=self.pg1.sw_if_index,
6353 # from client to service
6354 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6355 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6356 TCP(sport=12345, dport=external_port))
6357 self.pg1.add_stream(p)
6358 self.pg_enable_capture(self.pg_interfaces)
6360 capture = self.pg0.get_capture(1)
6365 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6366 self.assertEqual(tcp.dport, local_port)
6367 self.assert_packet_checksums_valid(p)
6369 self.logger.error(ppp("Unexpected or invalid packet:", p))
6373 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6374 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6375 ICMP(type=11) / capture[0][IP])
6376 self.pg0.add_stream(p)
6377 self.pg_enable_capture(self.pg_interfaces)
6379 capture = self.pg1.get_capture(1)
6382 self.assertEqual(p[IP].src, self.nat_addr)
6384 self.assertEqual(inner.dst, self.nat_addr)
6385 self.assertEqual(inner[TCPerror].dport, external_port)
6387 self.logger.error(ppp("Unexpected or invalid packet:", p))
6390 # from service back to client
6391 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6392 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6393 TCP(sport=local_port, dport=12345))
6394 self.pg0.add_stream(p)
6395 self.pg_enable_capture(self.pg_interfaces)
6397 capture = self.pg1.get_capture(1)
6402 self.assertEqual(ip.src, self.nat_addr)
6403 self.assertEqual(tcp.sport, external_port)
6404 self.assert_packet_checksums_valid(p)
6406 self.logger.error(ppp("Unexpected or invalid packet:", p))
6410 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6411 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6412 ICMP(type=11) / capture[0][IP])
6413 self.pg1.add_stream(p)
6414 self.pg_enable_capture(self.pg_interfaces)
6416 capture = self.pg0.get_capture(1)
6419 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
6421 self.assertEqual(inner.src, self.pg0.remote_ip4)
6422 self.assertEqual(inner[TCPerror].sport, local_port)
6424 self.logger.error(ppp("Unexpected or invalid packet:", p))
6427 # from client to server (no translation)
6428 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6429 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
6430 TCP(sport=12346, dport=local_port))
6431 self.pg1.add_stream(p)
6432 self.pg_enable_capture(self.pg_interfaces)
6434 capture = self.pg0.get_capture(1)
6439 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6440 self.assertEqual(tcp.dport, local_port)
6441 self.assert_packet_checksums_valid(p)
6443 self.logger.error(ppp("Unexpected or invalid packet:", p))
6446 # from service back to client (no translation)
6447 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6448 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6449 TCP(sport=local_port, dport=12346))
6450 self.pg0.add_stream(p)
6451 self.pg_enable_capture(self.pg_interfaces)
6453 capture = self.pg1.get_capture(1)
6458 self.assertEqual(ip.src, self.pg0.remote_ip4)
6459 self.assertEqual(tcp.sport, local_port)
6460 self.assert_packet_checksums_valid(p)
6462 self.logger.error(ppp("Unexpected or invalid packet:", p))
6465 def test_output_feature(self):
6466 """ NAT44 interface output feature (in2out postrouting) """
6467 self.vapi.nat44_forwarding_enable_disable(enable=1)
6468 self.nat44_add_address(self.nat_addr)
6469 self.vapi.nat44_interface_add_del_feature(
6470 sw_if_index=self.pg0.sw_if_index,
6472 self.vapi.nat44_interface_add_del_output_feature(
6474 sw_if_index=self.pg1.sw_if_index)
6477 pkts = self.create_stream_in(self.pg0, self.pg1)
6478 self.pg0.add_stream(pkts)
6479 self.pg_enable_capture(self.pg_interfaces)
6481 capture = self.pg1.get_capture(len(pkts))
6482 self.verify_capture_out(capture)
6485 pkts = self.create_stream_out(self.pg1)
6486 self.pg1.add_stream(pkts)
6487 self.pg_enable_capture(self.pg_interfaces)
6489 capture = self.pg0.get_capture(len(pkts))
6490 self.verify_capture_in(capture, self.pg0)
6492 def test_output_feature_stateful_acl(self):
6493 """ NAT44 endpoint-dependent output feature works with stateful ACL """
6494 self.nat44_add_address(self.nat_addr)
6495 self.vapi.nat44_interface_add_del_output_feature(
6496 sw_if_index=self.pg0.sw_if_index,
6497 flags=self.config_flags.NAT_IS_INSIDE,
6499 self.vapi.nat44_interface_add_del_output_feature(
6500 sw_if_index=self.pg1.sw_if_index,
6501 flags=self.config_flags.NAT_IS_OUTSIDE,
6504 # First ensure that the NAT is working sans ACL
6506 # send packets out2in, no sessions yet so packets should drop
6507 pkts_out2in = self.create_stream_out(self.pg1)
6508 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
6510 # send packets into inside intf, ensure received via outside intf
6511 pkts_in2out = self.create_stream_in(self.pg0, self.pg1)
6512 capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
6514 self.verify_capture_out(capture)
6516 # send out2in again, with sessions created it should work now
6517 pkts_out2in = self.create_stream_out(self.pg1)
6518 capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
6520 self.verify_capture_in(capture, self.pg0)
6522 # Create an ACL blocking everything
6523 out2in_deny_rule = AclRule(is_permit=0)
6524 out2in_acl = VppAcl(self, rules=[out2in_deny_rule])
6525 out2in_acl.add_vpp_config()
6527 # create an ACL to permit/reflect everything
6528 in2out_reflect_rule = AclRule(is_permit=2)
6529 in2out_acl = VppAcl(self, rules=[in2out_reflect_rule])
6530 in2out_acl.add_vpp_config()
6532 # apply as input acl on interface and confirm it blocks everything
6533 acl_if = VppAclInterface(self, sw_if_index=self.pg1.sw_if_index,
6534 n_input=1, acls=[out2in_acl])
6535 acl_if.add_vpp_config()
6536 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
6539 acl_if.acls = [out2in_acl, in2out_acl]
6540 acl_if.add_vpp_config()
6541 # send in2out to generate ACL state (NAT state was created earlier)
6542 capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
6544 self.verify_capture_out(capture)
6546 # send out2in again. ACL state exists so it should work now.
6547 # TCP packets with the syn flag set also need the ack flag
6548 for p in pkts_out2in:
6549 if p.haslayer(TCP) and p[TCP].flags & 0x02:
6550 p[TCP].flags |= 0x10
6551 capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
6553 self.verify_capture_in(capture, self.pg0)
6554 self.logger.info(self.vapi.cli("show trace"))
6556 def test_multiple_vrf(self):
6557 """ Multiple VRF setup """
6558 external_addr = '1.2.3.4'
6563 self.vapi.nat44_forwarding_enable_disable(enable=1)
6564 self.nat44_add_address(self.nat_addr)
6565 flags = self.config_flags.NAT_IS_INSIDE
6566 self.vapi.nat44_interface_add_del_feature(
6567 sw_if_index=self.pg0.sw_if_index,
6569 self.vapi.nat44_interface_add_del_feature(
6570 sw_if_index=self.pg0.sw_if_index,
6571 flags=flags, is_add=1)
6572 self.vapi.nat44_interface_add_del_output_feature(
6574 sw_if_index=self.pg1.sw_if_index)
6575 self.vapi.nat44_interface_add_del_feature(
6576 sw_if_index=self.pg5.sw_if_index,
6578 self.vapi.nat44_interface_add_del_feature(
6579 sw_if_index=self.pg5.sw_if_index,
6580 flags=flags, is_add=1)
6581 self.vapi.nat44_interface_add_del_feature(
6582 sw_if_index=self.pg6.sw_if_index,
6584 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6585 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
6586 local_port, external_port, vrf_id=1,
6587 proto=IP_PROTOS.tcp, flags=flags)
6588 self.nat44_add_static_mapping(
6589 self.pg0.remote_ip4,
6590 external_sw_if_index=self.pg0.sw_if_index,
6591 local_port=local_port,
6593 external_port=external_port,
6594 proto=IP_PROTOS.tcp,
6598 # from client to service (both VRF1)
6599 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6600 IP(src=self.pg6.remote_ip4, dst=external_addr) /
6601 TCP(sport=12345, dport=external_port))
6602 self.pg6.add_stream(p)
6603 self.pg_enable_capture(self.pg_interfaces)
6605 capture = self.pg5.get_capture(1)
6610 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6611 self.assertEqual(tcp.dport, local_port)
6612 self.assert_packet_checksums_valid(p)
6614 self.logger.error(ppp("Unexpected or invalid packet:", p))
6617 # from service back to client (both VRF1)
6618 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6619 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6620 TCP(sport=local_port, dport=12345))
6621 self.pg5.add_stream(p)
6622 self.pg_enable_capture(self.pg_interfaces)
6624 capture = self.pg6.get_capture(1)
6629 self.assertEqual(ip.src, external_addr)
6630 self.assertEqual(tcp.sport, external_port)
6631 self.assert_packet_checksums_valid(p)
6633 self.logger.error(ppp("Unexpected or invalid packet:", p))
6636 # dynamic NAT from VRF1 to VRF0 (output-feature)
6637 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6638 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6639 TCP(sport=2345, dport=22))
6640 self.pg5.add_stream(p)
6641 self.pg_enable_capture(self.pg_interfaces)
6643 capture = self.pg1.get_capture(1)
6648 self.assertEqual(ip.src, self.nat_addr)
6649 self.assertNotEqual(tcp.sport, 2345)
6650 self.assert_packet_checksums_valid(p)
6653 self.logger.error(ppp("Unexpected or invalid packet:", p))
6656 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6657 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6658 TCP(sport=22, dport=port))
6659 self.pg1.add_stream(p)
6660 self.pg_enable_capture(self.pg_interfaces)
6662 capture = self.pg5.get_capture(1)
6667 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6668 self.assertEqual(tcp.dport, 2345)
6669 self.assert_packet_checksums_valid(p)
6671 self.logger.error(ppp("Unexpected or invalid packet:", p))
6674 # from client VRF1 to service VRF0
6675 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6676 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6677 TCP(sport=12346, dport=external_port))
6678 self.pg6.add_stream(p)
6679 self.pg_enable_capture(self.pg_interfaces)
6681 capture = self.pg0.get_capture(1)
6686 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6687 self.assertEqual(tcp.dport, local_port)
6688 self.assert_packet_checksums_valid(p)
6690 self.logger.error(ppp("Unexpected or invalid packet:", p))
6693 # from service VRF0 back to client VRF1
6694 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6695 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6696 TCP(sport=local_port, dport=12346))
6697 self.pg0.add_stream(p)
6698 self.pg_enable_capture(self.pg_interfaces)
6700 capture = self.pg6.get_capture(1)
6705 self.assertEqual(ip.src, self.pg0.local_ip4)
6706 self.assertEqual(tcp.sport, external_port)
6707 self.assert_packet_checksums_valid(p)
6709 self.logger.error(ppp("Unexpected or invalid packet:", p))
6712 # from client VRF0 to service VRF1
6713 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6714 IP(src=self.pg0.remote_ip4, dst=external_addr) /
6715 TCP(sport=12347, dport=external_port))
6716 self.pg0.add_stream(p)
6717 self.pg_enable_capture(self.pg_interfaces)
6719 capture = self.pg5.get_capture(1)
6724 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6725 self.assertEqual(tcp.dport, local_port)
6726 self.assert_packet_checksums_valid(p)
6728 self.logger.error(ppp("Unexpected or invalid packet:", p))
6731 # from service VRF1 back to client VRF0
6732 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6733 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6734 TCP(sport=local_port, dport=12347))
6735 self.pg5.add_stream(p)
6736 self.pg_enable_capture(self.pg_interfaces)
6738 capture = self.pg0.get_capture(1)
6743 self.assertEqual(ip.src, external_addr)
6744 self.assertEqual(tcp.sport, external_port)
6745 self.assert_packet_checksums_valid(p)
6747 self.logger.error(ppp("Unexpected or invalid packet:", p))
6750 # from client to server (both VRF1, no translation)
6751 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6752 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6753 TCP(sport=12348, dport=local_port))
6754 self.pg6.add_stream(p)
6755 self.pg_enable_capture(self.pg_interfaces)
6757 capture = self.pg5.get_capture(1)
6762 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6763 self.assertEqual(tcp.dport, local_port)
6764 self.assert_packet_checksums_valid(p)
6766 self.logger.error(ppp("Unexpected or invalid packet:", p))
6769 # from server back to client (both VRF1, no translation)
6770 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6771 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6772 TCP(sport=local_port, dport=12348))
6773 self.pg5.add_stream(p)
6774 self.pg_enable_capture(self.pg_interfaces)
6776 capture = self.pg6.get_capture(1)
6781 self.assertEqual(ip.src, self.pg5.remote_ip4)
6782 self.assertEqual(tcp.sport, local_port)
6783 self.assert_packet_checksums_valid(p)
6785 self.logger.error(ppp("Unexpected or invalid packet:", p))
6788 # from client VRF1 to server VRF0 (no translation)
6789 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6790 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6791 TCP(sport=local_port, dport=12349))
6792 self.pg0.add_stream(p)
6793 self.pg_enable_capture(self.pg_interfaces)
6795 capture = self.pg6.get_capture(1)
6800 self.assertEqual(ip.src, self.pg0.remote_ip4)
6801 self.assertEqual(tcp.sport, local_port)
6802 self.assert_packet_checksums_valid(p)
6804 self.logger.error(ppp("Unexpected or invalid packet:", p))
6807 # from server VRF0 back to client VRF1 (no translation)
6808 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6809 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6810 TCP(sport=local_port, dport=12349))
6811 self.pg0.add_stream(p)
6812 self.pg_enable_capture(self.pg_interfaces)
6814 capture = self.pg6.get_capture(1)
6819 self.assertEqual(ip.src, self.pg0.remote_ip4)
6820 self.assertEqual(tcp.sport, local_port)
6821 self.assert_packet_checksums_valid(p)
6823 self.logger.error(ppp("Unexpected or invalid packet:", p))
6826 # from client VRF0 to server VRF1 (no translation)
6827 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6828 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6829 TCP(sport=12344, dport=local_port))
6830 self.pg0.add_stream(p)
6831 self.pg_enable_capture(self.pg_interfaces)
6833 capture = self.pg5.get_capture(1)
6838 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6839 self.assertEqual(tcp.dport, local_port)
6840 self.assert_packet_checksums_valid(p)
6842 self.logger.error(ppp("Unexpected or invalid packet:", p))
6845 # from server VRF1 back to client VRF0 (no translation)
6846 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6847 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6848 TCP(sport=local_port, dport=12344))
6849 self.pg5.add_stream(p)
6850 self.pg_enable_capture(self.pg_interfaces)
6852 capture = self.pg0.get_capture(1)
6857 self.assertEqual(ip.src, self.pg5.remote_ip4)
6858 self.assertEqual(tcp.sport, local_port)
6859 self.assert_packet_checksums_valid(p)
6861 self.logger.error(ppp("Unexpected or invalid packet:", p))
6864 @unittest.skipUnless(running_extended_tests, "part of extended tests")
6865 def test_session_timeout(self):
6866 """ NAT44 session timeouts """
6867 self.nat44_add_address(self.nat_addr)
6868 flags = self.config_flags.NAT_IS_INSIDE
6869 self.vapi.nat44_interface_add_del_feature(
6870 sw_if_index=self.pg0.sw_if_index,
6871 flags=flags, is_add=1)
6872 self.vapi.nat44_interface_add_del_feature(
6873 sw_if_index=self.pg1.sw_if_index,
6875 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6876 tcp_transitory=240, icmp=5)
6880 for i in range(0, max_sessions):
6881 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6882 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6883 IP(src=src, dst=self.pg1.remote_ip4) /
6884 ICMP(id=1025, type='echo-request'))
6886 self.pg0.add_stream(pkts)
6887 self.pg_enable_capture(self.pg_interfaces)
6889 self.pg1.get_capture(max_sessions)
6894 for i in range(0, max_sessions):
6895 src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6896 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6897 IP(src=src, dst=self.pg1.remote_ip4) /
6898 ICMP(id=1026, type='echo-request'))
6900 self.pg0.add_stream(pkts)
6901 self.pg_enable_capture(self.pg_interfaces)
6903 self.pg1.get_capture(max_sessions)
6906 users = self.vapi.nat44_user_dump()
6908 nsessions = nsessions + user.nsessions
6909 self.assertLess(nsessions, 2 * max_sessions)
6911 @unittest.skipUnless(running_extended_tests, "part of extended tests")
6912 def test_session_rst_timeout(self):
6913 """ NAT44 session RST timeouts """
6914 self.nat44_add_address(self.nat_addr)
6915 flags = self.config_flags.NAT_IS_INSIDE
6916 self.vapi.nat44_interface_add_del_feature(
6917 sw_if_index=self.pg0.sw_if_index,
6918 flags=flags, is_add=1)
6919 self.vapi.nat44_interface_add_del_feature(
6920 sw_if_index=self.pg1.sw_if_index,
6922 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6923 tcp_transitory=5, icmp=60)
6925 self.initiate_tcp_session(self.pg0, self.pg1)
6926 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6927 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6928 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6930 self.pg0.add_stream(p)
6931 self.pg_enable_capture(self.pg_interfaces)
6933 self.pg1.get_capture(1)
6937 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6938 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6939 TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6941 self.pg0.add_stream(p)
6942 self.pg_enable_capture(self.pg_interfaces)
6944 self.pg1.get_capture(1)
6946 def test_syslog_sess(self):
6947 """ Test syslog session creation and deletion """
6948 self.vapi.syslog_set_filter(
6949 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
6950 self.vapi.syslog_set_sender(self.pg2.local_ip4, self.pg2.remote_ip4)
6951 self.nat44_add_address(self.nat_addr)
6952 flags = self.config_flags.NAT_IS_INSIDE
6953 self.vapi.nat44_interface_add_del_feature(
6954 sw_if_index=self.pg0.sw_if_index,
6955 flags=flags, is_add=1)
6956 self.vapi.nat44_interface_add_del_feature(
6957 sw_if_index=self.pg1.sw_if_index,
6960 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6961 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6962 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6963 self.pg0.add_stream(p)
6964 self.pg_enable_capture(self.pg_interfaces)
6966 capture = self.pg1.get_capture(1)
6967 self.tcp_port_out = capture[0][TCP].sport
6968 capture = self.pg2.get_capture(1)
6969 self.verify_syslog_sess(capture[0][Raw].load)
6971 self.pg_enable_capture(self.pg_interfaces)
6973 self.nat44_add_address(self.nat_addr, is_add=0)
6974 capture = self.pg2.get_capture(1)
6975 self.verify_syslog_sess(capture[0][Raw].load, False)
6978 super(TestNAT44EndpointDependent, self).tearDown()
6979 if not self.vpp_dead:
6981 self.vapi.cli("clear logging")
6983 def show_commands_at_teardown(self):
6984 self.logger.info(self.vapi.cli("show nat44 addresses"))
6985 self.logger.info(self.vapi.cli("show nat44 interfaces"))
6986 self.logger.info(self.vapi.cli("show nat44 static mappings"))
6987 self.logger.info(self.vapi.cli("show nat44 interface address"))
6988 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
6989 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
6990 self.logger.info(self.vapi.cli("show nat timeouts"))
6993 class TestNAT44Out2InDPO(MethodHolder):
6994 """ NAT44 Test Cases using out2in DPO """
6997 def setUpConstants(cls):
6998 super(TestNAT44Out2InDPO, cls).setUpConstants()
6999 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
7002 def setUpClass(cls):
7003 super(TestNAT44Out2InDPO, cls).setUpClass()
7004 cls.vapi.cli("set log class nat level debug")
7006 cls.tcp_port_in = 6303
7007 cls.tcp_port_out = 6303
7008 cls.udp_port_in = 6304
7009 cls.udp_port_out = 6304
7010 cls.icmp_id_in = 6305
7011 cls.icmp_id_out = 6305
7012 cls.nat_addr = '10.0.0.3'
7013 cls.dst_ip4 = '192.168.70.1'
7015 cls.create_pg_interfaces(range(2))
7018 cls.pg0.config_ip4()
7019 cls.pg0.resolve_arp()
7022 cls.pg1.config_ip6()
7023 cls.pg1.resolve_ndp()
7025 r1 = VppIpRoute(cls, "::", 0,
7026 [VppRoutePath(cls.pg1.remote_ip6,
7027 cls.pg1.sw_if_index)],
7032 def tearDownClass(cls):
7033 super(TestNAT44Out2InDPO, cls).tearDownClass()
7035 def configure_xlat(self):
7036 self.dst_ip6_pfx = '1:2:3::'
7037 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
7039 self.dst_ip6_pfx_len = 96
7040 self.src_ip6_pfx = '4:5:6::'
7041 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
7043 self.src_ip6_pfx_len = 96
7044 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
7045 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
7046 '\x00\x00\x00\x00', 0)
7048 @unittest.skip('Temporary disabled')
7049 def test_464xlat_ce(self):
7050 """ Test 464XLAT CE with NAT44 """
7052 nat_config = self.vapi.nat_show_config()
7053 self.assertEqual(1, nat_config.out2in_dpo)
7055 self.configure_xlat()
7057 flags = self.config_flags.NAT_IS_INSIDE
7058 self.vapi.nat44_interface_add_del_feature(
7059 sw_if_index=self.pg0.sw_if_index,
7060 flags=flags, is_add=1)
7061 self.vapi.nat44_add_del_address_range(first_ip_address=self.nat_addr_n,
7062 last_ip_address=self.nat_addr_n,
7063 vrf_id=0xFFFFFFFF, is_add=1)
7065 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7066 self.dst_ip6_pfx_len)
7067 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
7068 self.src_ip6_pfx_len)
7071 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7072 self.pg0.add_stream(pkts)
7073 self.pg_enable_capture(self.pg_interfaces)
7075 capture = self.pg1.get_capture(len(pkts))
7076 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
7079 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
7081 self.pg1.add_stream(pkts)
7082 self.pg_enable_capture(self.pg_interfaces)
7084 capture = self.pg0.get_capture(len(pkts))
7085 self.verify_capture_in(capture, self.pg0)
7087 self.vapi.nat44_interface_add_del_feature(
7088 sw_if_index=self.pg0.sw_if_index,
7090 self.vapi.nat44_add_del_address_range(
7091 first_ip_address=self.nat_addr_n,
7092 last_ip_address=self.nat_addr_n,
7095 @unittest.skip('Temporary disabled')
7096 def test_464xlat_ce_no_nat(self):
7097 """ Test 464XLAT CE without NAT44 """
7099 self.configure_xlat()
7101 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7102 self.dst_ip6_pfx_len)
7103 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
7104 self.src_ip6_pfx_len)
7106 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7107 self.pg0.add_stream(pkts)
7108 self.pg_enable_capture(self.pg_interfaces)
7110 capture = self.pg1.get_capture(len(pkts))
7111 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
7112 nat_ip=out_dst_ip6, same_port=True)
7114 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
7115 self.pg1.add_stream(pkts)
7116 self.pg_enable_capture(self.pg_interfaces)
7118 capture = self.pg0.get_capture(len(pkts))
7119 self.verify_capture_in(capture, self.pg0)
7122 class TestDeterministicNAT(MethodHolder):
7123 """ Deterministic NAT Test Cases """
7126 def setUpConstants(cls):
7127 super(TestDeterministicNAT, cls).setUpConstants()
7128 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
7131 def setUpClass(cls):
7132 super(TestDeterministicNAT, cls).setUpClass()
7133 cls.vapi.cli("set log class nat level debug")
7135 cls.tcp_port_in = 6303
7136 cls.tcp_external_port = 6303
7137 cls.udp_port_in = 6304
7138 cls.udp_external_port = 6304
7139 cls.icmp_id_in = 6305
7140 cls.nat_addr = '10.0.0.3'
7142 cls.create_pg_interfaces(range(3))
7143 cls.interfaces = list(cls.pg_interfaces)
7145 for i in cls.interfaces:
7150 cls.pg0.generate_remote_hosts(2)
7151 cls.pg0.configure_ipv4_neighbors()
7154 def tearDownClass(cls):
7155 super(TestDeterministicNAT, cls).tearDownClass()
7157 def create_stream_in(self, in_if, out_if, ttl=64):
7159 Create packet stream for inside network
7161 :param in_if: Inside interface
7162 :param out_if: Outside interface
7163 :param ttl: TTL of generated packets
7167 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7168 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7169 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
7173 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7174 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7175 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
7179 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7180 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7181 ICMP(id=self.icmp_id_in, type='echo-request'))
7186 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
7188 Create packet stream for outside network
7190 :param out_if: Outside interface
7191 :param dst_ip: Destination IP address (Default use global NAT address)
7192 :param ttl: TTL of generated packets
7195 dst_ip = self.nat_addr
7198 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7199 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7200 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
7204 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7205 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7206 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
7210 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7211 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7212 ICMP(id=self.icmp_external_id, type='echo-reply'))
7217 def verify_capture_out(self, capture, nat_ip=None):
7219 Verify captured packets on outside network
7221 :param capture: Captured packets
7222 :param nat_ip: Translated IP address (Default use global NAT address)
7223 :param same_port: Source port number is not translated (Default False)
7226 nat_ip = self.nat_addr
7227 for packet in capture:
7229 self.assertEqual(packet[IP].src, nat_ip)
7230 if packet.haslayer(TCP):
7231 self.tcp_port_out = packet[TCP].sport
7232 elif packet.haslayer(UDP):
7233 self.udp_port_out = packet[UDP].sport
7235 self.icmp_external_id = packet[ICMP].id
7237 self.logger.error(ppp("Unexpected or invalid packet "
7238 "(outside network):", packet))
7241 def test_deterministic_mode(self):
7242 """ NAT plugin run deterministic mode """
7243 in_addr = '172.16.255.0'
7244 out_addr = '172.17.255.50'
7245 in_addr_t = '172.16.255.20'
7249 nat_config = self.vapi.nat_show_config()
7250 self.assertEqual(1, nat_config.deterministic)
7252 self.vapi.nat_det_add_del_map(is_add=1, in_addr=in_addr,
7253 in_plen=in_plen, out_addr=out_addr,
7256 rep1 = self.vapi.nat_det_forward(in_addr_t)
7257 self.assertEqual(str(rep1.out_addr), out_addr)
7258 rep2 = self.vapi.nat_det_reverse(rep1.out_port_hi, out_addr)
7260 self.assertEqual(str(rep2.in_addr), in_addr_t)
7262 deterministic_mappings = self.vapi.nat_det_map_dump()
7263 self.assertEqual(len(deterministic_mappings), 1)
7264 dsm = deterministic_mappings[0]
7265 self.assertEqual(in_addr, str(dsm.in_addr))
7266 self.assertEqual(in_plen, dsm.in_plen)
7267 self.assertEqual(out_addr, str(dsm.out_addr))
7268 self.assertEqual(out_plen, dsm.out_plen)
7270 self.clear_nat_det()
7271 deterministic_mappings = self.vapi.nat_det_map_dump()
7272 self.assertEqual(len(deterministic_mappings), 0)
7274 def test_set_timeouts(self):
7275 """ Set deterministic NAT timeouts """
7276 timeouts_before = self.vapi.nat_get_timeouts()
7278 self.vapi.nat_set_timeouts(
7279 udp=timeouts_before.udp + 10,
7280 tcp_established=timeouts_before.tcp_established + 10,
7281 tcp_transitory=timeouts_before.tcp_transitory + 10,
7282 icmp=timeouts_before.icmp + 10)
7284 timeouts_after = self.vapi.nat_get_timeouts()
7286 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
7287 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
7288 self.assertNotEqual(timeouts_before.tcp_established,
7289 timeouts_after.tcp_established)
7290 self.assertNotEqual(timeouts_before.tcp_transitory,
7291 timeouts_after.tcp_transitory)
7293 def test_det_in(self):
7294 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
7296 nat_ip = "10.0.0.10"
7298 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7300 out_addr=socket.inet_aton(nat_ip),
7303 flags = self.config_flags.NAT_IS_INSIDE
7304 self.vapi.nat44_interface_add_del_feature(
7305 sw_if_index=self.pg0.sw_if_index,
7306 flags=flags, is_add=1)
7307 self.vapi.nat44_interface_add_del_feature(
7308 sw_if_index=self.pg1.sw_if_index,
7312 pkts = self.create_stream_in(self.pg0, self.pg1)
7313 self.pg0.add_stream(pkts)
7314 self.pg_enable_capture(self.pg_interfaces)
7316 capture = self.pg1.get_capture(len(pkts))
7317 self.verify_capture_out(capture, nat_ip)
7320 pkts = self.create_stream_out(self.pg1, nat_ip)
7321 self.pg1.add_stream(pkts)
7322 self.pg_enable_capture(self.pg_interfaces)
7324 capture = self.pg0.get_capture(len(pkts))
7325 self.verify_capture_in(capture, self.pg0)
7328 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4)
7329 self.assertEqual(len(sessions), 3)
7333 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7334 self.assertEqual(s.in_port, self.tcp_port_in)
7335 self.assertEqual(s.out_port, self.tcp_port_out)
7336 self.assertEqual(s.ext_port, self.tcp_external_port)
7340 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7341 self.assertEqual(s.in_port, self.udp_port_in)
7342 self.assertEqual(s.out_port, self.udp_port_out)
7343 self.assertEqual(s.ext_port, self.udp_external_port)
7347 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7348 self.assertEqual(s.in_port, self.icmp_id_in)
7349 self.assertEqual(s.out_port, self.icmp_external_id)
7351 def test_multiple_users(self):
7352 """ Deterministic NAT multiple users """
7354 nat_ip = "10.0.0.10"
7356 external_port = 6303
7358 host0 = self.pg0.remote_hosts[0]
7359 host1 = self.pg0.remote_hosts[1]
7361 self.vapi.nat_det_add_del_map(is_add=1, in_addr=host0.ip4, in_plen=24,
7362 out_addr=socket.inet_aton(nat_ip),
7364 flags = self.config_flags.NAT_IS_INSIDE
7365 self.vapi.nat44_interface_add_del_feature(
7366 sw_if_index=self.pg0.sw_if_index,
7367 flags=flags, is_add=1)
7368 self.vapi.nat44_interface_add_del_feature(
7369 sw_if_index=self.pg1.sw_if_index,
7373 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
7374 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
7375 TCP(sport=port_in, dport=external_port))
7376 self.pg0.add_stream(p)
7377 self.pg_enable_capture(self.pg_interfaces)
7379 capture = self.pg1.get_capture(1)
7384 self.assertEqual(ip.src, nat_ip)
7385 self.assertEqual(ip.dst, self.pg1.remote_ip4)
7386 self.assertEqual(tcp.dport, external_port)
7387 port_out0 = tcp.sport
7389 self.logger.error(ppp("Unexpected or invalid packet:", p))
7393 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
7394 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
7395 TCP(sport=port_in, dport=external_port))
7396 self.pg0.add_stream(p)
7397 self.pg_enable_capture(self.pg_interfaces)
7399 capture = self.pg1.get_capture(1)
7404 self.assertEqual(ip.src, nat_ip)
7405 self.assertEqual(ip.dst, self.pg1.remote_ip4)
7406 self.assertEqual(tcp.dport, external_port)
7407 port_out1 = tcp.sport
7409 self.logger.error(ppp("Unexpected or invalid packet:", p))
7412 dms = self.vapi.nat_det_map_dump()
7413 self.assertEqual(1, len(dms))
7414 self.assertEqual(2, dms[0].ses_num)
7417 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7418 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
7419 TCP(sport=external_port, dport=port_out0))
7420 self.pg1.add_stream(p)
7421 self.pg_enable_capture(self.pg_interfaces)
7423 capture = self.pg0.get_capture(1)
7428 self.assertEqual(ip.src, self.pg1.remote_ip4)
7429 self.assertEqual(ip.dst, host0.ip4)
7430 self.assertEqual(tcp.dport, port_in)
7431 self.assertEqual(tcp.sport, external_port)
7433 self.logger.error(ppp("Unexpected or invalid packet:", p))
7437 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7438 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
7439 TCP(sport=external_port, dport=port_out1))
7440 self.pg1.add_stream(p)
7441 self.pg_enable_capture(self.pg_interfaces)
7443 capture = self.pg0.get_capture(1)
7448 self.assertEqual(ip.src, self.pg1.remote_ip4)
7449 self.assertEqual(ip.dst, host1.ip4)
7450 self.assertEqual(tcp.dport, port_in)
7451 self.assertEqual(tcp.sport, external_port)
7453 self.logger.error(ppp("Unexpected or invalid packet", p))
7456 # session close api test
7457 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
7459 self.pg1.remote_ip4,
7461 dms = self.vapi.nat_det_map_dump()
7462 self.assertEqual(dms[0].ses_num, 1)
7464 self.vapi.nat_det_close_session_in(host0.ip4,
7466 self.pg1.remote_ip4,
7468 dms = self.vapi.nat_det_map_dump()
7469 self.assertEqual(dms[0].ses_num, 0)
7471 def test_tcp_session_close_detection_in(self):
7472 """ Deterministic NAT TCP session close from inside network """
7473 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7475 out_addr=socket.inet_aton(self.nat_addr),
7477 flags = self.config_flags.NAT_IS_INSIDE
7478 self.vapi.nat44_interface_add_del_feature(
7479 sw_if_index=self.pg0.sw_if_index,
7480 flags=flags, is_add=1)
7481 self.vapi.nat44_interface_add_del_feature(
7482 sw_if_index=self.pg1.sw_if_index,
7485 self.initiate_tcp_session(self.pg0, self.pg1)
7487 # close the session from inside
7489 # FIN packet in -> out
7490 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7491 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7492 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7494 self.pg0.add_stream(p)
7495 self.pg_enable_capture(self.pg_interfaces)
7497 self.pg1.get_capture(1)
7501 # ACK packet out -> in
7502 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7503 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7504 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7508 # FIN packet out -> in
7509 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7510 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7511 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7515 self.pg1.add_stream(pkts)
7516 self.pg_enable_capture(self.pg_interfaces)
7518 self.pg0.get_capture(2)
7520 # ACK packet in -> out
7521 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7522 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7523 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7525 self.pg0.add_stream(p)
7526 self.pg_enable_capture(self.pg_interfaces)
7528 self.pg1.get_capture(1)
7530 # Check if deterministic NAT44 closed the session
7531 dms = self.vapi.nat_det_map_dump()
7532 self.assertEqual(0, dms[0].ses_num)
7534 self.logger.error("TCP session termination failed")
7537 def test_tcp_session_close_detection_out(self):
7538 """ Deterministic NAT TCP session close from outside network """
7539 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7541 out_addr=socket.inet_aton(self.nat_addr),
7543 flags = self.config_flags.NAT_IS_INSIDE
7544 self.vapi.nat44_interface_add_del_feature(
7545 sw_if_index=self.pg0.sw_if_index,
7546 flags=flags, is_add=1)
7547 self.vapi.nat44_interface_add_del_feature(
7548 sw_if_index=self.pg1.sw_if_index,
7551 self.initiate_tcp_session(self.pg0, self.pg1)
7553 # close the session from outside
7555 # FIN packet out -> in
7556 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7557 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7558 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7560 self.pg1.add_stream(p)
7561 self.pg_enable_capture(self.pg_interfaces)
7563 self.pg0.get_capture(1)
7567 # ACK packet in -> out
7568 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7569 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7570 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7574 # ACK packet in -> out
7575 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7576 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7577 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7581 self.pg0.add_stream(pkts)
7582 self.pg_enable_capture(self.pg_interfaces)
7584 self.pg1.get_capture(2)
7586 # ACK packet out -> in
7587 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7588 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7589 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7591 self.pg1.add_stream(p)
7592 self.pg_enable_capture(self.pg_interfaces)
7594 self.pg0.get_capture(1)
7596 # Check if deterministic NAT44 closed the session
7597 dms = self.vapi.nat_det_map_dump()
7598 self.assertEqual(0, dms[0].ses_num)
7600 self.logger.error("TCP session termination failed")
7603 @unittest.skipUnless(running_extended_tests, "part of extended tests")
7604 def test_session_timeout(self):
7605 """ Deterministic NAT session timeouts """
7606 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7608 out_addr=socket.inet_aton(self.nat_addr),
7610 flags = self.config_flags.NAT_IS_INSIDE
7611 self.vapi.nat44_interface_add_del_feature(
7612 sw_if_index=self.pg0.sw_if_index,
7613 flags=flags, is_add=1)
7614 self.vapi.nat44_interface_add_del_feature(
7615 sw_if_index=self.pg1.sw_if_index,
7618 self.initiate_tcp_session(self.pg0, self.pg1)
7619 self.vapi.nat_set_timeouts(udp=5, tcp_established=5, tcp_transitory=5,
7621 pkts = self.create_stream_in(self.pg0, self.pg1)
7622 self.pg0.add_stream(pkts)
7623 self.pg_enable_capture(self.pg_interfaces)
7625 capture = self.pg1.get_capture(len(pkts))
7628 dms = self.vapi.nat_det_map_dump()
7629 self.assertEqual(0, dms[0].ses_num)
7631 @unittest.skipUnless(running_extended_tests, "part of extended tests")
7632 def test_session_limit_per_user(self):
7633 """ Deterministic NAT maximum sessions per user limit """
7634 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7636 out_addr=socket.inet_aton(self.nat_addr),
7638 flags = self.config_flags.NAT_IS_INSIDE
7639 self.vapi.nat44_interface_add_del_feature(
7640 sw_if_index=self.pg0.sw_if_index,
7641 flags=flags, is_add=1)
7642 self.vapi.nat44_interface_add_del_feature(
7643 sw_if_index=self.pg1.sw_if_index,
7645 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4,
7646 src_address=self.pg2.local_ip4,
7648 template_interval=10)
7649 self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7653 for port in range(1025, 2025):
7654 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7655 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7656 UDP(sport=port, dport=port))
7659 self.pg0.add_stream(pkts)
7660 self.pg_enable_capture(self.pg_interfaces)
7662 capture = self.pg1.get_capture(len(pkts))
7664 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7665 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7666 UDP(sport=3001, dport=3002))
7667 self.pg0.add_stream(p)
7668 self.pg_enable_capture(self.pg_interfaces)
7670 capture = self.pg1.assert_nothing_captured()
7672 # verify ICMP error packet
7673 capture = self.pg0.get_capture(1)
7675 self.assertTrue(p.haslayer(ICMP))
7677 self.assertEqual(icmp.type, 3)
7678 self.assertEqual(icmp.code, 1)
7679 self.assertTrue(icmp.haslayer(IPerror))
7680 inner_ip = icmp[IPerror]
7681 self.assertEqual(inner_ip[UDPerror].sport, 3001)
7682 self.assertEqual(inner_ip[UDPerror].dport, 3002)
7684 dms = self.vapi.nat_det_map_dump()
7686 self.assertEqual(1000, dms[0].ses_num)
7688 # verify IPFIX logging
7689 self.vapi.ipfix_flush()
7691 capture = self.pg2.get_capture(2)
7692 ipfix = IPFIXDecoder()
7693 # first load template
7695 self.assertTrue(p.haslayer(IPFIX))
7696 if p.haslayer(Template):
7697 ipfix.add_template(p.getlayer(Template))
7698 # verify events in data set
7700 if p.haslayer(Data):
7701 data = ipfix.decode_data_set(p.getlayer(Set))
7702 self.verify_ipfix_max_entries_per_user(data,
7704 self.pg0.remote_ip4)
7706 def clear_nat_det(self):
7708 Clear deterministic NAT configuration.
7710 self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7712 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
7713 tcp_transitory=240, icmp=60)
7714 deterministic_mappings = self.vapi.nat_det_map_dump()
7715 for dsm in deterministic_mappings:
7716 self.vapi.nat_det_add_del_map(is_add=0, in_addr=dsm.in_addr,
7717 in_plen=dsm.in_plen,
7718 out_addr=dsm.out_addr,
7719 out_plen=dsm.out_plen)
7721 interfaces = self.vapi.nat44_interface_dump()
7722 for intf in interfaces:
7723 self.vapi.nat44_interface_add_del_feature(
7724 sw_if_index=intf.sw_if_index,
7728 super(TestDeterministicNAT, self).tearDown()
7729 if not self.vpp_dead:
7730 self.clear_nat_det()
7732 def show_commands_at_teardown(self):
7733 self.logger.info(self.vapi.cli("show nat44 interfaces"))
7734 self.logger.info(self.vapi.cli("show nat timeouts"))
7736 self.vapi.cli("show nat44 deterministic mappings"))
7738 self.vapi.cli("show nat44 deterministic sessions"))
7741 class TestNAT64(MethodHolder):
7742 """ NAT64 Test Cases """
7745 def setUpConstants(cls):
7746 super(TestNAT64, cls).setUpConstants()
7747 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
7748 "nat64 st hash buckets 256", "}"])
7751 def setUpClass(cls):
7752 super(TestNAT64, cls).setUpClass()
7754 cls.tcp_port_in = 6303
7755 cls.tcp_port_out = 6303
7756 cls.udp_port_in = 6304
7757 cls.udp_port_out = 6304
7758 cls.icmp_id_in = 6305
7759 cls.icmp_id_out = 6305
7760 cls.tcp_external_port = 80
7761 cls.nat_addr = '10.0.0.3'
7762 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
7764 cls.vrf1_nat_addr = '10.0.10.3'
7765 cls.ipfix_src_port = 4739
7766 cls.ipfix_domain_id = 1
7768 cls.create_pg_interfaces(range(6))
7769 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
7770 cls.ip6_interfaces.append(cls.pg_interfaces[2])
7771 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
7773 cls.vapi.ip_table_add_del(is_add=1,
7774 table={'table_id': cls.vrf1_id,
7777 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
7779 cls.pg0.generate_remote_hosts(2)
7781 for i in cls.ip6_interfaces:
7784 i.configure_ipv6_neighbors()
7786 for i in cls.ip4_interfaces:
7792 cls.pg3.config_ip4()
7793 cls.pg3.resolve_arp()
7794 cls.pg3.config_ip6()
7795 cls.pg3.configure_ipv6_neighbors()
7798 cls.pg5.config_ip6()
7801 def tearDownClass(cls):
7802 super(TestNAT64, cls).tearDownClass()
7804 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
7805 """ NAT64 inside interface handles Neighbor Advertisement """
7807 flags = self.config_flags.NAT_IS_INSIDE
7808 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7809 sw_if_index=self.pg5.sw_if_index)
7812 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7813 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7814 ICMPv6EchoRequest())
7816 self.pg5.add_stream(pkts)
7817 self.pg_enable_capture(self.pg_interfaces)
7820 # Wait for Neighbor Solicitation
7821 capture = self.pg5.get_capture(len(pkts))
7824 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7825 self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
7826 tgt = packet[ICMPv6ND_NS].tgt
7828 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7831 # Send Neighbor Advertisement
7832 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7833 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7834 ICMPv6ND_NA(tgt=tgt) /
7835 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
7837 self.pg5.add_stream(pkts)
7838 self.pg_enable_capture(self.pg_interfaces)
7841 # Try to send ping again
7843 self.pg5.add_stream(pkts)
7844 self.pg_enable_capture(self.pg_interfaces)
7847 # Wait for ping reply
7848 capture = self.pg5.get_capture(len(pkts))
7851 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7852 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
7853 self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
7855 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7858 def test_pool(self):
7859 """ Add/delete address to NAT64 pool """
7860 nat_addr = '1.2.3.4'
7862 self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7864 vrf_id=0xFFFFFFFF, is_add=1)
7866 addresses = self.vapi.nat64_pool_addr_dump()
7867 self.assertEqual(len(addresses), 1)
7868 self.assertEqual(str(addresses[0].address), nat_addr)
7870 self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7872 vrf_id=0xFFFFFFFF, is_add=0)
7874 addresses = self.vapi.nat64_pool_addr_dump()
7875 self.assertEqual(len(addresses), 0)
7877 def test_interface(self):
7878 """ Enable/disable NAT64 feature on the interface """
7879 flags = self.config_flags.NAT_IS_INSIDE
7880 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7881 sw_if_index=self.pg0.sw_if_index)
7882 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7883 sw_if_index=self.pg1.sw_if_index)
7885 interfaces = self.vapi.nat64_interface_dump()
7886 self.assertEqual(len(interfaces), 2)
7889 for intf in interfaces:
7890 if intf.sw_if_index == self.pg0.sw_if_index:
7891 self.assertEqual(intf.flags, self.config_flags.NAT_IS_INSIDE)
7893 elif intf.sw_if_index == self.pg1.sw_if_index:
7894 self.assertEqual(intf.flags, self.config_flags.NAT_IS_OUTSIDE)
7896 self.assertTrue(pg0_found)
7897 self.assertTrue(pg1_found)
7899 features = self.vapi.cli("show interface features pg0")
7900 self.assertIn('nat64-in2out', features)
7901 features = self.vapi.cli("show interface features pg1")
7902 self.assertIn('nat64-out2in', features)
7904 self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7905 sw_if_index=self.pg0.sw_if_index)
7906 self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7907 sw_if_index=self.pg1.sw_if_index)
7909 interfaces = self.vapi.nat64_interface_dump()
7910 self.assertEqual(len(interfaces), 0)
7912 def test_static_bib(self):
7913 """ Add/delete static BIB entry """
7914 in_addr = '2001:db8:85a3::8a2e:370:7334'
7915 out_addr = '10.1.1.3'
7918 proto = IP_PROTOS.tcp
7920 self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7921 i_port=in_port, o_port=out_port,
7922 proto=proto, vrf_id=0, is_add=1)
7923 bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
7926 if bibe.flags & self.config_flags.NAT_IS_STATIC:
7928 self.assertEqual(str(bibe.i_addr), in_addr)
7929 self.assertEqual(str(bibe.o_addr), out_addr)
7930 self.assertEqual(bibe.i_port, in_port)
7931 self.assertEqual(bibe.o_port, out_port)
7932 self.assertEqual(static_bib_num, 1)
7933 bibs = self.statistics.get_counter('/nat64/total-bibs')
7934 self.assertEqual(bibs[0][0], 1)
7936 self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7937 i_port=in_port, o_port=out_port,
7938 proto=proto, vrf_id=0, is_add=0)
7939 bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
7942 if bibe.flags & self.config_flags.NAT_IS_STATIC:
7944 self.assertEqual(static_bib_num, 0)
7945 bibs = self.statistics.get_counter('/nat64/total-bibs')
7946 self.assertEqual(bibs[0][0], 0)
7948 def test_set_timeouts(self):
7949 """ Set NAT64 timeouts """
7950 # verify default values
7951 timeouts = self.vapi.nat_get_timeouts()
7952 self.assertEqual(timeouts.udp, 300)
7953 self.assertEqual(timeouts.icmp, 60)
7954 self.assertEqual(timeouts.tcp_transitory, 240)
7955 self.assertEqual(timeouts.tcp_established, 7440)
7957 # set and verify custom values
7958 self.vapi.nat_set_timeouts(udp=200, tcp_established=7450,
7959 tcp_transitory=250, icmp=30)
7960 timeouts = self.vapi.nat_get_timeouts()
7961 self.assertEqual(timeouts.udp, 200)
7962 self.assertEqual(timeouts.icmp, 30)
7963 self.assertEqual(timeouts.tcp_transitory, 250)
7964 self.assertEqual(timeouts.tcp_established, 7450)
7966 def test_dynamic(self):
7967 """ NAT64 dynamic translation test """
7968 self.tcp_port_in = 6303
7969 self.udp_port_in = 6304
7970 self.icmp_id_in = 6305
7972 ses_num_start = self.nat64_get_ses_num()
7974 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
7975 end_addr=self.nat_addr,
7978 flags = self.config_flags.NAT_IS_INSIDE
7979 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7980 sw_if_index=self.pg0.sw_if_index)
7981 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7982 sw_if_index=self.pg1.sw_if_index)
7985 tcpn = self.statistics.get_err_counter('/err/nat64-in2out/TCP packets')
7986 udpn = self.statistics.get_err_counter('/err/nat64-in2out/UDP packets')
7987 icmpn = self.statistics.get_err_counter(
7988 '/err/nat64-in2out/ICMP packets')
7989 totaln = self.statistics.get_err_counter(
7990 '/err/nat64-in2out/good in2out packets processed')
7992 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7993 self.pg0.add_stream(pkts)
7994 self.pg_enable_capture(self.pg_interfaces)
7996 capture = self.pg1.get_capture(len(pkts))
7997 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7998 dst_ip=self.pg1.remote_ip4)
8000 err = self.statistics.get_err_counter('/err/nat64-in2out/TCP packets')
8001 self.assertEqual(err - tcpn, 1)
8002 err = self.statistics.get_err_counter('/err/nat64-in2out/UDP packets')
8003 self.assertEqual(err - udpn, 1)
8004 err = self.statistics.get_err_counter('/err/nat64-in2out/ICMP packets')
8005 self.assertEqual(err - icmpn, 1)
8006 err = self.statistics.get_err_counter(
8007 '/err/nat64-in2out/good in2out packets processed')
8008 self.assertEqual(err - totaln, 3)
8011 tcpn = self.statistics.get_err_counter('/err/nat64-out2in/TCP packets')
8012 udpn = self.statistics.get_err_counter('/err/nat64-out2in/UDP packets')
8013 icmpn = self.statistics.get_err_counter(
8014 '/err/nat64-out2in/ICMP packets')
8015 totaln = self.statistics.get_err_counter(
8016 '/err/nat64-out2in/good out2in packets processed')
8018 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8019 self.pg1.add_stream(pkts)
8020 self.pg_enable_capture(self.pg_interfaces)
8022 capture = self.pg0.get_capture(len(pkts))
8023 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8024 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8026 err = self.statistics.get_err_counter('/err/nat64-out2in/TCP packets')
8027 self.assertEqual(err - tcpn, 2)
8028 err = self.statistics.get_err_counter('/err/nat64-out2in/UDP packets')
8029 self.assertEqual(err - udpn, 1)
8030 err = self.statistics.get_err_counter('/err/nat64-out2in/ICMP packets')
8031 self.assertEqual(err - icmpn, 1)
8032 err = self.statistics.get_err_counter(
8033 '/err/nat64-out2in/good out2in packets processed')
8034 self.assertEqual(err - totaln, 4)
8036 bibs = self.statistics.get_counter('/nat64/total-bibs')
8037 self.assertEqual(bibs[0][0], 3)
8038 sessions = self.statistics.get_counter('/nat64/total-sessions')
8039 self.assertEqual(sessions[0][0], 3)
8042 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8043 self.pg0.add_stream(pkts)
8044 self.pg_enable_capture(self.pg_interfaces)
8046 capture = self.pg1.get_capture(len(pkts))
8047 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8048 dst_ip=self.pg1.remote_ip4)
8051 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8052 self.pg1.add_stream(pkts)
8053 self.pg_enable_capture(self.pg_interfaces)
8055 capture = self.pg0.get_capture(len(pkts))
8056 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8058 ses_num_end = self.nat64_get_ses_num()
8060 self.assertEqual(ses_num_end - ses_num_start, 3)
8062 # tenant with specific VRF
8063 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
8064 end_addr=self.vrf1_nat_addr,
8065 vrf_id=self.vrf1_id, is_add=1)
8066 flags = self.config_flags.NAT_IS_INSIDE
8067 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8068 sw_if_index=self.pg2.sw_if_index)
8070 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
8071 self.pg2.add_stream(pkts)
8072 self.pg_enable_capture(self.pg_interfaces)
8074 capture = self.pg1.get_capture(len(pkts))
8075 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
8076 dst_ip=self.pg1.remote_ip4)
8078 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
8079 self.pg1.add_stream(pkts)
8080 self.pg_enable_capture(self.pg_interfaces)
8082 capture = self.pg2.get_capture(len(pkts))
8083 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
8085 def test_static(self):
8086 """ NAT64 static translation test """
8087 self.tcp_port_in = 60303
8088 self.udp_port_in = 60304
8089 self.icmp_id_in = 60305
8090 self.tcp_port_out = 60303
8091 self.udp_port_out = 60304
8092 self.icmp_id_out = 60305
8094 ses_num_start = self.nat64_get_ses_num()
8096 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8097 end_addr=self.nat_addr,
8100 flags = self.config_flags.NAT_IS_INSIDE
8101 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8102 sw_if_index=self.pg0.sw_if_index)
8103 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8104 sw_if_index=self.pg1.sw_if_index)
8106 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6,
8107 o_addr=self.nat_addr,
8108 i_port=self.tcp_port_in,
8109 o_port=self.tcp_port_out,
8110 proto=IP_PROTOS.tcp, vrf_id=0,
8112 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6,
8113 o_addr=self.nat_addr,
8114 i_port=self.udp_port_in,
8115 o_port=self.udp_port_out,
8116 proto=IP_PROTOS.udp, vrf_id=0,
8118 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6,
8119 o_addr=self.nat_addr,
8120 i_port=self.icmp_id_in,
8121 o_port=self.icmp_id_out,
8122 proto=IP_PROTOS.icmp, vrf_id=0,
8126 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8127 self.pg0.add_stream(pkts)
8128 self.pg_enable_capture(self.pg_interfaces)
8130 capture = self.pg1.get_capture(len(pkts))
8131 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8132 dst_ip=self.pg1.remote_ip4, same_port=True)
8135 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8136 self.pg1.add_stream(pkts)
8137 self.pg_enable_capture(self.pg_interfaces)
8139 capture = self.pg0.get_capture(len(pkts))
8140 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8141 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8143 ses_num_end = self.nat64_get_ses_num()
8145 self.assertEqual(ses_num_end - ses_num_start, 3)
8147 @unittest.skipUnless(running_extended_tests, "part of extended tests")
8148 def test_session_timeout(self):
8149 """ NAT64 session timeout """
8150 self.icmp_id_in = 1234
8151 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8152 end_addr=self.nat_addr,
8155 flags = self.config_flags.NAT_IS_INSIDE
8156 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8157 sw_if_index=self.pg0.sw_if_index)
8158 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8159 sw_if_index=self.pg1.sw_if_index)
8160 self.vapi.nat_set_timeouts(udp=300, tcp_established=5,
8164 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8165 self.pg0.add_stream(pkts)
8166 self.pg_enable_capture(self.pg_interfaces)
8168 capture = self.pg1.get_capture(len(pkts))
8170 ses_num_before_timeout = self.nat64_get_ses_num()
8174 # ICMP and TCP session after timeout
8175 ses_num_after_timeout = self.nat64_get_ses_num()
8176 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
8178 def test_icmp_error(self):
8179 """ NAT64 ICMP Error message translation """
8180 self.tcp_port_in = 6303
8181 self.udp_port_in = 6304
8182 self.icmp_id_in = 6305
8184 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8185 end_addr=self.nat_addr,
8188 flags = self.config_flags.NAT_IS_INSIDE
8189 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8190 sw_if_index=self.pg0.sw_if_index)
8191 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8192 sw_if_index=self.pg1.sw_if_index)
8194 # send some packets to create sessions
8195 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8196 self.pg0.add_stream(pkts)
8197 self.pg_enable_capture(self.pg_interfaces)
8199 capture_ip4 = self.pg1.get_capture(len(pkts))
8200 self.verify_capture_out(capture_ip4,
8201 nat_ip=self.nat_addr,
8202 dst_ip=self.pg1.remote_ip4)
8204 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8205 self.pg1.add_stream(pkts)
8206 self.pg_enable_capture(self.pg_interfaces)
8208 capture_ip6 = self.pg0.get_capture(len(pkts))
8209 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8210 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
8211 self.pg0.remote_ip6)
8214 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8215 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
8216 ICMPv6DestUnreach(code=1) /
8217 packet[IPv6] for packet in capture_ip6]
8218 self.pg0.add_stream(pkts)
8219 self.pg_enable_capture(self.pg_interfaces)
8221 capture = self.pg1.get_capture(len(pkts))
8222 for packet in capture:
8224 self.assertEqual(packet[IP].src, self.nat_addr)
8225 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
8226 self.assertEqual(packet[ICMP].type, 3)
8227 self.assertEqual(packet[ICMP].code, 13)
8228 inner = packet[IPerror]
8229 self.assertEqual(inner.src, self.pg1.remote_ip4)
8230 self.assertEqual(inner.dst, self.nat_addr)
8231 self.assert_packet_checksums_valid(packet)
8232 if inner.haslayer(TCPerror):
8233 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
8234 elif inner.haslayer(UDPerror):
8235 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
8237 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
8239 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8243 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8244 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8245 ICMP(type=3, code=13) /
8246 packet[IP] for packet in capture_ip4]
8247 self.pg1.add_stream(pkts)
8248 self.pg_enable_capture(self.pg_interfaces)
8250 capture = self.pg0.get_capture(len(pkts))
8251 for packet in capture:
8253 self.assertEqual(packet[IPv6].src, ip.src)
8254 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8255 icmp = packet[ICMPv6DestUnreach]
8256 self.assertEqual(icmp.code, 1)
8257 inner = icmp[IPerror6]
8258 self.assertEqual(inner.src, self.pg0.remote_ip6)
8259 self.assertEqual(inner.dst, ip.src)
8260 self.assert_icmpv6_checksum_valid(packet)
8261 if inner.haslayer(TCPerror):
8262 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
8263 elif inner.haslayer(UDPerror):
8264 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
8266 self.assertEqual(inner[ICMPv6EchoRequest].id,
8269 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8272 def test_hairpinning(self):
8273 """ NAT64 hairpinning """
8275 client = self.pg0.remote_hosts[0]
8276 server = self.pg0.remote_hosts[1]
8277 server_tcp_in_port = 22
8278 server_tcp_out_port = 4022
8279 server_udp_in_port = 23
8280 server_udp_out_port = 4023
8281 client_tcp_in_port = 1234
8282 client_udp_in_port = 1235
8283 client_tcp_out_port = 0
8284 client_udp_out_port = 0
8285 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8286 nat_addr_ip6 = ip.src
8288 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8289 end_addr=self.nat_addr,
8292 flags = self.config_flags.NAT_IS_INSIDE
8293 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8294 sw_if_index=self.pg0.sw_if_index)
8295 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8296 sw_if_index=self.pg1.sw_if_index)
8298 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8299 o_addr=self.nat_addr,
8300 i_port=server_tcp_in_port,
8301 o_port=server_tcp_out_port,
8302 proto=IP_PROTOS.tcp, vrf_id=0,
8304 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8305 o_addr=self.nat_addr,
8306 i_port=server_udp_in_port,
8307 o_port=server_udp_out_port,
8308 proto=IP_PROTOS.udp, vrf_id=0,
8313 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8314 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8315 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8317 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8318 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8319 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
8321 self.pg0.add_stream(pkts)
8322 self.pg_enable_capture(self.pg_interfaces)
8324 capture = self.pg0.get_capture(len(pkts))
8325 for packet in capture:
8327 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8328 self.assertEqual(packet[IPv6].dst, server.ip6)
8329 self.assert_packet_checksums_valid(packet)
8330 if packet.haslayer(TCP):
8331 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
8332 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
8333 client_tcp_out_port = packet[TCP].sport
8335 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
8336 self.assertEqual(packet[UDP].dport, server_udp_in_port)
8337 client_udp_out_port = packet[UDP].sport
8339 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8344 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8345 IPv6(src=server.ip6, dst=nat_addr_ip6) /
8346 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
8348 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8349 IPv6(src=server.ip6, dst=nat_addr_ip6) /
8350 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
8352 self.pg0.add_stream(pkts)
8353 self.pg_enable_capture(self.pg_interfaces)
8355 capture = self.pg0.get_capture(len(pkts))
8356 for packet in capture:
8358 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8359 self.assertEqual(packet[IPv6].dst, client.ip6)
8360 self.assert_packet_checksums_valid(packet)
8361 if packet.haslayer(TCP):
8362 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
8363 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
8365 self.assertEqual(packet[UDP].sport, server_udp_out_port)
8366 self.assertEqual(packet[UDP].dport, client_udp_in_port)
8368 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8373 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8374 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8375 ICMPv6DestUnreach(code=1) /
8376 packet[IPv6] for packet in capture]
8377 self.pg0.add_stream(pkts)
8378 self.pg_enable_capture(self.pg_interfaces)
8380 capture = self.pg0.get_capture(len(pkts))
8381 for packet in capture:
8383 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8384 self.assertEqual(packet[IPv6].dst, server.ip6)
8385 icmp = packet[ICMPv6DestUnreach]
8386 self.assertEqual(icmp.code, 1)
8387 inner = icmp[IPerror6]
8388 self.assertEqual(inner.src, server.ip6)
8389 self.assertEqual(inner.dst, nat_addr_ip6)
8390 self.assert_packet_checksums_valid(packet)
8391 if inner.haslayer(TCPerror):
8392 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
8393 self.assertEqual(inner[TCPerror].dport,
8394 client_tcp_out_port)
8396 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
8397 self.assertEqual(inner[UDPerror].dport,
8398 client_udp_out_port)
8400 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8403 def test_prefix(self):
8404 """ NAT64 Network-Specific Prefix """
8406 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8407 end_addr=self.nat_addr,
8410 flags = self.config_flags.NAT_IS_INSIDE
8411 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8412 sw_if_index=self.pg0.sw_if_index)
8413 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8414 sw_if_index=self.pg1.sw_if_index)
8415 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
8416 end_addr=self.vrf1_nat_addr,
8417 vrf_id=self.vrf1_id, is_add=1)
8418 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8419 sw_if_index=self.pg2.sw_if_index)
8422 global_pref64 = "2001:db8::"
8423 global_pref64_len = 32
8424 global_pref64_str = "{}/{}".format(global_pref64, global_pref64_len)
8425 self.vapi.nat64_add_del_prefix(prefix=global_pref64_str, vrf_id=0,
8428 prefix = self.vapi.nat64_prefix_dump()
8429 self.assertEqual(len(prefix), 1)
8430 self.assertEqual(str(prefix[0].prefix), global_pref64_str)
8431 self.assertEqual(prefix[0].vrf_id, 0)
8433 # Add tenant specific prefix
8434 vrf1_pref64 = "2001:db8:122:300::"
8435 vrf1_pref64_len = 56
8436 vrf1_pref64_str = "{}/{}".format(vrf1_pref64, vrf1_pref64_len)
8437 self.vapi.nat64_add_del_prefix(prefix=vrf1_pref64_str,
8438 vrf_id=self.vrf1_id, is_add=1)
8440 prefix = self.vapi.nat64_prefix_dump()
8441 self.assertEqual(len(prefix), 2)
8444 pkts = self.create_stream_in_ip6(self.pg0,
8447 plen=global_pref64_len)
8448 self.pg0.add_stream(pkts)
8449 self.pg_enable_capture(self.pg_interfaces)
8451 capture = self.pg1.get_capture(len(pkts))
8452 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8453 dst_ip=self.pg1.remote_ip4)
8455 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8456 self.pg1.add_stream(pkts)
8457 self.pg_enable_capture(self.pg_interfaces)
8459 capture = self.pg0.get_capture(len(pkts))
8460 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8463 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
8465 # Tenant specific prefix
8466 pkts = self.create_stream_in_ip6(self.pg2,
8469 plen=vrf1_pref64_len)
8470 self.pg2.add_stream(pkts)
8471 self.pg_enable_capture(self.pg_interfaces)
8473 capture = self.pg1.get_capture(len(pkts))
8474 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
8475 dst_ip=self.pg1.remote_ip4)
8477 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
8478 self.pg1.add_stream(pkts)
8479 self.pg_enable_capture(self.pg_interfaces)
8481 capture = self.pg2.get_capture(len(pkts))
8482 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8485 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
8487 def test_unknown_proto(self):
8488 """ NAT64 translate packet with unknown protocol """
8490 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8491 end_addr=self.nat_addr,
8494 flags = self.config_flags.NAT_IS_INSIDE
8495 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8496 sw_if_index=self.pg0.sw_if_index)
8497 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8498 sw_if_index=self.pg1.sw_if_index)
8499 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8502 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8503 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
8504 TCP(sport=self.tcp_port_in, dport=20))
8505 self.pg0.add_stream(p)
8506 self.pg_enable_capture(self.pg_interfaces)
8508 p = self.pg1.get_capture(1)
8510 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8511 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
8513 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8514 TCP(sport=1234, dport=1234))
8515 self.pg0.add_stream(p)
8516 self.pg_enable_capture(self.pg_interfaces)
8518 p = self.pg1.get_capture(1)
8521 self.assertEqual(packet[IP].src, self.nat_addr)
8522 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
8523 self.assertEqual(packet.haslayer(GRE), 1)
8524 self.assert_packet_checksums_valid(packet)
8526 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8530 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8531 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8533 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8534 TCP(sport=1234, dport=1234))
8535 self.pg1.add_stream(p)
8536 self.pg_enable_capture(self.pg_interfaces)
8538 p = self.pg0.get_capture(1)
8541 self.assertEqual(packet[IPv6].src, remote_ip6)
8542 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8543 self.assertEqual(packet[IPv6].nh, 47)
8545 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8548 def test_hairpinning_unknown_proto(self):
8549 """ NAT64 translate packet with unknown protocol - hairpinning """
8551 client = self.pg0.remote_hosts[0]
8552 server = self.pg0.remote_hosts[1]
8553 server_tcp_in_port = 22
8554 server_tcp_out_port = 4022
8555 client_tcp_in_port = 1234
8556 client_tcp_out_port = 1235
8557 server_nat_ip = "10.0.0.100"
8558 client_nat_ip = "10.0.0.110"
8559 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
8560 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
8562 self.vapi.nat64_add_del_pool_addr_range(start_addr=server_nat_ip,
8563 end_addr=client_nat_ip,
8566 flags = self.config_flags.NAT_IS_INSIDE
8567 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8568 sw_if_index=self.pg0.sw_if_index)
8569 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8570 sw_if_index=self.pg1.sw_if_index)
8572 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8573 o_addr=server_nat_ip,
8574 i_port=server_tcp_in_port,
8575 o_port=server_tcp_out_port,
8576 proto=IP_PROTOS.tcp, vrf_id=0,
8579 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8580 o_addr=server_nat_ip, i_port=0,
8582 proto=IP_PROTOS.gre, vrf_id=0,
8585 self.vapi.nat64_add_del_static_bib(i_addr=client.ip6n,
8586 o_addr=client_nat_ip,
8587 i_port=client_tcp_in_port,
8588 o_port=client_tcp_out_port,
8589 proto=IP_PROTOS.tcp, vrf_id=0,
8593 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8594 IPv6(src=client.ip6, dst=server_nat_ip6) /
8595 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8596 self.pg0.add_stream(p)
8597 self.pg_enable_capture(self.pg_interfaces)
8599 p = self.pg0.get_capture(1)
8601 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8602 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
8604 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8605 TCP(sport=1234, dport=1234))
8606 self.pg0.add_stream(p)
8607 self.pg_enable_capture(self.pg_interfaces)
8609 p = self.pg0.get_capture(1)
8612 self.assertEqual(packet[IPv6].src, client_nat_ip6)
8613 self.assertEqual(packet[IPv6].dst, server.ip6)
8614 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
8616 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8620 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8621 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
8623 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8624 TCP(sport=1234, dport=1234))
8625 self.pg0.add_stream(p)
8626 self.pg_enable_capture(self.pg_interfaces)
8628 p = self.pg0.get_capture(1)
8631 self.assertEqual(packet[IPv6].src, server_nat_ip6)
8632 self.assertEqual(packet[IPv6].dst, client.ip6)
8633 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
8635 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8638 def test_one_armed_nat64(self):
8639 """ One armed NAT64 """
8641 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
8645 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8646 end_addr=self.nat_addr,
8649 flags = self.config_flags.NAT_IS_INSIDE
8650 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8651 sw_if_index=self.pg3.sw_if_index)
8652 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8653 sw_if_index=self.pg3.sw_if_index)
8656 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8657 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
8658 TCP(sport=12345, dport=80))
8659 self.pg3.add_stream(p)
8660 self.pg_enable_capture(self.pg_interfaces)
8662 capture = self.pg3.get_capture(1)
8667 self.assertEqual(ip.src, self.nat_addr)
8668 self.assertEqual(ip.dst, self.pg3.remote_ip4)
8669 self.assertNotEqual(tcp.sport, 12345)
8670 external_port = tcp.sport
8671 self.assertEqual(tcp.dport, 80)
8672 self.assert_packet_checksums_valid(p)
8674 self.logger.error(ppp("Unexpected or invalid packet:", p))
8678 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8679 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
8680 TCP(sport=80, dport=external_port))
8681 self.pg3.add_stream(p)
8682 self.pg_enable_capture(self.pg_interfaces)
8684 capture = self.pg3.get_capture(1)
8689 self.assertEqual(ip.src, remote_host_ip6)
8690 self.assertEqual(ip.dst, self.pg3.remote_ip6)
8691 self.assertEqual(tcp.sport, 80)
8692 self.assertEqual(tcp.dport, 12345)
8693 self.assert_packet_checksums_valid(p)
8695 self.logger.error(ppp("Unexpected or invalid packet:", p))
8698 def test_frag_in_order(self):
8699 """ NAT64 translate fragments arriving in order """
8700 self.tcp_port_in = random.randint(1025, 65535)
8702 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8703 end_addr=self.nat_addr,
8706 flags = self.config_flags.NAT_IS_INSIDE
8707 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8708 sw_if_index=self.pg0.sw_if_index)
8709 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8710 sw_if_index=self.pg1.sw_if_index)
8714 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8715 self.tcp_port_in, 20, data)
8716 self.pg0.add_stream(pkts)
8717 self.pg_enable_capture(self.pg_interfaces)
8719 frags = self.pg1.get_capture(len(pkts))
8720 p = self.reass_frags_and_verify(frags,
8722 self.pg1.remote_ip4)
8723 self.assertEqual(p[TCP].dport, 20)
8724 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8725 self.tcp_port_out = p[TCP].sport
8726 self.assertEqual(data, p[Raw].load)
8729 data = b"A" * 4 + b"b" * 16 + b"C" * 3
8730 pkts = self.create_stream_frag(self.pg1,
8735 self.pg1.add_stream(pkts)
8736 self.pg_enable_capture(self.pg_interfaces)
8738 frags = self.pg0.get_capture(len(pkts))
8739 self.logger.debug(ppc("Captured:", frags))
8740 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8741 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8742 self.assertEqual(p[TCP].sport, 20)
8743 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8744 self.assertEqual(data, p[Raw].load)
8746 def test_reass_hairpinning(self):
8747 """ NAT64 fragments hairpinning """
8749 server = self.pg0.remote_hosts[1]
8750 server_in_port = random.randint(1025, 65535)
8751 server_out_port = random.randint(1025, 65535)
8752 client_in_port = random.randint(1025, 65535)
8753 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8754 nat_addr_ip6 = ip.src
8756 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8757 end_addr=self.nat_addr,
8760 flags = self.config_flags.NAT_IS_INSIDE
8761 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8762 sw_if_index=self.pg0.sw_if_index)
8763 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8764 sw_if_index=self.pg1.sw_if_index)
8766 # add static BIB entry for server
8767 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8768 o_addr=self.nat_addr,
8769 i_port=server_in_port,
8770 o_port=server_out_port,
8771 proto=IP_PROTOS.tcp, vrf_id=0,
8774 # send packet from host to server
8775 pkts = self.create_stream_frag_ip6(self.pg0,
8780 self.pg0.add_stream(pkts)
8781 self.pg_enable_capture(self.pg_interfaces)
8783 frags = self.pg0.get_capture(len(pkts))
8784 self.logger.debug(ppc("Captured:", frags))
8785 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
8786 self.assertNotEqual(p[TCP].sport, client_in_port)
8787 self.assertEqual(p[TCP].dport, server_in_port)
8788 self.assertEqual(data, p[Raw].load)
8790 def test_frag_out_of_order(self):
8791 """ NAT64 translate fragments arriving out of order """
8792 self.tcp_port_in = random.randint(1025, 65535)
8794 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8795 end_addr=self.nat_addr,
8798 flags = self.config_flags.NAT_IS_INSIDE
8799 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8800 sw_if_index=self.pg0.sw_if_index)
8801 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8802 sw_if_index=self.pg1.sw_if_index)
8806 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8807 self.tcp_port_in, 20, data)
8809 self.pg0.add_stream(pkts)
8810 self.pg_enable_capture(self.pg_interfaces)
8812 frags = self.pg1.get_capture(len(pkts))
8813 p = self.reass_frags_and_verify(frags,
8815 self.pg1.remote_ip4)
8816 self.assertEqual(p[TCP].dport, 20)
8817 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8818 self.tcp_port_out = p[TCP].sport
8819 self.assertEqual(data, p[Raw].load)
8822 data = b"A" * 4 + b"B" * 16 + b"C" * 3
8823 pkts = self.create_stream_frag(self.pg1,
8829 self.pg1.add_stream(pkts)
8830 self.pg_enable_capture(self.pg_interfaces)
8832 frags = self.pg0.get_capture(len(pkts))
8833 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8834 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8835 self.assertEqual(p[TCP].sport, 20)
8836 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8837 self.assertEqual(data, p[Raw].load)
8839 def test_interface_addr(self):
8840 """ Acquire NAT64 pool addresses from interface """
8841 self.vapi.nat64_add_del_interface_addr(
8843 sw_if_index=self.pg4.sw_if_index)
8845 # no address in NAT64 pool
8846 addresses = self.vapi.nat44_address_dump()
8847 self.assertEqual(0, len(addresses))
8849 # configure interface address and check NAT64 address pool
8850 self.pg4.config_ip4()
8851 addresses = self.vapi.nat64_pool_addr_dump()
8852 self.assertEqual(len(addresses), 1)
8854 self.assertEqual(str(addresses[0].address),
8857 # remove interface address and check NAT64 address pool
8858 self.pg4.unconfig_ip4()
8859 addresses = self.vapi.nat64_pool_addr_dump()
8860 self.assertEqual(0, len(addresses))
8862 @unittest.skipUnless(running_extended_tests, "part of extended tests")
8863 def test_ipfix_max_bibs_sessions(self):
8864 """ IPFIX logging maximum session and BIB entries exceeded """
8867 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8871 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8872 end_addr=self.nat_addr,
8875 flags = self.config_flags.NAT_IS_INSIDE
8876 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8877 sw_if_index=self.pg0.sw_if_index)
8878 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8879 sw_if_index=self.pg1.sw_if_index)
8883 for i in range(0, max_bibs):
8884 src = "fd01:aa::%x" % (i)
8885 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8886 IPv6(src=src, dst=remote_host_ip6) /
8887 TCP(sport=12345, dport=80))
8889 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8890 IPv6(src=src, dst=remote_host_ip6) /
8891 TCP(sport=12345, dport=22))
8893 self.pg0.add_stream(pkts)
8894 self.pg_enable_capture(self.pg_interfaces)
8896 self.pg1.get_capture(max_sessions)
8898 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
8899 src_address=self.pg3.local_ip4,
8901 template_interval=10)
8902 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8903 src_port=self.ipfix_src_port,
8906 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8907 IPv6(src=src, dst=remote_host_ip6) /
8908 TCP(sport=12345, dport=25))
8909 self.pg0.add_stream(p)
8910 self.pg_enable_capture(self.pg_interfaces)
8912 self.pg1.assert_nothing_captured()
8914 self.vapi.ipfix_flush()
8915 capture = self.pg3.get_capture(7)
8916 ipfix = IPFIXDecoder()
8917 # first load template
8919 self.assertTrue(p.haslayer(IPFIX))
8920 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8921 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8922 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8923 self.assertEqual(p[UDP].dport, 4739)
8924 self.assertEqual(p[IPFIX].observationDomainID,
8925 self.ipfix_domain_id)
8926 if p.haslayer(Template):
8927 ipfix.add_template(p.getlayer(Template))
8928 # verify events in data set
8930 if p.haslayer(Data):
8931 data = ipfix.decode_data_set(p.getlayer(Set))
8932 self.verify_ipfix_max_sessions(data, max_sessions)
8934 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8935 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8936 TCP(sport=12345, dport=80))
8937 self.pg0.add_stream(p)
8938 self.pg_enable_capture(self.pg_interfaces)
8940 self.pg1.assert_nothing_captured()
8942 self.vapi.ipfix_flush()
8943 capture = self.pg3.get_capture(1)
8944 # verify events in data set
8946 self.assertTrue(p.haslayer(IPFIX))
8947 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8948 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8949 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8950 self.assertEqual(p[UDP].dport, 4739)
8951 self.assertEqual(p[IPFIX].observationDomainID,
8952 self.ipfix_domain_id)
8953 if p.haslayer(Data):
8954 data = ipfix.decode_data_set(p.getlayer(Set))
8955 self.verify_ipfix_max_bibs(data, max_bibs)
8957 def test_ipfix_bib_ses(self):
8958 """ IPFIX logging NAT64 BIB/session create and delete events """
8959 self.tcp_port_in = random.randint(1025, 65535)
8960 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8964 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8965 end_addr=self.nat_addr,
8968 flags = self.config_flags.NAT_IS_INSIDE
8969 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8970 sw_if_index=self.pg0.sw_if_index)
8971 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8972 sw_if_index=self.pg1.sw_if_index)
8973 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
8974 src_address=self.pg3.local_ip4,
8976 template_interval=10)
8977 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8978 src_port=self.ipfix_src_port,
8982 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8983 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8984 TCP(sport=self.tcp_port_in, dport=25))
8985 self.pg0.add_stream(p)
8986 self.pg_enable_capture(self.pg_interfaces)
8988 p = self.pg1.get_capture(1)
8989 self.tcp_port_out = p[0][TCP].sport
8990 self.vapi.ipfix_flush()
8991 capture = self.pg3.get_capture(8)
8992 ipfix = IPFIXDecoder()
8993 # first load template
8995 self.assertTrue(p.haslayer(IPFIX))
8996 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8997 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8998 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8999 self.assertEqual(p[UDP].dport, 4739)
9000 self.assertEqual(p[IPFIX].observationDomainID,
9001 self.ipfix_domain_id)
9002 if p.haslayer(Template):
9003 ipfix.add_template(p.getlayer(Template))
9004 # verify events in data set
9006 if p.haslayer(Data):
9007 data = ipfix.decode_data_set(p.getlayer(Set))
9008 if scapy.compat.orb(data[0][230]) == 10:
9009 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6)
9010 elif scapy.compat.orb(data[0][230]) == 6:
9011 self.verify_ipfix_nat64_ses(data,
9013 self.pg0.remote_ip6,
9014 self.pg1.remote_ip4,
9017 self.logger.error(ppp("Unexpected or invalid packet: ", p))
9020 self.pg_enable_capture(self.pg_interfaces)
9021 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9022 end_addr=self.nat_addr,
9025 self.vapi.ipfix_flush()
9026 capture = self.pg3.get_capture(2)
9027 # verify events in data set
9029 self.assertTrue(p.haslayer(IPFIX))
9030 self.assertEqual(p[IP].src, self.pg3.local_ip4)
9031 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
9032 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
9033 self.assertEqual(p[UDP].dport, 4739)
9034 self.assertEqual(p[IPFIX].observationDomainID,
9035 self.ipfix_domain_id)
9036 if p.haslayer(Data):
9037 data = ipfix.decode_data_set(p.getlayer(Set))
9038 if scapy.compat.orb(data[0][230]) == 11:
9039 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6)
9040 elif scapy.compat.orb(data[0][230]) == 7:
9041 self.verify_ipfix_nat64_ses(data,
9043 self.pg0.remote_ip6,
9044 self.pg1.remote_ip4,
9047 self.logger.error(ppp("Unexpected or invalid packet: ", p))
9049 def test_syslog_sess(self):
9050 """ Test syslog session creation and deletion """
9051 self.tcp_port_in = random.randint(1025, 65535)
9052 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
9056 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9057 end_addr=self.nat_addr,
9060 flags = self.config_flags.NAT_IS_INSIDE
9061 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
9062 sw_if_index=self.pg0.sw_if_index)
9063 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
9064 sw_if_index=self.pg1.sw_if_index)
9065 self.vapi.syslog_set_filter(
9066 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
9067 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
9069 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
9070 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
9071 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
9072 self.pg0.add_stream(p)
9073 self.pg_enable_capture(self.pg_interfaces)
9075 p = self.pg1.get_capture(1)
9076 self.tcp_port_out = p[0][TCP].sport
9077 capture = self.pg3.get_capture(1)
9078 self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
9080 self.pg_enable_capture(self.pg_interfaces)
9082 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9083 end_addr=self.nat_addr,
9086 capture = self.pg3.get_capture(1)
9087 self.verify_syslog_sess(capture[0][Raw].load, False, True)
9089 def nat64_get_ses_num(self):
9091 Return number of active NAT64 sessions.
9093 st = self.vapi.nat64_st_dump(proto=255)
9096 def clear_nat64(self):
9098 Clear NAT64 configuration.
9100 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
9101 src_port=self.ipfix_src_port,
9103 self.ipfix_src_port = 4739
9104 self.ipfix_domain_id = 1
9106 self.vapi.syslog_set_filter(
9107 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_EMERG)
9109 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
9110 tcp_transitory=240, icmp=60)
9112 interfaces = self.vapi.nat64_interface_dump()
9113 for intf in interfaces:
9114 self.vapi.nat64_add_del_interface(is_add=0, flags=intf.flags,
9115 sw_if_index=intf.sw_if_index)
9117 bib = self.vapi.nat64_bib_dump(proto=255)
9119 if bibe.flags & self.config_flags.NAT_IS_STATIC:
9120 self.vapi.nat64_add_del_static_bib(i_addr=bibe.i_addr,
9128 adresses = self.vapi.nat64_pool_addr_dump()
9129 for addr in adresses:
9130 self.vapi.nat64_add_del_pool_addr_range(start_addr=addr.address,
9131 end_addr=addr.address,
9135 prefixes = self.vapi.nat64_prefix_dump()
9136 for prefix in prefixes:
9137 self.vapi.nat64_add_del_prefix(prefix=str(prefix.prefix),
9138 vrf_id=prefix.vrf_id, is_add=0)
9140 bibs = self.statistics.get_counter('/nat64/total-bibs')
9141 self.assertEqual(bibs[0][0], 0)
9142 sessions = self.statistics.get_counter('/nat64/total-sessions')
9143 self.assertEqual(sessions[0][0], 0)
9146 super(TestNAT64, self).tearDown()
9147 if not self.vpp_dead:
9150 def show_commands_at_teardown(self):
9151 self.logger.info(self.vapi.cli("show nat64 pool"))
9152 self.logger.info(self.vapi.cli("show nat64 interfaces"))
9153 self.logger.info(self.vapi.cli("show nat64 prefix"))
9154 self.logger.info(self.vapi.cli("show nat64 bib all"))
9155 self.logger.info(self.vapi.cli("show nat64 session table all"))
9158 class TestNAT66(MethodHolder):
9159 """ NAT66 Test Cases """
9162 def setUpClass(cls):
9163 super(TestNAT66, cls).setUpClass()
9165 cls.nat_addr = 'fd01:ff::2'
9167 cls.create_pg_interfaces(range(2))
9168 cls.interfaces = list(cls.pg_interfaces)
9170 for i in cls.interfaces:
9173 i.configure_ipv6_neighbors()
9176 def tearDownClass(cls):
9177 super(TestNAT66, cls).tearDownClass()
9179 def test_static(self):
9180 """ 1:1 NAT66 test """
9181 flags = self.config_flags.NAT_IS_INSIDE
9182 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9183 sw_if_index=self.pg0.sw_if_index)
9184 self.vapi.nat66_add_del_interface(is_add=1,
9185 sw_if_index=self.pg1.sw_if_index)
9186 self.vapi.nat66_add_del_static_mapping(
9187 local_ip_address=self.pg0.remote_ip6,
9188 external_ip_address=self.nat_addr,
9193 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9194 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9197 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9198 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9201 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9202 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9203 ICMPv6EchoRequest())
9205 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9206 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9207 GRE() / IP() / TCP())
9209 self.pg0.add_stream(pkts)
9210 self.pg_enable_capture(self.pg_interfaces)
9212 capture = self.pg1.get_capture(len(pkts))
9214 for packet in capture:
9216 self.assertEqual(packet[IPv6].src, self.nat_addr)
9217 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9218 self.assert_packet_checksums_valid(packet)
9220 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9225 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9226 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9229 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9230 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9233 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9234 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9237 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9238 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9239 GRE() / IP() / TCP())
9241 self.pg1.add_stream(pkts)
9242 self.pg_enable_capture(self.pg_interfaces)
9244 capture = self.pg0.get_capture(len(pkts))
9245 for packet in capture:
9247 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
9248 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
9249 self.assert_packet_checksums_valid(packet)
9251 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9254 sm = self.vapi.nat66_static_mapping_dump()
9255 self.assertEqual(len(sm), 1)
9256 self.assertEqual(sm[0].total_pkts, 8)
9258 def test_check_no_translate(self):
9259 """ NAT66 translate only when egress interface is outside interface """
9260 flags = self.config_flags.NAT_IS_INSIDE
9261 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9262 sw_if_index=self.pg0.sw_if_index)
9263 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9264 sw_if_index=self.pg1.sw_if_index)
9265 self.vapi.nat66_add_del_static_mapping(
9266 local_ip_address=self.pg0.remote_ip6,
9267 external_ip_address=self.nat_addr,
9271 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9272 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9274 self.pg0.add_stream([p])
9275 self.pg_enable_capture(self.pg_interfaces)
9277 capture = self.pg1.get_capture(1)
9280 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
9281 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9283 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9286 def clear_nat66(self):
9288 Clear NAT66 configuration.
9290 interfaces = self.vapi.nat66_interface_dump()
9291 for intf in interfaces:
9292 self.vapi.nat66_add_del_interface(is_add=0, flags=intf.flags,
9293 sw_if_index=intf.sw_if_index)
9295 static_mappings = self.vapi.nat66_static_mapping_dump()
9296 for sm in static_mappings:
9297 self.vapi.nat66_add_del_static_mapping(
9298 local_ip_address=sm.local_ip_address,
9299 external_ip_address=sm.external_ip_address, vrf_id=sm.vrf_id,
9303 super(TestNAT66, self).tearDown()
9306 def show_commands_at_teardown(self):
9307 self.logger.info(self.vapi.cli("show nat66 interfaces"))
9308 self.logger.info(self.vapi.cli("show nat66 static mappings"))
9311 if __name__ == '__main__':
9312 unittest.main(testRunner=VppTestRunner)