8 from framework import VppTestCase, VppTestRunner, running_extended_tests
11 from scapy.layers.inet import IP, TCP, UDP, ICMP
12 from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
13 from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply, \
14 ICMPv6ND_NS, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr, fragment6
15 from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
16 from scapy.layers.l2 import Ether, ARP, GRE
17 from scapy.data import IP_PROTOS
18 from scapy.packet import bind_layers, Raw
20 from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
21 from time import sleep
22 from util import ip4_range
23 from vpp_papi import mac_pton
24 from syslog_rfc5424_parser import SyslogMessage, ParseError
25 from syslog_rfc5424_parser.constants import SyslogFacility, SyslogSeverity
26 from io import BytesIO
27 from vpp_papi import VppEnum
28 from vpp_ip_route import VppIpRoute, VppRoutePath, FibPathType
29 from vpp_neighbor import VppNeighbor
30 from vpp_ip import VppIpAddress, VppIpPrefix
31 from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \
32 IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \
34 from ipaddress import IPv6Network
37 # NAT HA protocol event data
40 fields_desc = [ByteEnumField("event_type", None,
41 {1: "add", 2: "del", 3: "refresh"}),
42 ByteEnumField("protocol", None,
43 {0: "udp", 1: "tcp", 2: "icmp"}),
44 ShortField("flags", 0),
45 IPField("in_addr", None),
46 IPField("out_addr", None),
47 ShortField("in_port", None),
48 ShortField("out_port", None),
49 IPField("eh_addr", None),
50 IPField("ehn_addr", None),
51 ShortField("eh_port", None),
52 ShortField("ehn_port", None),
53 IntField("fib_index", None),
54 IntField("total_pkts", 0),
55 LongField("total_bytes", 0)]
57 def extract_padding(self, s):
61 # NAT HA protocol header
62 class HANATStateSync(Packet):
63 name = "HA NAT state sync"
64 fields_desc = [XByteField("version", 1),
65 FlagsField("flags", 0, 8, ['ACK']),
66 FieldLenField("count", None, count_of="events"),
67 IntField("sequence_number", 1),
68 IntField("thread_index", 0),
69 PacketListField("events", [], Event,
70 count_from=lambda pkt: pkt.count)]
73 class MethodHolder(VppTestCase):
74 """ NAT create capture and verify method holder """
77 def config_flags(self):
78 return VppEnum.vl_api_nat_config_flags_t
81 def SYSLOG_SEVERITY(self):
82 return VppEnum.vl_api_syslog_severity_t
84 def clear_nat44(self):
86 Clear NAT44 configuration.
88 if hasattr(self, 'pg7') and hasattr(self, 'pg8'):
89 if self.pg7.has_ip4_config:
90 self.pg7.unconfig_ip4()
92 self.vapi.nat44_forwarding_enable_disable(enable=0)
94 interfaces = self.vapi.nat44_interface_addr_dump()
95 for intf in interfaces:
96 self.vapi.nat44_add_del_interface_addr(
98 sw_if_index=intf.sw_if_index,
101 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
102 src_port=self.ipfix_src_port,
104 self.ipfix_src_port = 4739
105 self.ipfix_domain_id = 1
107 self.vapi.syslog_set_filter(
108 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_EMERG)
110 self.vapi.nat_ha_set_listener(ip_address='0.0.0.0', port=0,
112 self.vapi.nat_ha_set_failover(ip_address='0.0.0.0', port=0,
113 session_refresh_interval=10)
115 interfaces = self.vapi.nat44_interface_dump()
116 for intf in interfaces:
117 if intf.flags & self.config_flags.NAT_IS_INSIDE and \
118 intf.flags & self.config_flags.NAT_IS_OUTSIDE:
119 self.vapi.nat44_interface_add_del_feature(
120 sw_if_index=intf.sw_if_index)
121 self.vapi.nat44_interface_add_del_feature(
122 sw_if_index=intf.sw_if_index,
125 interfaces = self.vapi.nat44_interface_output_feature_dump()
126 for intf in interfaces:
127 self.vapi.nat44_interface_add_del_output_feature(
130 sw_if_index=intf.sw_if_index)
131 static_mappings = self.vapi.nat44_static_mapping_dump()
132 for sm in static_mappings:
133 self.vapi.nat44_add_del_static_mapping(
135 local_ip_address=sm.local_ip_address,
136 external_ip_address=sm.external_ip_address,
137 external_sw_if_index=sm.external_sw_if_index,
138 local_port=sm.local_port,
139 external_port=sm.external_port,
141 protocol=sm.protocol,
142 flags=sm.flags, tag=sm.tag)
144 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
145 for lb_sm in lb_static_mappings:
146 self.vapi.nat44_add_del_lb_static_mapping(
149 external_addr=lb_sm.external_addr,
150 external_port=lb_sm.external_port,
151 protocol=lb_sm.protocol,
152 local_num=0, locals=[],
155 identity_mappings = self.vapi.nat44_identity_mapping_dump()
156 for id_m in identity_mappings:
157 self.vapi.nat44_add_del_identity_mapping(
158 ip_address=id_m.ip_address,
159 sw_if_index=id_m.sw_if_index,
163 protocol=id_m.protocol)
165 addresses = self.vapi.nat44_address_dump()
166 for addr in addresses:
167 self.vapi.nat44_add_del_address_range(
168 first_ip_address=addr.ip_address,
169 last_ip_address=addr.ip_address,
170 vrf_id=0xFFFFFFFF, flags=addr.flags)
172 self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=5,
174 self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=5,
175 drop_frag=0, is_ip6=1)
176 self.verify_no_nat44_user()
177 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
178 tcp_transitory=240, icmp=60)
179 self.vapi.nat_set_addr_and_port_alloc_alg()
180 self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
182 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
183 local_port=0, external_port=0, vrf_id=0,
184 is_add=1, external_sw_if_index=0xFFFFFFFF,
185 proto=0, tag="", flags=0):
187 Add/delete NAT44 static mapping
189 :param local_ip: Local IP address
190 :param external_ip: External IP address
191 :param local_port: Local port number (Optional)
192 :param external_port: External port number (Optional)
193 :param vrf_id: VRF ID (Default 0)
194 :param is_add: 1 if add, 0 if delete (Default add)
195 :param external_sw_if_index: External interface instead of IP address
196 :param proto: IP protocol (Mandatory if port specified)
197 :param tag: Opaque string tag
198 :param flags: NAT configuration flags
201 if not (local_port and external_port):
202 flags |= self.config_flags.NAT_IS_ADDR_ONLY
204 self.vapi.nat44_add_del_static_mapping(
206 local_ip_address=local_ip,
207 external_ip_address=external_ip,
208 external_sw_if_index=external_sw_if_index,
209 local_port=local_port,
210 external_port=external_port,
211 vrf_id=vrf_id, protocol=proto,
215 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
217 Add/delete NAT44 address
219 :param ip: IP address
220 :param is_add: 1 if add, 0 if delete (Default add)
221 :param twice_nat: twice NAT address for external hosts
223 flags = self.config_flags.NAT_IS_TWICE_NAT if twice_nat else 0
224 self.vapi.nat44_add_del_address_range(first_ip_address=ip,
230 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
232 Create packet stream for inside network
234 :param in_if: Inside interface
235 :param out_if: Outside interface
236 :param dst_ip: Destination address
237 :param ttl: TTL of generated packets
240 dst_ip = out_if.remote_ip4
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 TCP(sport=self.tcp_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 UDP(sport=self.udp_port_in, dport=20))
256 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
257 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
258 ICMP(id=self.icmp_id_in, type='echo-request'))
263 def compose_ip6(self, ip4, pref, plen):
265 Compose IPv4-embedded IPv6 addresses
267 :param ip4: IPv4 address
268 :param pref: IPv6 prefix
269 :param plen: IPv6 prefix length
270 :returns: IPv4-embedded IPv6 addresses
272 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
273 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
288 pref_n[10] = ip4_n[3]
292 pref_n[10] = ip4_n[2]
293 pref_n[11] = ip4_n[3]
296 pref_n[10] = ip4_n[1]
297 pref_n[11] = ip4_n[2]
298 pref_n[12] = ip4_n[3]
300 pref_n[12] = ip4_n[0]
301 pref_n[13] = ip4_n[1]
302 pref_n[14] = ip4_n[2]
303 pref_n[15] = ip4_n[3]
304 packed_pref_n = b''.join([scapy.compat.chb(x) for x in pref_n])
305 return socket.inet_ntop(socket.AF_INET6, packed_pref_n)
307 def extract_ip4(self, ip6, plen):
309 Extract IPv4 address embedded in IPv6 addresses
311 :param ip6: IPv6 address
312 :param plen: IPv6 prefix length
313 :returns: extracted IPv4 address
315 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
347 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
349 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
351 Create IPv6 packet stream for inside network
353 :param in_if: Inside interface
354 :param out_if: Outside interface
355 :param ttl: Hop Limit of generated packets
356 :param pref: NAT64 prefix
357 :param plen: NAT64 prefix length
361 dst = ''.join(['64:ff9b::', out_if.remote_ip4])
363 dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
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 TCP(sport=self.tcp_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 UDP(sport=self.udp_port_in, dport=20))
378 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
379 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
380 ICMPv6EchoRequest(id=self.icmp_id_in))
385 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
386 use_inside_ports=False):
388 Create packet stream for outside network
390 :param out_if: Outside interface
391 :param dst_ip: Destination IP address (Default use global NAT address)
392 :param ttl: TTL of generated packets
393 :param use_inside_ports: Use inside NAT ports as destination ports
394 instead of outside ports
397 dst_ip = self.nat_addr
398 if not use_inside_ports:
399 tcp_port = self.tcp_port_out
400 udp_port = self.udp_port_out
401 icmp_id = self.icmp_id_out
403 tcp_port = self.tcp_port_in
404 udp_port = self.udp_port_in
405 icmp_id = self.icmp_id_in
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 TCP(dport=tcp_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 UDP(dport=udp_port, sport=20))
420 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
421 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
422 ICMP(id=icmp_id, type='echo-reply'))
427 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
429 Create packet stream for outside network
431 :param out_if: Outside interface
432 :param dst_ip: Destination IP address (Default use global NAT address)
433 :param hl: HL of generated packets
437 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
438 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
439 TCP(dport=self.tcp_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 UDP(dport=self.udp_port_out, sport=20))
449 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
450 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
451 ICMPv6EchoReply(id=self.icmp_id_out))
456 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
457 dst_ip=None, is_ip6=False):
459 Verify captured packets on outside network
461 :param capture: Captured packets
462 :param nat_ip: Translated IP address (Default use global NAT address)
463 :param same_port: Source port number is not translated (Default False)
464 :param dst_ip: Destination IP address (Default do not verify)
465 :param is_ip6: If L3 protocol is IPv6 (Default False)
469 ICMP46 = ICMPv6EchoRequest
474 nat_ip = self.nat_addr
475 for packet in capture:
478 self.assert_packet_checksums_valid(packet)
479 self.assertEqual(packet[IP46].src, nat_ip)
480 if dst_ip is not None:
481 self.assertEqual(packet[IP46].dst, dst_ip)
482 if packet.haslayer(TCP):
484 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
487 packet[TCP].sport, self.tcp_port_in)
488 self.tcp_port_out = packet[TCP].sport
489 self.assert_packet_checksums_valid(packet)
490 elif packet.haslayer(UDP):
492 self.assertEqual(packet[UDP].sport, self.udp_port_in)
495 packet[UDP].sport, self.udp_port_in)
496 self.udp_port_out = packet[UDP].sport
499 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
501 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
502 self.icmp_id_out = packet[ICMP46].id
503 self.assert_packet_checksums_valid(packet)
505 self.logger.error(ppp("Unexpected or invalid packet "
506 "(outside network):", packet))
509 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
512 Verify captured packets on outside network
514 :param capture: Captured packets
515 :param nat_ip: Translated IP address
516 :param same_port: Source port number is not translated (Default False)
517 :param dst_ip: Destination IP address (Default do not verify)
519 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
522 def verify_capture_in(self, capture, in_if):
524 Verify captured packets on inside network
526 :param capture: Captured packets
527 :param in_if: Inside interface
529 for packet in capture:
531 self.assert_packet_checksums_valid(packet)
532 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
533 if packet.haslayer(TCP):
534 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
535 elif packet.haslayer(UDP):
536 self.assertEqual(packet[UDP].dport, self.udp_port_in)
538 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
540 self.logger.error(ppp("Unexpected or invalid packet "
541 "(inside network):", packet))
544 def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
546 Verify captured IPv6 packets on inside network
548 :param capture: Captured packets
549 :param src_ip: Source IP
550 :param dst_ip: Destination IP address
552 for packet in capture:
554 self.assertEqual(packet[IPv6].src, src_ip)
555 self.assertEqual(packet[IPv6].dst, dst_ip)
556 self.assert_packet_checksums_valid(packet)
557 if packet.haslayer(TCP):
558 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
559 elif packet.haslayer(UDP):
560 self.assertEqual(packet[UDP].dport, self.udp_port_in)
562 self.assertEqual(packet[ICMPv6EchoReply].id,
565 self.logger.error(ppp("Unexpected or invalid packet "
566 "(inside network):", packet))
569 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
571 Verify captured packet that don't have to be translated
573 :param capture: Captured packets
574 :param ingress_if: Ingress interface
575 :param egress_if: Egress interface
577 for packet in capture:
579 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
580 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
581 if packet.haslayer(TCP):
582 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
583 elif packet.haslayer(UDP):
584 self.assertEqual(packet[UDP].sport, self.udp_port_in)
586 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
588 self.logger.error(ppp("Unexpected or invalid packet "
589 "(inside network):", packet))
592 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
595 Verify captured packets with ICMP errors on outside network
597 :param capture: Captured packets
598 :param src_ip: Translated IP address or IP address of VPP
599 (Default use global NAT address)
600 :param icmp_type: Type of error ICMP packet
601 we are expecting (Default 11)
604 src_ip = self.nat_addr
605 for packet in capture:
607 self.assertEqual(packet[IP].src, src_ip)
608 self.assertEqual(packet.haslayer(ICMP), 1)
610 self.assertEqual(icmp.type, icmp_type)
611 self.assertTrue(icmp.haslayer(IPerror))
612 inner_ip = icmp[IPerror]
613 if inner_ip.haslayer(TCPerror):
614 self.assertEqual(inner_ip[TCPerror].dport,
616 elif inner_ip.haslayer(UDPerror):
617 self.assertEqual(inner_ip[UDPerror].dport,
620 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
622 self.logger.error(ppp("Unexpected or invalid packet "
623 "(outside network):", packet))
626 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
628 Verify captured packets with ICMP errors on inside network
630 :param capture: Captured packets
631 :param in_if: Inside interface
632 :param icmp_type: Type of error ICMP packet
633 we are expecting (Default 11)
635 for packet in capture:
637 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
638 self.assertEqual(packet.haslayer(ICMP), 1)
640 self.assertEqual(icmp.type, icmp_type)
641 self.assertTrue(icmp.haslayer(IPerror))
642 inner_ip = icmp[IPerror]
643 if inner_ip.haslayer(TCPerror):
644 self.assertEqual(inner_ip[TCPerror].sport,
646 elif inner_ip.haslayer(UDPerror):
647 self.assertEqual(inner_ip[UDPerror].sport,
650 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
652 self.logger.error(ppp("Unexpected or invalid packet "
653 "(inside network):", packet))
656 def create_stream_frag(self, src_if, dst, sport, dport, data,
657 proto=IP_PROTOS.tcp, echo_reply=False):
659 Create fragmented packet stream
661 :param src_if: Source interface
662 :param dst: Destination IPv4 address
663 :param sport: Source port
664 :param dport: Destination port
665 :param data: Payload data
666 :param proto: protocol (TCP, UDP, ICMP)
667 :param echo_reply: use echo_reply if protocol is ICMP
670 if proto == IP_PROTOS.tcp:
671 p = (IP(src=src_if.remote_ip4, dst=dst) /
672 TCP(sport=sport, dport=dport) /
674 p = p.__class__(scapy.compat.raw(p))
675 chksum = p[TCP].chksum
676 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
677 elif proto == IP_PROTOS.udp:
678 proto_header = UDP(sport=sport, dport=dport)
679 elif proto == IP_PROTOS.icmp:
681 proto_header = ICMP(id=sport, type='echo-request')
683 proto_header = ICMP(id=sport, type='echo-reply')
685 raise Exception("Unsupported protocol")
686 id = random.randint(0, 65535)
688 if proto == IP_PROTOS.tcp:
691 raw = Raw(data[0:16])
692 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
693 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
697 if proto == IP_PROTOS.tcp:
698 raw = Raw(data[4:20])
700 raw = Raw(data[16:32])
701 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
702 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
706 if proto == IP_PROTOS.tcp:
710 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
711 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
717 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
718 pref=None, plen=0, frag_size=128):
720 Create fragmented packet stream
722 :param src_if: Source interface
723 :param dst: Destination IPv4 address
724 :param sport: Source TCP port
725 :param dport: Destination TCP port
726 :param data: Payload data
727 :param pref: NAT64 prefix
728 :param plen: NAT64 prefix length
729 :param fragsize: size of fragments
733 dst_ip6 = ''.join(['64:ff9b::', dst])
735 dst_ip6 = self.compose_ip6(dst, pref, plen)
737 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
738 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
739 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
740 TCP(sport=sport, dport=dport) /
743 return fragment6(p, frag_size)
745 def reass_frags_and_verify(self, frags, src, dst):
747 Reassemble and verify fragmented packet
749 :param frags: Captured fragments
750 :param src: Source IPv4 address to verify
751 :param dst: Destination IPv4 address to verify
753 :returns: Reassembled IPv4 packet
757 self.assertEqual(p[IP].src, src)
758 self.assertEqual(p[IP].dst, dst)
759 self.assert_ip_checksum_valid(p)
760 buffer.seek(p[IP].frag * 8)
761 buffer.write(bytes(p[IP].payload))
762 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
763 proto=frags[0][IP].proto)
764 if ip.proto == IP_PROTOS.tcp:
765 p = (ip / TCP(buffer.getvalue()))
766 self.assert_tcp_checksum_valid(p)
767 elif ip.proto == IP_PROTOS.udp:
768 p = (ip / UDP(buffer.getvalue()[:8]) /
769 Raw(buffer.getvalue()[8:]))
770 elif ip.proto == IP_PROTOS.icmp:
771 p = (ip / ICMP(buffer.getvalue()))
774 def reass_frags_and_verify_ip6(self, frags, src, dst):
776 Reassemble and verify fragmented packet
778 :param frags: Captured fragments
779 :param src: Source IPv6 address to verify
780 :param dst: Destination IPv6 address to verify
782 :returns: Reassembled IPv6 packet
786 self.assertEqual(p[IPv6].src, src)
787 self.assertEqual(p[IPv6].dst, dst)
788 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
789 buffer.write(bytes(p[IPv6ExtHdrFragment].payload))
790 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
791 nh=frags[0][IPv6ExtHdrFragment].nh)
792 if ip.nh == IP_PROTOS.tcp:
793 p = (ip / TCP(buffer.getvalue()))
794 elif ip.nh == IP_PROTOS.udp:
795 p = (ip / UDP(buffer.getvalue()))
796 self.assert_packet_checksums_valid(p)
799 def initiate_tcp_session(self, in_if, out_if):
801 Initiates TCP session
803 :param in_if: Inside interface
804 :param out_if: Outside interface
808 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
809 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
810 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
813 self.pg_enable_capture(self.pg_interfaces)
815 capture = out_if.get_capture(1)
817 self.tcp_port_out = p[TCP].sport
819 # SYN + ACK packet out->in
820 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
821 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
822 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
825 self.pg_enable_capture(self.pg_interfaces)
830 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
831 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
832 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
835 self.pg_enable_capture(self.pg_interfaces)
837 out_if.get_capture(1)
840 self.logger.error("TCP 3 way handshake failed")
843 def verify_ipfix_nat44_ses(self, data):
845 Verify IPFIX NAT44 session create/delete event
847 :param data: Decoded IPFIX data records
849 nat44_ses_create_num = 0
850 nat44_ses_delete_num = 0
851 self.assertEqual(6, len(data))
854 self.assertIn(scapy.compat.orb(record[230]), [4, 5])
855 if scapy.compat.orb(record[230]) == 4:
856 nat44_ses_create_num += 1
858 nat44_ses_delete_num += 1
860 self.assertEqual(self.pg0.remote_ip4n, record[8])
861 # postNATSourceIPv4Address
862 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
865 self.assertEqual(struct.pack("!I", 0), record[234])
866 # protocolIdentifier/sourceTransportPort
867 # /postNAPTSourceTransportPort
868 if IP_PROTOS.icmp == scapy.compat.orb(record[4]):
869 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
870 self.assertEqual(struct.pack("!H", self.icmp_id_out),
872 elif IP_PROTOS.tcp == scapy.compat.orb(record[4]):
873 self.assertEqual(struct.pack("!H", self.tcp_port_in),
875 self.assertEqual(struct.pack("!H", self.tcp_port_out),
877 elif IP_PROTOS.udp == scapy.compat.orb(record[4]):
878 self.assertEqual(struct.pack("!H", self.udp_port_in),
880 self.assertEqual(struct.pack("!H", self.udp_port_out),
883 self.fail("Invalid protocol")
884 self.assertEqual(3, nat44_ses_create_num)
885 self.assertEqual(3, nat44_ses_delete_num)
887 def verify_ipfix_addr_exhausted(self, data):
889 Verify IPFIX NAT addresses event
891 :param data: Decoded IPFIX data records
893 self.assertEqual(1, len(data))
896 self.assertEqual(scapy.compat.orb(record[230]), 3)
898 self.assertEqual(struct.pack("!I", 0), record[283])
900 def verify_ipfix_max_sessions(self, data, limit):
902 Verify IPFIX maximum session entries exceeded event
904 :param data: Decoded IPFIX data records
905 :param limit: Number of maximum session entries that can be created.
907 self.assertEqual(1, len(data))
910 self.assertEqual(scapy.compat.orb(record[230]), 13)
911 # natQuotaExceededEvent
912 self.assertEqual(struct.pack("I", 1), record[466])
914 self.assertEqual(struct.pack("I", limit), record[471])
916 def verify_ipfix_max_bibs(self, data, limit):
918 Verify IPFIX maximum BIB entries exceeded event
920 :param data: Decoded IPFIX data records
921 :param limit: Number of maximum BIB entries that can be created.
923 self.assertEqual(1, len(data))
926 self.assertEqual(scapy.compat.orb(record[230]), 13)
927 # natQuotaExceededEvent
928 self.assertEqual(struct.pack("I", 2), record[466])
930 self.assertEqual(struct.pack("I", limit), record[472])
932 def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
934 Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
936 :param data: Decoded IPFIX data records
937 :param limit: Number of maximum fragments pending reassembly
938 :param src_addr: IPv6 source address
940 self.assertEqual(1, len(data))
943 self.assertEqual(scapy.compat.orb(record[230]), 13)
944 # natQuotaExceededEvent
945 self.assertEqual(struct.pack("I", 5), record[466])
946 # maxFragmentsPendingReassembly
947 self.assertEqual(struct.pack("I", limit), record[475])
949 self.assertEqual(src_addr, record[27])
951 def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
953 Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
955 :param data: Decoded IPFIX data records
956 :param limit: Number of maximum fragments pending reassembly
957 :param src_addr: IPv4 source address
959 self.assertEqual(1, len(data))
962 self.assertEqual(scapy.compat.orb(record[230]), 13)
963 # natQuotaExceededEvent
964 self.assertEqual(struct.pack("I", 5), record[466])
965 # maxFragmentsPendingReassembly
966 self.assertEqual(struct.pack("I", limit), record[475])
968 self.assertEqual(src_addr, record[8])
970 def verify_ipfix_bib(self, data, is_create, src_addr):
972 Verify IPFIX NAT64 BIB create and delete events
974 :param data: Decoded IPFIX data records
975 :param is_create: Create event if nonzero value otherwise delete event
976 :param src_addr: IPv6 source address
978 self.assertEqual(1, len(data))
982 self.assertEqual(scapy.compat.orb(record[230]), 10)
984 self.assertEqual(scapy.compat.orb(record[230]), 11)
986 self.assertEqual(src_addr, record[27])
987 # postNATSourceIPv4Address
988 self.assertEqual(self.nat_addr_n, record[225])
990 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
992 self.assertEqual(struct.pack("!I", 0), record[234])
993 # sourceTransportPort
994 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
995 # postNAPTSourceTransportPort
996 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
998 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
1001 Verify IPFIX NAT64 session create and delete events
1003 :param data: Decoded IPFIX data records
1004 :param is_create: Create event if nonzero value otherwise delete event
1005 :param src_addr: IPv6 source address
1006 :param dst_addr: IPv4 destination address
1007 :param dst_port: destination TCP port
1009 self.assertEqual(1, len(data))
1013 self.assertEqual(scapy.compat.orb(record[230]), 6)
1015 self.assertEqual(scapy.compat.orb(record[230]), 7)
1017 self.assertEqual(src_addr, record[27])
1018 # destinationIPv6Address
1019 self.assertEqual(socket.inet_pton(socket.AF_INET6,
1020 self.compose_ip6(dst_addr,
1024 # postNATSourceIPv4Address
1025 self.assertEqual(self.nat_addr_n, record[225])
1026 # postNATDestinationIPv4Address
1027 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
1029 # protocolIdentifier
1030 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
1032 self.assertEqual(struct.pack("!I", 0), record[234])
1033 # sourceTransportPort
1034 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1035 # postNAPTSourceTransportPort
1036 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1037 # destinationTransportPort
1038 self.assertEqual(struct.pack("!H", dst_port), record[11])
1039 # postNAPTDestinationTransportPort
1040 self.assertEqual(struct.pack("!H", dst_port), record[228])
1042 def verify_no_nat44_user(self):
1043 """ Verify that there is no NAT44 user """
1044 users = self.vapi.nat44_user_dump()
1045 self.assertEqual(len(users), 0)
1046 users = self.statistics.get_counter('/nat44/total-users')
1047 self.assertEqual(users[0][0], 0)
1048 sessions = self.statistics.get_counter('/nat44/total-sessions')
1049 self.assertEqual(sessions[0][0], 0)
1051 def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
1053 Verify IPFIX maximum entries per user exceeded event
1055 :param data: Decoded IPFIX data records
1056 :param limit: Number of maximum entries per user
1057 :param src_addr: IPv4 source address
1059 self.assertEqual(1, len(data))
1062 self.assertEqual(scapy.compat.orb(record[230]), 13)
1063 # natQuotaExceededEvent
1064 self.assertEqual(struct.pack("I", 3), record[466])
1066 self.assertEqual(struct.pack("I", limit), record[473])
1068 self.assertEqual(socket.inet_pton(socket.AF_INET, src_addr), record[8])
1070 def verify_syslog_apmap(self, data, is_add=True):
1071 message = data.decode('utf-8')
1073 message = SyslogMessage.parse(message)
1074 except ParseError as e:
1075 self.logger.error(e)
1078 self.assertEqual(message.severity, SyslogSeverity.info)
1079 self.assertEqual(message.appname, 'NAT')
1080 self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
1081 sd_params = message.sd.get('napmap')
1082 self.assertTrue(sd_params is not None)
1083 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1084 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1085 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1086 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1087 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1088 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1089 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1090 self.assertTrue(sd_params.get('SSUBIX') is not None)
1091 self.assertEqual(sd_params.get('SVLAN'), '0')
1093 def verify_syslog_sess(self, data, is_add=True, is_ip6=False):
1094 message = data.decode('utf-8')
1096 message = SyslogMessage.parse(message)
1097 except ParseError as e:
1098 self.logger.error(e)
1101 self.assertEqual(message.severity, SyslogSeverity.info)
1102 self.assertEqual(message.appname, 'NAT')
1103 self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL')
1104 sd_params = message.sd.get('nsess')
1105 self.assertTrue(sd_params is not None)
1107 self.assertEqual(sd_params.get('IATYP'), 'IPv6')
1108 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
1110 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1111 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1112 self.assertTrue(sd_params.get('SSUBIX') is not None)
1113 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1114 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1115 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1116 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1117 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1118 self.assertEqual(sd_params.get('SVLAN'), '0')
1119 self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
1120 self.assertEqual(sd_params.get('XDPORT'),
1121 "%d" % self.tcp_external_port)
1123 def verify_mss_value(self, pkt, mss):
1125 Verify TCP MSS value
1130 if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
1131 raise TypeError("Not a TCP/IP packet")
1133 for option in pkt[TCP].options:
1134 if option[0] == 'MSS':
1135 self.assertEqual(option[1], mss)
1136 self.assert_tcp_checksum_valid(pkt)
1139 def proto2layer(proto):
1140 if proto == IP_PROTOS.tcp:
1142 elif proto == IP_PROTOS.udp:
1144 elif proto == IP_PROTOS.icmp:
1147 raise Exception("Unsupported protocol")
1149 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1150 layer = self.proto2layer(proto)
1152 if proto == IP_PROTOS.tcp:
1153 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1155 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1156 self.port_in = random.randint(1025, 65535)
1158 reass = self.vapi.nat_reass_dump()
1159 reass_n_start = len(reass)
1162 pkts = self.create_stream_frag(self.pg0,
1163 self.pg1.remote_ip4,
1168 self.pg0.add_stream(pkts)
1169 self.pg_enable_capture(self.pg_interfaces)
1171 frags = self.pg1.get_capture(len(pkts))
1172 if not dont_translate:
1173 p = self.reass_frags_and_verify(frags,
1175 self.pg1.remote_ip4)
1177 p = self.reass_frags_and_verify(frags,
1178 self.pg0.remote_ip4,
1179 self.pg1.remote_ip4)
1180 if proto != IP_PROTOS.icmp:
1181 if not dont_translate:
1182 self.assertEqual(p[layer].dport, 20)
1183 self.assertNotEqual(p[layer].sport, self.port_in)
1185 self.assertEqual(p[layer].sport, self.port_in)
1187 if not dont_translate:
1188 self.assertNotEqual(p[layer].id, self.port_in)
1190 self.assertEqual(p[layer].id, self.port_in)
1191 self.assertEqual(data, p[Raw].load)
1194 if not dont_translate:
1195 dst_addr = self.nat_addr
1197 dst_addr = self.pg0.remote_ip4
1198 if proto != IP_PROTOS.icmp:
1200 dport = p[layer].sport
1204 pkts = self.create_stream_frag(self.pg1,
1211 self.pg1.add_stream(pkts)
1212 self.pg_enable_capture(self.pg_interfaces)
1214 frags = self.pg0.get_capture(len(pkts))
1215 p = self.reass_frags_and_verify(frags,
1216 self.pg1.remote_ip4,
1217 self.pg0.remote_ip4)
1218 if proto != IP_PROTOS.icmp:
1219 self.assertEqual(p[layer].sport, 20)
1220 self.assertEqual(p[layer].dport, self.port_in)
1222 self.assertEqual(p[layer].id, self.port_in)
1223 self.assertEqual(data, p[Raw].load)
1225 reass = self.vapi.nat_reass_dump()
1226 reass_n_end = len(reass)
1228 self.assertEqual(reass_n_end - reass_n_start, 2)
1230 def frag_in_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1231 layer = self.proto2layer(proto)
1233 if proto == IP_PROTOS.tcp:
1234 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1236 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1237 self.port_in = random.randint(1025, 65535)
1240 reass = self.vapi.nat_reass_dump()
1241 reass_n_start = len(reass)
1244 pkts = self.create_stream_frag(self.pg0,
1245 self.server_out_addr,
1247 self.server_out_port,
1250 self.pg0.add_stream(pkts)
1251 self.pg_enable_capture(self.pg_interfaces)
1253 frags = self.pg1.get_capture(len(pkts))
1254 p = self.reass_frags_and_verify(frags,
1255 self.pg0.remote_ip4,
1256 self.server_in_addr)
1257 if proto != IP_PROTOS.icmp:
1258 self.assertEqual(p[layer].sport, self.port_in)
1259 self.assertEqual(p[layer].dport, self.server_in_port)
1261 self.assertEqual(p[layer].id, self.port_in)
1262 self.assertEqual(data, p[Raw].load)
1265 if proto != IP_PROTOS.icmp:
1266 pkts = self.create_stream_frag(self.pg1,
1267 self.pg0.remote_ip4,
1268 self.server_in_port,
1273 pkts = self.create_stream_frag(self.pg1,
1274 self.pg0.remote_ip4,
1280 self.pg1.add_stream(pkts)
1281 self.pg_enable_capture(self.pg_interfaces)
1283 frags = self.pg0.get_capture(len(pkts))
1284 p = self.reass_frags_and_verify(frags,
1285 self.server_out_addr,
1286 self.pg0.remote_ip4)
1287 if proto != IP_PROTOS.icmp:
1288 self.assertEqual(p[layer].sport, self.server_out_port)
1289 self.assertEqual(p[layer].dport, self.port_in)
1291 self.assertEqual(p[layer].id, self.port_in)
1292 self.assertEqual(data, p[Raw].load)
1294 reass = self.vapi.nat_reass_dump()
1295 reass_n_end = len(reass)
1297 self.assertEqual(reass_n_end - reass_n_start, 2)
1299 def reass_hairpinning(self, proto=IP_PROTOS.tcp):
1300 layer = self.proto2layer(proto)
1302 if proto == IP_PROTOS.tcp:
1303 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1305 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1307 # send packet from host to server
1308 pkts = self.create_stream_frag(self.pg0,
1311 self.server_out_port,
1314 self.pg0.add_stream(pkts)
1315 self.pg_enable_capture(self.pg_interfaces)
1317 frags = self.pg0.get_capture(len(pkts))
1318 p = self.reass_frags_and_verify(frags,
1321 if proto != IP_PROTOS.icmp:
1322 self.assertNotEqual(p[layer].sport, self.host_in_port)
1323 self.assertEqual(p[layer].dport, self.server_in_port)
1325 self.assertNotEqual(p[layer].id, self.host_in_port)
1326 self.assertEqual(data, p[Raw].load)
1328 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1329 layer = self.proto2layer(proto)
1331 if proto == IP_PROTOS.tcp:
1332 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1334 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1335 self.port_in = random.randint(1025, 65535)
1339 pkts = self.create_stream_frag(self.pg0,
1340 self.pg1.remote_ip4,
1346 self.pg0.add_stream(pkts)
1347 self.pg_enable_capture(self.pg_interfaces)
1349 frags = self.pg1.get_capture(len(pkts))
1350 if not dont_translate:
1351 p = self.reass_frags_and_verify(frags,
1353 self.pg1.remote_ip4)
1355 p = self.reass_frags_and_verify(frags,
1356 self.pg0.remote_ip4,
1357 self.pg1.remote_ip4)
1358 if proto != IP_PROTOS.icmp:
1359 if not dont_translate:
1360 self.assertEqual(p[layer].dport, 20)
1361 self.assertNotEqual(p[layer].sport, self.port_in)
1363 self.assertEqual(p[layer].sport, self.port_in)
1365 if not dont_translate:
1366 self.assertNotEqual(p[layer].id, self.port_in)
1368 self.assertEqual(p[layer].id, self.port_in)
1369 self.assertEqual(data, p[Raw].load)
1372 if not dont_translate:
1373 dst_addr = self.nat_addr
1375 dst_addr = self.pg0.remote_ip4
1376 if proto != IP_PROTOS.icmp:
1378 dport = p[layer].sport
1382 pkts = self.create_stream_frag(self.pg1,
1390 self.pg1.add_stream(pkts)
1391 self.pg_enable_capture(self.pg_interfaces)
1393 frags = self.pg0.get_capture(len(pkts))
1394 p = self.reass_frags_and_verify(frags,
1395 self.pg1.remote_ip4,
1396 self.pg0.remote_ip4)
1397 if proto != IP_PROTOS.icmp:
1398 self.assertEqual(p[layer].sport, 20)
1399 self.assertEqual(p[layer].dport, self.port_in)
1401 self.assertEqual(p[layer].id, self.port_in)
1402 self.assertEqual(data, p[Raw].load)
1404 def frag_out_of_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1405 layer = self.proto2layer(proto)
1407 if proto == IP_PROTOS.tcp:
1408 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1410 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1411 self.port_in = random.randint(1025, 65535)
1415 pkts = self.create_stream_frag(self.pg0,
1416 self.server_out_addr,
1418 self.server_out_port,
1422 self.pg0.add_stream(pkts)
1423 self.pg_enable_capture(self.pg_interfaces)
1425 frags = self.pg1.get_capture(len(pkts))
1426 p = self.reass_frags_and_verify(frags,
1427 self.pg0.remote_ip4,
1428 self.server_in_addr)
1429 if proto != IP_PROTOS.icmp:
1430 self.assertEqual(p[layer].dport, self.server_in_port)
1431 self.assertEqual(p[layer].sport, self.port_in)
1432 self.assertEqual(p[layer].dport, self.server_in_port)
1434 self.assertEqual(p[layer].id, self.port_in)
1435 self.assertEqual(data, p[Raw].load)
1438 if proto != IP_PROTOS.icmp:
1439 pkts = self.create_stream_frag(self.pg1,
1440 self.pg0.remote_ip4,
1441 self.server_in_port,
1446 pkts = self.create_stream_frag(self.pg1,
1447 self.pg0.remote_ip4,
1454 self.pg1.add_stream(pkts)
1455 self.pg_enable_capture(self.pg_interfaces)
1457 frags = self.pg0.get_capture(len(pkts))
1458 p = self.reass_frags_and_verify(frags,
1459 self.server_out_addr,
1460 self.pg0.remote_ip4)
1461 if proto != IP_PROTOS.icmp:
1462 self.assertEqual(p[layer].sport, self.server_out_port)
1463 self.assertEqual(p[layer].dport, self.port_in)
1465 self.assertEqual(p[layer].id, self.port_in)
1466 self.assertEqual(data, p[Raw].load)
1469 class TestNAT44(MethodHolder):
1470 """ NAT44 Test Cases """
1473 def setUpClass(cls):
1474 super(TestNAT44, cls).setUpClass()
1475 cls.vapi.cli("set log class nat level debug")
1478 cls.tcp_port_in = 6303
1479 cls.tcp_port_out = 6303
1480 cls.udp_port_in = 6304
1481 cls.udp_port_out = 6304
1482 cls.icmp_id_in = 6305
1483 cls.icmp_id_out = 6305
1484 cls.nat_addr = '10.0.0.3'
1485 cls.ipfix_src_port = 4739
1486 cls.ipfix_domain_id = 1
1487 cls.tcp_external_port = 80
1488 cls.udp_external_port = 69
1490 cls.create_pg_interfaces(range(10))
1491 cls.interfaces = list(cls.pg_interfaces[0:4])
1493 for i in cls.interfaces:
1498 cls.pg0.generate_remote_hosts(3)
1499 cls.pg0.configure_ipv4_neighbors()
1501 cls.pg1.generate_remote_hosts(1)
1502 cls.pg1.configure_ipv4_neighbors()
1504 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
1505 cls.vapi.ip_table_add_del(is_add=1, table_id=10)
1506 cls.vapi.ip_table_add_del(is_add=1, table_id=20)
1508 cls.pg4._local_ip4 = VppIpPrefix("172.16.255.1",
1509 cls.pg4.local_ip4_prefix.len)
1510 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1511 cls.pg4.set_table_ip4(10)
1512 cls.pg5._local_ip4 = VppIpPrefix("172.17.255.3",
1513 cls.pg5.local_ip4_prefix.len)
1514 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
1515 cls.pg5.set_table_ip4(10)
1516 cls.pg6._local_ip4 = VppIpPrefix("172.16.255.1",
1517 cls.pg6.local_ip4_prefix.len)
1518 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1519 cls.pg6.set_table_ip4(20)
1520 for i in cls.overlapping_interfaces:
1528 cls.pg9.generate_remote_hosts(2)
1529 cls.pg9.config_ip4()
1530 cls.vapi.sw_interface_add_del_address(
1531 sw_if_index=cls.pg9.sw_if_index,
1532 prefix=VppIpPrefix("10.0.0.1", 24).encode())
1535 cls.pg9.resolve_arp()
1536 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1537 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1538 cls.pg9.resolve_arp()
1541 super(TestNAT44, cls).tearDownClass()
1545 def tearDownClass(cls):
1546 super(TestNAT44, cls).tearDownClass()
1548 def test_dynamic(self):
1549 """ NAT44 dynamic translation test """
1550 self.nat44_add_address(self.nat_addr)
1551 flags = self.config_flags.NAT_IS_INSIDE
1552 self.vapi.nat44_interface_add_del_feature(
1553 sw_if_index=self.pg0.sw_if_index,
1554 flags=flags, is_add=1)
1555 self.vapi.nat44_interface_add_del_feature(
1556 sw_if_index=self.pg1.sw_if_index,
1560 tcpn = self.statistics.get_err_counter(
1561 '/err/nat44-in2out-slowpath/TCP packets')
1562 udpn = self.statistics.get_err_counter(
1563 '/err/nat44-in2out-slowpath/UDP packets')
1564 icmpn = self.statistics.get_err_counter(
1565 '/err/nat44-in2out-slowpath/ICMP packets')
1566 totaln = self.statistics.get_err_counter(
1567 '/err/nat44-in2out-slowpath/good in2out packets processed')
1569 pkts = self.create_stream_in(self.pg0, self.pg1)
1570 self.pg0.add_stream(pkts)
1571 self.pg_enable_capture(self.pg_interfaces)
1573 capture = self.pg1.get_capture(len(pkts))
1574 self.verify_capture_out(capture)
1576 err = self.statistics.get_err_counter(
1577 '/err/nat44-in2out-slowpath/TCP packets')
1578 self.assertEqual(err - tcpn, 2)
1579 err = self.statistics.get_err_counter(
1580 '/err/nat44-in2out-slowpath/UDP packets')
1581 self.assertEqual(err - udpn, 1)
1582 err = self.statistics.get_err_counter(
1583 '/err/nat44-in2out-slowpath/ICMP packets')
1584 self.assertEqual(err - icmpn, 1)
1585 err = self.statistics.get_err_counter(
1586 '/err/nat44-in2out-slowpath/good in2out packets processed')
1587 self.assertEqual(err - totaln, 4)
1590 tcpn = self.statistics.get_err_counter('/err/nat44-out2in/TCP packets')
1591 udpn = self.statistics.get_err_counter('/err/nat44-out2in/UDP packets')
1592 icmpn = self.statistics.get_err_counter(
1593 '/err/nat44-out2in/ICMP packets')
1594 totaln = self.statistics.get_err_counter(
1595 '/err/nat44-out2in/good out2in packets processed')
1597 pkts = self.create_stream_out(self.pg1)
1598 self.pg1.add_stream(pkts)
1599 self.pg_enable_capture(self.pg_interfaces)
1601 capture = self.pg0.get_capture(len(pkts))
1602 self.verify_capture_in(capture, self.pg0)
1604 err = self.statistics.get_err_counter('/err/nat44-out2in/TCP packets')
1605 self.assertEqual(err - tcpn, 2)
1606 err = self.statistics.get_err_counter('/err/nat44-out2in/UDP packets')
1607 self.assertEqual(err - udpn, 1)
1608 err = self.statistics.get_err_counter('/err/nat44-out2in/ICMP packets')
1609 self.assertEqual(err - icmpn, 1)
1610 err = self.statistics.get_err_counter(
1611 '/err/nat44-out2in/good out2in packets processed')
1612 self.assertEqual(err - totaln, 4)
1614 users = self.statistics.get_counter('/nat44/total-users')
1615 self.assertEqual(users[0][0], 1)
1616 sessions = self.statistics.get_counter('/nat44/total-sessions')
1617 self.assertEqual(sessions[0][0], 3)
1619 def test_dynamic_icmp_errors_in2out_ttl_1(self):
1620 """ NAT44 handling of client packets with TTL=1 """
1622 self.nat44_add_address(self.nat_addr)
1623 flags = self.config_flags.NAT_IS_INSIDE
1624 self.vapi.nat44_interface_add_del_feature(
1625 sw_if_index=self.pg0.sw_if_index,
1626 flags=flags, is_add=1)
1627 self.vapi.nat44_interface_add_del_feature(
1628 sw_if_index=self.pg1.sw_if_index,
1631 # Client side - generate traffic
1632 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1633 self.pg0.add_stream(pkts)
1634 self.pg_enable_capture(self.pg_interfaces)
1637 # Client side - verify ICMP type 11 packets
1638 capture = self.pg0.get_capture(len(pkts))
1639 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1641 def test_dynamic_icmp_errors_out2in_ttl_1(self):
1642 """ NAT44 handling of server packets with TTL=1 """
1644 self.nat44_add_address(self.nat_addr)
1645 flags = self.config_flags.NAT_IS_INSIDE
1646 self.vapi.nat44_interface_add_del_feature(
1647 sw_if_index=self.pg0.sw_if_index,
1648 flags=flags, is_add=1)
1649 self.vapi.nat44_interface_add_del_feature(
1650 sw_if_index=self.pg1.sw_if_index,
1653 # Client side - create sessions
1654 pkts = self.create_stream_in(self.pg0, self.pg1)
1655 self.pg0.add_stream(pkts)
1656 self.pg_enable_capture(self.pg_interfaces)
1659 # Server side - generate traffic
1660 capture = self.pg1.get_capture(len(pkts))
1661 self.verify_capture_out(capture)
1662 pkts = self.create_stream_out(self.pg1, ttl=1)
1663 self.pg1.add_stream(pkts)
1664 self.pg_enable_capture(self.pg_interfaces)
1667 # Server side - verify ICMP type 11 packets
1668 capture = self.pg1.get_capture(len(pkts))
1669 self.verify_capture_out_with_icmp_errors(capture,
1670 src_ip=self.pg1.local_ip4)
1672 def test_dynamic_icmp_errors_in2out_ttl_2(self):
1673 """ NAT44 handling of error responses to client packets with TTL=2 """
1675 self.nat44_add_address(self.nat_addr)
1676 flags = self.config_flags.NAT_IS_INSIDE
1677 self.vapi.nat44_interface_add_del_feature(
1678 sw_if_index=self.pg0.sw_if_index,
1679 flags=flags, is_add=1)
1680 self.vapi.nat44_interface_add_del_feature(
1681 sw_if_index=self.pg1.sw_if_index,
1684 # Client side - generate traffic
1685 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1686 self.pg0.add_stream(pkts)
1687 self.pg_enable_capture(self.pg_interfaces)
1690 # Server side - simulate ICMP type 11 response
1691 capture = self.pg1.get_capture(len(pkts))
1692 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1693 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1694 ICMP(type=11) / packet[IP] for packet in capture]
1695 self.pg1.add_stream(pkts)
1696 self.pg_enable_capture(self.pg_interfaces)
1699 # Client side - verify ICMP type 11 packets
1700 capture = self.pg0.get_capture(len(pkts))
1701 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1703 def test_dynamic_icmp_errors_out2in_ttl_2(self):
1704 """ NAT44 handling of error responses to server packets with TTL=2 """
1706 self.nat44_add_address(self.nat_addr)
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,
1715 # Client side - create sessions
1716 pkts = self.create_stream_in(self.pg0, self.pg1)
1717 self.pg0.add_stream(pkts)
1718 self.pg_enable_capture(self.pg_interfaces)
1721 # Server side - generate traffic
1722 capture = self.pg1.get_capture(len(pkts))
1723 self.verify_capture_out(capture)
1724 pkts = self.create_stream_out(self.pg1, ttl=2)
1725 self.pg1.add_stream(pkts)
1726 self.pg_enable_capture(self.pg_interfaces)
1729 # Client side - simulate ICMP type 11 response
1730 capture = self.pg0.get_capture(len(pkts))
1731 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1732 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1733 ICMP(type=11) / packet[IP] for packet in capture]
1734 self.pg0.add_stream(pkts)
1735 self.pg_enable_capture(self.pg_interfaces)
1738 # Server side - verify ICMP type 11 packets
1739 capture = self.pg1.get_capture(len(pkts))
1740 self.verify_capture_out_with_icmp_errors(capture)
1742 def test_ping_out_interface_from_outside(self):
1743 """ Ping NAT44 out interface from outside network """
1745 self.nat44_add_address(self.nat_addr)
1746 flags = self.config_flags.NAT_IS_INSIDE
1747 self.vapi.nat44_interface_add_del_feature(
1748 sw_if_index=self.pg0.sw_if_index,
1749 flags=flags, is_add=1)
1750 self.vapi.nat44_interface_add_del_feature(
1751 sw_if_index=self.pg1.sw_if_index,
1754 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1755 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1756 ICMP(id=self.icmp_id_out, type='echo-request'))
1758 self.pg1.add_stream(pkts)
1759 self.pg_enable_capture(self.pg_interfaces)
1761 capture = self.pg1.get_capture(len(pkts))
1764 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1765 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1766 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1767 self.assertEqual(packet[ICMP].type, 0) # echo reply
1769 self.logger.error(ppp("Unexpected or invalid packet "
1770 "(outside network):", packet))
1773 def test_ping_internal_host_from_outside(self):
1774 """ Ping internal host from outside network """
1776 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1777 flags = self.config_flags.NAT_IS_INSIDE
1778 self.vapi.nat44_interface_add_del_feature(
1779 sw_if_index=self.pg0.sw_if_index,
1780 flags=flags, is_add=1)
1781 self.vapi.nat44_interface_add_del_feature(
1782 sw_if_index=self.pg1.sw_if_index,
1786 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1787 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
1788 ICMP(id=self.icmp_id_out, type='echo-request'))
1789 self.pg1.add_stream(pkt)
1790 self.pg_enable_capture(self.pg_interfaces)
1792 capture = self.pg0.get_capture(1)
1793 self.verify_capture_in(capture, self.pg0)
1794 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1797 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1798 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1799 ICMP(id=self.icmp_id_in, type='echo-reply'))
1800 self.pg0.add_stream(pkt)
1801 self.pg_enable_capture(self.pg_interfaces)
1803 capture = self.pg1.get_capture(1)
1804 self.verify_capture_out(capture, same_port=True)
1805 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1807 def test_forwarding(self):
1808 """ NAT44 forwarding test """
1810 flags = self.config_flags.NAT_IS_INSIDE
1811 self.vapi.nat44_interface_add_del_feature(
1812 sw_if_index=self.pg0.sw_if_index,
1813 flags=flags, is_add=1)
1814 self.vapi.nat44_interface_add_del_feature(
1815 sw_if_index=self.pg1.sw_if_index,
1817 self.vapi.nat44_forwarding_enable_disable(enable=1)
1819 real_ip = self.pg0.remote_ip4
1820 alias_ip = self.nat_addr
1821 flags = self.config_flags.NAT_IS_ADDR_ONLY
1822 self.vapi.nat44_add_del_static_mapping(is_add=1,
1823 local_ip_address=real_ip,
1824 external_ip_address=alias_ip,
1825 external_sw_if_index=0xFFFFFFFF,
1829 # static mapping match
1831 pkts = self.create_stream_out(self.pg1)
1832 self.pg1.add_stream(pkts)
1833 self.pg_enable_capture(self.pg_interfaces)
1835 capture = self.pg0.get_capture(len(pkts))
1836 self.verify_capture_in(capture, self.pg0)
1838 pkts = self.create_stream_in(self.pg0, self.pg1)
1839 self.pg0.add_stream(pkts)
1840 self.pg_enable_capture(self.pg_interfaces)
1842 capture = self.pg1.get_capture(len(pkts))
1843 self.verify_capture_out(capture, same_port=True)
1845 # no static mapping match
1847 host0 = self.pg0.remote_hosts[0]
1848 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1850 pkts = self.create_stream_out(self.pg1,
1851 dst_ip=self.pg0.remote_ip4,
1852 use_inside_ports=True)
1853 self.pg1.add_stream(pkts)
1854 self.pg_enable_capture(self.pg_interfaces)
1856 capture = self.pg0.get_capture(len(pkts))
1857 self.verify_capture_in(capture, self.pg0)
1859 pkts = self.create_stream_in(self.pg0, self.pg1)
1860 self.pg0.add_stream(pkts)
1861 self.pg_enable_capture(self.pg_interfaces)
1863 capture = self.pg1.get_capture(len(pkts))
1864 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1867 self.pg0.remote_hosts[0] = host0
1870 self.vapi.nat44_forwarding_enable_disable(enable=0)
1871 flags = self.config_flags.NAT_IS_ADDR_ONLY
1872 self.vapi.nat44_add_del_static_mapping(
1874 local_ip_address=real_ip,
1875 external_ip_address=alias_ip,
1876 external_sw_if_index=0xFFFFFFFF,
1879 def test_static_in(self):
1880 """ 1:1 NAT initialized from inside network """
1882 nat_ip = "10.0.0.10"
1883 self.tcp_port_out = 6303
1884 self.udp_port_out = 6304
1885 self.icmp_id_out = 6305
1887 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1888 flags = self.config_flags.NAT_IS_INSIDE
1889 self.vapi.nat44_interface_add_del_feature(
1890 sw_if_index=self.pg0.sw_if_index,
1891 flags=flags, is_add=1)
1892 self.vapi.nat44_interface_add_del_feature(
1893 sw_if_index=self.pg1.sw_if_index,
1895 sm = self.vapi.nat44_static_mapping_dump()
1896 self.assertEqual(len(sm), 1)
1897 self.assertEqual(sm[0].tag, '')
1898 self.assertEqual(sm[0].protocol, 0)
1899 self.assertEqual(sm[0].local_port, 0)
1900 self.assertEqual(sm[0].external_port, 0)
1903 pkts = self.create_stream_in(self.pg0, self.pg1)
1904 self.pg0.add_stream(pkts)
1905 self.pg_enable_capture(self.pg_interfaces)
1907 capture = self.pg1.get_capture(len(pkts))
1908 self.verify_capture_out(capture, nat_ip, True)
1911 pkts = self.create_stream_out(self.pg1, nat_ip)
1912 self.pg1.add_stream(pkts)
1913 self.pg_enable_capture(self.pg_interfaces)
1915 capture = self.pg0.get_capture(len(pkts))
1916 self.verify_capture_in(capture, self.pg0)
1918 def test_static_out(self):
1919 """ 1:1 NAT initialized from outside network """
1921 nat_ip = "10.0.0.20"
1922 self.tcp_port_out = 6303
1923 self.udp_port_out = 6304
1924 self.icmp_id_out = 6305
1927 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
1928 flags = self.config_flags.NAT_IS_INSIDE
1929 self.vapi.nat44_interface_add_del_feature(
1930 sw_if_index=self.pg0.sw_if_index,
1931 flags=flags, is_add=1)
1932 self.vapi.nat44_interface_add_del_feature(
1933 sw_if_index=self.pg1.sw_if_index,
1935 sm = self.vapi.nat44_static_mapping_dump()
1936 self.assertEqual(len(sm), 1)
1937 self.assertEqual(sm[0].tag, tag)
1940 pkts = self.create_stream_out(self.pg1, nat_ip)
1941 self.pg1.add_stream(pkts)
1942 self.pg_enable_capture(self.pg_interfaces)
1944 capture = self.pg0.get_capture(len(pkts))
1945 self.verify_capture_in(capture, self.pg0)
1948 pkts = self.create_stream_in(self.pg0, self.pg1)
1949 self.pg0.add_stream(pkts)
1950 self.pg_enable_capture(self.pg_interfaces)
1952 capture = self.pg1.get_capture(len(pkts))
1953 self.verify_capture_out(capture, nat_ip, True)
1955 def test_static_with_port_in(self):
1956 """ 1:1 NAPT initialized from inside network """
1958 self.tcp_port_out = 3606
1959 self.udp_port_out = 3607
1960 self.icmp_id_out = 3608
1962 self.nat44_add_address(self.nat_addr)
1963 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1964 self.tcp_port_in, self.tcp_port_out,
1965 proto=IP_PROTOS.tcp)
1966 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1967 self.udp_port_in, self.udp_port_out,
1968 proto=IP_PROTOS.udp)
1969 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1970 self.icmp_id_in, self.icmp_id_out,
1971 proto=IP_PROTOS.icmp)
1972 flags = self.config_flags.NAT_IS_INSIDE
1973 self.vapi.nat44_interface_add_del_feature(
1974 sw_if_index=self.pg0.sw_if_index,
1975 flags=flags, is_add=1)
1976 self.vapi.nat44_interface_add_del_feature(
1977 sw_if_index=self.pg1.sw_if_index,
1981 pkts = self.create_stream_in(self.pg0, self.pg1)
1982 self.pg0.add_stream(pkts)
1983 self.pg_enable_capture(self.pg_interfaces)
1985 capture = self.pg1.get_capture(len(pkts))
1986 self.verify_capture_out(capture)
1989 pkts = self.create_stream_out(self.pg1)
1990 self.pg1.add_stream(pkts)
1991 self.pg_enable_capture(self.pg_interfaces)
1993 capture = self.pg0.get_capture(len(pkts))
1994 self.verify_capture_in(capture, self.pg0)
1996 def test_static_with_port_out(self):
1997 """ 1:1 NAPT initialized from outside network """
1999 self.tcp_port_out = 30606
2000 self.udp_port_out = 30607
2001 self.icmp_id_out = 30608
2003 self.nat44_add_address(self.nat_addr)
2004 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2005 self.tcp_port_in, self.tcp_port_out,
2006 proto=IP_PROTOS.tcp)
2007 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2008 self.udp_port_in, self.udp_port_out,
2009 proto=IP_PROTOS.udp)
2010 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2011 self.icmp_id_in, self.icmp_id_out,
2012 proto=IP_PROTOS.icmp)
2013 flags = self.config_flags.NAT_IS_INSIDE
2014 self.vapi.nat44_interface_add_del_feature(
2015 sw_if_index=self.pg0.sw_if_index,
2016 flags=flags, is_add=1)
2017 self.vapi.nat44_interface_add_del_feature(
2018 sw_if_index=self.pg1.sw_if_index,
2022 pkts = self.create_stream_out(self.pg1)
2023 self.pg1.add_stream(pkts)
2024 self.pg_enable_capture(self.pg_interfaces)
2026 capture = self.pg0.get_capture(len(pkts))
2027 self.verify_capture_in(capture, self.pg0)
2030 pkts = self.create_stream_in(self.pg0, self.pg1)
2031 self.pg0.add_stream(pkts)
2032 self.pg_enable_capture(self.pg_interfaces)
2034 capture = self.pg1.get_capture(len(pkts))
2035 self.verify_capture_out(capture)
2037 def test_static_vrf_aware(self):
2038 """ 1:1 NAT VRF awareness """
2040 nat_ip1 = "10.0.0.30"
2041 nat_ip2 = "10.0.0.40"
2042 self.tcp_port_out = 6303
2043 self.udp_port_out = 6304
2044 self.icmp_id_out = 6305
2046 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
2048 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
2050 flags = self.config_flags.NAT_IS_INSIDE
2051 self.vapi.nat44_interface_add_del_feature(
2052 sw_if_index=self.pg3.sw_if_index,
2054 self.vapi.nat44_interface_add_del_feature(
2055 sw_if_index=self.pg0.sw_if_index,
2056 flags=flags, is_add=1)
2057 self.vapi.nat44_interface_add_del_feature(
2058 sw_if_index=self.pg4.sw_if_index,
2059 flags=flags, is_add=1)
2061 # inside interface VRF match NAT44 static mapping VRF
2062 pkts = self.create_stream_in(self.pg4, self.pg3)
2063 self.pg4.add_stream(pkts)
2064 self.pg_enable_capture(self.pg_interfaces)
2066 capture = self.pg3.get_capture(len(pkts))
2067 self.verify_capture_out(capture, nat_ip1, True)
2069 # inside interface VRF don't match NAT44 static mapping VRF (packets
2071 pkts = self.create_stream_in(self.pg0, self.pg3)
2072 self.pg0.add_stream(pkts)
2073 self.pg_enable_capture(self.pg_interfaces)
2075 self.pg3.assert_nothing_captured()
2077 def test_dynamic_to_static(self):
2078 """ Switch from dynamic translation to 1:1NAT """
2079 nat_ip = "10.0.0.10"
2080 self.tcp_port_out = 6303
2081 self.udp_port_out = 6304
2082 self.icmp_id_out = 6305
2084 self.nat44_add_address(self.nat_addr)
2085 flags = self.config_flags.NAT_IS_INSIDE
2086 self.vapi.nat44_interface_add_del_feature(
2087 sw_if_index=self.pg0.sw_if_index,
2088 flags=flags, is_add=1)
2089 self.vapi.nat44_interface_add_del_feature(
2090 sw_if_index=self.pg1.sw_if_index,
2094 pkts = self.create_stream_in(self.pg0, self.pg1)
2095 self.pg0.add_stream(pkts)
2096 self.pg_enable_capture(self.pg_interfaces)
2098 capture = self.pg1.get_capture(len(pkts))
2099 self.verify_capture_out(capture)
2102 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2103 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
2104 self.assertEqual(len(sessions), 0)
2105 pkts = self.create_stream_in(self.pg0, self.pg1)
2106 self.pg0.add_stream(pkts)
2107 self.pg_enable_capture(self.pg_interfaces)
2109 capture = self.pg1.get_capture(len(pkts))
2110 self.verify_capture_out(capture, nat_ip, True)
2112 def test_identity_nat(self):
2113 """ Identity NAT """
2114 flags = self.config_flags.NAT_IS_ADDR_ONLY
2115 self.vapi.nat44_add_del_identity_mapping(
2116 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
2117 flags=flags, is_add=1)
2118 flags = self.config_flags.NAT_IS_INSIDE
2119 self.vapi.nat44_interface_add_del_feature(
2120 sw_if_index=self.pg0.sw_if_index,
2121 flags=flags, is_add=1)
2122 self.vapi.nat44_interface_add_del_feature(
2123 sw_if_index=self.pg1.sw_if_index,
2126 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2127 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2128 TCP(sport=12345, dport=56789))
2129 self.pg1.add_stream(p)
2130 self.pg_enable_capture(self.pg_interfaces)
2132 capture = self.pg0.get_capture(1)
2137 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2138 self.assertEqual(ip.src, self.pg1.remote_ip4)
2139 self.assertEqual(tcp.dport, 56789)
2140 self.assertEqual(tcp.sport, 12345)
2141 self.assert_packet_checksums_valid(p)
2143 self.logger.error(ppp("Unexpected or invalid packet:", p))
2146 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
2147 self.assertEqual(len(sessions), 0)
2148 flags = self.config_flags.NAT_IS_ADDR_ONLY
2149 self.vapi.nat44_add_del_identity_mapping(
2150 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
2151 flags=flags, vrf_id=1, is_add=1)
2152 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2153 self.assertEqual(len(identity_mappings), 2)
2155 def test_multiple_inside_interfaces(self):
2156 """ NAT44 multiple non-overlapping address space inside interfaces """
2158 self.nat44_add_address(self.nat_addr)
2159 flags = self.config_flags.NAT_IS_INSIDE
2160 self.vapi.nat44_interface_add_del_feature(
2161 sw_if_index=self.pg0.sw_if_index,
2162 flags=flags, is_add=1)
2163 self.vapi.nat44_interface_add_del_feature(
2164 sw_if_index=self.pg1.sw_if_index,
2165 flags=flags, is_add=1)
2166 self.vapi.nat44_interface_add_del_feature(
2167 sw_if_index=self.pg3.sw_if_index,
2170 # between two NAT44 inside interfaces (no translation)
2171 pkts = self.create_stream_in(self.pg0, self.pg1)
2172 self.pg0.add_stream(pkts)
2173 self.pg_enable_capture(self.pg_interfaces)
2175 capture = self.pg1.get_capture(len(pkts))
2176 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
2178 # from NAT44 inside to interface without NAT44 feature (no translation)
2179 pkts = self.create_stream_in(self.pg0, self.pg2)
2180 self.pg0.add_stream(pkts)
2181 self.pg_enable_capture(self.pg_interfaces)
2183 capture = self.pg2.get_capture(len(pkts))
2184 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2186 # in2out 1st interface
2187 pkts = self.create_stream_in(self.pg0, self.pg3)
2188 self.pg0.add_stream(pkts)
2189 self.pg_enable_capture(self.pg_interfaces)
2191 capture = self.pg3.get_capture(len(pkts))
2192 self.verify_capture_out(capture)
2194 # out2in 1st interface
2195 pkts = self.create_stream_out(self.pg3)
2196 self.pg3.add_stream(pkts)
2197 self.pg_enable_capture(self.pg_interfaces)
2199 capture = self.pg0.get_capture(len(pkts))
2200 self.verify_capture_in(capture, self.pg0)
2202 # in2out 2nd interface
2203 pkts = self.create_stream_in(self.pg1, self.pg3)
2204 self.pg1.add_stream(pkts)
2205 self.pg_enable_capture(self.pg_interfaces)
2207 capture = self.pg3.get_capture(len(pkts))
2208 self.verify_capture_out(capture)
2210 # out2in 2nd interface
2211 pkts = self.create_stream_out(self.pg3)
2212 self.pg3.add_stream(pkts)
2213 self.pg_enable_capture(self.pg_interfaces)
2215 capture = self.pg1.get_capture(len(pkts))
2216 self.verify_capture_in(capture, self.pg1)
2218 def test_inside_overlapping_interfaces(self):
2219 """ NAT44 multiple inside interfaces with overlapping address space """
2221 static_nat_ip = "10.0.0.10"
2222 self.nat44_add_address(self.nat_addr)
2223 flags = self.config_flags.NAT_IS_INSIDE
2224 self.vapi.nat44_interface_add_del_feature(
2225 sw_if_index=self.pg3.sw_if_index,
2227 self.vapi.nat44_interface_add_del_feature(
2228 sw_if_index=self.pg4.sw_if_index,
2229 flags=flags, is_add=1)
2230 self.vapi.nat44_interface_add_del_feature(
2231 sw_if_index=self.pg5.sw_if_index,
2232 flags=flags, is_add=1)
2233 self.vapi.nat44_interface_add_del_feature(
2234 sw_if_index=self.pg6.sw_if_index,
2235 flags=flags, is_add=1)
2236 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2239 # between NAT44 inside interfaces with same VRF (no translation)
2240 pkts = self.create_stream_in(self.pg4, self.pg5)
2241 self.pg4.add_stream(pkts)
2242 self.pg_enable_capture(self.pg_interfaces)
2244 capture = self.pg5.get_capture(len(pkts))
2245 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2247 # between NAT44 inside interfaces with different VRF (hairpinning)
2248 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2249 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2250 TCP(sport=1234, dport=5678))
2251 self.pg4.add_stream(p)
2252 self.pg_enable_capture(self.pg_interfaces)
2254 capture = self.pg6.get_capture(1)
2259 self.assertEqual(ip.src, self.nat_addr)
2260 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2261 self.assertNotEqual(tcp.sport, 1234)
2262 self.assertEqual(tcp.dport, 5678)
2264 self.logger.error(ppp("Unexpected or invalid packet:", p))
2267 # in2out 1st interface
2268 pkts = self.create_stream_in(self.pg4, self.pg3)
2269 self.pg4.add_stream(pkts)
2270 self.pg_enable_capture(self.pg_interfaces)
2272 capture = self.pg3.get_capture(len(pkts))
2273 self.verify_capture_out(capture)
2275 # out2in 1st interface
2276 pkts = self.create_stream_out(self.pg3)
2277 self.pg3.add_stream(pkts)
2278 self.pg_enable_capture(self.pg_interfaces)
2280 capture = self.pg4.get_capture(len(pkts))
2281 self.verify_capture_in(capture, self.pg4)
2283 # in2out 2nd interface
2284 pkts = self.create_stream_in(self.pg5, self.pg3)
2285 self.pg5.add_stream(pkts)
2286 self.pg_enable_capture(self.pg_interfaces)
2288 capture = self.pg3.get_capture(len(pkts))
2289 self.verify_capture_out(capture)
2291 # out2in 2nd interface
2292 pkts = self.create_stream_out(self.pg3)
2293 self.pg3.add_stream(pkts)
2294 self.pg_enable_capture(self.pg_interfaces)
2296 capture = self.pg5.get_capture(len(pkts))
2297 self.verify_capture_in(capture, self.pg5)
2300 addresses = self.vapi.nat44_address_dump()
2301 self.assertEqual(len(addresses), 1)
2302 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4, 10)
2303 self.assertEqual(len(sessions), 3)
2304 for session in sessions:
2305 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2306 self.assertEqual(str(session.inside_ip_address),
2307 self.pg5.remote_ip4)
2308 self.assertEqual(session.outside_ip_address,
2309 addresses[0].ip_address)
2310 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2311 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2312 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2313 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2314 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2315 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2316 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2317 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2318 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2320 # in2out 3rd interface
2321 pkts = self.create_stream_in(self.pg6, self.pg3)
2322 self.pg6.add_stream(pkts)
2323 self.pg_enable_capture(self.pg_interfaces)
2325 capture = self.pg3.get_capture(len(pkts))
2326 self.verify_capture_out(capture, static_nat_ip, True)
2328 # out2in 3rd interface
2329 pkts = self.create_stream_out(self.pg3, static_nat_ip)
2330 self.pg3.add_stream(pkts)
2331 self.pg_enable_capture(self.pg_interfaces)
2333 capture = self.pg6.get_capture(len(pkts))
2334 self.verify_capture_in(capture, self.pg6)
2336 # general user and session dump verifications
2337 users = self.vapi.nat44_user_dump()
2338 self.assertGreaterEqual(len(users), 3)
2339 addresses = self.vapi.nat44_address_dump()
2340 self.assertEqual(len(addresses), 1)
2342 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2344 for session in sessions:
2345 self.assertEqual(user.ip_address, session.inside_ip_address)
2346 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2347 self.assertTrue(session.protocol in
2348 [IP_PROTOS.tcp, IP_PROTOS.udp,
2350 self.assertFalse(session.flags &
2351 self.config_flags.NAT_IS_EXT_HOST_VALID)
2354 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4, 10)
2355 self.assertGreaterEqual(len(sessions), 4)
2356 for session in sessions:
2357 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2358 self.assertEqual(str(session.inside_ip_address),
2359 self.pg4.remote_ip4)
2360 self.assertEqual(session.outside_ip_address,
2361 addresses[0].ip_address)
2364 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4, 20)
2365 self.assertGreaterEqual(len(sessions), 3)
2366 for session in sessions:
2367 self.assertTrue(session.flags & self.config_flags.NAT_IS_STATIC)
2368 self.assertEqual(str(session.inside_ip_address),
2369 self.pg6.remote_ip4)
2370 self.assertEqual(str(session.outside_ip_address),
2372 self.assertTrue(session.inside_port in
2373 [self.tcp_port_in, self.udp_port_in,
2376 def test_hairpinning(self):
2377 """ NAT44 hairpinning - 1:1 NAPT """
2379 host = self.pg0.remote_hosts[0]
2380 server = self.pg0.remote_hosts[1]
2383 server_in_port = 5678
2384 server_out_port = 8765
2386 self.nat44_add_address(self.nat_addr)
2387 flags = self.config_flags.NAT_IS_INSIDE
2388 self.vapi.nat44_interface_add_del_feature(
2389 sw_if_index=self.pg0.sw_if_index,
2390 flags=flags, is_add=1)
2391 self.vapi.nat44_interface_add_del_feature(
2392 sw_if_index=self.pg1.sw_if_index,
2395 # add static mapping for server
2396 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2397 server_in_port, server_out_port,
2398 proto=IP_PROTOS.tcp)
2400 # send packet from host to server
2401 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2402 IP(src=host.ip4, dst=self.nat_addr) /
2403 TCP(sport=host_in_port, dport=server_out_port))
2404 self.pg0.add_stream(p)
2405 self.pg_enable_capture(self.pg_interfaces)
2407 capture = self.pg0.get_capture(1)
2412 self.assertEqual(ip.src, self.nat_addr)
2413 self.assertEqual(ip.dst, server.ip4)
2414 self.assertNotEqual(tcp.sport, host_in_port)
2415 self.assertEqual(tcp.dport, server_in_port)
2416 self.assert_packet_checksums_valid(p)
2417 host_out_port = tcp.sport
2419 self.logger.error(ppp("Unexpected or invalid packet:", p))
2422 # send reply from server to host
2423 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2424 IP(src=server.ip4, dst=self.nat_addr) /
2425 TCP(sport=server_in_port, dport=host_out_port))
2426 self.pg0.add_stream(p)
2427 self.pg_enable_capture(self.pg_interfaces)
2429 capture = self.pg0.get_capture(1)
2434 self.assertEqual(ip.src, self.nat_addr)
2435 self.assertEqual(ip.dst, host.ip4)
2436 self.assertEqual(tcp.sport, server_out_port)
2437 self.assertEqual(tcp.dport, host_in_port)
2438 self.assert_packet_checksums_valid(p)
2440 self.logger.error(ppp("Unexpected or invalid packet:", p))
2443 def test_hairpinning2(self):
2444 """ NAT44 hairpinning - 1:1 NAT"""
2446 server1_nat_ip = "10.0.0.10"
2447 server2_nat_ip = "10.0.0.11"
2448 host = self.pg0.remote_hosts[0]
2449 server1 = self.pg0.remote_hosts[1]
2450 server2 = self.pg0.remote_hosts[2]
2451 server_tcp_port = 22
2452 server_udp_port = 20
2454 self.nat44_add_address(self.nat_addr)
2455 flags = self.config_flags.NAT_IS_INSIDE
2456 self.vapi.nat44_interface_add_del_feature(
2457 sw_if_index=self.pg0.sw_if_index,
2458 flags=flags, is_add=1)
2459 self.vapi.nat44_interface_add_del_feature(
2460 sw_if_index=self.pg1.sw_if_index,
2463 # add static mapping for servers
2464 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2465 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
2469 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2470 IP(src=host.ip4, dst=server1_nat_ip) /
2471 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2473 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2474 IP(src=host.ip4, dst=server1_nat_ip) /
2475 UDP(sport=self.udp_port_in, dport=server_udp_port))
2477 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2478 IP(src=host.ip4, dst=server1_nat_ip) /
2479 ICMP(id=self.icmp_id_in, type='echo-request'))
2481 self.pg0.add_stream(pkts)
2482 self.pg_enable_capture(self.pg_interfaces)
2484 capture = self.pg0.get_capture(len(pkts))
2485 for packet in capture:
2487 self.assertEqual(packet[IP].src, self.nat_addr)
2488 self.assertEqual(packet[IP].dst, server1.ip4)
2489 if packet.haslayer(TCP):
2490 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2491 self.assertEqual(packet[TCP].dport, server_tcp_port)
2492 self.tcp_port_out = packet[TCP].sport
2493 self.assert_packet_checksums_valid(packet)
2494 elif packet.haslayer(UDP):
2495 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2496 self.assertEqual(packet[UDP].dport, server_udp_port)
2497 self.udp_port_out = packet[UDP].sport
2499 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2500 self.icmp_id_out = packet[ICMP].id
2502 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2507 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2508 IP(src=server1.ip4, dst=self.nat_addr) /
2509 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2511 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2512 IP(src=server1.ip4, dst=self.nat_addr) /
2513 UDP(sport=server_udp_port, dport=self.udp_port_out))
2515 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2516 IP(src=server1.ip4, dst=self.nat_addr) /
2517 ICMP(id=self.icmp_id_out, type='echo-reply'))
2519 self.pg0.add_stream(pkts)
2520 self.pg_enable_capture(self.pg_interfaces)
2522 capture = self.pg0.get_capture(len(pkts))
2523 for packet in capture:
2525 self.assertEqual(packet[IP].src, server1_nat_ip)
2526 self.assertEqual(packet[IP].dst, host.ip4)
2527 if packet.haslayer(TCP):
2528 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2529 self.assertEqual(packet[TCP].sport, server_tcp_port)
2530 self.assert_packet_checksums_valid(packet)
2531 elif packet.haslayer(UDP):
2532 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2533 self.assertEqual(packet[UDP].sport, server_udp_port)
2535 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2537 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2540 # server2 to server1
2542 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2543 IP(src=server2.ip4, dst=server1_nat_ip) /
2544 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2546 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2547 IP(src=server2.ip4, dst=server1_nat_ip) /
2548 UDP(sport=self.udp_port_in, dport=server_udp_port))
2550 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2551 IP(src=server2.ip4, dst=server1_nat_ip) /
2552 ICMP(id=self.icmp_id_in, type='echo-request'))
2554 self.pg0.add_stream(pkts)
2555 self.pg_enable_capture(self.pg_interfaces)
2557 capture = self.pg0.get_capture(len(pkts))
2558 for packet in capture:
2560 self.assertEqual(packet[IP].src, server2_nat_ip)
2561 self.assertEqual(packet[IP].dst, server1.ip4)
2562 if packet.haslayer(TCP):
2563 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2564 self.assertEqual(packet[TCP].dport, server_tcp_port)
2565 self.tcp_port_out = packet[TCP].sport
2566 self.assert_packet_checksums_valid(packet)
2567 elif packet.haslayer(UDP):
2568 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2569 self.assertEqual(packet[UDP].dport, server_udp_port)
2570 self.udp_port_out = packet[UDP].sport
2572 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2573 self.icmp_id_out = packet[ICMP].id
2575 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2578 # server1 to server2
2580 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2581 IP(src=server1.ip4, dst=server2_nat_ip) /
2582 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2584 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2585 IP(src=server1.ip4, dst=server2_nat_ip) /
2586 UDP(sport=server_udp_port, dport=self.udp_port_out))
2588 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2589 IP(src=server1.ip4, dst=server2_nat_ip) /
2590 ICMP(id=self.icmp_id_out, type='echo-reply'))
2592 self.pg0.add_stream(pkts)
2593 self.pg_enable_capture(self.pg_interfaces)
2595 capture = self.pg0.get_capture(len(pkts))
2596 for packet in capture:
2598 self.assertEqual(packet[IP].src, server1_nat_ip)
2599 self.assertEqual(packet[IP].dst, server2.ip4)
2600 if packet.haslayer(TCP):
2601 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2602 self.assertEqual(packet[TCP].sport, server_tcp_port)
2603 self.assert_packet_checksums_valid(packet)
2604 elif packet.haslayer(UDP):
2605 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2606 self.assertEqual(packet[UDP].sport, server_udp_port)
2608 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2610 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2613 def test_max_translations_per_user(self):
2614 """ MAX translations per user - recycle the least recently used """
2616 self.nat44_add_address(self.nat_addr)
2617 flags = self.config_flags.NAT_IS_INSIDE
2618 self.vapi.nat44_interface_add_del_feature(
2619 sw_if_index=self.pg0.sw_if_index,
2620 flags=flags, is_add=1)
2621 self.vapi.nat44_interface_add_del_feature(
2622 sw_if_index=self.pg1.sw_if_index,
2625 # get maximum number of translations per user
2626 nat44_config = self.vapi.nat_show_config()
2628 # send more than maximum number of translations per user packets
2629 pkts_num = nat44_config.max_translations_per_user + 5
2631 for port in range(0, pkts_num):
2632 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2633 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2634 TCP(sport=1025 + port))
2636 self.pg0.add_stream(pkts)
2637 self.pg_enable_capture(self.pg_interfaces)
2640 # verify number of translated packet
2641 self.pg1.get_capture(pkts_num)
2643 users = self.vapi.nat44_user_dump()
2645 if user.ip_address == self.pg0.remote_ip4:
2646 self.assertEqual(user.nsessions,
2647 nat44_config.max_translations_per_user)
2648 self.assertEqual(user.nstaticsessions, 0)
2651 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2653 proto=IP_PROTOS.tcp)
2654 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2655 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2656 TCP(sport=tcp_port))
2657 self.pg0.add_stream(p)
2658 self.pg_enable_capture(self.pg_interfaces)
2660 self.pg1.get_capture(1)
2661 users = self.vapi.nat44_user_dump()
2663 if user.ip_address == self.pg0.remote_ip4:
2664 self.assertEqual(user.nsessions,
2665 nat44_config.max_translations_per_user - 1)
2666 self.assertEqual(user.nstaticsessions, 1)
2668 def test_interface_addr(self):
2669 """ Acquire NAT44 addresses from interface """
2670 self.vapi.nat44_add_del_interface_addr(
2672 sw_if_index=self.pg7.sw_if_index)
2674 # no address in NAT pool
2675 addresses = self.vapi.nat44_address_dump()
2676 self.assertEqual(0, len(addresses))
2678 # configure interface address and check NAT address pool
2679 self.pg7.config_ip4()
2680 addresses = self.vapi.nat44_address_dump()
2681 self.assertEqual(1, len(addresses))
2682 self.assertEqual(str(addresses[0].ip_address), self.pg7.local_ip4)
2684 # remove interface address and check NAT address pool
2685 self.pg7.unconfig_ip4()
2686 addresses = self.vapi.nat44_address_dump()
2687 self.assertEqual(0, len(addresses))
2689 def test_interface_addr_static_mapping(self):
2690 """ Static mapping with addresses from interface """
2693 self.vapi.nat44_add_del_interface_addr(
2695 sw_if_index=self.pg7.sw_if_index)
2696 self.nat44_add_static_mapping(
2698 external_sw_if_index=self.pg7.sw_if_index,
2701 # static mappings with external interface
2702 static_mappings = self.vapi.nat44_static_mapping_dump()
2703 self.assertEqual(1, len(static_mappings))
2704 self.assertEqual(self.pg7.sw_if_index,
2705 static_mappings[0].external_sw_if_index)
2706 self.assertEqual(static_mappings[0].tag, tag)
2708 # configure interface address and check static mappings
2709 self.pg7.config_ip4()
2710 static_mappings = self.vapi.nat44_static_mapping_dump()
2711 self.assertEqual(2, len(static_mappings))
2713 for sm in static_mappings:
2714 if sm.external_sw_if_index == 0xFFFFFFFF:
2715 self.assertEqual(str(sm.external_ip_address),
2717 self.assertEqual(sm.tag, tag)
2719 self.assertTrue(resolved)
2721 # remove interface address and check static mappings
2722 self.pg7.unconfig_ip4()
2723 static_mappings = self.vapi.nat44_static_mapping_dump()
2724 self.assertEqual(1, len(static_mappings))
2725 self.assertEqual(self.pg7.sw_if_index,
2726 static_mappings[0].external_sw_if_index)
2727 self.assertEqual(static_mappings[0].tag, tag)
2729 # configure interface address again and check static mappings
2730 self.pg7.config_ip4()
2731 static_mappings = self.vapi.nat44_static_mapping_dump()
2732 self.assertEqual(2, len(static_mappings))
2734 for sm in static_mappings:
2735 if sm.external_sw_if_index == 0xFFFFFFFF:
2736 self.assertEqual(str(sm.external_ip_address),
2738 self.assertEqual(sm.tag, tag)
2740 self.assertTrue(resolved)
2742 # remove static mapping
2743 self.nat44_add_static_mapping(
2745 external_sw_if_index=self.pg7.sw_if_index,
2748 static_mappings = self.vapi.nat44_static_mapping_dump()
2749 self.assertEqual(0, len(static_mappings))
2751 def test_interface_addr_identity_nat(self):
2752 """ Identity NAT with addresses from interface """
2755 self.vapi.nat44_add_del_interface_addr(
2757 sw_if_index=self.pg7.sw_if_index)
2758 self.vapi.nat44_add_del_identity_mapping(
2760 sw_if_index=self.pg7.sw_if_index,
2762 protocol=IP_PROTOS.tcp,
2765 # identity mappings with external interface
2766 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2767 self.assertEqual(1, len(identity_mappings))
2768 self.assertEqual(self.pg7.sw_if_index,
2769 identity_mappings[0].sw_if_index)
2771 # configure interface address and check identity mappings
2772 self.pg7.config_ip4()
2773 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2775 self.assertEqual(2, len(identity_mappings))
2776 for sm in identity_mappings:
2777 if sm.sw_if_index == 0xFFFFFFFF:
2778 self.assertEqual(str(identity_mappings[0].ip_address),
2780 self.assertEqual(port, identity_mappings[0].port)
2781 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2783 self.assertTrue(resolved)
2785 # remove interface address and check identity mappings
2786 self.pg7.unconfig_ip4()
2787 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2788 self.assertEqual(1, len(identity_mappings))
2789 self.assertEqual(self.pg7.sw_if_index,
2790 identity_mappings[0].sw_if_index)
2792 def test_ipfix_nat44_sess(self):
2793 """ IPFIX logging NAT44 session created/deleted """
2794 self.ipfix_domain_id = 10
2795 self.ipfix_src_port = 20202
2796 collector_port = 30303
2797 bind_layers(UDP, IPFIX, dport=30303)
2798 self.nat44_add_address(self.nat_addr)
2799 flags = self.config_flags.NAT_IS_INSIDE
2800 self.vapi.nat44_interface_add_del_feature(
2801 sw_if_index=self.pg0.sw_if_index,
2802 flags=flags, is_add=1)
2803 self.vapi.nat44_interface_add_del_feature(
2804 sw_if_index=self.pg1.sw_if_index,
2806 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2807 src_address=self.pg3.local_ip4,
2809 template_interval=10,
2810 collector_port=collector_port)
2811 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2812 src_port=self.ipfix_src_port,
2815 pkts = self.create_stream_in(self.pg0, self.pg1)
2816 self.pg0.add_stream(pkts)
2817 self.pg_enable_capture(self.pg_interfaces)
2819 capture = self.pg1.get_capture(len(pkts))
2820 self.verify_capture_out(capture)
2821 self.nat44_add_address(self.nat_addr, is_add=0)
2822 self.vapi.ipfix_flush()
2823 capture = self.pg3.get_capture(9)
2824 ipfix = IPFIXDecoder()
2825 # first load template
2827 self.assertTrue(p.haslayer(IPFIX))
2828 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2829 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2830 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2831 self.assertEqual(p[UDP].dport, collector_port)
2832 self.assertEqual(p[IPFIX].observationDomainID,
2833 self.ipfix_domain_id)
2834 if p.haslayer(Template):
2835 ipfix.add_template(p.getlayer(Template))
2836 # verify events in data set
2838 if p.haslayer(Data):
2839 data = ipfix.decode_data_set(p.getlayer(Set))
2840 self.verify_ipfix_nat44_ses(data)
2842 def test_ipfix_addr_exhausted(self):
2843 """ IPFIX logging NAT addresses exhausted """
2844 flags = self.config_flags.NAT_IS_INSIDE
2845 self.vapi.nat44_interface_add_del_feature(
2846 sw_if_index=self.pg0.sw_if_index,
2847 flags=flags, is_add=1)
2848 self.vapi.nat44_interface_add_del_feature(
2849 sw_if_index=self.pg1.sw_if_index,
2851 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2852 src_address=self.pg3.local_ip4,
2854 template_interval=10)
2855 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2856 src_port=self.ipfix_src_port,
2859 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2860 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2862 self.pg0.add_stream(p)
2863 self.pg_enable_capture(self.pg_interfaces)
2865 self.pg1.assert_nothing_captured()
2867 self.vapi.ipfix_flush()
2868 capture = self.pg3.get_capture(9)
2869 ipfix = IPFIXDecoder()
2870 # first load template
2872 self.assertTrue(p.haslayer(IPFIX))
2873 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2874 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2875 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2876 self.assertEqual(p[UDP].dport, 4739)
2877 self.assertEqual(p[IPFIX].observationDomainID,
2878 self.ipfix_domain_id)
2879 if p.haslayer(Template):
2880 ipfix.add_template(p.getlayer(Template))
2881 # verify events in data set
2883 if p.haslayer(Data):
2884 data = ipfix.decode_data_set(p.getlayer(Set))
2885 self.verify_ipfix_addr_exhausted(data)
2887 @unittest.skipUnless(running_extended_tests, "part of extended tests")
2888 def test_ipfix_max_sessions(self):
2889 """ IPFIX logging maximum session entries exceeded """
2890 self.nat44_add_address(self.nat_addr)
2891 flags = self.config_flags.NAT_IS_INSIDE
2892 self.vapi.nat44_interface_add_del_feature(
2893 sw_if_index=self.pg0.sw_if_index,
2894 flags=flags, is_add=1)
2895 self.vapi.nat44_interface_add_del_feature(
2896 sw_if_index=self.pg1.sw_if_index,
2899 nat44_config = self.vapi.nat_show_config()
2900 max_sessions = 10 * nat44_config.translation_buckets
2903 for i in range(0, max_sessions):
2904 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2905 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2906 IP(src=src, dst=self.pg1.remote_ip4) /
2909 self.pg0.add_stream(pkts)
2910 self.pg_enable_capture(self.pg_interfaces)
2913 self.pg1.get_capture(max_sessions)
2914 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2915 src_address=self.pg3.local_ip4,
2917 template_interval=10)
2918 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2919 src_port=self.ipfix_src_port,
2922 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2923 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2925 self.pg0.add_stream(p)
2926 self.pg_enable_capture(self.pg_interfaces)
2928 self.pg1.assert_nothing_captured()
2930 self.vapi.ipfix_flush()
2931 capture = self.pg3.get_capture(9)
2932 ipfix = IPFIXDecoder()
2933 # first load template
2935 self.assertTrue(p.haslayer(IPFIX))
2936 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2937 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2938 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2939 self.assertEqual(p[UDP].dport, 4739)
2940 self.assertEqual(p[IPFIX].observationDomainID,
2941 self.ipfix_domain_id)
2942 if p.haslayer(Template):
2943 ipfix.add_template(p.getlayer(Template))
2944 # verify events in data set
2946 if p.haslayer(Data):
2947 data = ipfix.decode_data_set(p.getlayer(Set))
2948 self.verify_ipfix_max_sessions(data, max_sessions)
2950 def test_syslog_apmap(self):
2951 """ Test syslog address and port mapping creation and deletion """
2952 self.vapi.syslog_set_filter(
2953 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
2954 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
2955 self.nat44_add_address(self.nat_addr)
2956 flags = self.config_flags.NAT_IS_INSIDE
2957 self.vapi.nat44_interface_add_del_feature(
2958 sw_if_index=self.pg0.sw_if_index,
2959 flags=flags, is_add=1)
2960 self.vapi.nat44_interface_add_del_feature(
2961 sw_if_index=self.pg1.sw_if_index,
2964 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2965 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2966 TCP(sport=self.tcp_port_in, dport=20))
2967 self.pg0.add_stream(p)
2968 self.pg_enable_capture(self.pg_interfaces)
2970 capture = self.pg1.get_capture(1)
2971 self.tcp_port_out = capture[0][TCP].sport
2972 capture = self.pg3.get_capture(1)
2973 self.verify_syslog_apmap(capture[0][Raw].load)
2975 self.pg_enable_capture(self.pg_interfaces)
2977 self.nat44_add_address(self.nat_addr, is_add=0)
2978 capture = self.pg3.get_capture(1)
2979 self.verify_syslog_apmap(capture[0][Raw].load, False)
2981 def test_pool_addr_fib(self):
2982 """ NAT44 add pool addresses to FIB """
2983 static_addr = '10.0.0.10'
2984 self.nat44_add_address(self.nat_addr)
2985 flags = self.config_flags.NAT_IS_INSIDE
2986 self.vapi.nat44_interface_add_del_feature(
2987 sw_if_index=self.pg0.sw_if_index,
2988 flags=flags, is_add=1)
2989 self.vapi.nat44_interface_add_del_feature(
2990 sw_if_index=self.pg1.sw_if_index,
2992 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
2995 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2996 ARP(op=ARP.who_has, pdst=self.nat_addr,
2997 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2998 self.pg1.add_stream(p)
2999 self.pg_enable_capture(self.pg_interfaces)
3001 capture = self.pg1.get_capture(1)
3002 self.assertTrue(capture[0].haslayer(ARP))
3003 self.assertTrue(capture[0][ARP].op, ARP.is_at)
3006 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
3007 ARP(op=ARP.who_has, pdst=static_addr,
3008 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
3009 self.pg1.add_stream(p)
3010 self.pg_enable_capture(self.pg_interfaces)
3012 capture = self.pg1.get_capture(1)
3013 self.assertTrue(capture[0].haslayer(ARP))
3014 self.assertTrue(capture[0][ARP].op, ARP.is_at)
3016 # send ARP to non-NAT44 interface
3017 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
3018 ARP(op=ARP.who_has, pdst=self.nat_addr,
3019 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
3020 self.pg2.add_stream(p)
3021 self.pg_enable_capture(self.pg_interfaces)
3023 self.pg1.assert_nothing_captured()
3025 # remove addresses and verify
3026 self.nat44_add_address(self.nat_addr, is_add=0)
3027 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
3030 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
3031 ARP(op=ARP.who_has, pdst=self.nat_addr,
3032 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
3033 self.pg1.add_stream(p)
3034 self.pg_enable_capture(self.pg_interfaces)
3036 self.pg1.assert_nothing_captured()
3038 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
3039 ARP(op=ARP.who_has, pdst=static_addr,
3040 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
3041 self.pg1.add_stream(p)
3042 self.pg_enable_capture(self.pg_interfaces)
3044 self.pg1.assert_nothing_captured()
3046 def test_vrf_mode(self):
3047 """ NAT44 tenant VRF aware address pool mode """
3051 nat_ip1 = "10.0.0.10"
3052 nat_ip2 = "10.0.0.11"
3054 self.pg0.unconfig_ip4()
3055 self.pg1.unconfig_ip4()
3056 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
3057 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
3058 self.pg0.set_table_ip4(vrf_id1)
3059 self.pg1.set_table_ip4(vrf_id2)
3060 self.pg0.config_ip4()
3061 self.pg1.config_ip4()
3062 self.pg0.resolve_arp()
3063 self.pg1.resolve_arp()
3065 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
3066 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
3067 flags = self.config_flags.NAT_IS_INSIDE
3068 self.vapi.nat44_interface_add_del_feature(
3069 sw_if_index=self.pg0.sw_if_index,
3070 flags=flags, is_add=1)
3071 self.vapi.nat44_interface_add_del_feature(
3072 sw_if_index=self.pg1.sw_if_index,
3073 flags=flags, is_add=1)
3074 self.vapi.nat44_interface_add_del_feature(
3075 sw_if_index=self.pg2.sw_if_index,
3080 pkts = self.create_stream_in(self.pg0, self.pg2)
3081 self.pg0.add_stream(pkts)
3082 self.pg_enable_capture(self.pg_interfaces)
3084 capture = self.pg2.get_capture(len(pkts))
3085 self.verify_capture_out(capture, nat_ip1)
3088 pkts = self.create_stream_in(self.pg1, self.pg2)
3089 self.pg1.add_stream(pkts)
3090 self.pg_enable_capture(self.pg_interfaces)
3092 capture = self.pg2.get_capture(len(pkts))
3093 self.verify_capture_out(capture, nat_ip2)
3096 self.pg0.unconfig_ip4()
3097 self.pg1.unconfig_ip4()
3098 self.pg0.set_table_ip4(0)
3099 self.pg1.set_table_ip4(0)
3100 self.pg0.config_ip4()
3101 self.pg1.config_ip4()
3102 self.pg0.resolve_arp()
3103 self.pg1.resolve_arp()
3104 self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id1)
3105 self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id2)
3107 def test_vrf_feature_independent(self):
3108 """ NAT44 tenant VRF independent address pool mode """
3110 nat_ip1 = "10.0.0.10"
3111 nat_ip2 = "10.0.0.11"
3113 self.nat44_add_address(nat_ip1)
3114 self.nat44_add_address(nat_ip2, vrf_id=99)
3115 flags = self.config_flags.NAT_IS_INSIDE
3116 self.vapi.nat44_interface_add_del_feature(
3117 sw_if_index=self.pg0.sw_if_index,
3118 flags=flags, is_add=1)
3119 self.vapi.nat44_interface_add_del_feature(
3120 sw_if_index=self.pg1.sw_if_index,
3121 flags=flags, is_add=1)
3122 self.vapi.nat44_interface_add_del_feature(
3123 sw_if_index=self.pg2.sw_if_index,
3127 pkts = self.create_stream_in(self.pg0, self.pg2)
3128 self.pg0.add_stream(pkts)
3129 self.pg_enable_capture(self.pg_interfaces)
3131 capture = self.pg2.get_capture(len(pkts))
3132 self.verify_capture_out(capture, nat_ip1)
3135 pkts = self.create_stream_in(self.pg1, self.pg2)
3136 self.pg1.add_stream(pkts)
3137 self.pg_enable_capture(self.pg_interfaces)
3139 capture = self.pg2.get_capture(len(pkts))
3140 self.verify_capture_out(capture, nat_ip1)
3142 def create_routes_and_neigbors(self):
3143 r1 = VppIpRoute(self, self.pg7.remote_ip4, 32,
3144 [VppRoutePath(self.pg7.remote_ip4,
3145 self.pg7.sw_if_index)])
3146 r2 = VppIpRoute(self, self.pg8.remote_ip4, 32,
3147 [VppRoutePath(self.pg8.remote_ip4,
3148 self.pg8.sw_if_index)])
3152 n1 = VppNeighbor(self,
3153 self.pg7.sw_if_index,
3154 self.pg7.remote_mac,
3155 self.pg7.remote_ip4,
3157 n2 = VppNeighbor(self,
3158 self.pg8.sw_if_index,
3159 self.pg8.remote_mac,
3160 self.pg8.remote_ip4,
3165 def test_dynamic_ipless_interfaces(self):
3166 """ NAT44 interfaces without configured IP address """
3167 self.create_routes_and_neigbors()
3168 self.nat44_add_address(self.nat_addr)
3169 flags = self.config_flags.NAT_IS_INSIDE
3170 self.vapi.nat44_interface_add_del_feature(
3171 sw_if_index=self.pg7.sw_if_index,
3172 flags=flags, is_add=1)
3173 self.vapi.nat44_interface_add_del_feature(
3174 sw_if_index=self.pg8.sw_if_index,
3178 pkts = self.create_stream_in(self.pg7, self.pg8)
3179 self.pg7.add_stream(pkts)
3180 self.pg_enable_capture(self.pg_interfaces)
3182 capture = self.pg8.get_capture(len(pkts))
3183 self.verify_capture_out(capture)
3186 pkts = self.create_stream_out(self.pg8, self.nat_addr)
3187 self.pg8.add_stream(pkts)
3188 self.pg_enable_capture(self.pg_interfaces)
3190 capture = self.pg7.get_capture(len(pkts))
3191 self.verify_capture_in(capture, self.pg7)
3193 def test_static_ipless_interfaces(self):
3194 """ NAT44 interfaces without configured IP address - 1:1 NAT """
3196 self.create_routes_and_neigbors()
3197 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
3198 flags = self.config_flags.NAT_IS_INSIDE
3199 self.vapi.nat44_interface_add_del_feature(
3200 sw_if_index=self.pg7.sw_if_index,
3201 flags=flags, is_add=1)
3202 self.vapi.nat44_interface_add_del_feature(
3203 sw_if_index=self.pg8.sw_if_index,
3207 pkts = self.create_stream_out(self.pg8)
3208 self.pg8.add_stream(pkts)
3209 self.pg_enable_capture(self.pg_interfaces)
3211 capture = self.pg7.get_capture(len(pkts))
3212 self.verify_capture_in(capture, self.pg7)
3215 pkts = self.create_stream_in(self.pg7, self.pg8)
3216 self.pg7.add_stream(pkts)
3217 self.pg_enable_capture(self.pg_interfaces)
3219 capture = self.pg8.get_capture(len(pkts))
3220 self.verify_capture_out(capture, self.nat_addr, True)
3222 def test_static_with_port_ipless_interfaces(self):
3223 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
3225 self.tcp_port_out = 30606
3226 self.udp_port_out = 30607
3227 self.icmp_id_out = 30608
3229 self.create_routes_and_neigbors()
3230 self.nat44_add_address(self.nat_addr)
3231 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3232 self.tcp_port_in, self.tcp_port_out,
3233 proto=IP_PROTOS.tcp)
3234 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3235 self.udp_port_in, self.udp_port_out,
3236 proto=IP_PROTOS.udp)
3237 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3238 self.icmp_id_in, self.icmp_id_out,
3239 proto=IP_PROTOS.icmp)
3240 flags = self.config_flags.NAT_IS_INSIDE
3241 self.vapi.nat44_interface_add_del_feature(
3242 sw_if_index=self.pg7.sw_if_index,
3243 flags=flags, is_add=1)
3244 self.vapi.nat44_interface_add_del_feature(
3245 sw_if_index=self.pg8.sw_if_index,
3249 pkts = self.create_stream_out(self.pg8)
3250 self.pg8.add_stream(pkts)
3251 self.pg_enable_capture(self.pg_interfaces)
3253 capture = self.pg7.get_capture(len(pkts))
3254 self.verify_capture_in(capture, self.pg7)
3257 pkts = self.create_stream_in(self.pg7, self.pg8)
3258 self.pg7.add_stream(pkts)
3259 self.pg_enable_capture(self.pg_interfaces)
3261 capture = self.pg8.get_capture(len(pkts))
3262 self.verify_capture_out(capture)
3264 def test_static_unknown_proto(self):
3265 """ 1:1 NAT translate packet with unknown protocol """
3266 nat_ip = "10.0.0.10"
3267 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
3268 flags = self.config_flags.NAT_IS_INSIDE
3269 self.vapi.nat44_interface_add_del_feature(
3270 sw_if_index=self.pg0.sw_if_index,
3271 flags=flags, is_add=1)
3272 self.vapi.nat44_interface_add_del_feature(
3273 sw_if_index=self.pg1.sw_if_index,
3277 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3278 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3280 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3281 TCP(sport=1234, dport=1234))
3282 self.pg0.add_stream(p)
3283 self.pg_enable_capture(self.pg_interfaces)
3285 p = self.pg1.get_capture(1)
3288 self.assertEqual(packet[IP].src, nat_ip)
3289 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3290 self.assertEqual(packet.haslayer(GRE), 1)
3291 self.assert_packet_checksums_valid(packet)
3293 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3297 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3298 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3300 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3301 TCP(sport=1234, dport=1234))
3302 self.pg1.add_stream(p)
3303 self.pg_enable_capture(self.pg_interfaces)
3305 p = self.pg0.get_capture(1)
3308 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3309 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3310 self.assertEqual(packet.haslayer(GRE), 1)
3311 self.assert_packet_checksums_valid(packet)
3313 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3316 def test_hairpinning_static_unknown_proto(self):
3317 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3319 host = self.pg0.remote_hosts[0]
3320 server = self.pg0.remote_hosts[1]
3322 host_nat_ip = "10.0.0.10"
3323 server_nat_ip = "10.0.0.11"
3325 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3326 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3327 flags = self.config_flags.NAT_IS_INSIDE
3328 self.vapi.nat44_interface_add_del_feature(
3329 sw_if_index=self.pg0.sw_if_index,
3330 flags=flags, is_add=1)
3331 self.vapi.nat44_interface_add_del_feature(
3332 sw_if_index=self.pg1.sw_if_index,
3336 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3337 IP(src=host.ip4, dst=server_nat_ip) /
3339 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3340 TCP(sport=1234, dport=1234))
3341 self.pg0.add_stream(p)
3342 self.pg_enable_capture(self.pg_interfaces)
3344 p = self.pg0.get_capture(1)
3347 self.assertEqual(packet[IP].src, host_nat_ip)
3348 self.assertEqual(packet[IP].dst, server.ip4)
3349 self.assertEqual(packet.haslayer(GRE), 1)
3350 self.assert_packet_checksums_valid(packet)
3352 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3356 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3357 IP(src=server.ip4, dst=host_nat_ip) /
3359 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3360 TCP(sport=1234, dport=1234))
3361 self.pg0.add_stream(p)
3362 self.pg_enable_capture(self.pg_interfaces)
3364 p = self.pg0.get_capture(1)
3367 self.assertEqual(packet[IP].src, server_nat_ip)
3368 self.assertEqual(packet[IP].dst, host.ip4)
3369 self.assertEqual(packet.haslayer(GRE), 1)
3370 self.assert_packet_checksums_valid(packet)
3372 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3375 def test_output_feature(self):
3376 """ NAT44 interface output feature (in2out postrouting) """
3377 self.nat44_add_address(self.nat_addr)
3378 flags = self.config_flags.NAT_IS_INSIDE
3379 self.vapi.nat44_interface_add_del_output_feature(
3380 is_add=1, flags=flags,
3381 sw_if_index=self.pg0.sw_if_index)
3382 self.vapi.nat44_interface_add_del_output_feature(
3383 is_add=1, flags=flags,
3384 sw_if_index=self.pg1.sw_if_index)
3385 self.vapi.nat44_interface_add_del_output_feature(
3387 sw_if_index=self.pg3.sw_if_index)
3390 pkts = self.create_stream_in(self.pg0, self.pg3)
3391 self.pg0.add_stream(pkts)
3392 self.pg_enable_capture(self.pg_interfaces)
3394 capture = self.pg3.get_capture(len(pkts))
3395 self.verify_capture_out(capture)
3398 pkts = self.create_stream_out(self.pg3)
3399 self.pg3.add_stream(pkts)
3400 self.pg_enable_capture(self.pg_interfaces)
3402 capture = self.pg0.get_capture(len(pkts))
3403 self.verify_capture_in(capture, self.pg0)
3405 # from non-NAT interface to NAT inside interface
3406 pkts = self.create_stream_in(self.pg2, self.pg0)
3407 self.pg2.add_stream(pkts)
3408 self.pg_enable_capture(self.pg_interfaces)
3410 capture = self.pg0.get_capture(len(pkts))
3411 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3413 def test_output_feature_vrf_aware(self):
3414 """ NAT44 interface output feature VRF aware (in2out postrouting) """
3415 nat_ip_vrf10 = "10.0.0.10"
3416 nat_ip_vrf20 = "10.0.0.20"
3418 r1 = VppIpRoute(self, self.pg3.remote_ip4, 32,
3419 [VppRoutePath(self.pg3.remote_ip4,
3420 self.pg3.sw_if_index)],
3422 r2 = VppIpRoute(self, self.pg3.remote_ip4, 32,
3423 [VppRoutePath(self.pg3.remote_ip4,
3424 self.pg3.sw_if_index)],
3429 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3430 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3431 flags = self.config_flags.NAT_IS_INSIDE
3432 self.vapi.nat44_interface_add_del_output_feature(
3433 is_add=1, flags=flags,
3434 sw_if_index=self.pg4.sw_if_index)
3435 self.vapi.nat44_interface_add_del_output_feature(
3436 is_add=1, flags=flags,
3437 sw_if_index=self.pg6.sw_if_index)
3438 self.vapi.nat44_interface_add_del_output_feature(
3440 sw_if_index=self.pg3.sw_if_index)
3443 pkts = self.create_stream_in(self.pg4, self.pg3)
3444 self.pg4.add_stream(pkts)
3445 self.pg_enable_capture(self.pg_interfaces)
3447 capture = self.pg3.get_capture(len(pkts))
3448 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3451 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3452 self.pg3.add_stream(pkts)
3453 self.pg_enable_capture(self.pg_interfaces)
3455 capture = self.pg4.get_capture(len(pkts))
3456 self.verify_capture_in(capture, self.pg4)
3459 pkts = self.create_stream_in(self.pg6, self.pg3)
3460 self.pg6.add_stream(pkts)
3461 self.pg_enable_capture(self.pg_interfaces)
3463 capture = self.pg3.get_capture(len(pkts))
3464 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3467 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3468 self.pg3.add_stream(pkts)
3469 self.pg_enable_capture(self.pg_interfaces)
3471 capture = self.pg6.get_capture(len(pkts))
3472 self.verify_capture_in(capture, self.pg6)
3474 def test_output_feature_hairpinning(self):
3475 """ NAT44 interface output feature hairpinning (in2out postrouting) """
3476 host = self.pg0.remote_hosts[0]
3477 server = self.pg0.remote_hosts[1]
3480 server_in_port = 5678
3481 server_out_port = 8765
3483 self.nat44_add_address(self.nat_addr)
3484 flags = self.config_flags.NAT_IS_INSIDE
3485 self.vapi.nat44_interface_add_del_output_feature(
3486 is_add=1, flags=flags,
3487 sw_if_index=self.pg0.sw_if_index)
3488 self.vapi.nat44_interface_add_del_output_feature(
3490 sw_if_index=self.pg1.sw_if_index)
3492 # add static mapping for server
3493 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3494 server_in_port, server_out_port,
3495 proto=IP_PROTOS.tcp)
3497 # send packet from host to server
3498 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3499 IP(src=host.ip4, dst=self.nat_addr) /
3500 TCP(sport=host_in_port, dport=server_out_port))
3501 self.pg0.add_stream(p)
3502 self.pg_enable_capture(self.pg_interfaces)
3504 capture = self.pg0.get_capture(1)
3509 self.assertEqual(ip.src, self.nat_addr)
3510 self.assertEqual(ip.dst, server.ip4)
3511 self.assertNotEqual(tcp.sport, host_in_port)
3512 self.assertEqual(tcp.dport, server_in_port)
3513 self.assert_packet_checksums_valid(p)
3514 host_out_port = tcp.sport
3516 self.logger.error(ppp("Unexpected or invalid packet:", p))
3519 # send reply from server to host
3520 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3521 IP(src=server.ip4, dst=self.nat_addr) /
3522 TCP(sport=server_in_port, dport=host_out_port))
3523 self.pg0.add_stream(p)
3524 self.pg_enable_capture(self.pg_interfaces)
3526 capture = self.pg0.get_capture(1)
3531 self.assertEqual(ip.src, self.nat_addr)
3532 self.assertEqual(ip.dst, host.ip4)
3533 self.assertEqual(tcp.sport, server_out_port)
3534 self.assertEqual(tcp.dport, host_in_port)
3535 self.assert_packet_checksums_valid(p)
3537 self.logger.error(ppp("Unexpected or invalid packet:", p))
3540 def test_one_armed_nat44(self):
3541 """ One armed NAT44 """
3542 remote_host = self.pg9.remote_hosts[0]
3543 local_host = self.pg9.remote_hosts[1]
3546 self.nat44_add_address(self.nat_addr)
3547 flags = self.config_flags.NAT_IS_INSIDE
3548 self.vapi.nat44_interface_add_del_feature(
3549 sw_if_index=self.pg9.sw_if_index,
3551 self.vapi.nat44_interface_add_del_feature(
3552 sw_if_index=self.pg9.sw_if_index,
3553 flags=flags, is_add=1)
3556 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3557 IP(src=local_host.ip4, dst=remote_host.ip4) /
3558 TCP(sport=12345, dport=80))
3559 self.pg9.add_stream(p)
3560 self.pg_enable_capture(self.pg_interfaces)
3562 capture = self.pg9.get_capture(1)
3567 self.assertEqual(ip.src, self.nat_addr)
3568 self.assertEqual(ip.dst, remote_host.ip4)
3569 self.assertNotEqual(tcp.sport, 12345)
3570 external_port = tcp.sport
3571 self.assertEqual(tcp.dport, 80)
3572 self.assert_packet_checksums_valid(p)
3574 self.logger.error(ppp("Unexpected or invalid packet:", p))
3578 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3579 IP(src=remote_host.ip4, dst=self.nat_addr) /
3580 TCP(sport=80, dport=external_port))
3581 self.pg9.add_stream(p)
3582 self.pg_enable_capture(self.pg_interfaces)
3584 capture = self.pg9.get_capture(1)
3589 self.assertEqual(ip.src, remote_host.ip4)
3590 self.assertEqual(ip.dst, local_host.ip4)
3591 self.assertEqual(tcp.sport, 80)
3592 self.assertEqual(tcp.dport, 12345)
3593 self.assert_packet_checksums_valid(p)
3595 self.logger.error(ppp("Unexpected or invalid packet:", p))
3598 err = self.statistics.get_err_counter(
3599 '/err/nat44-classify/next in2out')
3600 self.assertEqual(err, 1)
3601 err = self.statistics.get_err_counter(
3602 '/err/nat44-classify/next out2in')
3603 self.assertEqual(err, 1)
3605 def test_del_session(self):
3606 """ Delete NAT44 session """
3607 self.nat44_add_address(self.nat_addr)
3608 flags = self.config_flags.NAT_IS_INSIDE
3609 self.vapi.nat44_interface_add_del_feature(
3610 sw_if_index=self.pg0.sw_if_index,
3611 flags=flags, is_add=1)
3612 self.vapi.nat44_interface_add_del_feature(
3613 sw_if_index=self.pg1.sw_if_index,
3616 pkts = self.create_stream_in(self.pg0, self.pg1)
3617 self.pg0.add_stream(pkts)
3618 self.pg_enable_capture(self.pg_interfaces)
3620 self.pg1.get_capture(len(pkts))
3622 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3623 nsessions = len(sessions)
3625 self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3626 port=sessions[0].inside_port,
3627 protocol=sessions[0].protocol,
3628 flags=self.config_flags.NAT_IS_INSIDE)
3629 self.vapi.nat44_del_session(address=sessions[1].outside_ip_address,
3630 port=sessions[1].outside_port,
3631 protocol=sessions[1].protocol)
3633 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3634 self.assertEqual(nsessions - len(sessions), 2)
3636 self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3637 port=sessions[0].inside_port,
3638 protocol=sessions[0].protocol,
3639 flags=self.config_flags.NAT_IS_INSIDE)
3641 self.verify_no_nat44_user()
3643 def test_set_get_reass(self):
3644 """ NAT44 set/get virtual fragmentation reassembly """
3645 reas_cfg1 = self.vapi.nat_get_reass()
3647 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3648 max_reass=reas_cfg1.ip4_max_reass * 2,
3649 max_frag=reas_cfg1.ip4_max_frag * 2,
3652 reas_cfg2 = self.vapi.nat_get_reass()
3654 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3655 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3656 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3658 self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=5,
3660 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3662 def test_frag_in_order(self):
3663 """ NAT44 translate fragments arriving in order """
3665 self.nat44_add_address(self.nat_addr)
3666 flags = self.config_flags.NAT_IS_INSIDE
3667 self.vapi.nat44_interface_add_del_feature(
3668 sw_if_index=self.pg0.sw_if_index,
3669 flags=flags, is_add=1)
3670 self.vapi.nat44_interface_add_del_feature(
3671 sw_if_index=self.pg1.sw_if_index,
3674 reas_cfg1 = self.vapi.nat_get_reass()
3675 # this test was intermittently failing in some cases
3676 # until we temporarily bump the reassembly timeouts
3677 self.vapi.nat_set_reass(timeout=20, max_reass=1024, max_frag=5,
3680 self.frag_in_order(proto=IP_PROTOS.tcp)
3681 self.frag_in_order(proto=IP_PROTOS.udp)
3682 self.frag_in_order(proto=IP_PROTOS.icmp)
3684 # restore the reassembly timeouts
3685 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout,
3686 max_reass=reas_cfg1.ip4_max_reass,
3687 max_frag=reas_cfg1.ip4_max_frag,
3688 drop_frag=reas_cfg1.ip4_drop_frag)
3690 def test_frag_forwarding(self):
3691 """ NAT44 forwarding fragment test """
3692 self.vapi.nat44_add_del_interface_addr(
3694 sw_if_index=self.pg1.sw_if_index)
3695 flags = self.config_flags.NAT_IS_INSIDE
3696 self.vapi.nat44_interface_add_del_feature(
3697 sw_if_index=self.pg0.sw_if_index,
3698 flags=flags, is_add=1)
3699 self.vapi.nat44_interface_add_del_feature(
3700 sw_if_index=self.pg1.sw_if_index,
3702 self.vapi.nat44_forwarding_enable_disable(enable=1)
3704 data = b"A" * 16 + b"B" * 16 + b"C" * 3
3705 pkts = self.create_stream_frag(self.pg1,
3706 self.pg0.remote_ip4,
3710 proto=IP_PROTOS.udp)
3711 self.pg1.add_stream(pkts)
3712 self.pg_enable_capture(self.pg_interfaces)
3714 frags = self.pg0.get_capture(len(pkts))
3715 p = self.reass_frags_and_verify(frags,
3716 self.pg1.remote_ip4,
3717 self.pg0.remote_ip4)
3718 self.assertEqual(p[UDP].sport, 4789)
3719 self.assertEqual(p[UDP].dport, 4789)
3720 self.assertEqual(data, p[Raw].load)
3722 def test_reass_hairpinning(self):
3723 """ NAT44 fragments hairpinning """
3725 self.server = self.pg0.remote_hosts[1]
3726 self.host_in_port = random.randint(1025, 65535)
3727 self.server_in_port = random.randint(1025, 65535)
3728 self.server_out_port = random.randint(1025, 65535)
3730 self.nat44_add_address(self.nat_addr)
3731 flags = self.config_flags.NAT_IS_INSIDE
3732 self.vapi.nat44_interface_add_del_feature(
3733 sw_if_index=self.pg0.sw_if_index,
3734 flags=flags, is_add=1)
3735 self.vapi.nat44_interface_add_del_feature(
3736 sw_if_index=self.pg1.sw_if_index,
3738 # add static mapping for server
3739 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3740 self.server_in_port,
3741 self.server_out_port,
3742 proto=IP_PROTOS.tcp)
3743 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3744 self.server_in_port,
3745 self.server_out_port,
3746 proto=IP_PROTOS.udp)
3747 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
3749 self.reass_hairpinning(proto=IP_PROTOS.tcp)
3750 self.reass_hairpinning(proto=IP_PROTOS.udp)
3751 self.reass_hairpinning(proto=IP_PROTOS.icmp)
3753 def test_frag_out_of_order(self):
3754 """ NAT44 translate fragments arriving out of order """
3756 self.nat44_add_address(self.nat_addr)
3757 flags = self.config_flags.NAT_IS_INSIDE
3758 self.vapi.nat44_interface_add_del_feature(
3759 sw_if_index=self.pg0.sw_if_index,
3760 flags=flags, is_add=1)
3761 self.vapi.nat44_interface_add_del_feature(
3762 sw_if_index=self.pg1.sw_if_index,
3765 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3766 self.frag_out_of_order(proto=IP_PROTOS.udp)
3767 self.frag_out_of_order(proto=IP_PROTOS.icmp)
3769 def test_port_restricted(self):
3770 """ Port restricted NAT44 (MAP-E CE) """
3771 self.nat44_add_address(self.nat_addr)
3772 flags = self.config_flags.NAT_IS_INSIDE
3773 self.vapi.nat44_interface_add_del_feature(
3774 sw_if_index=self.pg0.sw_if_index,
3775 flags=flags, is_add=1)
3776 self.vapi.nat44_interface_add_del_feature(
3777 sw_if_index=self.pg1.sw_if_index,
3779 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3784 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3785 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3786 TCP(sport=4567, dport=22))
3787 self.pg0.add_stream(p)
3788 self.pg_enable_capture(self.pg_interfaces)
3790 capture = self.pg1.get_capture(1)
3795 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3796 self.assertEqual(ip.src, self.nat_addr)
3797 self.assertEqual(tcp.dport, 22)
3798 self.assertNotEqual(tcp.sport, 4567)
3799 self.assertEqual((tcp.sport >> 6) & 63, 10)
3800 self.assert_packet_checksums_valid(p)
3802 self.logger.error(ppp("Unexpected or invalid packet:", p))
3805 def test_port_range(self):
3806 """ External address port range """
3807 self.nat44_add_address(self.nat_addr)
3808 flags = self.config_flags.NAT_IS_INSIDE
3809 self.vapi.nat44_interface_add_del_feature(
3810 sw_if_index=self.pg0.sw_if_index,
3811 flags=flags, is_add=1)
3812 self.vapi.nat44_interface_add_del_feature(
3813 sw_if_index=self.pg1.sw_if_index,
3815 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3820 for port in range(0, 5):
3821 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3822 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3823 TCP(sport=1125 + port))
3825 self.pg0.add_stream(pkts)
3826 self.pg_enable_capture(self.pg_interfaces)
3828 capture = self.pg1.get_capture(3)
3831 self.assertGreaterEqual(tcp.sport, 1025)
3832 self.assertLessEqual(tcp.sport, 1027)
3834 def test_ipfix_max_frags(self):
3835 """ IPFIX logging maximum fragments pending reassembly exceeded """
3836 self.nat44_add_address(self.nat_addr)
3837 flags = self.config_flags.NAT_IS_INSIDE
3838 self.vapi.nat44_interface_add_del_feature(
3839 sw_if_index=self.pg0.sw_if_index,
3840 flags=flags, is_add=1)
3841 self.vapi.nat44_interface_add_del_feature(
3842 sw_if_index=self.pg1.sw_if_index,
3844 self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=1,
3846 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
3847 src_address=self.pg3.local_ip4,
3849 template_interval=10)
3850 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
3851 src_port=self.ipfix_src_port,
3854 data = b"A" * 4 + b"B" * 16 + b"C" * 3
3855 self.tcp_port_in = random.randint(1025, 65535)
3856 pkts = self.create_stream_frag(self.pg0,
3857 self.pg1.remote_ip4,
3862 self.pg0.add_stream(pkts)
3863 self.pg_enable_capture(self.pg_interfaces)
3865 self.pg1.assert_nothing_captured()
3867 self.vapi.ipfix_flush()
3868 capture = self.pg3.get_capture(9)
3869 ipfix = IPFIXDecoder()
3870 # first load template
3872 self.assertTrue(p.haslayer(IPFIX))
3873 self.assertEqual(p[IP].src, self.pg3.local_ip4)
3874 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
3875 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
3876 self.assertEqual(p[UDP].dport, 4739)
3877 self.assertEqual(p[IPFIX].observationDomainID,
3878 self.ipfix_domain_id)
3879 if p.haslayer(Template):
3880 ipfix.add_template(p.getlayer(Template))
3881 # verify events in data set
3883 if p.haslayer(Data):
3884 data = ipfix.decode_data_set(p.getlayer(Set))
3885 self.verify_ipfix_max_fragments_ip4(data, 1,
3886 self.pg0.remote_ip4n)
3888 def test_multiple_outside_vrf(self):
3889 """ Multiple outside VRF """
3893 self.pg1.unconfig_ip4()
3894 self.pg2.unconfig_ip4()
3895 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
3896 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
3897 self.pg1.set_table_ip4(vrf_id1)
3898 self.pg2.set_table_ip4(vrf_id2)
3899 self.pg1.config_ip4()
3900 self.pg2.config_ip4()
3901 self.pg1.resolve_arp()
3902 self.pg2.resolve_arp()
3904 self.nat44_add_address(self.nat_addr)
3905 flags = self.config_flags.NAT_IS_INSIDE
3906 self.vapi.nat44_interface_add_del_feature(
3907 sw_if_index=self.pg0.sw_if_index,
3908 flags=flags, is_add=1)
3909 self.vapi.nat44_interface_add_del_feature(
3910 sw_if_index=self.pg1.sw_if_index,
3912 self.vapi.nat44_interface_add_del_feature(
3913 sw_if_index=self.pg2.sw_if_index,
3918 pkts = self.create_stream_in(self.pg0, self.pg1)
3919 self.pg0.add_stream(pkts)
3920 self.pg_enable_capture(self.pg_interfaces)
3922 capture = self.pg1.get_capture(len(pkts))
3923 self.verify_capture_out(capture, self.nat_addr)
3925 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3926 self.pg1.add_stream(pkts)
3927 self.pg_enable_capture(self.pg_interfaces)
3929 capture = self.pg0.get_capture(len(pkts))
3930 self.verify_capture_in(capture, self.pg0)
3932 self.tcp_port_in = 60303
3933 self.udp_port_in = 60304
3934 self.icmp_id_in = 60305
3937 pkts = self.create_stream_in(self.pg0, self.pg2)
3938 self.pg0.add_stream(pkts)
3939 self.pg_enable_capture(self.pg_interfaces)
3941 capture = self.pg2.get_capture(len(pkts))
3942 self.verify_capture_out(capture, self.nat_addr)
3944 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3945 self.pg2.add_stream(pkts)
3946 self.pg_enable_capture(self.pg_interfaces)
3948 capture = self.pg0.get_capture(len(pkts))
3949 self.verify_capture_in(capture, self.pg0)
3952 self.nat44_add_address(self.nat_addr, is_add=0)
3953 self.pg1.unconfig_ip4()
3954 self.pg2.unconfig_ip4()
3955 self.pg1.set_table_ip4(0)
3956 self.pg2.set_table_ip4(0)
3957 self.pg1.config_ip4()
3958 self.pg2.config_ip4()
3959 self.pg1.resolve_arp()
3960 self.pg2.resolve_arp()
3962 @unittest.skipUnless(running_extended_tests, "part of extended tests")
3963 def test_session_timeout(self):
3964 """ NAT44 session timeouts """
3965 self.nat44_add_address(self.nat_addr)
3966 flags = self.config_flags.NAT_IS_INSIDE
3967 self.vapi.nat44_interface_add_del_feature(
3968 sw_if_index=self.pg0.sw_if_index,
3969 flags=flags, is_add=1)
3970 self.vapi.nat44_interface_add_del_feature(
3971 sw_if_index=self.pg1.sw_if_index,
3973 self.vapi.nat_set_timeouts(udp=5, tcp_established=7440,
3974 tcp_transitory=240, icmp=60)
3978 for i in range(0, max_sessions):
3979 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3980 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3981 IP(src=src, dst=self.pg1.remote_ip4) /
3982 UDP(sport=1025, dport=53))
3984 self.pg0.add_stream(pkts)
3985 self.pg_enable_capture(self.pg_interfaces)
3987 self.pg1.get_capture(max_sessions)
3992 for i in range(0, max_sessions):
3993 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3994 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3995 IP(src=src, dst=self.pg1.remote_ip4) /
3996 UDP(sport=1026, dport=53))
3998 self.pg0.add_stream(pkts)
3999 self.pg_enable_capture(self.pg_interfaces)
4001 self.pg1.get_capture(max_sessions)
4004 users = self.vapi.nat44_user_dump()
4006 nsessions = nsessions + user.nsessions
4007 self.assertLess(nsessions, 2 * max_sessions)
4009 def test_mss_clamping(self):
4010 """ TCP MSS clamping """
4011 self.nat44_add_address(self.nat_addr)
4012 flags = self.config_flags.NAT_IS_INSIDE
4013 self.vapi.nat44_interface_add_del_feature(
4014 sw_if_index=self.pg0.sw_if_index,
4015 flags=flags, is_add=1)
4016 self.vapi.nat44_interface_add_del_feature(
4017 sw_if_index=self.pg1.sw_if_index,
4020 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4021 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4022 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
4023 flags="S", options=[('MSS', 1400)]))
4025 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
4026 self.pg0.add_stream(p)
4027 self.pg_enable_capture(self.pg_interfaces)
4029 capture = self.pg1.get_capture(1)
4030 # Negotiated MSS value greater than configured - changed
4031 self.verify_mss_value(capture[0], 1000)
4033 self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
4034 self.pg0.add_stream(p)
4035 self.pg_enable_capture(self.pg_interfaces)
4037 capture = self.pg1.get_capture(1)
4038 # MSS clamping disabled - negotiated MSS unchanged
4039 self.verify_mss_value(capture[0], 1400)
4041 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
4042 self.pg0.add_stream(p)
4043 self.pg_enable_capture(self.pg_interfaces)
4045 capture = self.pg1.get_capture(1)
4046 # Negotiated MSS value smaller than configured - unchanged
4047 self.verify_mss_value(capture[0], 1400)
4049 @unittest.skipUnless(running_extended_tests, "part of extended tests")
4050 def test_ha_send(self):
4051 """ Send HA session synchronization events (active) """
4052 self.nat44_add_address(self.nat_addr)
4053 flags = self.config_flags.NAT_IS_INSIDE
4054 self.vapi.nat44_interface_add_del_feature(
4055 sw_if_index=self.pg0.sw_if_index,
4056 flags=flags, is_add=1)
4057 self.vapi.nat44_interface_add_del_feature(
4058 sw_if_index=self.pg1.sw_if_index,
4060 self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
4063 self.vapi.nat_ha_set_failover(ip_address=self.pg3.remote_ip4,
4064 port=12346, session_refresh_interval=10)
4065 bind_layers(UDP, HANATStateSync, sport=12345)
4068 pkts = self.create_stream_in(self.pg0, self.pg1)
4069 self.pg0.add_stream(pkts)
4070 self.pg_enable_capture(self.pg_interfaces)
4072 capture = self.pg1.get_capture(len(pkts))
4073 self.verify_capture_out(capture)
4074 # active send HA events
4075 self.vapi.nat_ha_flush()
4076 stats = self.statistics.get_counter('/nat44/ha/add-event-send')
4077 self.assertEqual(stats[0][0], 3)
4078 capture = self.pg3.get_capture(1)
4080 self.assert_packet_checksums_valid(p)
4084 hanat = p[HANATStateSync]
4086 self.logger.error(ppp("Invalid packet:", p))
4089 self.assertEqual(ip.src, self.pg3.local_ip4)
4090 self.assertEqual(ip.dst, self.pg3.remote_ip4)
4091 self.assertEqual(udp.sport, 12345)
4092 self.assertEqual(udp.dport, 12346)
4093 self.assertEqual(hanat.version, 1)
4094 self.assertEqual(hanat.thread_index, 0)
4095 self.assertEqual(hanat.count, 3)
4096 seq = hanat.sequence_number
4097 for event in hanat.events:
4098 self.assertEqual(event.event_type, 1)
4099 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
4100 self.assertEqual(event.out_addr, self.nat_addr)
4101 self.assertEqual(event.fib_index, 0)
4103 # ACK received events
4104 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4105 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4106 UDP(sport=12346, dport=12345) /
4107 HANATStateSync(sequence_number=seq, flags='ACK'))
4108 self.pg3.add_stream(ack)
4110 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
4111 self.assertEqual(stats[0][0], 1)
4113 # delete one session
4114 self.pg_enable_capture(self.pg_interfaces)
4115 self.vapi.nat44_del_session(address=self.pg0.remote_ip4,
4116 port=self.tcp_port_in,
4117 protocol=IP_PROTOS.tcp,
4118 flags=self.config_flags.NAT_IS_INSIDE)
4119 self.vapi.nat_ha_flush()
4120 stats = self.statistics.get_counter('/nat44/ha/del-event-send')
4121 self.assertEqual(stats[0][0], 1)
4122 capture = self.pg3.get_capture(1)
4125 hanat = p[HANATStateSync]
4127 self.logger.error(ppp("Invalid packet:", p))
4130 self.assertGreater(hanat.sequence_number, seq)
4132 # do not send ACK, active retry send HA event again
4133 self.pg_enable_capture(self.pg_interfaces)
4135 stats = self.statistics.get_counter('/nat44/ha/retry-count')
4136 self.assertEqual(stats[0][0], 3)
4137 stats = self.statistics.get_counter('/nat44/ha/missed-count')
4138 self.assertEqual(stats[0][0], 1)
4139 capture = self.pg3.get_capture(3)
4140 for packet in capture:
4141 self.assertEqual(packet, p)
4143 # session counters refresh
4144 pkts = self.create_stream_out(self.pg1)
4145 self.pg1.add_stream(pkts)
4146 self.pg_enable_capture(self.pg_interfaces)
4148 self.pg0.get_capture(2)
4149 self.vapi.nat_ha_flush()
4150 stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
4151 self.assertEqual(stats[0][0], 2)
4152 capture = self.pg3.get_capture(1)
4154 self.assert_packet_checksums_valid(p)
4158 hanat = p[HANATStateSync]
4160 self.logger.error(ppp("Invalid packet:", p))
4163 self.assertEqual(ip.src, self.pg3.local_ip4)
4164 self.assertEqual(ip.dst, self.pg3.remote_ip4)
4165 self.assertEqual(udp.sport, 12345)
4166 self.assertEqual(udp.dport, 12346)
4167 self.assertEqual(hanat.version, 1)
4168 self.assertEqual(hanat.count, 2)
4169 seq = hanat.sequence_number
4170 for event in hanat.events:
4171 self.assertEqual(event.event_type, 3)
4172 self.assertEqual(event.out_addr, self.nat_addr)
4173 self.assertEqual(event.fib_index, 0)
4174 self.assertEqual(event.total_pkts, 2)
4175 self.assertGreater(event.total_bytes, 0)
4177 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4178 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4179 UDP(sport=12346, dport=12345) /
4180 HANATStateSync(sequence_number=seq, flags='ACK'))
4181 self.pg3.add_stream(ack)
4183 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
4184 self.assertEqual(stats[0][0], 2)
4186 def test_ha_recv(self):
4187 """ Receive HA session synchronization events (passive) """
4188 self.nat44_add_address(self.nat_addr)
4189 flags = self.config_flags.NAT_IS_INSIDE
4190 self.vapi.nat44_interface_add_del_feature(
4191 sw_if_index=self.pg0.sw_if_index,
4192 flags=flags, is_add=1)
4193 self.vapi.nat44_interface_add_del_feature(
4194 sw_if_index=self.pg1.sw_if_index,
4196 self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
4199 bind_layers(UDP, HANATStateSync, sport=12345)
4201 self.tcp_port_out = random.randint(1025, 65535)
4202 self.udp_port_out = random.randint(1025, 65535)
4204 # send HA session add events to failover/passive
4205 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4206 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4207 UDP(sport=12346, dport=12345) /
4208 HANATStateSync(sequence_number=1, events=[
4209 Event(event_type='add', protocol='tcp',
4210 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4211 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4212 eh_addr=self.pg1.remote_ip4,
4213 ehn_addr=self.pg1.remote_ip4,
4214 eh_port=self.tcp_external_port,
4215 ehn_port=self.tcp_external_port, fib_index=0),
4216 Event(event_type='add', protocol='udp',
4217 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4218 in_port=self.udp_port_in, out_port=self.udp_port_out,
4219 eh_addr=self.pg1.remote_ip4,
4220 ehn_addr=self.pg1.remote_ip4,
4221 eh_port=self.udp_external_port,
4222 ehn_port=self.udp_external_port, fib_index=0)]))
4224 self.pg3.add_stream(p)
4225 self.pg_enable_capture(self.pg_interfaces)
4228 capture = self.pg3.get_capture(1)
4231 hanat = p[HANATStateSync]
4233 self.logger.error(ppp("Invalid packet:", p))
4236 self.assertEqual(hanat.sequence_number, 1)
4237 self.assertEqual(hanat.flags, 'ACK')
4238 self.assertEqual(hanat.version, 1)
4239 self.assertEqual(hanat.thread_index, 0)
4240 stats = self.statistics.get_counter('/nat44/ha/ack-send')
4241 self.assertEqual(stats[0][0], 1)
4242 stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
4243 self.assertEqual(stats[0][0], 2)
4244 users = self.statistics.get_counter('/nat44/total-users')
4245 self.assertEqual(users[0][0], 1)
4246 sessions = self.statistics.get_counter('/nat44/total-sessions')
4247 self.assertEqual(sessions[0][0], 2)
4248 users = self.vapi.nat44_user_dump()
4249 self.assertEqual(len(users), 1)
4250 self.assertEqual(str(users[0].ip_address),
4251 self.pg0.remote_ip4)
4252 # there should be 2 sessions created by HA
4253 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4255 self.assertEqual(len(sessions), 2)
4256 for session in sessions:
4257 self.assertEqual(str(session.inside_ip_address),
4258 self.pg0.remote_ip4)
4259 self.assertEqual(str(session.outside_ip_address),
4261 self.assertIn(session.inside_port,
4262 [self.tcp_port_in, self.udp_port_in])
4263 self.assertIn(session.outside_port,
4264 [self.tcp_port_out, self.udp_port_out])
4265 self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
4267 # send HA session delete event to failover/passive
4268 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4269 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4270 UDP(sport=12346, dport=12345) /
4271 HANATStateSync(sequence_number=2, events=[
4272 Event(event_type='del', protocol='udp',
4273 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4274 in_port=self.udp_port_in, out_port=self.udp_port_out,
4275 eh_addr=self.pg1.remote_ip4,
4276 ehn_addr=self.pg1.remote_ip4,
4277 eh_port=self.udp_external_port,
4278 ehn_port=self.udp_external_port, fib_index=0)]))
4280 self.pg3.add_stream(p)
4281 self.pg_enable_capture(self.pg_interfaces)
4284 capture = self.pg3.get_capture(1)
4287 hanat = p[HANATStateSync]
4289 self.logger.error(ppp("Invalid packet:", p))
4292 self.assertEqual(hanat.sequence_number, 2)
4293 self.assertEqual(hanat.flags, 'ACK')
4294 self.assertEqual(hanat.version, 1)
4295 users = self.vapi.nat44_user_dump()
4296 self.assertEqual(len(users), 1)
4297 self.assertEqual(str(users[0].ip_address),
4298 self.pg0.remote_ip4)
4299 # now we should have only 1 session, 1 deleted by HA
4300 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4302 self.assertEqual(len(sessions), 1)
4303 stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
4304 self.assertEqual(stats[0][0], 1)
4306 stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
4307 self.assertEqual(stats, 2)
4309 # send HA session refresh event to failover/passive
4310 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4311 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4312 UDP(sport=12346, dport=12345) /
4313 HANATStateSync(sequence_number=3, events=[
4314 Event(event_type='refresh', protocol='tcp',
4315 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4316 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4317 eh_addr=self.pg1.remote_ip4,
4318 ehn_addr=self.pg1.remote_ip4,
4319 eh_port=self.tcp_external_port,
4320 ehn_port=self.tcp_external_port, fib_index=0,
4321 total_bytes=1024, total_pkts=2)]))
4322 self.pg3.add_stream(p)
4323 self.pg_enable_capture(self.pg_interfaces)
4326 capture = self.pg3.get_capture(1)
4329 hanat = p[HANATStateSync]
4331 self.logger.error(ppp("Invalid packet:", p))
4334 self.assertEqual(hanat.sequence_number, 3)
4335 self.assertEqual(hanat.flags, 'ACK')
4336 self.assertEqual(hanat.version, 1)
4337 users = self.vapi.nat44_user_dump()
4338 self.assertEqual(len(users), 1)
4339 self.assertEqual(str(users[0].ip_address),
4340 self.pg0.remote_ip4)
4341 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4343 self.assertEqual(len(sessions), 1)
4344 session = sessions[0]
4345 self.assertEqual(session.total_bytes, 1024)
4346 self.assertEqual(session.total_pkts, 2)
4347 stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
4348 self.assertEqual(stats[0][0], 1)
4350 stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
4351 self.assertEqual(stats, 3)
4353 # send packet to test session created by HA
4354 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4355 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4356 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
4357 self.pg1.add_stream(p)
4358 self.pg_enable_capture(self.pg_interfaces)
4360 capture = self.pg0.get_capture(1)
4366 self.logger.error(ppp("Invalid packet:", p))
4369 self.assertEqual(ip.src, self.pg1.remote_ip4)
4370 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4371 self.assertEqual(tcp.sport, self.tcp_external_port)
4372 self.assertEqual(tcp.dport, self.tcp_port_in)
4375 super(TestNAT44, self).tearDown()
4377 self.vapi.cli("clear logging")
4379 def show_commands_at_teardown(self):
4380 self.logger.info(self.vapi.cli("show nat44 addresses"))
4381 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4382 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4383 self.logger.info(self.vapi.cli("show nat44 interface address"))
4384 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
4385 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
4386 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
4387 self.logger.info(self.vapi.cli("show nat timeouts"))
4389 self.vapi.cli("show nat addr-port-assignment-alg"))
4390 self.logger.info(self.vapi.cli("show nat ha"))
4393 class TestNAT44EndpointDependent(MethodHolder):
4394 """ Endpoint-Dependent mapping and filtering test cases """
4397 def setUpConstants(cls):
4398 super(TestNAT44EndpointDependent, cls).setUpConstants()
4399 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4402 def setUpClass(cls):
4403 super(TestNAT44EndpointDependent, cls).setUpClass()
4404 cls.vapi.cli("set log class nat level debug")
4406 cls.tcp_port_in = 6303
4407 cls.tcp_port_out = 6303
4408 cls.udp_port_in = 6304
4409 cls.udp_port_out = 6304
4410 cls.icmp_id_in = 6305
4411 cls.icmp_id_out = 6305
4412 cls.nat_addr = '10.0.0.3'
4413 cls.ipfix_src_port = 4739
4414 cls.ipfix_domain_id = 1
4415 cls.tcp_external_port = 80
4417 cls.create_pg_interfaces(range(9))
4418 cls.interfaces = list(cls.pg_interfaces[0:3])
4420 for i in cls.interfaces:
4425 cls.pg0.generate_remote_hosts(3)
4426 cls.pg0.configure_ipv4_neighbors()
4430 cls.pg4.generate_remote_hosts(2)
4431 cls.pg4.config_ip4()
4432 cls.vapi.sw_interface_add_del_address(
4433 sw_if_index=cls.pg4.sw_if_index,
4434 prefix=VppIpPrefix("10.0.0.1", 24).encode())
4437 cls.pg4.resolve_arp()
4438 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4439 cls.pg4.resolve_arp()
4441 zero_ip4 = socket.inet_pton(socket.AF_INET, "0.0.0.0")
4442 cls.vapi.ip_table_add_del(is_add=1, table_id=1)
4444 cls.pg5._local_ip4 = VppIpPrefix("10.1.1.1",
4445 cls.pg5.local_ip4_prefix.len)
4446 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4447 cls.pg5.set_table_ip4(1)
4448 cls.pg5.config_ip4()
4450 r1 = VppIpRoute(cls, cls.pg5.remote_ip4, 32,
4451 [VppRoutePath("0.0.0.0",
4452 cls.pg5.sw_if_index)],
4457 cls.pg6._local_ip4 = VppIpPrefix("10.1.2.1",
4458 cls.pg6.local_ip4_prefix.len)
4459 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4460 cls.pg6.set_table_ip4(1)
4461 cls.pg6.config_ip4()
4464 r2 = VppIpRoute(cls, cls.pg6.remote_ip4, 32,
4465 [VppRoutePath("0.0.0.0",
4466 cls.pg6.sw_if_index)],
4469 r3 = VppIpRoute(cls, cls.pg6.remote_ip4, 16,
4470 [VppRoutePath("0.0.0.0",
4475 r4 = VppIpRoute(cls, "0.0.0.0", 0,
4476 [VppRoutePath("0.0.0.0", 0xffffffff,
4480 r5 = VppIpRoute(cls, "0.0.0.0", 0,
4481 [VppRoutePath(cls.pg1.local_ip4,
4482 cls.pg1.sw_if_index)],
4489 cls.pg5.resolve_arp()
4490 cls.pg6.resolve_arp()
4493 cls.pg7.config_ip4()
4494 cls.pg7.resolve_arp()
4495 cls.pg7.generate_remote_hosts(3)
4496 cls.pg7.configure_ipv4_neighbors()
4499 cls.pg8.config_ip4()
4500 cls.pg8.resolve_arp()
4503 super(TestNAT44EndpointDependent, cls).tearDownClass()
4507 def tearDownClass(cls):
4508 super(TestNAT44EndpointDependent, cls).tearDownClass()
4510 def test_frag_in_order(self):
4511 """ NAT44 translate fragments arriving in order """
4512 self.nat44_add_address(self.nat_addr)
4513 flags = self.config_flags.NAT_IS_INSIDE
4514 self.vapi.nat44_interface_add_del_feature(
4515 sw_if_index=self.pg0.sw_if_index,
4516 flags=flags, is_add=1)
4517 self.vapi.nat44_interface_add_del_feature(
4518 sw_if_index=self.pg1.sw_if_index,
4520 self.frag_in_order(proto=IP_PROTOS.tcp)
4521 self.frag_in_order(proto=IP_PROTOS.udp)
4522 self.frag_in_order(proto=IP_PROTOS.icmp)
4524 def test_frag_in_order_dont_translate(self):
4525 """ NAT44 don't translate fragments arriving in order """
4526 flags = self.config_flags.NAT_IS_INSIDE
4527 self.vapi.nat44_interface_add_del_feature(
4528 sw_if_index=self.pg0.sw_if_index,
4529 flags=flags, is_add=1)
4530 self.vapi.nat44_interface_add_del_feature(
4531 sw_if_index=self.pg1.sw_if_index,
4533 self.vapi.nat44_forwarding_enable_disable(enable=True)
4534 reas_cfg1 = self.vapi.nat_get_reass()
4535 # this test was intermittently failing in some cases
4536 # until we temporarily bump the reassembly timeouts
4537 self.vapi.nat_set_reass(timeout=20, max_reass=1024, max_frag=5,
4539 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4540 # restore the reassembly timeouts
4541 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout,
4542 max_reass=reas_cfg1.ip4_max_reass,
4543 max_frag=reas_cfg1.ip4_max_frag,
4544 drop_frag=reas_cfg1.ip4_drop_frag)
4546 def test_frag_out_of_order(self):
4547 """ NAT44 translate fragments arriving out of order """
4548 self.nat44_add_address(self.nat_addr)
4549 flags = self.config_flags.NAT_IS_INSIDE
4550 self.vapi.nat44_interface_add_del_feature(
4551 sw_if_index=self.pg0.sw_if_index,
4552 flags=flags, is_add=1)
4553 self.vapi.nat44_interface_add_del_feature(
4554 sw_if_index=self.pg1.sw_if_index,
4556 self.frag_out_of_order(proto=IP_PROTOS.tcp)
4557 self.frag_out_of_order(proto=IP_PROTOS.udp)
4558 self.frag_out_of_order(proto=IP_PROTOS.icmp)
4560 def test_frag_out_of_order_dont_translate(self):
4561 """ NAT44 don't translate fragments arriving out of order """
4562 flags = self.config_flags.NAT_IS_INSIDE
4563 self.vapi.nat44_interface_add_del_feature(
4564 sw_if_index=self.pg0.sw_if_index,
4565 flags=flags, is_add=1)
4566 self.vapi.nat44_interface_add_del_feature(
4567 sw_if_index=self.pg1.sw_if_index,
4569 self.vapi.nat44_forwarding_enable_disable(enable=True)
4570 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4572 def test_frag_in_order_in_plus_out(self):
4573 """ in+out interface fragments in order """
4574 flags = self.config_flags.NAT_IS_INSIDE
4575 self.vapi.nat44_interface_add_del_feature(
4576 sw_if_index=self.pg0.sw_if_index,
4578 self.vapi.nat44_interface_add_del_feature(
4579 sw_if_index=self.pg0.sw_if_index,
4580 flags=flags, is_add=1)
4581 self.vapi.nat44_interface_add_del_feature(
4582 sw_if_index=self.pg1.sw_if_index,
4584 self.vapi.nat44_interface_add_del_feature(
4585 sw_if_index=self.pg1.sw_if_index,
4586 flags=flags, is_add=1)
4588 self.server = self.pg1.remote_hosts[0]
4590 self.server_in_addr = self.server.ip4
4591 self.server_out_addr = '11.11.11.11'
4592 self.server_in_port = random.randint(1025, 65535)
4593 self.server_out_port = random.randint(1025, 65535)
4595 self.nat44_add_address(self.server_out_addr)
4597 # add static mappings for server
4598 self.nat44_add_static_mapping(self.server_in_addr,
4599 self.server_out_addr,
4600 self.server_in_port,
4601 self.server_out_port,
4602 proto=IP_PROTOS.tcp)
4603 self.nat44_add_static_mapping(self.server_in_addr,
4604 self.server_out_addr,
4605 self.server_in_port,
4606 self.server_out_port,
4607 proto=IP_PROTOS.udp)
4608 self.nat44_add_static_mapping(self.server_in_addr,
4609 self.server_out_addr,
4610 proto=IP_PROTOS.icmp)
4612 self.vapi.nat_set_reass(timeout=10, max_reass=1024, max_frag=5,
4615 self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4616 self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4617 self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4619 def test_frag_out_of_order_in_plus_out(self):
4620 """ in+out interface fragments out of order """
4621 flags = self.config_flags.NAT_IS_INSIDE
4622 self.vapi.nat44_interface_add_del_feature(
4623 sw_if_index=self.pg0.sw_if_index,
4625 self.vapi.nat44_interface_add_del_feature(
4626 sw_if_index=self.pg0.sw_if_index,
4627 flags=flags, is_add=1)
4628 self.vapi.nat44_interface_add_del_feature(
4629 sw_if_index=self.pg1.sw_if_index,
4631 self.vapi.nat44_interface_add_del_feature(
4632 sw_if_index=self.pg1.sw_if_index,
4633 flags=flags, is_add=1)
4635 self.server = self.pg1.remote_hosts[0]
4637 self.server_in_addr = self.server.ip4
4638 self.server_out_addr = '11.11.11.11'
4639 self.server_in_port = random.randint(1025, 65535)
4640 self.server_out_port = random.randint(1025, 65535)
4642 self.nat44_add_address(self.server_out_addr)
4644 # add static mappings for server
4645 self.nat44_add_static_mapping(self.server_in_addr,
4646 self.server_out_addr,
4647 self.server_in_port,
4648 self.server_out_port,
4649 proto=IP_PROTOS.tcp)
4650 self.nat44_add_static_mapping(self.server_in_addr,
4651 self.server_out_addr,
4652 self.server_in_port,
4653 self.server_out_port,
4654 proto=IP_PROTOS.udp)
4655 self.nat44_add_static_mapping(self.server_in_addr,
4656 self.server_out_addr,
4657 proto=IP_PROTOS.icmp)
4659 self.vapi.nat_set_reass(timeout=10, max_reass=1024, max_frag=5,
4662 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4663 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4664 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4666 def test_reass_hairpinning(self):
4667 """ NAT44 fragments hairpinning """
4668 self.server = self.pg0.remote_hosts[1]
4669 self.host_in_port = random.randint(1025, 65535)
4670 self.server_in_port = random.randint(1025, 65535)
4671 self.server_out_port = random.randint(1025, 65535)
4673 self.nat44_add_address(self.nat_addr)
4674 flags = self.config_flags.NAT_IS_INSIDE
4675 self.vapi.nat44_interface_add_del_feature(
4676 sw_if_index=self.pg0.sw_if_index,
4677 flags=flags, is_add=1)
4678 self.vapi.nat44_interface_add_del_feature(
4679 sw_if_index=self.pg1.sw_if_index,
4681 # add static mapping for server
4682 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4683 self.server_in_port,
4684 self.server_out_port,
4685 proto=IP_PROTOS.tcp)
4686 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4687 self.server_in_port,
4688 self.server_out_port,
4689 proto=IP_PROTOS.udp)
4690 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
4692 self.reass_hairpinning(proto=IP_PROTOS.tcp)
4693 self.reass_hairpinning(proto=IP_PROTOS.udp)
4694 self.reass_hairpinning(proto=IP_PROTOS.icmp)
4696 def test_dynamic(self):
4697 """ NAT44 dynamic translation test """
4699 self.nat44_add_address(self.nat_addr)
4700 flags = self.config_flags.NAT_IS_INSIDE
4701 self.vapi.nat44_interface_add_del_feature(
4702 sw_if_index=self.pg0.sw_if_index,
4703 flags=flags, is_add=1)
4704 self.vapi.nat44_interface_add_del_feature(
4705 sw_if_index=self.pg1.sw_if_index,
4708 nat_config = self.vapi.nat_show_config()
4709 self.assertEqual(1, nat_config.endpoint_dependent)
4712 tcpn = self.statistics.get_err_counter(
4713 '/err/nat44-ed-in2out-slowpath/TCP packets')
4714 udpn = self.statistics.get_err_counter(
4715 '/err/nat44-ed-in2out-slowpath/UDP packets')
4716 icmpn = self.statistics.get_err_counter(
4717 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4718 totaln = self.statistics.get_err_counter(
4719 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4721 pkts = self.create_stream_in(self.pg0, self.pg1)
4722 self.pg0.add_stream(pkts)
4723 self.pg_enable_capture(self.pg_interfaces)
4725 capture = self.pg1.get_capture(len(pkts))
4726 self.verify_capture_out(capture)
4728 err = self.statistics.get_err_counter(
4729 '/err/nat44-ed-in2out-slowpath/TCP packets')
4730 self.assertEqual(err - tcpn, 2)
4731 err = self.statistics.get_err_counter(
4732 '/err/nat44-ed-in2out-slowpath/UDP packets')
4733 self.assertEqual(err - udpn, 1)
4734 err = self.statistics.get_err_counter(
4735 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4736 self.assertEqual(err - icmpn, 1)
4737 err = self.statistics.get_err_counter(
4738 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4739 self.assertEqual(err - totaln, 4)
4742 tcpn = self.statistics.get_err_counter(
4743 '/err/nat44-ed-out2in/TCP packets')
4744 udpn = self.statistics.get_err_counter(
4745 '/err/nat44-ed-out2in/UDP packets')
4746 icmpn = self.statistics.get_err_counter(
4747 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4748 totaln = self.statistics.get_err_counter(
4749 '/err/nat44-ed-out2in/good out2in packets processed')
4751 pkts = self.create_stream_out(self.pg1)
4752 self.pg1.add_stream(pkts)
4753 self.pg_enable_capture(self.pg_interfaces)
4755 capture = self.pg0.get_capture(len(pkts))
4756 self.verify_capture_in(capture, self.pg0)
4758 err = self.statistics.get_err_counter(
4759 '/err/nat44-ed-out2in/TCP packets')
4760 self.assertEqual(err - tcpn, 2)
4761 err = self.statistics.get_err_counter(
4762 '/err/nat44-ed-out2in/UDP packets')
4763 self.assertEqual(err - udpn, 1)
4764 err = self.statistics.get_err_counter(
4765 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4766 self.assertEqual(err - icmpn, 1)
4767 err = self.statistics.get_err_counter(
4768 '/err/nat44-ed-out2in/good out2in packets processed')
4769 self.assertEqual(err - totaln, 3)
4771 users = self.statistics.get_counter('/nat44/total-users')
4772 self.assertEqual(users[0][0], 1)
4773 sessions = self.statistics.get_counter('/nat44/total-sessions')
4774 self.assertEqual(sessions[0][0], 3)
4776 def test_dynamic_output_feature_vrf(self):
4777 """ NAT44 dynamic translation test: output-feature, VRF"""
4779 # other then default (0)
4782 self.nat44_add_address(self.nat_addr)
4783 flags = self.config_flags.NAT_IS_INSIDE
4784 self.vapi.nat44_interface_add_del_output_feature(
4785 sw_if_index=self.pg7.sw_if_index,
4786 flags=flags, is_add=1)
4787 self.vapi.nat44_interface_add_del_output_feature(
4788 sw_if_index=self.pg8.sw_if_index,
4792 self.vapi.ip_table_add_del(is_add=1, table_id=new_vrf_id)
4794 self.pg7.unconfig_ip4()
4795 self.pg7.set_table_ip4(new_vrf_id)
4796 self.pg7.config_ip4()
4797 self.pg7.resolve_arp()
4799 self.pg8.unconfig_ip4()
4800 self.pg8.set_table_ip4(new_vrf_id)
4801 self.pg8.config_ip4()
4802 self.pg8.resolve_arp()
4804 nat_config = self.vapi.nat_show_config()
4805 self.assertEqual(1, nat_config.endpoint_dependent)
4808 tcpn = self.statistics.get_err_counter(
4809 '/err/nat44-ed-in2out-slowpath/TCP packets')
4810 udpn = self.statistics.get_err_counter(
4811 '/err/nat44-ed-in2out-slowpath/UDP packets')
4812 icmpn = self.statistics.get_err_counter(
4813 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4814 totaln = self.statistics.get_err_counter(
4815 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4817 pkts = self.create_stream_in(self.pg7, self.pg8)
4818 self.pg7.add_stream(pkts)
4819 self.pg_enable_capture(self.pg_interfaces)
4821 capture = self.pg8.get_capture(len(pkts))
4822 self.verify_capture_out(capture)
4824 err = self.statistics.get_err_counter(
4825 '/err/nat44-ed-in2out-slowpath/TCP packets')
4826 self.assertEqual(err - tcpn, 2)
4827 err = self.statistics.get_err_counter(
4828 '/err/nat44-ed-in2out-slowpath/UDP packets')
4829 self.assertEqual(err - udpn, 1)
4830 err = self.statistics.get_err_counter(
4831 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4832 self.assertEqual(err - icmpn, 1)
4833 err = self.statistics.get_err_counter(
4834 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4835 self.assertEqual(err - totaln, 4)
4838 tcpn = self.statistics.get_err_counter(
4839 '/err/nat44-ed-out2in/TCP packets')
4840 udpn = self.statistics.get_err_counter(
4841 '/err/nat44-ed-out2in/UDP packets')
4842 icmpn = self.statistics.get_err_counter(
4843 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4844 totaln = self.statistics.get_err_counter(
4845 '/err/nat44-ed-out2in/good out2in packets processed')
4847 pkts = self.create_stream_out(self.pg8)
4848 self.pg8.add_stream(pkts)
4849 self.pg_enable_capture(self.pg_interfaces)
4851 capture = self.pg7.get_capture(len(pkts))
4852 self.verify_capture_in(capture, self.pg7)
4854 err = self.statistics.get_err_counter(
4855 '/err/nat44-ed-out2in/TCP packets')
4856 self.assertEqual(err - tcpn, 2)
4857 err = self.statistics.get_err_counter(
4858 '/err/nat44-ed-out2in/UDP packets')
4859 self.assertEqual(err - udpn, 1)
4860 err = self.statistics.get_err_counter(
4861 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4862 self.assertEqual(err - icmpn, 1)
4863 err = self.statistics.get_err_counter(
4864 '/err/nat44-ed-out2in/good out2in packets processed')
4865 self.assertEqual(err - totaln, 3)
4867 users = self.statistics.get_counter('/nat44/total-users')
4868 self.assertEqual(users[0][0], 1)
4869 sessions = self.statistics.get_counter('/nat44/total-sessions')
4870 self.assertEqual(sessions[0][0], 3)
4873 self.pg7.unconfig_ip4()
4874 self.pg7.set_table_ip4(1)
4875 self.pg7.config_ip4()
4876 self.pg7.resolve_arp()
4878 self.pg8.unconfig_ip4()
4879 self.pg8.set_table_ip4(1)
4880 self.pg8.config_ip4()
4881 self.pg8.resolve_arp()
4883 self.vapi.ip_table_add_del(is_add=0, table_id=new_vrf_id)
4885 def test_forwarding(self):
4886 """ NAT44 forwarding test """
4888 flags = self.config_flags.NAT_IS_INSIDE
4889 self.vapi.nat44_interface_add_del_feature(
4890 sw_if_index=self.pg0.sw_if_index,
4891 flags=flags, is_add=1)
4892 self.vapi.nat44_interface_add_del_feature(
4893 sw_if_index=self.pg1.sw_if_index,
4895 self.vapi.nat44_forwarding_enable_disable(enable=1)
4897 real_ip = self.pg0.remote_ip4
4898 alias_ip = self.nat_addr
4899 flags = self.config_flags.NAT_IS_ADDR_ONLY
4900 self.vapi.nat44_add_del_static_mapping(is_add=1,
4901 local_ip_address=real_ip,
4902 external_ip_address=alias_ip,
4903 external_sw_if_index=0xFFFFFFFF,
4907 # in2out - static mapping match
4909 pkts = self.create_stream_out(self.pg1)
4910 self.pg1.add_stream(pkts)
4911 self.pg_enable_capture(self.pg_interfaces)
4913 capture = self.pg0.get_capture(len(pkts))
4914 self.verify_capture_in(capture, self.pg0)
4916 pkts = self.create_stream_in(self.pg0, self.pg1)
4917 self.pg0.add_stream(pkts)
4918 self.pg_enable_capture(self.pg_interfaces)
4920 capture = self.pg1.get_capture(len(pkts))
4921 self.verify_capture_out(capture, same_port=True)
4923 # in2out - no static mapping match
4925 host0 = self.pg0.remote_hosts[0]
4926 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4928 pkts = self.create_stream_out(self.pg1,
4929 dst_ip=self.pg0.remote_ip4,
4930 use_inside_ports=True)
4931 self.pg1.add_stream(pkts)
4932 self.pg_enable_capture(self.pg_interfaces)
4934 capture = self.pg0.get_capture(len(pkts))
4935 self.verify_capture_in(capture, self.pg0)
4937 pkts = self.create_stream_in(self.pg0, self.pg1)
4938 self.pg0.add_stream(pkts)
4939 self.pg_enable_capture(self.pg_interfaces)
4941 capture = self.pg1.get_capture(len(pkts))
4942 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4945 self.pg0.remote_hosts[0] = host0
4947 user = self.pg0.remote_hosts[1]
4948 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4949 self.assertEqual(len(sessions), 3)
4950 self.assertTrue(sessions[0].flags &
4951 self.config_flags.NAT_IS_EXT_HOST_VALID)
4952 self.vapi.nat44_del_session(
4953 address=sessions[0].inside_ip_address,
4954 port=sessions[0].inside_port,
4955 protocol=sessions[0].protocol,
4956 flags=(self.config_flags.NAT_IS_INSIDE |
4957 self.config_flags.NAT_IS_EXT_HOST_VALID),
4958 ext_host_address=sessions[0].ext_host_address,
4959 ext_host_port=sessions[0].ext_host_port)
4960 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4961 self.assertEqual(len(sessions), 2)
4964 self.vapi.nat44_forwarding_enable_disable(enable=0)
4965 flags = self.config_flags.NAT_IS_ADDR_ONLY
4966 self.vapi.nat44_add_del_static_mapping(
4968 local_ip_address=real_ip,
4969 external_ip_address=alias_ip,
4970 external_sw_if_index=0xFFFFFFFF,
4973 def test_static_lb(self):
4974 """ NAT44 local service load balancing """
4975 external_addr_n = self.nat_addr
4978 server1 = self.pg0.remote_hosts[0]
4979 server2 = self.pg0.remote_hosts[1]
4981 locals = [{'addr': server1.ip4,
4985 {'addr': server2.ip4,
4990 self.nat44_add_address(self.nat_addr)
4991 self.vapi.nat44_add_del_lb_static_mapping(
4993 external_addr=external_addr_n,
4994 external_port=external_port,
4995 protocol=IP_PROTOS.tcp,
4996 local_num=len(locals),
4998 flags = self.config_flags.NAT_IS_INSIDE
4999 self.vapi.nat44_interface_add_del_feature(
5000 sw_if_index=self.pg0.sw_if_index,
5001 flags=flags, is_add=1)
5002 self.vapi.nat44_interface_add_del_feature(
5003 sw_if_index=self.pg1.sw_if_index,
5006 # from client to service
5007 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5008 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5009 TCP(sport=12345, dport=external_port))
5010 self.pg1.add_stream(p)
5011 self.pg_enable_capture(self.pg_interfaces)
5013 capture = self.pg0.get_capture(1)
5019 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
5020 if ip.dst == server1.ip4:
5024 self.assertEqual(tcp.dport, local_port)
5025 self.assert_packet_checksums_valid(p)
5027 self.logger.error(ppp("Unexpected or invalid packet:", p))
5030 # from service back to client
5031 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
5032 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
5033 TCP(sport=local_port, dport=12345))
5034 self.pg0.add_stream(p)
5035 self.pg_enable_capture(self.pg_interfaces)
5037 capture = self.pg1.get_capture(1)
5042 self.assertEqual(ip.src, self.nat_addr)
5043 self.assertEqual(tcp.sport, external_port)
5044 self.assert_packet_checksums_valid(p)
5046 self.logger.error(ppp("Unexpected or invalid packet:", p))
5049 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5050 self.assertEqual(len(sessions), 1)
5051 self.assertTrue(sessions[0].flags &
5052 self.config_flags.NAT_IS_EXT_HOST_VALID)
5053 self.vapi.nat44_del_session(
5054 address=sessions[0].inside_ip_address,
5055 port=sessions[0].inside_port,
5056 protocol=sessions[0].protocol,
5057 flags=(self.config_flags.NAT_IS_INSIDE |
5058 self.config_flags.NAT_IS_EXT_HOST_VALID),
5059 ext_host_address=sessions[0].ext_host_address,
5060 ext_host_port=sessions[0].ext_host_port)
5061 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5062 self.assertEqual(len(sessions), 0)
5064 @unittest.skipUnless(running_extended_tests, "part of extended tests")
5065 def test_static_lb_multi_clients(self):
5066 """ NAT44 local service load balancing - multiple clients"""
5068 external_addr = self.nat_addr
5071 server1 = self.pg0.remote_hosts[0]
5072 server2 = self.pg0.remote_hosts[1]
5073 server3 = self.pg0.remote_hosts[2]
5075 locals = [{'addr': server1.ip4,
5079 {'addr': server2.ip4,
5084 self.nat44_add_address(self.nat_addr)
5085 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
5086 external_addr=external_addr,
5087 external_port=external_port,
5088 protocol=IP_PROTOS.tcp,
5089 local_num=len(locals),
5091 flags = self.config_flags.NAT_IS_INSIDE
5092 self.vapi.nat44_interface_add_del_feature(
5093 sw_if_index=self.pg0.sw_if_index,
5094 flags=flags, is_add=1)
5095 self.vapi.nat44_interface_add_del_feature(
5096 sw_if_index=self.pg1.sw_if_index,
5101 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
5103 for client in clients:
5104 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5105 IP(src=client, dst=self.nat_addr) /
5106 TCP(sport=12345, dport=external_port))
5108 self.pg1.add_stream(pkts)
5109 self.pg_enable_capture(self.pg_interfaces)
5111 capture = self.pg0.get_capture(len(pkts))
5113 if p[IP].dst == server1.ip4:
5117 self.assertGreater(server1_n, server2_n)
5120 'addr': server3.ip4,
5127 self.vapi.nat44_lb_static_mapping_add_del_local(
5129 external_addr=external_addr,
5130 external_port=external_port,
5132 protocol=IP_PROTOS.tcp)
5136 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
5138 for client in clients:
5139 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5140 IP(src=client, dst=self.nat_addr) /
5141 TCP(sport=12346, dport=external_port))
5143 self.assertGreater(len(pkts), 0)
5144 self.pg1.add_stream(pkts)
5145 self.pg_enable_capture(self.pg_interfaces)
5147 capture = self.pg0.get_capture(len(pkts))
5149 if p[IP].dst == server1.ip4:
5151 elif p[IP].dst == server2.ip4:
5155 self.assertGreater(server1_n, 0)
5156 self.assertGreater(server2_n, 0)
5157 self.assertGreater(server3_n, 0)
5160 'addr': server2.ip4,
5166 # remove one back-end
5167 self.vapi.nat44_lb_static_mapping_add_del_local(
5169 external_addr=external_addr,
5170 external_port=external_port,
5172 protocol=IP_PROTOS.tcp)
5176 self.pg1.add_stream(pkts)
5177 self.pg_enable_capture(self.pg_interfaces)
5179 capture = self.pg0.get_capture(len(pkts))
5181 if p[IP].dst == server1.ip4:
5183 elif p[IP].dst == server2.ip4:
5187 self.assertGreater(server1_n, 0)
5188 self.assertEqual(server2_n, 0)
5189 self.assertGreater(server3_n, 0)
5191 def test_static_lb_2(self):
5192 """ NAT44 local service load balancing (asymmetrical rule) """
5193 external_addr = self.nat_addr
5196 server1 = self.pg0.remote_hosts[0]
5197 server2 = self.pg0.remote_hosts[1]
5199 locals = [{'addr': server1.ip4,
5203 {'addr': server2.ip4,
5208 self.vapi.nat44_forwarding_enable_disable(enable=1)
5209 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5210 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5211 external_addr=external_addr,
5212 external_port=external_port,
5213 protocol=IP_PROTOS.tcp,
5214 local_num=len(locals),
5216 flags = self.config_flags.NAT_IS_INSIDE
5217 self.vapi.nat44_interface_add_del_feature(
5218 sw_if_index=self.pg0.sw_if_index,
5219 flags=flags, is_add=1)
5220 self.vapi.nat44_interface_add_del_feature(
5221 sw_if_index=self.pg1.sw_if_index,
5224 # from client to service
5225 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5226 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5227 TCP(sport=12345, dport=external_port))
5228 self.pg1.add_stream(p)
5229 self.pg_enable_capture(self.pg_interfaces)
5231 capture = self.pg0.get_capture(1)
5237 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
5238 if ip.dst == server1.ip4:
5242 self.assertEqual(tcp.dport, local_port)
5243 self.assert_packet_checksums_valid(p)
5245 self.logger.error(ppp("Unexpected or invalid packet:", p))
5248 # from service back to client
5249 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
5250 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
5251 TCP(sport=local_port, dport=12345))
5252 self.pg0.add_stream(p)
5253 self.pg_enable_capture(self.pg_interfaces)
5255 capture = self.pg1.get_capture(1)
5260 self.assertEqual(ip.src, self.nat_addr)
5261 self.assertEqual(tcp.sport, external_port)
5262 self.assert_packet_checksums_valid(p)
5264 self.logger.error(ppp("Unexpected or invalid packet:", p))
5267 # from client to server (no translation)
5268 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5269 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
5270 TCP(sport=12346, dport=local_port))
5271 self.pg1.add_stream(p)
5272 self.pg_enable_capture(self.pg_interfaces)
5274 capture = self.pg0.get_capture(1)
5280 self.assertEqual(ip.dst, server1.ip4)
5281 self.assertEqual(tcp.dport, local_port)
5282 self.assert_packet_checksums_valid(p)
5284 self.logger.error(ppp("Unexpected or invalid packet:", p))
5287 # from service back to client (no translation)
5288 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
5289 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
5290 TCP(sport=local_port, dport=12346))
5291 self.pg0.add_stream(p)
5292 self.pg_enable_capture(self.pg_interfaces)
5294 capture = self.pg1.get_capture(1)
5299 self.assertEqual(ip.src, server1.ip4)
5300 self.assertEqual(tcp.sport, local_port)
5301 self.assert_packet_checksums_valid(p)
5303 self.logger.error(ppp("Unexpected or invalid packet:", p))
5306 def test_lb_affinity(self):
5307 """ NAT44 local service load balancing affinity """
5308 external_addr = self.nat_addr
5311 server1 = self.pg0.remote_hosts[0]
5312 server2 = self.pg0.remote_hosts[1]
5314 locals = [{'addr': server1.ip4,
5318 {'addr': server2.ip4,
5323 self.nat44_add_address(self.nat_addr)
5324 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
5325 external_addr=external_addr,
5326 external_port=external_port,
5327 protocol=IP_PROTOS.tcp,
5329 local_num=len(locals),
5331 flags = self.config_flags.NAT_IS_INSIDE
5332 self.vapi.nat44_interface_add_del_feature(
5333 sw_if_index=self.pg0.sw_if_index,
5334 flags=flags, is_add=1)
5335 self.vapi.nat44_interface_add_del_feature(
5336 sw_if_index=self.pg1.sw_if_index,
5339 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5340 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5341 TCP(sport=1025, dport=external_port))
5342 self.pg1.add_stream(p)
5343 self.pg_enable_capture(self.pg_interfaces)
5345 capture = self.pg0.get_capture(1)
5346 backend = capture[0][IP].dst
5348 sessions = self.vapi.nat44_user_session_dump(backend, 0)
5349 self.assertEqual(len(sessions), 1)
5350 self.assertTrue(sessions[0].flags &
5351 self.config_flags.NAT_IS_EXT_HOST_VALID)
5352 self.vapi.nat44_del_session(
5353 address=sessions[0].inside_ip_address,
5354 port=sessions[0].inside_port,
5355 protocol=sessions[0].protocol,
5356 flags=(self.config_flags.NAT_IS_INSIDE |
5357 self.config_flags.NAT_IS_EXT_HOST_VALID),
5358 ext_host_address=sessions[0].ext_host_address,
5359 ext_host_port=sessions[0].ext_host_port)
5362 for port in range(1030, 1100):
5363 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5364 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5365 TCP(sport=port, dport=external_port))
5367 self.pg1.add_stream(pkts)
5368 self.pg_enable_capture(self.pg_interfaces)
5370 capture = self.pg0.get_capture(len(pkts))
5372 self.assertEqual(p[IP].dst, backend)
5374 def test_unknown_proto(self):
5375 """ NAT44 translate packet with unknown protocol """
5376 self.nat44_add_address(self.nat_addr)
5377 flags = self.config_flags.NAT_IS_INSIDE
5378 self.vapi.nat44_interface_add_del_feature(
5379 sw_if_index=self.pg0.sw_if_index,
5380 flags=flags, is_add=1)
5381 self.vapi.nat44_interface_add_del_feature(
5382 sw_if_index=self.pg1.sw_if_index,
5386 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5387 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5388 TCP(sport=self.tcp_port_in, dport=20))
5389 self.pg0.add_stream(p)
5390 self.pg_enable_capture(self.pg_interfaces)
5392 p = self.pg1.get_capture(1)
5394 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5395 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5397 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5398 TCP(sport=1234, dport=1234))
5399 self.pg0.add_stream(p)
5400 self.pg_enable_capture(self.pg_interfaces)
5402 p = self.pg1.get_capture(1)
5405 self.assertEqual(packet[IP].src, self.nat_addr)
5406 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5407 self.assertEqual(packet.haslayer(GRE), 1)
5408 self.assert_packet_checksums_valid(packet)
5410 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5414 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5415 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5417 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5418 TCP(sport=1234, dport=1234))
5419 self.pg1.add_stream(p)
5420 self.pg_enable_capture(self.pg_interfaces)
5422 p = self.pg0.get_capture(1)
5425 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
5426 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
5427 self.assertEqual(packet.haslayer(GRE), 1)
5428 self.assert_packet_checksums_valid(packet)
5430 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5433 def test_hairpinning_unknown_proto(self):
5434 """ NAT44 translate packet with unknown protocol - hairpinning """
5435 host = self.pg0.remote_hosts[0]
5436 server = self.pg0.remote_hosts[1]
5438 server_out_port = 8765
5439 server_nat_ip = "10.0.0.11"
5441 self.nat44_add_address(self.nat_addr)
5442 flags = self.config_flags.NAT_IS_INSIDE
5443 self.vapi.nat44_interface_add_del_feature(
5444 sw_if_index=self.pg0.sw_if_index,
5445 flags=flags, is_add=1)
5446 self.vapi.nat44_interface_add_del_feature(
5447 sw_if_index=self.pg1.sw_if_index,
5450 # add static mapping for server
5451 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
5454 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
5455 IP(src=host.ip4, dst=server_nat_ip) /
5456 TCP(sport=host_in_port, dport=server_out_port))
5457 self.pg0.add_stream(p)
5458 self.pg_enable_capture(self.pg_interfaces)
5460 self.pg0.get_capture(1)
5462 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5463 IP(src=host.ip4, dst=server_nat_ip) /
5465 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5466 TCP(sport=1234, dport=1234))
5467 self.pg0.add_stream(p)
5468 self.pg_enable_capture(self.pg_interfaces)
5470 p = self.pg0.get_capture(1)
5473 self.assertEqual(packet[IP].src, self.nat_addr)
5474 self.assertEqual(packet[IP].dst, server.ip4)
5475 self.assertEqual(packet.haslayer(GRE), 1)
5476 self.assert_packet_checksums_valid(packet)
5478 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5482 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5483 IP(src=server.ip4, dst=self.nat_addr) /
5485 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5486 TCP(sport=1234, dport=1234))
5487 self.pg0.add_stream(p)
5488 self.pg_enable_capture(self.pg_interfaces)
5490 p = self.pg0.get_capture(1)
5493 self.assertEqual(packet[IP].src, server_nat_ip)
5494 self.assertEqual(packet[IP].dst, host.ip4)
5495 self.assertEqual(packet.haslayer(GRE), 1)
5496 self.assert_packet_checksums_valid(packet)
5498 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5501 def test_output_feature_and_service(self):
5502 """ NAT44 interface output feature and services """
5503 external_addr = '1.2.3.4'
5507 self.vapi.nat44_forwarding_enable_disable(enable=1)
5508 self.nat44_add_address(self.nat_addr)
5509 flags = self.config_flags.NAT_IS_ADDR_ONLY
5510 self.vapi.nat44_add_del_identity_mapping(
5511 ip_address=self.pg1.remote_ip4, sw_if_index=0xFFFFFFFF,
5512 flags=flags, is_add=1)
5513 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5514 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5515 local_port, external_port,
5516 proto=IP_PROTOS.tcp, flags=flags)
5517 flags = self.config_flags.NAT_IS_INSIDE
5518 self.vapi.nat44_interface_add_del_feature(
5519 sw_if_index=self.pg0.sw_if_index,
5521 self.vapi.nat44_interface_add_del_feature(
5522 sw_if_index=self.pg0.sw_if_index,
5523 flags=flags, is_add=1)
5524 self.vapi.nat44_interface_add_del_output_feature(
5526 sw_if_index=self.pg1.sw_if_index)
5528 # from client to service
5529 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5530 IP(src=self.pg1.remote_ip4, dst=external_addr) /
5531 TCP(sport=12345, dport=external_port))
5532 self.pg1.add_stream(p)
5533 self.pg_enable_capture(self.pg_interfaces)
5535 capture = self.pg0.get_capture(1)
5540 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5541 self.assertEqual(tcp.dport, local_port)
5542 self.assert_packet_checksums_valid(p)
5544 self.logger.error(ppp("Unexpected or invalid packet:", p))
5547 # from service back to client
5548 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5549 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5550 TCP(sport=local_port, dport=12345))
5551 self.pg0.add_stream(p)
5552 self.pg_enable_capture(self.pg_interfaces)
5554 capture = self.pg1.get_capture(1)
5559 self.assertEqual(ip.src, external_addr)
5560 self.assertEqual(tcp.sport, external_port)
5561 self.assert_packet_checksums_valid(p)
5563 self.logger.error(ppp("Unexpected or invalid packet:", p))
5566 # from local network host to external network
5567 pkts = self.create_stream_in(self.pg0, self.pg1)
5568 self.pg0.add_stream(pkts)
5569 self.pg_enable_capture(self.pg_interfaces)
5571 capture = self.pg1.get_capture(len(pkts))
5572 self.verify_capture_out(capture)
5573 pkts = self.create_stream_in(self.pg0, self.pg1)
5574 self.pg0.add_stream(pkts)
5575 self.pg_enable_capture(self.pg_interfaces)
5577 capture = self.pg1.get_capture(len(pkts))
5578 self.verify_capture_out(capture)
5580 # from external network back to local network host
5581 pkts = self.create_stream_out(self.pg1)
5582 self.pg1.add_stream(pkts)
5583 self.pg_enable_capture(self.pg_interfaces)
5585 capture = self.pg0.get_capture(len(pkts))
5586 self.verify_capture_in(capture, self.pg0)
5588 def test_output_feature_and_service2(self):
5589 """ NAT44 interface output feature and service host direct access """
5590 self.vapi.nat44_forwarding_enable_disable(enable=1)
5591 self.nat44_add_address(self.nat_addr)
5592 self.vapi.nat44_interface_add_del_output_feature(
5594 sw_if_index=self.pg1.sw_if_index)
5596 # session initiated from service host - translate
5597 pkts = self.create_stream_in(self.pg0, self.pg1)
5598 self.pg0.add_stream(pkts)
5599 self.pg_enable_capture(self.pg_interfaces)
5601 capture = self.pg1.get_capture(len(pkts))
5602 self.verify_capture_out(capture)
5604 pkts = self.create_stream_out(self.pg1)
5605 self.pg1.add_stream(pkts)
5606 self.pg_enable_capture(self.pg_interfaces)
5608 capture = self.pg0.get_capture(len(pkts))
5609 self.verify_capture_in(capture, self.pg0)
5611 # session initiated from remote host - do not translate
5612 self.tcp_port_in = 60303
5613 self.udp_port_in = 60304
5614 self.icmp_id_in = 60305
5615 pkts = self.create_stream_out(self.pg1,
5616 self.pg0.remote_ip4,
5617 use_inside_ports=True)
5618 self.pg1.add_stream(pkts)
5619 self.pg_enable_capture(self.pg_interfaces)
5621 capture = self.pg0.get_capture(len(pkts))
5622 self.verify_capture_in(capture, self.pg0)
5624 pkts = self.create_stream_in(self.pg0, self.pg1)
5625 self.pg0.add_stream(pkts)
5626 self.pg_enable_capture(self.pg_interfaces)
5628 capture = self.pg1.get_capture(len(pkts))
5629 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5632 def test_output_feature_and_service3(self):
5633 """ NAT44 interface output feature and DST NAT """
5634 external_addr = '1.2.3.4'
5638 self.vapi.nat44_forwarding_enable_disable(enable=1)
5639 self.nat44_add_address(self.nat_addr)
5640 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5641 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5642 local_port, external_port,
5643 proto=IP_PROTOS.tcp, flags=flags)
5644 flags = self.config_flags.NAT_IS_INSIDE
5645 self.vapi.nat44_interface_add_del_feature(
5646 sw_if_index=self.pg0.sw_if_index,
5648 self.vapi.nat44_interface_add_del_feature(
5649 sw_if_index=self.pg0.sw_if_index,
5650 flags=flags, is_add=1)
5651 self.vapi.nat44_interface_add_del_output_feature(
5653 sw_if_index=self.pg1.sw_if_index)
5655 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5656 IP(src=self.pg0.remote_ip4, dst=external_addr) /
5657 TCP(sport=12345, dport=external_port))
5658 self.pg0.add_stream(p)
5659 self.pg_enable_capture(self.pg_interfaces)
5661 capture = self.pg1.get_capture(1)
5666 self.assertEqual(ip.src, self.pg0.remote_ip4)
5667 self.assertEqual(tcp.sport, 12345)
5668 self.assertEqual(ip.dst, self.pg1.remote_ip4)
5669 self.assertEqual(tcp.dport, local_port)
5670 self.assert_packet_checksums_valid(p)
5672 self.logger.error(ppp("Unexpected or invalid packet:", p))
5675 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5676 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5677 TCP(sport=local_port, dport=12345))
5678 self.pg1.add_stream(p)
5679 self.pg_enable_capture(self.pg_interfaces)
5681 capture = self.pg0.get_capture(1)
5686 self.assertEqual(ip.src, external_addr)
5687 self.assertEqual(tcp.sport, external_port)
5688 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5689 self.assertEqual(tcp.dport, 12345)
5690 self.assert_packet_checksums_valid(p)
5692 self.logger.error(ppp("Unexpected or invalid packet:", p))
5695 def test_next_src_nat(self):
5696 """ On way back forward packet to nat44-in2out node. """
5697 twice_nat_addr = '10.0.1.3'
5700 post_twice_nat_port = 0
5702 self.vapi.nat44_forwarding_enable_disable(enable=1)
5703 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5704 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5705 self.config_flags.NAT_IS_SELF_TWICE_NAT)
5706 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5707 local_port, external_port,
5708 proto=IP_PROTOS.tcp, vrf_id=1,
5710 self.vapi.nat44_interface_add_del_feature(
5711 sw_if_index=self.pg6.sw_if_index,
5714 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5715 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5716 TCP(sport=12345, dport=external_port))
5717 self.pg6.add_stream(p)
5718 self.pg_enable_capture(self.pg_interfaces)
5720 capture = self.pg6.get_capture(1)
5725 self.assertEqual(ip.src, twice_nat_addr)
5726 self.assertNotEqual(tcp.sport, 12345)
5727 post_twice_nat_port = tcp.sport
5728 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5729 self.assertEqual(tcp.dport, local_port)
5730 self.assert_packet_checksums_valid(p)
5732 self.logger.error(ppp("Unexpected or invalid packet:", p))
5735 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5736 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5737 TCP(sport=local_port, dport=post_twice_nat_port))
5738 self.pg6.add_stream(p)
5739 self.pg_enable_capture(self.pg_interfaces)
5741 capture = self.pg6.get_capture(1)
5746 self.assertEqual(ip.src, self.pg1.remote_ip4)
5747 self.assertEqual(tcp.sport, external_port)
5748 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5749 self.assertEqual(tcp.dport, 12345)
5750 self.assert_packet_checksums_valid(p)
5752 self.logger.error(ppp("Unexpected or invalid packet:", p))
5755 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5757 twice_nat_addr = '10.0.1.3'
5765 port_in1 = port_in + 1
5766 port_in2 = port_in + 2
5771 server1 = self.pg0.remote_hosts[0]
5772 server2 = self.pg0.remote_hosts[1]
5784 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5787 self.nat44_add_address(self.nat_addr)
5788 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5792 flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
5794 flags |= self.config_flags.NAT_IS_TWICE_NAT
5797 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5799 proto=IP_PROTOS.tcp,
5802 locals = [{'addr': server1.ip4,
5806 {'addr': server2.ip4,
5810 out_addr = self.nat_addr
5812 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5813 external_addr=out_addr,
5814 external_port=port_out,
5815 protocol=IP_PROTOS.tcp,
5816 local_num=len(locals),
5818 flags = self.config_flags.NAT_IS_INSIDE
5819 self.vapi.nat44_interface_add_del_feature(
5820 sw_if_index=pg0.sw_if_index,
5821 flags=flags, is_add=1)
5822 self.vapi.nat44_interface_add_del_feature(
5823 sw_if_index=pg1.sw_if_index,
5830 assert client_id is not None
5832 client = self.pg0.remote_hosts[0]
5833 elif client_id == 2:
5834 client = self.pg0.remote_hosts[1]
5836 client = pg1.remote_hosts[0]
5837 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5838 IP(src=client.ip4, dst=self.nat_addr) /
5839 TCP(sport=eh_port_out, dport=port_out))
5841 self.pg_enable_capture(self.pg_interfaces)
5843 capture = pg0.get_capture(1)
5849 if ip.dst == server1.ip4:
5855 self.assertEqual(ip.dst, server.ip4)
5857 self.assertIn(tcp.dport, [port_in1, port_in2])
5859 self.assertEqual(tcp.dport, port_in)
5861 self.assertEqual(ip.src, twice_nat_addr)
5862 self.assertNotEqual(tcp.sport, eh_port_out)
5864 self.assertEqual(ip.src, client.ip4)
5865 self.assertEqual(tcp.sport, eh_port_out)
5867 eh_port_in = tcp.sport
5868 saved_port_in = tcp.dport
5869 self.assert_packet_checksums_valid(p)
5871 self.logger.error(ppp("Unexpected or invalid packet:", p))
5874 p = (Ether(src=server.mac, dst=pg0.local_mac) /
5875 IP(src=server.ip4, dst=eh_addr_in) /
5876 TCP(sport=saved_port_in, dport=eh_port_in))
5878 self.pg_enable_capture(self.pg_interfaces)
5880 capture = pg1.get_capture(1)
5885 self.assertEqual(ip.dst, client.ip4)
5886 self.assertEqual(ip.src, self.nat_addr)
5887 self.assertEqual(tcp.dport, eh_port_out)
5888 self.assertEqual(tcp.sport, port_out)
5889 self.assert_packet_checksums_valid(p)
5891 self.logger.error(ppp("Unexpected or invalid packet:", p))
5895 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5896 self.assertEqual(len(sessions), 1)
5897 self.assertTrue(sessions[0].flags &
5898 self.config_flags.NAT_IS_EXT_HOST_VALID)
5899 self.assertTrue(sessions[0].flags &
5900 self.config_flags.NAT_IS_TWICE_NAT)
5901 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
5902 self.vapi.nat44_del_session(
5903 address=sessions[0].inside_ip_address,
5904 port=sessions[0].inside_port,
5905 protocol=sessions[0].protocol,
5906 flags=(self.config_flags.NAT_IS_INSIDE |
5907 self.config_flags.NAT_IS_EXT_HOST_VALID),
5908 ext_host_address=sessions[0].ext_host_nat_address,
5909 ext_host_port=sessions[0].ext_host_nat_port)
5910 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5911 self.assertEqual(len(sessions), 0)
5913 def test_twice_nat(self):
5915 self.twice_nat_common()
5917 def test_self_twice_nat_positive(self):
5918 """ Self Twice NAT44 (positive test) """
5919 self.twice_nat_common(self_twice_nat=True, same_pg=True)
5921 def test_self_twice_nat_negative(self):
5922 """ Self Twice NAT44 (negative test) """
5923 self.twice_nat_common(self_twice_nat=True)
5925 def test_twice_nat_lb(self):
5926 """ Twice NAT44 local service load balancing """
5927 self.twice_nat_common(lb=True)
5929 def test_self_twice_nat_lb_positive(self):
5930 """ Self Twice NAT44 local service load balancing (positive test) """
5931 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5934 def test_self_twice_nat_lb_negative(self):
5935 """ Self Twice NAT44 local service load balancing (negative test) """
5936 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5939 def test_twice_nat_interface_addr(self):
5940 """ Acquire twice NAT44 addresses from interface """
5941 flags = self.config_flags.NAT_IS_TWICE_NAT
5942 self.vapi.nat44_add_del_interface_addr(
5944 sw_if_index=self.pg3.sw_if_index,
5947 # no address in NAT pool
5948 adresses = self.vapi.nat44_address_dump()
5949 self.assertEqual(0, len(adresses))
5951 # configure interface address and check NAT address pool
5952 self.pg3.config_ip4()
5953 adresses = self.vapi.nat44_address_dump()
5954 self.assertEqual(1, len(adresses))
5955 self.assertEqual(str(adresses[0].ip_address),
5957 self.assertEqual(adresses[0].flags, flags)
5959 # remove interface address and check NAT address pool
5960 self.pg3.unconfig_ip4()
5961 adresses = self.vapi.nat44_address_dump()
5962 self.assertEqual(0, len(adresses))
5964 def test_tcp_close(self):
5965 """ Close TCP session from inside network - output feature """
5966 self.vapi.nat44_forwarding_enable_disable(enable=1)
5967 self.nat44_add_address(self.pg1.local_ip4)
5968 twice_nat_addr = '10.0.1.3'
5969 service_ip = '192.168.16.150'
5970 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5971 flags = self.config_flags.NAT_IS_INSIDE
5972 self.vapi.nat44_interface_add_del_feature(
5973 sw_if_index=self.pg0.sw_if_index,
5975 self.vapi.nat44_interface_add_del_feature(
5976 sw_if_index=self.pg0.sw_if_index,
5977 flags=flags, is_add=1)
5978 self.vapi.nat44_interface_add_del_output_feature(
5980 sw_if_index=self.pg1.sw_if_index)
5981 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5982 self.config_flags.NAT_IS_TWICE_NAT)
5983 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5987 proto=IP_PROTOS.tcp,
5989 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5990 start_sessnum = len(sessions)
5992 # SYN packet out->in
5993 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5994 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5995 TCP(sport=33898, dport=80, flags="S"))
5996 self.pg1.add_stream(p)
5997 self.pg_enable_capture(self.pg_interfaces)
5999 capture = self.pg0.get_capture(1)
6001 tcp_port = p[TCP].sport
6003 # SYN + ACK packet in->out
6004 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6005 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
6006 TCP(sport=80, dport=tcp_port, flags="SA"))
6007 self.pg0.add_stream(p)
6008 self.pg_enable_capture(self.pg_interfaces)
6010 self.pg1.get_capture(1)
6012 # ACK packet out->in
6013 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6014 IP(src=self.pg1.remote_ip4, dst=service_ip) /
6015 TCP(sport=33898, dport=80, flags="A"))
6016 self.pg1.add_stream(p)
6017 self.pg_enable_capture(self.pg_interfaces)
6019 self.pg0.get_capture(1)
6021 # FIN packet in -> out
6022 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6023 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
6024 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
6025 self.pg0.add_stream(p)
6026 self.pg_enable_capture(self.pg_interfaces)
6028 self.pg1.get_capture(1)
6030 # FIN+ACK packet out -> in
6031 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6032 IP(src=self.pg1.remote_ip4, dst=service_ip) /
6033 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
6034 self.pg1.add_stream(p)
6035 self.pg_enable_capture(self.pg_interfaces)
6037 self.pg0.get_capture(1)
6039 # ACK packet in -> out
6040 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6041 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
6042 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
6043 self.pg0.add_stream(p)
6044 self.pg_enable_capture(self.pg_interfaces)
6046 self.pg1.get_capture(1)
6048 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4,
6050 self.assertEqual(len(sessions) - start_sessnum, 0)
6052 def test_tcp_session_close_in(self):
6053 """ Close TCP session from inside network """
6054 self.tcp_port_out = 10505
6055 self.nat44_add_address(self.nat_addr)
6056 flags = self.config_flags.NAT_IS_TWICE_NAT
6057 self.nat44_add_static_mapping(self.pg0.remote_ip4,
6061 proto=IP_PROTOS.tcp,
6063 flags = self.config_flags.NAT_IS_INSIDE
6064 self.vapi.nat44_interface_add_del_feature(
6065 sw_if_index=self.pg0.sw_if_index,
6066 flags=flags, is_add=1)
6067 self.vapi.nat44_interface_add_del_feature(
6068 sw_if_index=self.pg1.sw_if_index,
6071 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6072 start_sessnum = len(sessions)
6074 self.initiate_tcp_session(self.pg0, self.pg1)
6076 # FIN packet in -> out
6077 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6078 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6079 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6080 flags="FA", seq=100, ack=300))
6081 self.pg0.add_stream(p)
6082 self.pg_enable_capture(self.pg_interfaces)
6084 self.pg1.get_capture(1)
6088 # ACK packet out -> in
6089 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6090 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6091 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6092 flags="A", seq=300, ack=101))
6095 # FIN packet out -> in
6096 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6097 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6098 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6099 flags="FA", seq=300, ack=101))
6102 self.pg1.add_stream(pkts)
6103 self.pg_enable_capture(self.pg_interfaces)
6105 self.pg0.get_capture(2)
6107 # ACK packet in -> out
6108 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6109 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6110 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6111 flags="A", seq=101, ack=301))
6112 self.pg0.add_stream(p)
6113 self.pg_enable_capture(self.pg_interfaces)
6115 self.pg1.get_capture(1)
6117 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4,
6119 self.assertEqual(len(sessions) - start_sessnum, 0)
6121 def test_tcp_session_close_out(self):
6122 """ Close TCP session from outside network """
6123 self.tcp_port_out = 10505
6124 self.nat44_add_address(self.nat_addr)
6125 flags = self.config_flags.NAT_IS_TWICE_NAT
6126 self.nat44_add_static_mapping(self.pg0.remote_ip4,
6130 proto=IP_PROTOS.tcp,
6132 flags = self.config_flags.NAT_IS_INSIDE
6133 self.vapi.nat44_interface_add_del_feature(
6134 sw_if_index=self.pg0.sw_if_index,
6135 flags=flags, is_add=1)
6136 self.vapi.nat44_interface_add_del_feature(
6137 sw_if_index=self.pg1.sw_if_index,
6140 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6141 start_sessnum = len(sessions)
6143 self.initiate_tcp_session(self.pg0, self.pg1)
6145 # FIN packet out -> in
6146 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6147 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6148 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6149 flags="FA", seq=100, ack=300))
6150 self.pg1.add_stream(p)
6151 self.pg_enable_capture(self.pg_interfaces)
6153 self.pg0.get_capture(1)
6155 # FIN+ACK packet in -> out
6156 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6157 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6158 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6159 flags="FA", seq=300, ack=101))
6161 self.pg0.add_stream(p)
6162 self.pg_enable_capture(self.pg_interfaces)
6164 self.pg1.get_capture(1)
6166 # ACK packet out -> in
6167 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6168 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6169 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6170 flags="A", seq=101, ack=301))
6171 self.pg1.add_stream(p)
6172 self.pg_enable_capture(self.pg_interfaces)
6174 self.pg0.get_capture(1)
6176 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4,
6178 self.assertEqual(len(sessions) - start_sessnum, 0)
6180 def test_tcp_session_close_simultaneous(self):
6181 """ Close TCP session from inside network """
6182 self.tcp_port_out = 10505
6183 self.nat44_add_address(self.nat_addr)
6184 flags = self.config_flags.NAT_IS_TWICE_NAT
6185 self.nat44_add_static_mapping(self.pg0.remote_ip4,
6189 proto=IP_PROTOS.tcp,
6191 flags = self.config_flags.NAT_IS_INSIDE
6192 self.vapi.nat44_interface_add_del_feature(
6193 sw_if_index=self.pg0.sw_if_index,
6194 flags=flags, is_add=1)
6195 self.vapi.nat44_interface_add_del_feature(
6196 sw_if_index=self.pg1.sw_if_index,
6199 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6200 start_sessnum = len(sessions)
6202 self.initiate_tcp_session(self.pg0, self.pg1)
6204 # FIN packet in -> out
6205 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6206 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6207 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6208 flags="FA", seq=100, ack=300))
6209 self.pg0.add_stream(p)
6210 self.pg_enable_capture(self.pg_interfaces)
6212 self.pg1.get_capture(1)
6214 # FIN packet out -> in
6215 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6216 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6217 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6218 flags="FA", seq=300, ack=100))
6219 self.pg1.add_stream(p)
6220 self.pg_enable_capture(self.pg_interfaces)
6222 self.pg0.get_capture(1)
6224 # ACK packet in -> out
6225 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6226 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6227 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6228 flags="A", seq=101, ack=301))
6229 self.pg0.add_stream(p)
6230 self.pg_enable_capture(self.pg_interfaces)
6232 self.pg1.get_capture(1)
6234 # ACK packet out -> in
6235 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6236 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6237 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6238 flags="A", seq=301, ack=101))
6239 self.pg1.add_stream(p)
6240 self.pg_enable_capture(self.pg_interfaces)
6242 self.pg0.get_capture(1)
6244 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4,
6246 self.assertEqual(len(sessions) - start_sessnum, 0)
6248 def test_one_armed_nat44_static(self):
6249 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
6250 remote_host = self.pg4.remote_hosts[0]
6251 local_host = self.pg4.remote_hosts[1]
6256 self.vapi.nat44_forwarding_enable_disable(enable=1)
6257 self.nat44_add_address(self.nat_addr, twice_nat=1)
6258 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
6259 self.config_flags.NAT_IS_TWICE_NAT)
6260 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
6261 local_port, external_port,
6262 proto=IP_PROTOS.tcp, flags=flags)
6263 flags = self.config_flags.NAT_IS_INSIDE
6264 self.vapi.nat44_interface_add_del_feature(
6265 sw_if_index=self.pg4.sw_if_index,
6267 self.vapi.nat44_interface_add_del_feature(
6268 sw_if_index=self.pg4.sw_if_index,
6269 flags=flags, is_add=1)
6271 # from client to service
6272 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6273 IP(src=remote_host.ip4, dst=self.nat_addr) /
6274 TCP(sport=12345, dport=external_port))
6275 self.pg4.add_stream(p)
6276 self.pg_enable_capture(self.pg_interfaces)
6278 capture = self.pg4.get_capture(1)
6283 self.assertEqual(ip.dst, local_host.ip4)
6284 self.assertEqual(ip.src, self.nat_addr)
6285 self.assertEqual(tcp.dport, local_port)
6286 self.assertNotEqual(tcp.sport, 12345)
6287 eh_port_in = tcp.sport
6288 self.assert_packet_checksums_valid(p)
6290 self.logger.error(ppp("Unexpected or invalid packet:", p))
6293 # from service back to client
6294 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6295 IP(src=local_host.ip4, dst=self.nat_addr) /
6296 TCP(sport=local_port, dport=eh_port_in))
6297 self.pg4.add_stream(p)
6298 self.pg_enable_capture(self.pg_interfaces)
6300 capture = self.pg4.get_capture(1)
6305 self.assertEqual(ip.src, self.nat_addr)
6306 self.assertEqual(ip.dst, remote_host.ip4)
6307 self.assertEqual(tcp.sport, external_port)
6308 self.assertEqual(tcp.dport, 12345)
6309 self.assert_packet_checksums_valid(p)
6311 self.logger.error(ppp("Unexpected or invalid packet:", p))
6314 def test_static_with_port_out2(self):
6315 """ 1:1 NAPT asymmetrical rule """
6320 self.vapi.nat44_forwarding_enable_disable(enable=1)
6321 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6322 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
6323 local_port, external_port,
6324 proto=IP_PROTOS.tcp, flags=flags)
6325 flags = self.config_flags.NAT_IS_INSIDE
6326 self.vapi.nat44_interface_add_del_feature(
6327 sw_if_index=self.pg0.sw_if_index,
6328 flags=flags, is_add=1)
6329 self.vapi.nat44_interface_add_del_feature(
6330 sw_if_index=self.pg1.sw_if_index,
6333 # from client to service
6334 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6335 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6336 TCP(sport=12345, dport=external_port))
6337 self.pg1.add_stream(p)
6338 self.pg_enable_capture(self.pg_interfaces)
6340 capture = self.pg0.get_capture(1)
6345 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6346 self.assertEqual(tcp.dport, local_port)
6347 self.assert_packet_checksums_valid(p)
6349 self.logger.error(ppp("Unexpected or invalid packet:", p))
6353 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6354 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6355 ICMP(type=11) / capture[0][IP])
6356 self.pg0.add_stream(p)
6357 self.pg_enable_capture(self.pg_interfaces)
6359 capture = self.pg1.get_capture(1)
6362 self.assertEqual(p[IP].src, self.nat_addr)
6364 self.assertEqual(inner.dst, self.nat_addr)
6365 self.assertEqual(inner[TCPerror].dport, external_port)
6367 self.logger.error(ppp("Unexpected or invalid packet:", p))
6370 # from service back to client
6371 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6372 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6373 TCP(sport=local_port, dport=12345))
6374 self.pg0.add_stream(p)
6375 self.pg_enable_capture(self.pg_interfaces)
6377 capture = self.pg1.get_capture(1)
6382 self.assertEqual(ip.src, self.nat_addr)
6383 self.assertEqual(tcp.sport, external_port)
6384 self.assert_packet_checksums_valid(p)
6386 self.logger.error(ppp("Unexpected or invalid packet:", p))
6390 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6391 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6392 ICMP(type=11) / capture[0][IP])
6393 self.pg1.add_stream(p)
6394 self.pg_enable_capture(self.pg_interfaces)
6396 capture = self.pg0.get_capture(1)
6399 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
6401 self.assertEqual(inner.src, self.pg0.remote_ip4)
6402 self.assertEqual(inner[TCPerror].sport, local_port)
6404 self.logger.error(ppp("Unexpected or invalid packet:", p))
6407 # from client to server (no translation)
6408 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6409 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
6410 TCP(sport=12346, dport=local_port))
6411 self.pg1.add_stream(p)
6412 self.pg_enable_capture(self.pg_interfaces)
6414 capture = self.pg0.get_capture(1)
6419 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6420 self.assertEqual(tcp.dport, local_port)
6421 self.assert_packet_checksums_valid(p)
6423 self.logger.error(ppp("Unexpected or invalid packet:", p))
6426 # from service back to client (no translation)
6427 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6428 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6429 TCP(sport=local_port, dport=12346))
6430 self.pg0.add_stream(p)
6431 self.pg_enable_capture(self.pg_interfaces)
6433 capture = self.pg1.get_capture(1)
6438 self.assertEqual(ip.src, self.pg0.remote_ip4)
6439 self.assertEqual(tcp.sport, local_port)
6440 self.assert_packet_checksums_valid(p)
6442 self.logger.error(ppp("Unexpected or invalid packet:", p))
6445 def test_output_feature(self):
6446 """ NAT44 interface output feature (in2out postrouting) """
6447 self.vapi.nat44_forwarding_enable_disable(enable=1)
6448 self.nat44_add_address(self.nat_addr)
6449 self.vapi.nat44_interface_add_del_feature(
6450 sw_if_index=self.pg0.sw_if_index,
6452 self.vapi.nat44_interface_add_del_output_feature(
6454 sw_if_index=self.pg1.sw_if_index)
6457 pkts = self.create_stream_in(self.pg0, self.pg1)
6458 self.pg0.add_stream(pkts)
6459 self.pg_enable_capture(self.pg_interfaces)
6461 capture = self.pg1.get_capture(len(pkts))
6462 self.verify_capture_out(capture)
6465 pkts = self.create_stream_out(self.pg1)
6466 self.pg1.add_stream(pkts)
6467 self.pg_enable_capture(self.pg_interfaces)
6469 capture = self.pg0.get_capture(len(pkts))
6470 self.verify_capture_in(capture, self.pg0)
6472 def test_multiple_vrf(self):
6473 """ Multiple VRF setup """
6474 external_addr = '1.2.3.4'
6479 self.vapi.nat44_forwarding_enable_disable(enable=1)
6480 self.nat44_add_address(self.nat_addr)
6481 flags = self.config_flags.NAT_IS_INSIDE
6482 self.vapi.nat44_interface_add_del_feature(
6483 sw_if_index=self.pg0.sw_if_index,
6485 self.vapi.nat44_interface_add_del_feature(
6486 sw_if_index=self.pg0.sw_if_index,
6487 flags=flags, is_add=1)
6488 self.vapi.nat44_interface_add_del_output_feature(
6490 sw_if_index=self.pg1.sw_if_index)
6491 self.vapi.nat44_interface_add_del_feature(
6492 sw_if_index=self.pg5.sw_if_index,
6494 self.vapi.nat44_interface_add_del_feature(
6495 sw_if_index=self.pg5.sw_if_index,
6496 flags=flags, is_add=1)
6497 self.vapi.nat44_interface_add_del_feature(
6498 sw_if_index=self.pg6.sw_if_index,
6500 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6501 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
6502 local_port, external_port, vrf_id=1,
6503 proto=IP_PROTOS.tcp, flags=flags)
6504 self.nat44_add_static_mapping(
6505 self.pg0.remote_ip4,
6506 external_sw_if_index=self.pg0.sw_if_index,
6507 local_port=local_port,
6509 external_port=external_port,
6510 proto=IP_PROTOS.tcp,
6514 # from client to service (both VRF1)
6515 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6516 IP(src=self.pg6.remote_ip4, dst=external_addr) /
6517 TCP(sport=12345, dport=external_port))
6518 self.pg6.add_stream(p)
6519 self.pg_enable_capture(self.pg_interfaces)
6521 capture = self.pg5.get_capture(1)
6526 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6527 self.assertEqual(tcp.dport, local_port)
6528 self.assert_packet_checksums_valid(p)
6530 self.logger.error(ppp("Unexpected or invalid packet:", p))
6533 # from service back to client (both VRF1)
6534 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6535 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6536 TCP(sport=local_port, dport=12345))
6537 self.pg5.add_stream(p)
6538 self.pg_enable_capture(self.pg_interfaces)
6540 capture = self.pg6.get_capture(1)
6545 self.assertEqual(ip.src, external_addr)
6546 self.assertEqual(tcp.sport, external_port)
6547 self.assert_packet_checksums_valid(p)
6549 self.logger.error(ppp("Unexpected or invalid packet:", p))
6552 # dynamic NAT from VRF1 to VRF0 (output-feature)
6553 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6554 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6555 TCP(sport=2345, dport=22))
6556 self.pg5.add_stream(p)
6557 self.pg_enable_capture(self.pg_interfaces)
6559 capture = self.pg1.get_capture(1)
6564 self.assertEqual(ip.src, self.nat_addr)
6565 self.assertNotEqual(tcp.sport, 2345)
6566 self.assert_packet_checksums_valid(p)
6569 self.logger.error(ppp("Unexpected or invalid packet:", p))
6572 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6573 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6574 TCP(sport=22, dport=port))
6575 self.pg1.add_stream(p)
6576 self.pg_enable_capture(self.pg_interfaces)
6578 capture = self.pg5.get_capture(1)
6583 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6584 self.assertEqual(tcp.dport, 2345)
6585 self.assert_packet_checksums_valid(p)
6587 self.logger.error(ppp("Unexpected or invalid packet:", p))
6590 # from client VRF1 to service VRF0
6591 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6592 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6593 TCP(sport=12346, dport=external_port))
6594 self.pg6.add_stream(p)
6595 self.pg_enable_capture(self.pg_interfaces)
6597 capture = self.pg0.get_capture(1)
6602 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6603 self.assertEqual(tcp.dport, local_port)
6604 self.assert_packet_checksums_valid(p)
6606 self.logger.error(ppp("Unexpected or invalid packet:", p))
6609 # from service VRF0 back to client VRF1
6610 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6611 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6612 TCP(sport=local_port, dport=12346))
6613 self.pg0.add_stream(p)
6614 self.pg_enable_capture(self.pg_interfaces)
6616 capture = self.pg6.get_capture(1)
6621 self.assertEqual(ip.src, self.pg0.local_ip4)
6622 self.assertEqual(tcp.sport, external_port)
6623 self.assert_packet_checksums_valid(p)
6625 self.logger.error(ppp("Unexpected or invalid packet:", p))
6628 # from client VRF0 to service VRF1
6629 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6630 IP(src=self.pg0.remote_ip4, dst=external_addr) /
6631 TCP(sport=12347, dport=external_port))
6632 self.pg0.add_stream(p)
6633 self.pg_enable_capture(self.pg_interfaces)
6635 capture = self.pg5.get_capture(1)
6640 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6641 self.assertEqual(tcp.dport, local_port)
6642 self.assert_packet_checksums_valid(p)
6644 self.logger.error(ppp("Unexpected or invalid packet:", p))
6647 # from service VRF1 back to client VRF0
6648 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6649 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6650 TCP(sport=local_port, dport=12347))
6651 self.pg5.add_stream(p)
6652 self.pg_enable_capture(self.pg_interfaces)
6654 capture = self.pg0.get_capture(1)
6659 self.assertEqual(ip.src, external_addr)
6660 self.assertEqual(tcp.sport, external_port)
6661 self.assert_packet_checksums_valid(p)
6663 self.logger.error(ppp("Unexpected or invalid packet:", p))
6666 # from client to server (both VRF1, no translation)
6667 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6668 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6669 TCP(sport=12348, dport=local_port))
6670 self.pg6.add_stream(p)
6671 self.pg_enable_capture(self.pg_interfaces)
6673 capture = self.pg5.get_capture(1)
6678 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6679 self.assertEqual(tcp.dport, local_port)
6680 self.assert_packet_checksums_valid(p)
6682 self.logger.error(ppp("Unexpected or invalid packet:", p))
6685 # from server back to client (both VRF1, no translation)
6686 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6687 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6688 TCP(sport=local_port, dport=12348))
6689 self.pg5.add_stream(p)
6690 self.pg_enable_capture(self.pg_interfaces)
6692 capture = self.pg6.get_capture(1)
6697 self.assertEqual(ip.src, self.pg5.remote_ip4)
6698 self.assertEqual(tcp.sport, local_port)
6699 self.assert_packet_checksums_valid(p)
6701 self.logger.error(ppp("Unexpected or invalid packet:", p))
6704 # from client VRF1 to server VRF0 (no translation)
6705 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6706 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6707 TCP(sport=local_port, dport=12349))
6708 self.pg0.add_stream(p)
6709 self.pg_enable_capture(self.pg_interfaces)
6711 capture = self.pg6.get_capture(1)
6716 self.assertEqual(ip.src, self.pg0.remote_ip4)
6717 self.assertEqual(tcp.sport, local_port)
6718 self.assert_packet_checksums_valid(p)
6720 self.logger.error(ppp("Unexpected or invalid packet:", p))
6723 # from server VRF0 back to client VRF1 (no translation)
6724 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6725 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6726 TCP(sport=local_port, dport=12349))
6727 self.pg0.add_stream(p)
6728 self.pg_enable_capture(self.pg_interfaces)
6730 capture = self.pg6.get_capture(1)
6735 self.assertEqual(ip.src, self.pg0.remote_ip4)
6736 self.assertEqual(tcp.sport, local_port)
6737 self.assert_packet_checksums_valid(p)
6739 self.logger.error(ppp("Unexpected or invalid packet:", p))
6742 # from client VRF0 to server VRF1 (no translation)
6743 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6744 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6745 TCP(sport=12344, dport=local_port))
6746 self.pg0.add_stream(p)
6747 self.pg_enable_capture(self.pg_interfaces)
6749 capture = self.pg5.get_capture(1)
6754 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6755 self.assertEqual(tcp.dport, local_port)
6756 self.assert_packet_checksums_valid(p)
6758 self.logger.error(ppp("Unexpected or invalid packet:", p))
6761 # from server VRF1 back to client VRF0 (no translation)
6762 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6763 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6764 TCP(sport=local_port, dport=12344))
6765 self.pg5.add_stream(p)
6766 self.pg_enable_capture(self.pg_interfaces)
6768 capture = self.pg0.get_capture(1)
6773 self.assertEqual(ip.src, self.pg5.remote_ip4)
6774 self.assertEqual(tcp.sport, local_port)
6775 self.assert_packet_checksums_valid(p)
6777 self.logger.error(ppp("Unexpected or invalid packet:", p))
6780 @unittest.skipUnless(running_extended_tests, "part of extended tests")
6781 def test_session_timeout(self):
6782 """ NAT44 session timeouts """
6783 self.nat44_add_address(self.nat_addr)
6784 flags = self.config_flags.NAT_IS_INSIDE
6785 self.vapi.nat44_interface_add_del_feature(
6786 sw_if_index=self.pg0.sw_if_index,
6787 flags=flags, is_add=1)
6788 self.vapi.nat44_interface_add_del_feature(
6789 sw_if_index=self.pg1.sw_if_index,
6791 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6792 tcp_transitory=240, icmp=5)
6796 for i in range(0, max_sessions):
6797 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6798 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6799 IP(src=src, dst=self.pg1.remote_ip4) /
6800 ICMP(id=1025, type='echo-request'))
6802 self.pg0.add_stream(pkts)
6803 self.pg_enable_capture(self.pg_interfaces)
6805 self.pg1.get_capture(max_sessions)
6810 for i in range(0, max_sessions):
6811 src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6812 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6813 IP(src=src, dst=self.pg1.remote_ip4) /
6814 ICMP(id=1026, type='echo-request'))
6816 self.pg0.add_stream(pkts)
6817 self.pg_enable_capture(self.pg_interfaces)
6819 self.pg1.get_capture(max_sessions)
6822 users = self.vapi.nat44_user_dump()
6824 nsessions = nsessions + user.nsessions
6825 self.assertLess(nsessions, 2 * max_sessions)
6827 @unittest.skipUnless(running_extended_tests, "part of extended tests")
6828 def test_session_rst_timeout(self):
6829 """ NAT44 session RST timeouts """
6830 self.nat44_add_address(self.nat_addr)
6831 flags = self.config_flags.NAT_IS_INSIDE
6832 self.vapi.nat44_interface_add_del_feature(
6833 sw_if_index=self.pg0.sw_if_index,
6834 flags=flags, is_add=1)
6835 self.vapi.nat44_interface_add_del_feature(
6836 sw_if_index=self.pg1.sw_if_index,
6838 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6839 tcp_transitory=5, icmp=60)
6841 self.initiate_tcp_session(self.pg0, self.pg1)
6842 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6843 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6844 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6846 self.pg0.add_stream(p)
6847 self.pg_enable_capture(self.pg_interfaces)
6849 self.pg1.get_capture(1)
6853 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6854 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6855 TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6857 self.pg0.add_stream(p)
6858 self.pg_enable_capture(self.pg_interfaces)
6860 self.pg1.get_capture(1)
6863 users = self.vapi.nat44_user_dump()
6864 self.assertEqual(len(users), 1)
6865 self.assertEqual(str(users[0].ip_address),
6866 self.pg0.remote_ip4)
6867 self.assertEqual(users[0].nsessions, 1)
6869 @unittest.skipUnless(running_extended_tests, "part of extended tests")
6870 def test_session_limit_per_user(self):
6871 """ Maximum sessions per user limit """
6872 self.nat44_add_address(self.nat_addr)
6873 flags = self.config_flags.NAT_IS_INSIDE
6874 self.vapi.nat44_interface_add_del_feature(
6875 sw_if_index=self.pg0.sw_if_index,
6876 flags=flags, is_add=1)
6877 self.vapi.nat44_interface_add_del_feature(
6878 sw_if_index=self.pg1.sw_if_index,
6880 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4,
6881 src_address=self.pg2.local_ip4,
6883 template_interval=10)
6884 self.vapi.nat_set_timeouts(udp=5, tcp_established=7440,
6885 tcp_transitory=240, icmp=60)
6887 # get maximum number of translations per user
6888 nat44_config = self.vapi.nat_show_config()
6891 for port in range(0, nat44_config.max_translations_per_user):
6892 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6893 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6894 UDP(sport=1025 + port, dport=1025 + port))
6897 self.pg0.add_stream(pkts)
6898 self.pg_enable_capture(self.pg_interfaces)
6900 capture = self.pg1.get_capture(len(pkts))
6902 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
6903 src_port=self.ipfix_src_port,
6906 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6907 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6908 UDP(sport=3001, dport=3002))
6909 self.pg0.add_stream(p)
6910 self.pg_enable_capture(self.pg_interfaces)
6912 capture = self.pg1.assert_nothing_captured()
6914 # verify IPFIX logging
6915 self.vapi.ipfix_flush()
6917 capture = self.pg2.get_capture(10)
6918 ipfix = IPFIXDecoder()
6919 # first load template
6921 self.assertTrue(p.haslayer(IPFIX))
6922 if p.haslayer(Template):
6923 ipfix.add_template(p.getlayer(Template))
6924 # verify events in data set
6926 if p.haslayer(Data):
6927 data = ipfix.decode_data_set(p.getlayer(Set))
6928 self.verify_ipfix_max_entries_per_user(
6930 nat44_config.max_translations_per_user,
6931 self.pg0.remote_ip4)
6934 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6935 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6936 UDP(sport=3001, dport=3002))
6937 self.pg0.add_stream(p)
6938 self.pg_enable_capture(self.pg_interfaces)
6940 self.pg1.get_capture(1)
6942 def test_syslog_sess(self):
6943 """ Test syslog session creation and deletion """
6944 self.vapi.syslog_set_filter(
6945 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
6946 self.vapi.syslog_set_sender(self.pg2.local_ip4, self.pg2.remote_ip4)
6947 self.nat44_add_address(self.nat_addr)
6948 flags = self.config_flags.NAT_IS_INSIDE
6949 self.vapi.nat44_interface_add_del_feature(
6950 sw_if_index=self.pg0.sw_if_index,
6951 flags=flags, is_add=1)
6952 self.vapi.nat44_interface_add_del_feature(
6953 sw_if_index=self.pg1.sw_if_index,
6956 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6957 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6958 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6959 self.pg0.add_stream(p)
6960 self.pg_enable_capture(self.pg_interfaces)
6962 capture = self.pg1.get_capture(1)
6963 self.tcp_port_out = capture[0][TCP].sport
6964 capture = self.pg2.get_capture(1)
6965 self.verify_syslog_sess(capture[0][Raw].load)
6967 self.pg_enable_capture(self.pg_interfaces)
6969 self.nat44_add_address(self.nat_addr, is_add=0)
6970 capture = self.pg2.get_capture(1)
6971 self.verify_syslog_sess(capture[0][Raw].load, False)
6974 super(TestNAT44EndpointDependent, self).tearDown()
6975 if not self.vpp_dead:
6977 self.vapi.cli("clear logging")
6979 def show_commands_at_teardown(self):
6980 self.logger.info(self.vapi.cli("show nat44 addresses"))
6981 self.logger.info(self.vapi.cli("show nat44 interfaces"))
6982 self.logger.info(self.vapi.cli("show nat44 static mappings"))
6983 self.logger.info(self.vapi.cli("show nat44 interface address"))
6984 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
6985 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
6986 self.logger.info(self.vapi.cli("show nat timeouts"))
6989 class TestNAT44Out2InDPO(MethodHolder):
6990 """ NAT44 Test Cases using out2in DPO """
6993 def setUpConstants(cls):
6994 super(TestNAT44Out2InDPO, cls).setUpConstants()
6995 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
6998 def setUpClass(cls):
6999 super(TestNAT44Out2InDPO, cls).setUpClass()
7000 cls.vapi.cli("set log class nat level debug")
7003 cls.tcp_port_in = 6303
7004 cls.tcp_port_out = 6303
7005 cls.udp_port_in = 6304
7006 cls.udp_port_out = 6304
7007 cls.icmp_id_in = 6305
7008 cls.icmp_id_out = 6305
7009 cls.nat_addr = '10.0.0.3'
7010 cls.dst_ip4 = '192.168.70.1'
7012 cls.create_pg_interfaces(range(2))
7015 cls.pg0.config_ip4()
7016 cls.pg0.resolve_arp()
7019 cls.pg1.config_ip6()
7020 cls.pg1.resolve_ndp()
7022 r1 = VppIpRoute(cls, "::", 0,
7023 [VppRoutePath(cls.pg1.remote_ip6,
7024 cls.pg1.sw_if_index)],
7029 super(TestNAT44Out2InDPO, cls).tearDownClass()
7033 def tearDownClass(cls):
7034 super(TestNAT44Out2InDPO, cls).tearDownClass()
7036 def configure_xlat(self):
7037 self.dst_ip6_pfx = '1:2:3::'
7038 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
7040 self.dst_ip6_pfx_len = 96
7041 self.src_ip6_pfx = '4:5:6::'
7042 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
7044 self.src_ip6_pfx_len = 96
7045 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
7046 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
7047 '\x00\x00\x00\x00', 0)
7049 @unittest.skip('Temporary disabled')
7050 def test_464xlat_ce(self):
7051 """ Test 464XLAT CE with NAT44 """
7053 nat_config = self.vapi.nat_show_config()
7054 self.assertEqual(1, nat_config.out2in_dpo)
7056 self.configure_xlat()
7058 flags = self.config_flags.NAT_IS_INSIDE
7059 self.vapi.nat44_interface_add_del_feature(
7060 sw_if_index=self.pg0.sw_if_index,
7061 flags=flags, is_add=1)
7062 self.vapi.nat44_add_del_address_range(first_ip_address=self.nat_addr_n,
7063 last_ip_address=self.nat_addr_n,
7064 vrf_id=0xFFFFFFFF, is_add=1)
7066 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7067 self.dst_ip6_pfx_len)
7068 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
7069 self.src_ip6_pfx_len)
7072 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7073 self.pg0.add_stream(pkts)
7074 self.pg_enable_capture(self.pg_interfaces)
7076 capture = self.pg1.get_capture(len(pkts))
7077 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
7080 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
7082 self.pg1.add_stream(pkts)
7083 self.pg_enable_capture(self.pg_interfaces)
7085 capture = self.pg0.get_capture(len(pkts))
7086 self.verify_capture_in(capture, self.pg0)
7088 self.vapi.nat44_interface_add_del_feature(
7089 sw_if_index=self.pg0.sw_if_index,
7091 self.vapi.nat44_add_del_address_range(
7092 first_ip_address=self.nat_addr_n,
7093 last_ip_address=self.nat_addr_n,
7096 @unittest.skip('Temporary disabled')
7097 def test_464xlat_ce_no_nat(self):
7098 """ Test 464XLAT CE without NAT44 """
7100 self.configure_xlat()
7102 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7103 self.dst_ip6_pfx_len)
7104 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
7105 self.src_ip6_pfx_len)
7107 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7108 self.pg0.add_stream(pkts)
7109 self.pg_enable_capture(self.pg_interfaces)
7111 capture = self.pg1.get_capture(len(pkts))
7112 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
7113 nat_ip=out_dst_ip6, same_port=True)
7115 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
7116 self.pg1.add_stream(pkts)
7117 self.pg_enable_capture(self.pg_interfaces)
7119 capture = self.pg0.get_capture(len(pkts))
7120 self.verify_capture_in(capture, self.pg0)
7123 class TestDeterministicNAT(MethodHolder):
7124 """ Deterministic NAT Test Cases """
7127 def setUpConstants(cls):
7128 super(TestDeterministicNAT, cls).setUpConstants()
7129 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
7132 def setUpClass(cls):
7133 super(TestDeterministicNAT, cls).setUpClass()
7134 cls.vapi.cli("set log class nat level debug")
7137 cls.tcp_port_in = 6303
7138 cls.tcp_external_port = 6303
7139 cls.udp_port_in = 6304
7140 cls.udp_external_port = 6304
7141 cls.icmp_id_in = 6305
7142 cls.nat_addr = '10.0.0.3'
7144 cls.create_pg_interfaces(range(3))
7145 cls.interfaces = list(cls.pg_interfaces)
7147 for i in cls.interfaces:
7152 cls.pg0.generate_remote_hosts(2)
7153 cls.pg0.configure_ipv4_neighbors()
7156 super(TestDeterministicNAT, cls).tearDownClass()
7160 def tearDownClass(cls):
7161 super(TestDeterministicNAT, cls).tearDownClass()
7163 def create_stream_in(self, in_if, out_if, ttl=64):
7165 Create packet stream for inside network
7167 :param in_if: Inside interface
7168 :param out_if: Outside interface
7169 :param ttl: TTL of generated packets
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 TCP(sport=self.tcp_port_in, dport=self.tcp_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 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
7185 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7186 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7187 ICMP(id=self.icmp_id_in, type='echo-request'))
7192 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
7194 Create packet stream for outside network
7196 :param out_if: Outside interface
7197 :param dst_ip: Destination IP address (Default use global NAT address)
7198 :param ttl: TTL of generated packets
7201 dst_ip = self.nat_addr
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 TCP(dport=self.tcp_port_out, sport=self.tcp_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 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
7216 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7217 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7218 ICMP(id=self.icmp_external_id, type='echo-reply'))
7223 def verify_capture_out(self, capture, nat_ip=None):
7225 Verify captured packets on outside network
7227 :param capture: Captured packets
7228 :param nat_ip: Translated IP address (Default use global NAT address)
7229 :param same_port: Source port number is not translated (Default False)
7232 nat_ip = self.nat_addr
7233 for packet in capture:
7235 self.assertEqual(packet[IP].src, nat_ip)
7236 if packet.haslayer(TCP):
7237 self.tcp_port_out = packet[TCP].sport
7238 elif packet.haslayer(UDP):
7239 self.udp_port_out = packet[UDP].sport
7241 self.icmp_external_id = packet[ICMP].id
7243 self.logger.error(ppp("Unexpected or invalid packet "
7244 "(outside network):", packet))
7247 def test_deterministic_mode(self):
7248 """ NAT plugin run deterministic mode """
7249 in_addr = '172.16.255.0'
7250 out_addr = '172.17.255.50'
7251 in_addr_t = '172.16.255.20'
7255 nat_config = self.vapi.nat_show_config()
7256 self.assertEqual(1, nat_config.deterministic)
7258 self.vapi.nat_det_add_del_map(is_add=1, in_addr=in_addr,
7259 in_plen=in_plen, out_addr=out_addr,
7262 rep1 = self.vapi.nat_det_forward(in_addr_t)
7263 self.assertEqual(str(rep1.out_addr), out_addr)
7264 rep2 = self.vapi.nat_det_reverse(rep1.out_port_hi, out_addr)
7266 self.assertEqual(str(rep2.in_addr), in_addr_t)
7268 deterministic_mappings = self.vapi.nat_det_map_dump()
7269 self.assertEqual(len(deterministic_mappings), 1)
7270 dsm = deterministic_mappings[0]
7271 self.assertEqual(in_addr, str(dsm.in_addr))
7272 self.assertEqual(in_plen, dsm.in_plen)
7273 self.assertEqual(out_addr, str(dsm.out_addr))
7274 self.assertEqual(out_plen, dsm.out_plen)
7276 self.clear_nat_det()
7277 deterministic_mappings = self.vapi.nat_det_map_dump()
7278 self.assertEqual(len(deterministic_mappings), 0)
7280 def test_set_timeouts(self):
7281 """ Set deterministic NAT timeouts """
7282 timeouts_before = self.vapi.nat_get_timeouts()
7284 self.vapi.nat_set_timeouts(
7285 udp=timeouts_before.udp + 10,
7286 tcp_established=timeouts_before.tcp_established + 10,
7287 tcp_transitory=timeouts_before.tcp_transitory + 10,
7288 icmp=timeouts_before.icmp + 10)
7290 timeouts_after = self.vapi.nat_get_timeouts()
7292 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
7293 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
7294 self.assertNotEqual(timeouts_before.tcp_established,
7295 timeouts_after.tcp_established)
7296 self.assertNotEqual(timeouts_before.tcp_transitory,
7297 timeouts_after.tcp_transitory)
7299 def test_det_in(self):
7300 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
7302 nat_ip = "10.0.0.10"
7304 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7306 out_addr=socket.inet_aton(nat_ip),
7309 flags = self.config_flags.NAT_IS_INSIDE
7310 self.vapi.nat44_interface_add_del_feature(
7311 sw_if_index=self.pg0.sw_if_index,
7312 flags=flags, is_add=1)
7313 self.vapi.nat44_interface_add_del_feature(
7314 sw_if_index=self.pg1.sw_if_index,
7318 pkts = self.create_stream_in(self.pg0, self.pg1)
7319 self.pg0.add_stream(pkts)
7320 self.pg_enable_capture(self.pg_interfaces)
7322 capture = self.pg1.get_capture(len(pkts))
7323 self.verify_capture_out(capture, nat_ip)
7326 pkts = self.create_stream_out(self.pg1, nat_ip)
7327 self.pg1.add_stream(pkts)
7328 self.pg_enable_capture(self.pg_interfaces)
7330 capture = self.pg0.get_capture(len(pkts))
7331 self.verify_capture_in(capture, self.pg0)
7334 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4)
7335 self.assertEqual(len(sessions), 3)
7339 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7340 self.assertEqual(s.in_port, self.tcp_port_in)
7341 self.assertEqual(s.out_port, self.tcp_port_out)
7342 self.assertEqual(s.ext_port, self.tcp_external_port)
7346 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7347 self.assertEqual(s.in_port, self.udp_port_in)
7348 self.assertEqual(s.out_port, self.udp_port_out)
7349 self.assertEqual(s.ext_port, self.udp_external_port)
7353 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7354 self.assertEqual(s.in_port, self.icmp_id_in)
7355 self.assertEqual(s.out_port, self.icmp_external_id)
7357 def test_multiple_users(self):
7358 """ Deterministic NAT multiple users """
7360 nat_ip = "10.0.0.10"
7362 external_port = 6303
7364 host0 = self.pg0.remote_hosts[0]
7365 host1 = self.pg0.remote_hosts[1]
7367 self.vapi.nat_det_add_del_map(is_add=1, in_addr=host0.ip4, in_plen=24,
7368 out_addr=socket.inet_aton(nat_ip),
7370 flags = self.config_flags.NAT_IS_INSIDE
7371 self.vapi.nat44_interface_add_del_feature(
7372 sw_if_index=self.pg0.sw_if_index,
7373 flags=flags, is_add=1)
7374 self.vapi.nat44_interface_add_del_feature(
7375 sw_if_index=self.pg1.sw_if_index,
7379 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
7380 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
7381 TCP(sport=port_in, dport=external_port))
7382 self.pg0.add_stream(p)
7383 self.pg_enable_capture(self.pg_interfaces)
7385 capture = self.pg1.get_capture(1)
7390 self.assertEqual(ip.src, nat_ip)
7391 self.assertEqual(ip.dst, self.pg1.remote_ip4)
7392 self.assertEqual(tcp.dport, external_port)
7393 port_out0 = tcp.sport
7395 self.logger.error(ppp("Unexpected or invalid packet:", p))
7399 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
7400 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
7401 TCP(sport=port_in, dport=external_port))
7402 self.pg0.add_stream(p)
7403 self.pg_enable_capture(self.pg_interfaces)
7405 capture = self.pg1.get_capture(1)
7410 self.assertEqual(ip.src, nat_ip)
7411 self.assertEqual(ip.dst, self.pg1.remote_ip4)
7412 self.assertEqual(tcp.dport, external_port)
7413 port_out1 = tcp.sport
7415 self.logger.error(ppp("Unexpected or invalid packet:", p))
7418 dms = self.vapi.nat_det_map_dump()
7419 self.assertEqual(1, len(dms))
7420 self.assertEqual(2, dms[0].ses_num)
7423 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7424 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
7425 TCP(sport=external_port, dport=port_out0))
7426 self.pg1.add_stream(p)
7427 self.pg_enable_capture(self.pg_interfaces)
7429 capture = self.pg0.get_capture(1)
7434 self.assertEqual(ip.src, self.pg1.remote_ip4)
7435 self.assertEqual(ip.dst, host0.ip4)
7436 self.assertEqual(tcp.dport, port_in)
7437 self.assertEqual(tcp.sport, external_port)
7439 self.logger.error(ppp("Unexpected or invalid packet:", p))
7443 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7444 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
7445 TCP(sport=external_port, dport=port_out1))
7446 self.pg1.add_stream(p)
7447 self.pg_enable_capture(self.pg_interfaces)
7449 capture = self.pg0.get_capture(1)
7454 self.assertEqual(ip.src, self.pg1.remote_ip4)
7455 self.assertEqual(ip.dst, host1.ip4)
7456 self.assertEqual(tcp.dport, port_in)
7457 self.assertEqual(tcp.sport, external_port)
7459 self.logger.error(ppp("Unexpected or invalid packet", p))
7462 # session close api test
7463 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
7465 self.pg1.remote_ip4,
7467 dms = self.vapi.nat_det_map_dump()
7468 self.assertEqual(dms[0].ses_num, 1)
7470 self.vapi.nat_det_close_session_in(host0.ip4,
7472 self.pg1.remote_ip4,
7474 dms = self.vapi.nat_det_map_dump()
7475 self.assertEqual(dms[0].ses_num, 0)
7477 def test_tcp_session_close_detection_in(self):
7478 """ Deterministic NAT TCP session close from inside network """
7479 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7481 out_addr=socket.inet_aton(self.nat_addr),
7483 flags = self.config_flags.NAT_IS_INSIDE
7484 self.vapi.nat44_interface_add_del_feature(
7485 sw_if_index=self.pg0.sw_if_index,
7486 flags=flags, is_add=1)
7487 self.vapi.nat44_interface_add_del_feature(
7488 sw_if_index=self.pg1.sw_if_index,
7491 self.initiate_tcp_session(self.pg0, self.pg1)
7493 # close the session from inside
7495 # FIN packet in -> out
7496 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7497 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7498 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7500 self.pg0.add_stream(p)
7501 self.pg_enable_capture(self.pg_interfaces)
7503 self.pg1.get_capture(1)
7507 # ACK packet out -> in
7508 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7509 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7510 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7514 # FIN packet out -> in
7515 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7516 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7517 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7521 self.pg1.add_stream(pkts)
7522 self.pg_enable_capture(self.pg_interfaces)
7524 self.pg0.get_capture(2)
7526 # ACK packet in -> out
7527 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7528 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7529 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7531 self.pg0.add_stream(p)
7532 self.pg_enable_capture(self.pg_interfaces)
7534 self.pg1.get_capture(1)
7536 # Check if deterministic NAT44 closed the session
7537 dms = self.vapi.nat_det_map_dump()
7538 self.assertEqual(0, dms[0].ses_num)
7540 self.logger.error("TCP session termination failed")
7543 def test_tcp_session_close_detection_out(self):
7544 """ Deterministic NAT TCP session close from outside network """
7545 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7547 out_addr=socket.inet_aton(self.nat_addr),
7549 flags = self.config_flags.NAT_IS_INSIDE
7550 self.vapi.nat44_interface_add_del_feature(
7551 sw_if_index=self.pg0.sw_if_index,
7552 flags=flags, is_add=1)
7553 self.vapi.nat44_interface_add_del_feature(
7554 sw_if_index=self.pg1.sw_if_index,
7557 self.initiate_tcp_session(self.pg0, self.pg1)
7559 # close the session from outside
7561 # FIN packet out -> in
7562 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7563 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7564 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7566 self.pg1.add_stream(p)
7567 self.pg_enable_capture(self.pg_interfaces)
7569 self.pg0.get_capture(1)
7573 # ACK packet in -> out
7574 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7575 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7576 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7580 # ACK packet in -> out
7581 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7582 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7583 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7587 self.pg0.add_stream(pkts)
7588 self.pg_enable_capture(self.pg_interfaces)
7590 self.pg1.get_capture(2)
7592 # ACK packet out -> in
7593 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7594 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7595 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7597 self.pg1.add_stream(p)
7598 self.pg_enable_capture(self.pg_interfaces)
7600 self.pg0.get_capture(1)
7602 # Check if deterministic NAT44 closed the session
7603 dms = self.vapi.nat_det_map_dump()
7604 self.assertEqual(0, dms[0].ses_num)
7606 self.logger.error("TCP session termination failed")
7609 @unittest.skipUnless(running_extended_tests, "part of extended tests")
7610 def test_session_timeout(self):
7611 """ Deterministic NAT session timeouts """
7612 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7614 out_addr=socket.inet_aton(self.nat_addr),
7616 flags = self.config_flags.NAT_IS_INSIDE
7617 self.vapi.nat44_interface_add_del_feature(
7618 sw_if_index=self.pg0.sw_if_index,
7619 flags=flags, is_add=1)
7620 self.vapi.nat44_interface_add_del_feature(
7621 sw_if_index=self.pg1.sw_if_index,
7624 self.initiate_tcp_session(self.pg0, self.pg1)
7625 self.vapi.nat_set_timeouts(udp=5, tcp_established=5, tcp_transitory=5,
7627 pkts = self.create_stream_in(self.pg0, self.pg1)
7628 self.pg0.add_stream(pkts)
7629 self.pg_enable_capture(self.pg_interfaces)
7631 capture = self.pg1.get_capture(len(pkts))
7634 dms = self.vapi.nat_det_map_dump()
7635 self.assertEqual(0, dms[0].ses_num)
7637 @unittest.skipUnless(running_extended_tests, "part of extended tests")
7638 def test_session_limit_per_user(self):
7639 """ Deterministic NAT maximum sessions per user limit """
7640 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7642 out_addr=socket.inet_aton(self.nat_addr),
7644 flags = self.config_flags.NAT_IS_INSIDE
7645 self.vapi.nat44_interface_add_del_feature(
7646 sw_if_index=self.pg0.sw_if_index,
7647 flags=flags, is_add=1)
7648 self.vapi.nat44_interface_add_del_feature(
7649 sw_if_index=self.pg1.sw_if_index,
7651 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4,
7652 src_address=self.pg2.local_ip4,
7654 template_interval=10)
7655 self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7659 for port in range(1025, 2025):
7660 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7661 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7662 UDP(sport=port, dport=port))
7665 self.pg0.add_stream(pkts)
7666 self.pg_enable_capture(self.pg_interfaces)
7668 capture = self.pg1.get_capture(len(pkts))
7670 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7671 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7672 UDP(sport=3001, dport=3002))
7673 self.pg0.add_stream(p)
7674 self.pg_enable_capture(self.pg_interfaces)
7676 capture = self.pg1.assert_nothing_captured()
7678 # verify ICMP error packet
7679 capture = self.pg0.get_capture(1)
7681 self.assertTrue(p.haslayer(ICMP))
7683 self.assertEqual(icmp.type, 3)
7684 self.assertEqual(icmp.code, 1)
7685 self.assertTrue(icmp.haslayer(IPerror))
7686 inner_ip = icmp[IPerror]
7687 self.assertEqual(inner_ip[UDPerror].sport, 3001)
7688 self.assertEqual(inner_ip[UDPerror].dport, 3002)
7690 dms = self.vapi.nat_det_map_dump()
7692 self.assertEqual(1000, dms[0].ses_num)
7694 # verify IPFIX logging
7695 self.vapi.ipfix_flush()
7697 capture = self.pg2.get_capture(2)
7698 ipfix = IPFIXDecoder()
7699 # first load template
7701 self.assertTrue(p.haslayer(IPFIX))
7702 if p.haslayer(Template):
7703 ipfix.add_template(p.getlayer(Template))
7704 # verify events in data set
7706 if p.haslayer(Data):
7707 data = ipfix.decode_data_set(p.getlayer(Set))
7708 self.verify_ipfix_max_entries_per_user(data,
7710 self.pg0.remote_ip4)
7712 def clear_nat_det(self):
7714 Clear deterministic NAT configuration.
7716 self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7718 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
7719 tcp_transitory=240, icmp=60)
7720 deterministic_mappings = self.vapi.nat_det_map_dump()
7721 for dsm in deterministic_mappings:
7722 self.vapi.nat_det_add_del_map(is_add=0, in_addr=dsm.in_addr,
7723 in_plen=dsm.in_plen,
7724 out_addr=dsm.out_addr,
7725 out_plen=dsm.out_plen)
7727 interfaces = self.vapi.nat44_interface_dump()
7728 for intf in interfaces:
7729 self.vapi.nat44_interface_add_del_feature(
7730 sw_if_index=intf.sw_if_index,
7734 super(TestDeterministicNAT, self).tearDown()
7735 if not self.vpp_dead:
7736 self.clear_nat_det()
7738 def show_commands_at_teardown(self):
7739 self.logger.info(self.vapi.cli("show nat44 interfaces"))
7740 self.logger.info(self.vapi.cli("show nat timeouts"))
7742 self.vapi.cli("show nat44 deterministic mappings"))
7744 self.vapi.cli("show nat44 deterministic sessions"))
7747 class TestNAT64(MethodHolder):
7748 """ NAT64 Test Cases """
7751 def setUpConstants(cls):
7752 super(TestNAT64, cls).setUpConstants()
7753 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
7754 "nat64 st hash buckets 256", "}"])
7757 def setUpClass(cls):
7758 super(TestNAT64, cls).setUpClass()
7761 cls.tcp_port_in = 6303
7762 cls.tcp_port_out = 6303
7763 cls.udp_port_in = 6304
7764 cls.udp_port_out = 6304
7765 cls.icmp_id_in = 6305
7766 cls.icmp_id_out = 6305
7767 cls.tcp_external_port = 80
7768 cls.nat_addr = '10.0.0.3'
7769 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
7771 cls.vrf1_nat_addr = '10.0.10.3'
7772 cls.ipfix_src_port = 4739
7773 cls.ipfix_domain_id = 1
7775 cls.create_pg_interfaces(range(6))
7776 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
7777 cls.ip6_interfaces.append(cls.pg_interfaces[2])
7778 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
7780 cls.vapi.ip_table_add_del(is_ipv6=1, is_add=1,
7781 table_id=cls.vrf1_id)
7783 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
7785 cls.pg0.generate_remote_hosts(2)
7787 for i in cls.ip6_interfaces:
7790 i.configure_ipv6_neighbors()
7792 for i in cls.ip4_interfaces:
7798 cls.pg3.config_ip4()
7799 cls.pg3.resolve_arp()
7800 cls.pg3.config_ip6()
7801 cls.pg3.configure_ipv6_neighbors()
7804 cls.pg5.config_ip6()
7807 super(TestNAT64, cls).tearDownClass()
7811 def tearDownClass(cls):
7812 super(TestNAT64, cls).tearDownClass()
7814 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
7815 """ NAT64 inside interface handles Neighbor Advertisement """
7817 flags = self.config_flags.NAT_IS_INSIDE
7818 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7819 sw_if_index=self.pg5.sw_if_index)
7822 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7823 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7824 ICMPv6EchoRequest())
7826 self.pg5.add_stream(pkts)
7827 self.pg_enable_capture(self.pg_interfaces)
7830 # Wait for Neighbor Solicitation
7831 capture = self.pg5.get_capture(len(pkts))
7834 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7835 self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
7836 tgt = packet[ICMPv6ND_NS].tgt
7838 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7841 # Send Neighbor Advertisement
7842 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7843 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7844 ICMPv6ND_NA(tgt=tgt) /
7845 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
7847 self.pg5.add_stream(pkts)
7848 self.pg_enable_capture(self.pg_interfaces)
7851 # Try to send ping again
7853 self.pg5.add_stream(pkts)
7854 self.pg_enable_capture(self.pg_interfaces)
7857 # Wait for ping reply
7858 capture = self.pg5.get_capture(len(pkts))
7861 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7862 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
7863 self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
7865 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7868 def test_pool(self):
7869 """ Add/delete address to NAT64 pool """
7870 nat_addr = '1.2.3.4'
7872 self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7874 vrf_id=0xFFFFFFFF, is_add=1)
7876 addresses = self.vapi.nat64_pool_addr_dump()
7877 self.assertEqual(len(addresses), 1)
7878 self.assertEqual(str(addresses[0].address), nat_addr)
7880 self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7882 vrf_id=0xFFFFFFFF, is_add=0)
7884 addresses = self.vapi.nat64_pool_addr_dump()
7885 self.assertEqual(len(addresses), 0)
7887 def test_interface(self):
7888 """ Enable/disable NAT64 feature on the interface """
7889 flags = self.config_flags.NAT_IS_INSIDE
7890 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7891 sw_if_index=self.pg0.sw_if_index)
7892 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7893 sw_if_index=self.pg1.sw_if_index)
7895 interfaces = self.vapi.nat64_interface_dump()
7896 self.assertEqual(len(interfaces), 2)
7899 for intf in interfaces:
7900 if intf.sw_if_index == self.pg0.sw_if_index:
7901 self.assertEqual(intf.flags, self.config_flags.NAT_IS_INSIDE)
7903 elif intf.sw_if_index == self.pg1.sw_if_index:
7904 self.assertEqual(intf.flags, self.config_flags.NAT_IS_OUTSIDE)
7906 self.assertTrue(pg0_found)
7907 self.assertTrue(pg1_found)
7909 features = self.vapi.cli("show interface features pg0")
7910 self.assertIn('nat64-in2out', features)
7911 features = self.vapi.cli("show interface features pg1")
7912 self.assertIn('nat64-out2in', features)
7914 self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7915 sw_if_index=self.pg0.sw_if_index)
7916 self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7917 sw_if_index=self.pg1.sw_if_index)
7919 interfaces = self.vapi.nat64_interface_dump()
7920 self.assertEqual(len(interfaces), 0)
7922 def test_static_bib(self):
7923 """ Add/delete static BIB entry """
7924 in_addr = '2001:db8:85a3::8a2e:370:7334'
7925 out_addr = '10.1.1.3'
7928 proto = IP_PROTOS.tcp
7930 self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7931 i_port=in_port, o_port=out_port,
7932 proto=proto, vrf_id=0, is_add=1)
7933 bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
7936 if bibe.flags & self.config_flags.NAT_IS_STATIC:
7938 self.assertEqual(str(bibe.i_addr), in_addr)
7939 self.assertEqual(str(bibe.o_addr), out_addr)
7940 self.assertEqual(bibe.i_port, in_port)
7941 self.assertEqual(bibe.o_port, out_port)
7942 self.assertEqual(static_bib_num, 1)
7943 bibs = self.statistics.get_counter('/nat64/total-bibs')
7944 self.assertEqual(bibs[0][0], 1)
7946 self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7947 i_port=in_port, o_port=out_port,
7948 proto=proto, vrf_id=0, is_add=0)
7949 bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
7952 if bibe.flags & self.config_flags.NAT_IS_STATIC:
7954 self.assertEqual(static_bib_num, 0)
7955 bibs = self.statistics.get_counter('/nat64/total-bibs')
7956 self.assertEqual(bibs[0][0], 0)
7958 def test_set_timeouts(self):
7959 """ Set NAT64 timeouts """
7960 # verify default values
7961 timeouts = self.vapi.nat_get_timeouts()
7962 self.assertEqual(timeouts.udp, 300)
7963 self.assertEqual(timeouts.icmp, 60)
7964 self.assertEqual(timeouts.tcp_transitory, 240)
7965 self.assertEqual(timeouts.tcp_established, 7440)
7967 # set and verify custom values
7968 self.vapi.nat_set_timeouts(udp=200, tcp_established=7450,
7969 tcp_transitory=250, icmp=30)
7970 timeouts = self.vapi.nat_get_timeouts()
7971 self.assertEqual(timeouts.udp, 200)
7972 self.assertEqual(timeouts.icmp, 30)
7973 self.assertEqual(timeouts.tcp_transitory, 250)
7974 self.assertEqual(timeouts.tcp_established, 7450)
7976 def test_dynamic(self):
7977 """ NAT64 dynamic translation test """
7978 self.tcp_port_in = 6303
7979 self.udp_port_in = 6304
7980 self.icmp_id_in = 6305
7982 ses_num_start = self.nat64_get_ses_num()
7984 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
7985 end_addr=self.nat_addr,
7988 flags = self.config_flags.NAT_IS_INSIDE
7989 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7990 sw_if_index=self.pg0.sw_if_index)
7991 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7992 sw_if_index=self.pg1.sw_if_index)
7995 tcpn = self.statistics.get_err_counter('/err/nat64-in2out/TCP packets')
7996 udpn = self.statistics.get_err_counter('/err/nat64-in2out/UDP packets')
7997 icmpn = self.statistics.get_err_counter(
7998 '/err/nat64-in2out/ICMP packets')
7999 totaln = self.statistics.get_err_counter(
8000 '/err/nat64-in2out/good in2out packets processed')
8002 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8003 self.pg0.add_stream(pkts)
8004 self.pg_enable_capture(self.pg_interfaces)
8006 capture = self.pg1.get_capture(len(pkts))
8007 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8008 dst_ip=self.pg1.remote_ip4)
8010 err = self.statistics.get_err_counter('/err/nat64-in2out/TCP packets')
8011 self.assertEqual(err - tcpn, 1)
8012 err = self.statistics.get_err_counter('/err/nat64-in2out/UDP packets')
8013 self.assertEqual(err - udpn, 1)
8014 err = self.statistics.get_err_counter('/err/nat64-in2out/ICMP packets')
8015 self.assertEqual(err - icmpn, 1)
8016 err = self.statistics.get_err_counter(
8017 '/err/nat64-in2out/good in2out packets processed')
8018 self.assertEqual(err - totaln, 3)
8021 tcpn = self.statistics.get_err_counter('/err/nat64-out2in/TCP packets')
8022 udpn = self.statistics.get_err_counter('/err/nat64-out2in/UDP packets')
8023 icmpn = self.statistics.get_err_counter(
8024 '/err/nat64-out2in/ICMP packets')
8025 totaln = self.statistics.get_err_counter(
8026 '/err/nat64-out2in/good out2in packets processed')
8028 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8029 self.pg1.add_stream(pkts)
8030 self.pg_enable_capture(self.pg_interfaces)
8032 capture = self.pg0.get_capture(len(pkts))
8033 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8034 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8036 err = self.statistics.get_err_counter('/err/nat64-out2in/TCP packets')
8037 self.assertEqual(err - tcpn, 2)
8038 err = self.statistics.get_err_counter('/err/nat64-out2in/UDP packets')
8039 self.assertEqual(err - udpn, 1)
8040 err = self.statistics.get_err_counter('/err/nat64-out2in/ICMP packets')
8041 self.assertEqual(err - icmpn, 1)
8042 err = self.statistics.get_err_counter(
8043 '/err/nat64-out2in/good out2in packets processed')
8044 self.assertEqual(err - totaln, 4)
8046 bibs = self.statistics.get_counter('/nat64/total-bibs')
8047 self.assertEqual(bibs[0][0], 3)
8048 sessions = self.statistics.get_counter('/nat64/total-sessions')
8049 self.assertEqual(sessions[0][0], 3)
8052 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8053 self.pg0.add_stream(pkts)
8054 self.pg_enable_capture(self.pg_interfaces)
8056 capture = self.pg1.get_capture(len(pkts))
8057 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8058 dst_ip=self.pg1.remote_ip4)
8061 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8062 self.pg1.add_stream(pkts)
8063 self.pg_enable_capture(self.pg_interfaces)
8065 capture = self.pg0.get_capture(len(pkts))
8066 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8068 ses_num_end = self.nat64_get_ses_num()
8070 self.assertEqual(ses_num_end - ses_num_start, 3)
8072 # tenant with specific VRF
8073 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
8074 end_addr=self.vrf1_nat_addr,
8075 vrf_id=self.vrf1_id, is_add=1)
8076 flags = self.config_flags.NAT_IS_INSIDE
8077 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8078 sw_if_index=self.pg2.sw_if_index)
8080 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
8081 self.pg2.add_stream(pkts)
8082 self.pg_enable_capture(self.pg_interfaces)
8084 capture = self.pg1.get_capture(len(pkts))
8085 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
8086 dst_ip=self.pg1.remote_ip4)
8088 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
8089 self.pg1.add_stream(pkts)
8090 self.pg_enable_capture(self.pg_interfaces)
8092 capture = self.pg2.get_capture(len(pkts))
8093 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
8095 def test_static(self):
8096 """ NAT64 static translation test """
8097 self.tcp_port_in = 60303
8098 self.udp_port_in = 60304
8099 self.icmp_id_in = 60305
8100 self.tcp_port_out = 60303
8101 self.udp_port_out = 60304
8102 self.icmp_id_out = 60305
8104 ses_num_start = self.nat64_get_ses_num()
8106 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8107 end_addr=self.nat_addr,
8110 flags = self.config_flags.NAT_IS_INSIDE
8111 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8112 sw_if_index=self.pg0.sw_if_index)
8113 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8114 sw_if_index=self.pg1.sw_if_index)
8116 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8117 o_addr=self.nat_addr,
8118 i_port=self.tcp_port_in,
8119 o_port=self.tcp_port_out,
8120 proto=IP_PROTOS.tcp, vrf_id=0,
8122 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8123 o_addr=self.nat_addr,
8124 i_port=self.udp_port_in,
8125 o_port=self.udp_port_out,
8126 proto=IP_PROTOS.udp, vrf_id=0,
8128 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8129 o_addr=self.nat_addr,
8130 i_port=self.icmp_id_in,
8131 o_port=self.icmp_id_out,
8132 proto=IP_PROTOS.icmp, vrf_id=0,
8136 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8137 self.pg0.add_stream(pkts)
8138 self.pg_enable_capture(self.pg_interfaces)
8140 capture = self.pg1.get_capture(len(pkts))
8141 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8142 dst_ip=self.pg1.remote_ip4, same_port=True)
8145 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8146 self.pg1.add_stream(pkts)
8147 self.pg_enable_capture(self.pg_interfaces)
8149 capture = self.pg0.get_capture(len(pkts))
8150 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8151 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8153 ses_num_end = self.nat64_get_ses_num()
8155 self.assertEqual(ses_num_end - ses_num_start, 3)
8157 @unittest.skipUnless(running_extended_tests, "part of extended tests")
8158 def test_session_timeout(self):
8159 """ NAT64 session timeout """
8160 self.icmp_id_in = 1234
8161 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8162 end_addr=self.nat_addr,
8165 flags = self.config_flags.NAT_IS_INSIDE
8166 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8167 sw_if_index=self.pg0.sw_if_index)
8168 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8169 sw_if_index=self.pg1.sw_if_index)
8170 self.vapi.nat_set_timeouts(udp=300, tcp_established=5,
8174 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8175 self.pg0.add_stream(pkts)
8176 self.pg_enable_capture(self.pg_interfaces)
8178 capture = self.pg1.get_capture(len(pkts))
8180 ses_num_before_timeout = self.nat64_get_ses_num()
8184 # ICMP and TCP session after timeout
8185 ses_num_after_timeout = self.nat64_get_ses_num()
8186 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
8188 def test_icmp_error(self):
8189 """ NAT64 ICMP Error message translation """
8190 self.tcp_port_in = 6303
8191 self.udp_port_in = 6304
8192 self.icmp_id_in = 6305
8194 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8195 end_addr=self.nat_addr,
8198 flags = self.config_flags.NAT_IS_INSIDE
8199 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8200 sw_if_index=self.pg0.sw_if_index)
8201 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8202 sw_if_index=self.pg1.sw_if_index)
8204 # send some packets to create sessions
8205 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8206 self.pg0.add_stream(pkts)
8207 self.pg_enable_capture(self.pg_interfaces)
8209 capture_ip4 = self.pg1.get_capture(len(pkts))
8210 self.verify_capture_out(capture_ip4,
8211 nat_ip=self.nat_addr,
8212 dst_ip=self.pg1.remote_ip4)
8214 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8215 self.pg1.add_stream(pkts)
8216 self.pg_enable_capture(self.pg_interfaces)
8218 capture_ip6 = self.pg0.get_capture(len(pkts))
8219 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8220 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
8221 self.pg0.remote_ip6)
8224 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8225 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
8226 ICMPv6DestUnreach(code=1) /
8227 packet[IPv6] for packet in capture_ip6]
8228 self.pg0.add_stream(pkts)
8229 self.pg_enable_capture(self.pg_interfaces)
8231 capture = self.pg1.get_capture(len(pkts))
8232 for packet in capture:
8234 self.assertEqual(packet[IP].src, self.nat_addr)
8235 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
8236 self.assertEqual(packet[ICMP].type, 3)
8237 self.assertEqual(packet[ICMP].code, 13)
8238 inner = packet[IPerror]
8239 self.assertEqual(inner.src, self.pg1.remote_ip4)
8240 self.assertEqual(inner.dst, self.nat_addr)
8241 self.assert_packet_checksums_valid(packet)
8242 if inner.haslayer(TCPerror):
8243 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
8244 elif inner.haslayer(UDPerror):
8245 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
8247 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
8249 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8253 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8254 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8255 ICMP(type=3, code=13) /
8256 packet[IP] for packet in capture_ip4]
8257 self.pg1.add_stream(pkts)
8258 self.pg_enable_capture(self.pg_interfaces)
8260 capture = self.pg0.get_capture(len(pkts))
8261 for packet in capture:
8263 self.assertEqual(packet[IPv6].src, ip.src)
8264 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8265 icmp = packet[ICMPv6DestUnreach]
8266 self.assertEqual(icmp.code, 1)
8267 inner = icmp[IPerror6]
8268 self.assertEqual(inner.src, self.pg0.remote_ip6)
8269 self.assertEqual(inner.dst, ip.src)
8270 self.assert_icmpv6_checksum_valid(packet)
8271 if inner.haslayer(TCPerror):
8272 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
8273 elif inner.haslayer(UDPerror):
8274 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
8276 self.assertEqual(inner[ICMPv6EchoRequest].id,
8279 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8282 def test_hairpinning(self):
8283 """ NAT64 hairpinning """
8285 client = self.pg0.remote_hosts[0]
8286 server = self.pg0.remote_hosts[1]
8287 server_tcp_in_port = 22
8288 server_tcp_out_port = 4022
8289 server_udp_in_port = 23
8290 server_udp_out_port = 4023
8291 client_tcp_in_port = 1234
8292 client_udp_in_port = 1235
8293 client_tcp_out_port = 0
8294 client_udp_out_port = 0
8295 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8296 nat_addr_ip6 = ip.src
8298 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8299 end_addr=self.nat_addr,
8302 flags = self.config_flags.NAT_IS_INSIDE
8303 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8304 sw_if_index=self.pg0.sw_if_index)
8305 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8306 sw_if_index=self.pg1.sw_if_index)
8308 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8309 o_addr=self.nat_addr,
8310 i_port=server_tcp_in_port,
8311 o_port=server_tcp_out_port,
8312 proto=IP_PROTOS.tcp, vrf_id=0,
8314 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8315 o_addr=self.nat_addr,
8316 i_port=server_udp_in_port,
8317 o_port=server_udp_out_port,
8318 proto=IP_PROTOS.udp, vrf_id=0,
8323 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8324 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8325 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8327 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8328 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8329 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
8331 self.pg0.add_stream(pkts)
8332 self.pg_enable_capture(self.pg_interfaces)
8334 capture = self.pg0.get_capture(len(pkts))
8335 for packet in capture:
8337 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8338 self.assertEqual(packet[IPv6].dst, server.ip6)
8339 self.assert_packet_checksums_valid(packet)
8340 if packet.haslayer(TCP):
8341 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
8342 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
8343 client_tcp_out_port = packet[TCP].sport
8345 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
8346 self.assertEqual(packet[UDP].dport, server_udp_in_port)
8347 client_udp_out_port = packet[UDP].sport
8349 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8354 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8355 IPv6(src=server.ip6, dst=nat_addr_ip6) /
8356 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
8358 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8359 IPv6(src=server.ip6, dst=nat_addr_ip6) /
8360 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
8362 self.pg0.add_stream(pkts)
8363 self.pg_enable_capture(self.pg_interfaces)
8365 capture = self.pg0.get_capture(len(pkts))
8366 for packet in capture:
8368 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8369 self.assertEqual(packet[IPv6].dst, client.ip6)
8370 self.assert_packet_checksums_valid(packet)
8371 if packet.haslayer(TCP):
8372 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
8373 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
8375 self.assertEqual(packet[UDP].sport, server_udp_out_port)
8376 self.assertEqual(packet[UDP].dport, client_udp_in_port)
8378 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8383 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8384 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8385 ICMPv6DestUnreach(code=1) /
8386 packet[IPv6] for packet in capture]
8387 self.pg0.add_stream(pkts)
8388 self.pg_enable_capture(self.pg_interfaces)
8390 capture = self.pg0.get_capture(len(pkts))
8391 for packet in capture:
8393 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8394 self.assertEqual(packet[IPv6].dst, server.ip6)
8395 icmp = packet[ICMPv6DestUnreach]
8396 self.assertEqual(icmp.code, 1)
8397 inner = icmp[IPerror6]
8398 self.assertEqual(inner.src, server.ip6)
8399 self.assertEqual(inner.dst, nat_addr_ip6)
8400 self.assert_packet_checksums_valid(packet)
8401 if inner.haslayer(TCPerror):
8402 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
8403 self.assertEqual(inner[TCPerror].dport,
8404 client_tcp_out_port)
8406 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
8407 self.assertEqual(inner[UDPerror].dport,
8408 client_udp_out_port)
8410 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8413 def test_prefix(self):
8414 """ NAT64 Network-Specific Prefix """
8416 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8417 end_addr=self.nat_addr,
8420 flags = self.config_flags.NAT_IS_INSIDE
8421 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8422 sw_if_index=self.pg0.sw_if_index)
8423 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8424 sw_if_index=self.pg1.sw_if_index)
8425 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
8426 end_addr=self.vrf1_nat_addr,
8427 vrf_id=self.vrf1_id, is_add=1)
8428 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8429 sw_if_index=self.pg2.sw_if_index)
8432 global_pref64 = "2001:db8::"
8433 global_pref64_len = 32
8434 global_pref64_str = "{}/{}".format(global_pref64, global_pref64_len)
8435 self.vapi.nat64_add_del_prefix(prefix=global_pref64_str, vrf_id=0,
8438 prefix = self.vapi.nat64_prefix_dump()
8439 self.assertEqual(len(prefix), 1)
8440 self.assertEqual(str(prefix[0].prefix), global_pref64_str)
8441 self.assertEqual(prefix[0].vrf_id, 0)
8443 # Add tenant specific prefix
8444 vrf1_pref64 = "2001:db8:122:300::"
8445 vrf1_pref64_len = 56
8446 vrf1_pref64_str = "{}/{}".format(vrf1_pref64, vrf1_pref64_len)
8447 self.vapi.nat64_add_del_prefix(prefix=vrf1_pref64_str,
8448 vrf_id=self.vrf1_id, is_add=1)
8450 prefix = self.vapi.nat64_prefix_dump()
8451 self.assertEqual(len(prefix), 2)
8454 pkts = self.create_stream_in_ip6(self.pg0,
8457 plen=global_pref64_len)
8458 self.pg0.add_stream(pkts)
8459 self.pg_enable_capture(self.pg_interfaces)
8461 capture = self.pg1.get_capture(len(pkts))
8462 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8463 dst_ip=self.pg1.remote_ip4)
8465 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8466 self.pg1.add_stream(pkts)
8467 self.pg_enable_capture(self.pg_interfaces)
8469 capture = self.pg0.get_capture(len(pkts))
8470 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8473 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
8475 # Tenant specific prefix
8476 pkts = self.create_stream_in_ip6(self.pg2,
8479 plen=vrf1_pref64_len)
8480 self.pg2.add_stream(pkts)
8481 self.pg_enable_capture(self.pg_interfaces)
8483 capture = self.pg1.get_capture(len(pkts))
8484 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
8485 dst_ip=self.pg1.remote_ip4)
8487 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
8488 self.pg1.add_stream(pkts)
8489 self.pg_enable_capture(self.pg_interfaces)
8491 capture = self.pg2.get_capture(len(pkts))
8492 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8495 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
8497 def test_unknown_proto(self):
8498 """ NAT64 translate packet with unknown protocol """
8500 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8501 end_addr=self.nat_addr,
8504 flags = self.config_flags.NAT_IS_INSIDE
8505 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8506 sw_if_index=self.pg0.sw_if_index)
8507 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8508 sw_if_index=self.pg1.sw_if_index)
8509 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8512 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8513 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
8514 TCP(sport=self.tcp_port_in, dport=20))
8515 self.pg0.add_stream(p)
8516 self.pg_enable_capture(self.pg_interfaces)
8518 p = self.pg1.get_capture(1)
8520 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8521 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
8523 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8524 TCP(sport=1234, dport=1234))
8525 self.pg0.add_stream(p)
8526 self.pg_enable_capture(self.pg_interfaces)
8528 p = self.pg1.get_capture(1)
8531 self.assertEqual(packet[IP].src, self.nat_addr)
8532 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
8533 self.assertEqual(packet.haslayer(GRE), 1)
8534 self.assert_packet_checksums_valid(packet)
8536 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8540 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8541 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8543 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8544 TCP(sport=1234, dport=1234))
8545 self.pg1.add_stream(p)
8546 self.pg_enable_capture(self.pg_interfaces)
8548 p = self.pg0.get_capture(1)
8551 self.assertEqual(packet[IPv6].src, remote_ip6)
8552 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8553 self.assertEqual(packet[IPv6].nh, 47)
8555 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8558 def test_hairpinning_unknown_proto(self):
8559 """ NAT64 translate packet with unknown protocol - hairpinning """
8561 client = self.pg0.remote_hosts[0]
8562 server = self.pg0.remote_hosts[1]
8563 server_tcp_in_port = 22
8564 server_tcp_out_port = 4022
8565 client_tcp_in_port = 1234
8566 client_tcp_out_port = 1235
8567 server_nat_ip = "10.0.0.100"
8568 client_nat_ip = "10.0.0.110"
8569 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
8570 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
8572 self.vapi.nat64_add_del_pool_addr_range(start_addr=server_nat_ip,
8573 end_addr=client_nat_ip,
8576 flags = self.config_flags.NAT_IS_INSIDE
8577 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8578 sw_if_index=self.pg0.sw_if_index)
8579 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8580 sw_if_index=self.pg1.sw_if_index)
8582 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8583 o_addr=server_nat_ip,
8584 i_port=server_tcp_in_port,
8585 o_port=server_tcp_out_port,
8586 proto=IP_PROTOS.tcp, vrf_id=0,
8589 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8590 o_addr=server_nat_ip, i_port=0,
8592 proto=IP_PROTOS.gre, vrf_id=0,
8595 self.vapi.nat64_add_del_static_bib(i_addr=client.ip6n,
8596 o_addr=client_nat_ip,
8597 i_port=client_tcp_in_port,
8598 o_port=client_tcp_out_port,
8599 proto=IP_PROTOS.tcp, vrf_id=0,
8603 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8604 IPv6(src=client.ip6, dst=server_nat_ip6) /
8605 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8606 self.pg0.add_stream(p)
8607 self.pg_enable_capture(self.pg_interfaces)
8609 p = self.pg0.get_capture(1)
8611 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8612 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
8614 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8615 TCP(sport=1234, dport=1234))
8616 self.pg0.add_stream(p)
8617 self.pg_enable_capture(self.pg_interfaces)
8619 p = self.pg0.get_capture(1)
8622 self.assertEqual(packet[IPv6].src, client_nat_ip6)
8623 self.assertEqual(packet[IPv6].dst, server.ip6)
8624 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
8626 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8630 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8631 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
8633 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8634 TCP(sport=1234, dport=1234))
8635 self.pg0.add_stream(p)
8636 self.pg_enable_capture(self.pg_interfaces)
8638 p = self.pg0.get_capture(1)
8641 self.assertEqual(packet[IPv6].src, server_nat_ip6)
8642 self.assertEqual(packet[IPv6].dst, client.ip6)
8643 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
8645 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8648 def test_one_armed_nat64(self):
8649 """ One armed NAT64 """
8651 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
8655 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8656 end_addr=self.nat_addr,
8659 flags = self.config_flags.NAT_IS_INSIDE
8660 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8661 sw_if_index=self.pg3.sw_if_index)
8662 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8663 sw_if_index=self.pg3.sw_if_index)
8666 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8667 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
8668 TCP(sport=12345, dport=80))
8669 self.pg3.add_stream(p)
8670 self.pg_enable_capture(self.pg_interfaces)
8672 capture = self.pg3.get_capture(1)
8677 self.assertEqual(ip.src, self.nat_addr)
8678 self.assertEqual(ip.dst, self.pg3.remote_ip4)
8679 self.assertNotEqual(tcp.sport, 12345)
8680 external_port = tcp.sport
8681 self.assertEqual(tcp.dport, 80)
8682 self.assert_packet_checksums_valid(p)
8684 self.logger.error(ppp("Unexpected or invalid packet:", p))
8688 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8689 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
8690 TCP(sport=80, dport=external_port))
8691 self.pg3.add_stream(p)
8692 self.pg_enable_capture(self.pg_interfaces)
8694 capture = self.pg3.get_capture(1)
8699 self.assertEqual(ip.src, remote_host_ip6)
8700 self.assertEqual(ip.dst, self.pg3.remote_ip6)
8701 self.assertEqual(tcp.sport, 80)
8702 self.assertEqual(tcp.dport, 12345)
8703 self.assert_packet_checksums_valid(p)
8705 self.logger.error(ppp("Unexpected or invalid packet:", p))
8708 def test_frag_in_order(self):
8709 """ NAT64 translate fragments arriving in order """
8710 self.tcp_port_in = random.randint(1025, 65535)
8712 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8713 end_addr=self.nat_addr,
8716 flags = self.config_flags.NAT_IS_INSIDE
8717 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8718 sw_if_index=self.pg0.sw_if_index)
8719 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8720 sw_if_index=self.pg1.sw_if_index)
8722 reass = self.vapi.nat_reass_dump()
8723 reass_n_start = len(reass)
8727 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8728 self.tcp_port_in, 20, data)
8729 self.pg0.add_stream(pkts)
8730 self.pg_enable_capture(self.pg_interfaces)
8732 frags = self.pg1.get_capture(len(pkts))
8733 p = self.reass_frags_and_verify(frags,
8735 self.pg1.remote_ip4)
8736 self.assertEqual(p[TCP].dport, 20)
8737 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8738 self.tcp_port_out = p[TCP].sport
8739 self.assertEqual(data, p[Raw].load)
8742 data = b"A" * 4 + b"b" * 16 + b"C" * 3
8743 pkts = self.create_stream_frag(self.pg1,
8748 self.pg1.add_stream(pkts)
8749 self.pg_enable_capture(self.pg_interfaces)
8751 frags = self.pg0.get_capture(len(pkts))
8752 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8753 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8754 self.assertEqual(p[TCP].sport, 20)
8755 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8756 self.assertEqual(data, p[Raw].load)
8758 reass = self.vapi.nat_reass_dump()
8759 reass_n_end = len(reass)
8761 self.assertEqual(reass_n_end - reass_n_start, 2)
8763 def test_reass_hairpinning(self):
8764 """ NAT64 fragments hairpinning """
8766 server = self.pg0.remote_hosts[1]
8767 server_in_port = random.randint(1025, 65535)
8768 server_out_port = random.randint(1025, 65535)
8769 client_in_port = random.randint(1025, 65535)
8770 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8771 nat_addr_ip6 = ip.src
8773 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8774 end_addr=self.nat_addr,
8777 flags = self.config_flags.NAT_IS_INSIDE
8778 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8779 sw_if_index=self.pg0.sw_if_index)
8780 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8781 sw_if_index=self.pg1.sw_if_index)
8783 # add static BIB entry for server
8784 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8785 o_addr=self.nat_addr,
8786 i_port=server_in_port,
8787 o_port=server_out_port,
8788 proto=IP_PROTOS.tcp, vrf_id=0,
8791 # send packet from host to server
8792 pkts = self.create_stream_frag_ip6(self.pg0,
8797 self.pg0.add_stream(pkts)
8798 self.pg_enable_capture(self.pg_interfaces)
8800 frags = self.pg0.get_capture(len(pkts))
8801 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
8802 self.assertNotEqual(p[TCP].sport, client_in_port)
8803 self.assertEqual(p[TCP].dport, server_in_port)
8804 self.assertEqual(data, p[Raw].load)
8806 def test_frag_out_of_order(self):
8807 """ NAT64 translate fragments arriving out of order """
8808 self.tcp_port_in = random.randint(1025, 65535)
8810 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8811 end_addr=self.nat_addr,
8814 flags = self.config_flags.NAT_IS_INSIDE
8815 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8816 sw_if_index=self.pg0.sw_if_index)
8817 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8818 sw_if_index=self.pg1.sw_if_index)
8822 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8823 self.tcp_port_in, 20, data)
8825 self.pg0.add_stream(pkts)
8826 self.pg_enable_capture(self.pg_interfaces)
8828 frags = self.pg1.get_capture(len(pkts))
8829 p = self.reass_frags_and_verify(frags,
8831 self.pg1.remote_ip4)
8832 self.assertEqual(p[TCP].dport, 20)
8833 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8834 self.tcp_port_out = p[TCP].sport
8835 self.assertEqual(data, p[Raw].load)
8838 data = b"A" * 4 + b"B" * 16 + b"C" * 3
8839 pkts = self.create_stream_frag(self.pg1,
8845 self.pg1.add_stream(pkts)
8846 self.pg_enable_capture(self.pg_interfaces)
8848 frags = self.pg0.get_capture(len(pkts))
8849 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8850 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8851 self.assertEqual(p[TCP].sport, 20)
8852 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8853 self.assertEqual(data, p[Raw].load)
8855 def test_interface_addr(self):
8856 """ Acquire NAT64 pool addresses from interface """
8857 self.vapi.nat64_add_del_interface_addr(
8859 sw_if_index=self.pg4.sw_if_index)
8861 # no address in NAT64 pool
8862 addresses = self.vapi.nat44_address_dump()
8863 self.assertEqual(0, len(addresses))
8865 # configure interface address and check NAT64 address pool
8866 self.pg4.config_ip4()
8867 addresses = self.vapi.nat64_pool_addr_dump()
8868 self.assertEqual(len(addresses), 1)
8870 self.assertEqual(str(addresses[0].address),
8873 # remove interface address and check NAT64 address pool
8874 self.pg4.unconfig_ip4()
8875 addresses = self.vapi.nat64_pool_addr_dump()
8876 self.assertEqual(0, len(addresses))
8878 @unittest.skipUnless(running_extended_tests, "part of extended tests")
8879 def test_ipfix_max_bibs_sessions(self):
8880 """ IPFIX logging maximum session and BIB entries exceeded """
8883 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8887 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8888 end_addr=self.nat_addr,
8891 flags = self.config_flags.NAT_IS_INSIDE
8892 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8893 sw_if_index=self.pg0.sw_if_index)
8894 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8895 sw_if_index=self.pg1.sw_if_index)
8899 for i in range(0, max_bibs):
8900 src = "fd01:aa::%x" % (i)
8901 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8902 IPv6(src=src, dst=remote_host_ip6) /
8903 TCP(sport=12345, dport=80))
8905 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8906 IPv6(src=src, dst=remote_host_ip6) /
8907 TCP(sport=12345, dport=22))
8909 self.pg0.add_stream(pkts)
8910 self.pg_enable_capture(self.pg_interfaces)
8912 self.pg1.get_capture(max_sessions)
8914 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
8915 src_address=self.pg3.local_ip4,
8917 template_interval=10)
8918 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8919 src_port=self.ipfix_src_port,
8922 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8923 IPv6(src=src, dst=remote_host_ip6) /
8924 TCP(sport=12345, dport=25))
8925 self.pg0.add_stream(p)
8926 self.pg_enable_capture(self.pg_interfaces)
8928 self.pg1.assert_nothing_captured()
8930 self.vapi.ipfix_flush()
8931 capture = self.pg3.get_capture(9)
8932 ipfix = IPFIXDecoder()
8933 # first load template
8935 self.assertTrue(p.haslayer(IPFIX))
8936 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8937 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8938 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8939 self.assertEqual(p[UDP].dport, 4739)
8940 self.assertEqual(p[IPFIX].observationDomainID,
8941 self.ipfix_domain_id)
8942 if p.haslayer(Template):
8943 ipfix.add_template(p.getlayer(Template))
8944 # verify events in data set
8946 if p.haslayer(Data):
8947 data = ipfix.decode_data_set(p.getlayer(Set))
8948 self.verify_ipfix_max_sessions(data, max_sessions)
8950 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8951 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8952 TCP(sport=12345, dport=80))
8953 self.pg0.add_stream(p)
8954 self.pg_enable_capture(self.pg_interfaces)
8956 self.pg1.assert_nothing_captured()
8958 self.vapi.ipfix_flush()
8959 capture = self.pg3.get_capture(1)
8960 # verify events in data set
8962 self.assertTrue(p.haslayer(IPFIX))
8963 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8964 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8965 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8966 self.assertEqual(p[UDP].dport, 4739)
8967 self.assertEqual(p[IPFIX].observationDomainID,
8968 self.ipfix_domain_id)
8969 if p.haslayer(Data):
8970 data = ipfix.decode_data_set(p.getlayer(Set))
8971 self.verify_ipfix_max_bibs(data, max_bibs)
8973 def test_ipfix_max_frags(self):
8974 """ IPFIX logging maximum fragments pending reassembly exceeded """
8975 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8976 end_addr=self.nat_addr,
8979 flags = self.config_flags.NAT_IS_INSIDE
8980 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8981 sw_if_index=self.pg0.sw_if_index)
8982 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8983 sw_if_index=self.pg1.sw_if_index)
8984 self.vapi.nat_set_reass(timeout=2, max_reass=1024, max_frag=1,
8985 drop_frag=0, is_ip6=1)
8986 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
8987 src_address=self.pg3.local_ip4,
8989 template_interval=10)
8990 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8991 src_port=self.ipfix_src_port,
8995 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8996 self.tcp_port_in, 20, data)
8998 self.pg0.add_stream(pkts)
8999 self.pg_enable_capture(self.pg_interfaces)
9001 self.pg1.assert_nothing_captured()
9003 self.vapi.ipfix_flush()
9004 capture = self.pg3.get_capture(9)
9005 ipfix = IPFIXDecoder()
9006 # first load template
9008 self.assertTrue(p.haslayer(IPFIX))
9009 self.assertEqual(p[IP].src, self.pg3.local_ip4)
9010 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
9011 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
9012 self.assertEqual(p[UDP].dport, 4739)
9013 self.assertEqual(p[IPFIX].observationDomainID,
9014 self.ipfix_domain_id)
9015 if p.haslayer(Template):
9016 ipfix.add_template(p.getlayer(Template))
9017 # verify events in data set
9019 if p.haslayer(Data):
9020 data = ipfix.decode_data_set(p.getlayer(Set))
9021 self.verify_ipfix_max_fragments_ip6(data, 1,
9022 self.pg0.remote_ip6n)
9024 def test_ipfix_bib_ses(self):
9025 """ IPFIX logging NAT64 BIB/session create and delete events """
9026 self.tcp_port_in = random.randint(1025, 65535)
9027 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
9031 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9032 end_addr=self.nat_addr,
9035 flags = self.config_flags.NAT_IS_INSIDE
9036 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
9037 sw_if_index=self.pg0.sw_if_index)
9038 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
9039 sw_if_index=self.pg1.sw_if_index)
9040 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
9041 src_address=self.pg3.local_ip4,
9043 template_interval=10)
9044 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
9045 src_port=self.ipfix_src_port,
9049 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
9050 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
9051 TCP(sport=self.tcp_port_in, dport=25))
9052 self.pg0.add_stream(p)
9053 self.pg_enable_capture(self.pg_interfaces)
9055 p = self.pg1.get_capture(1)
9056 self.tcp_port_out = p[0][TCP].sport
9057 self.vapi.ipfix_flush()
9058 capture = self.pg3.get_capture(10)
9059 ipfix = IPFIXDecoder()
9060 # first load template
9062 self.assertTrue(p.haslayer(IPFIX))
9063 self.assertEqual(p[IP].src, self.pg3.local_ip4)
9064 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
9065 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
9066 self.assertEqual(p[UDP].dport, 4739)
9067 self.assertEqual(p[IPFIX].observationDomainID,
9068 self.ipfix_domain_id)
9069 if p.haslayer(Template):
9070 ipfix.add_template(p.getlayer(Template))
9071 # verify events in data set
9073 if p.haslayer(Data):
9074 data = ipfix.decode_data_set(p.getlayer(Set))
9075 if scapy.compat.orb(data[0][230]) == 10:
9076 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
9077 elif scapy.compat.orb(data[0][230]) == 6:
9078 self.verify_ipfix_nat64_ses(data,
9080 self.pg0.remote_ip6n,
9081 self.pg1.remote_ip4,
9084 self.logger.error(ppp("Unexpected or invalid packet: ", p))
9087 self.pg_enable_capture(self.pg_interfaces)
9088 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9089 end_addr=self.nat_addr,
9092 self.vapi.ipfix_flush()
9093 capture = self.pg3.get_capture(2)
9094 # verify events in data set
9096 self.assertTrue(p.haslayer(IPFIX))
9097 self.assertEqual(p[IP].src, self.pg3.local_ip4)
9098 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
9099 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
9100 self.assertEqual(p[UDP].dport, 4739)
9101 self.assertEqual(p[IPFIX].observationDomainID,
9102 self.ipfix_domain_id)
9103 if p.haslayer(Data):
9104 data = ipfix.decode_data_set(p.getlayer(Set))
9105 if scapy.compat.orb(data[0][230]) == 11:
9106 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
9107 elif scapy.compat.orb(data[0][230]) == 7:
9108 self.verify_ipfix_nat64_ses(data,
9110 self.pg0.remote_ip6n,
9111 self.pg1.remote_ip4,
9114 self.logger.error(ppp("Unexpected or invalid packet: ", p))
9116 def test_syslog_sess(self):
9117 """ Test syslog session creation and deletion """
9118 self.tcp_port_in = random.randint(1025, 65535)
9119 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
9123 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9124 end_addr=self.nat_addr,
9127 flags = self.config_flags.NAT_IS_INSIDE
9128 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
9129 sw_if_index=self.pg0.sw_if_index)
9130 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
9131 sw_if_index=self.pg1.sw_if_index)
9132 self.vapi.syslog_set_filter(
9133 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
9134 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
9136 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
9137 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
9138 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
9139 self.pg0.add_stream(p)
9140 self.pg_enable_capture(self.pg_interfaces)
9142 p = self.pg1.get_capture(1)
9143 self.tcp_port_out = p[0][TCP].sport
9144 capture = self.pg3.get_capture(1)
9145 self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
9147 self.pg_enable_capture(self.pg_interfaces)
9149 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9150 end_addr=self.nat_addr,
9153 capture = self.pg3.get_capture(1)
9154 self.verify_syslog_sess(capture[0][Raw].load, False, True)
9156 def nat64_get_ses_num(self):
9158 Return number of active NAT64 sessions.
9160 st = self.vapi.nat64_st_dump(proto=255)
9163 def clear_nat64(self):
9165 Clear NAT64 configuration.
9167 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
9168 src_port=self.ipfix_src_port,
9170 self.ipfix_src_port = 4739
9171 self.ipfix_domain_id = 1
9173 self.vapi.syslog_set_filter(
9174 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_EMERG)
9176 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
9177 tcp_transitory=240, icmp=60)
9179 interfaces = self.vapi.nat64_interface_dump()
9180 for intf in interfaces:
9181 self.vapi.nat64_add_del_interface(is_add=0, flags=intf.flags,
9182 sw_if_index=intf.sw_if_index)
9184 bib = self.vapi.nat64_bib_dump(proto=255)
9186 if bibe.flags & self.config_flags.NAT_IS_STATIC:
9187 self.vapi.nat64_add_del_static_bib(i_addr=bibe.i_addr,
9195 adresses = self.vapi.nat64_pool_addr_dump()
9196 for addr in adresses:
9197 self.vapi.nat64_add_del_pool_addr_range(start_addr=addr.address,
9198 end_addr=addr.address,
9202 prefixes = self.vapi.nat64_prefix_dump()
9203 for prefix in prefixes:
9204 self.vapi.nat64_add_del_prefix(prefix=str(prefix.prefix),
9205 vrf_id=prefix.vrf_id, is_add=0)
9207 bibs = self.statistics.get_counter('/nat64/total-bibs')
9208 self.assertEqual(bibs[0][0], 0)
9209 sessions = self.statistics.get_counter('/nat64/total-sessions')
9210 self.assertEqual(sessions[0][0], 0)
9213 super(TestNAT64, self).tearDown()
9214 if not self.vpp_dead:
9217 def show_commands_at_teardown(self):
9218 self.logger.info(self.vapi.cli("show nat64 pool"))
9219 self.logger.info(self.vapi.cli("show nat64 interfaces"))
9220 self.logger.info(self.vapi.cli("show nat64 prefix"))
9221 self.logger.info(self.vapi.cli("show nat64 bib all"))
9222 self.logger.info(self.vapi.cli("show nat64 session table all"))
9223 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
9226 class TestDSlite(MethodHolder):
9227 """ DS-Lite Test Cases """
9230 def setUpClass(cls):
9231 super(TestDSlite, cls).setUpClass()
9234 cls.nat_addr = '10.0.0.3'
9236 cls.create_pg_interfaces(range(3))
9238 cls.pg0.config_ip4()
9239 cls.pg0.resolve_arp()
9241 cls.pg1.config_ip6()
9242 cls.pg1.generate_remote_hosts(2)
9243 cls.pg1.configure_ipv6_neighbors()
9245 cls.pg2.config_ip4()
9246 cls.pg2.resolve_arp()
9249 super(TestDSlite, cls).tearDownClass()
9253 def tearDownClass(cls):
9254 super(TestDSlite, cls).tearDownClass()
9256 def verify_syslog_apmadd(self, data, isaddr, isport, xsaddr, xsport,
9258 message = data.decode('utf-8')
9260 message = SyslogMessage.parse(message)
9261 except ParseError as e:
9262 self.logger.error(e)
9264 self.assertEqual(message.severity, SyslogSeverity.info)
9265 self.assertEqual(message.appname, 'NAT')
9266 self.assertEqual(message.msgid, 'APMADD')
9267 sd_params = message.sd.get('napmap')
9268 self.assertTrue(sd_params is not None)
9269 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
9270 self.assertEqual(sd_params.get('ISADDR'), isaddr)
9271 self.assertEqual(sd_params.get('ISPORT'), "%d" % isport)
9272 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
9273 self.assertEqual(sd_params.get('XSADDR'), xsaddr)
9274 self.assertEqual(sd_params.get('XSPORT'), "%d" % xsport)
9275 self.assertEqual(sd_params.get('PROTO'), "%d" % proto)
9276 self.assertTrue(sd_params.get('SSUBIX') is not None)
9277 self.assertEqual(sd_params.get('SV6ENC'), sv6enc)
9279 def test_dslite(self):
9280 """ Test DS-Lite """
9281 nat_config = self.vapi.nat_show_config()
9282 self.assertEqual(0, nat_config.dslite_ce)
9284 self.vapi.dslite_add_del_pool_addr_range(start_addr=self.nat_addr,
9285 end_addr=self.nat_addr,
9287 aftr_ip4 = '192.0.0.1'
9288 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
9289 self.vapi.dslite_set_aftr_addr(ip4_addr=aftr_ip4, ip6_addr=aftr_ip6)
9290 self.vapi.syslog_set_sender(self.pg2.local_ip4, self.pg2.remote_ip4)
9293 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9294 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
9295 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
9296 UDP(sport=20000, dport=10000))
9297 self.pg1.add_stream(p)
9298 self.pg_enable_capture(self.pg_interfaces)
9300 capture = self.pg0.get_capture(1)
9301 capture = capture[0]
9302 self.assertFalse(capture.haslayer(IPv6))
9303 self.assertEqual(capture[IP].src, self.nat_addr)
9304 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
9305 self.assertNotEqual(capture[UDP].sport, 20000)
9306 self.assertEqual(capture[UDP].dport, 10000)
9307 self.assert_packet_checksums_valid(capture)
9308 out_port = capture[UDP].sport
9309 capture = self.pg2.get_capture(1)
9310 self.verify_syslog_apmadd(capture[0][Raw].load, '192.168.1.1',
9311 20000, self.nat_addr, out_port,
9312 self.pg1.remote_hosts[0].ip6, IP_PROTOS.udp)
9314 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9315 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
9316 UDP(sport=10000, dport=out_port))
9317 self.pg0.add_stream(p)
9318 self.pg_enable_capture(self.pg_interfaces)
9320 capture = self.pg1.get_capture(1)
9321 capture = capture[0]
9322 self.assertEqual(capture[IPv6].src, aftr_ip6)
9323 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
9324 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
9325 self.assertEqual(capture[IP].dst, '192.168.1.1')
9326 self.assertEqual(capture[UDP].sport, 10000)
9327 self.assertEqual(capture[UDP].dport, 20000)
9328 self.assert_packet_checksums_valid(capture)
9331 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9332 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
9333 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
9334 TCP(sport=20001, dport=10001))
9335 self.pg1.add_stream(p)
9336 self.pg_enable_capture(self.pg_interfaces)
9338 capture = self.pg0.get_capture(1)
9339 capture = capture[0]
9340 self.assertFalse(capture.haslayer(IPv6))
9341 self.assertEqual(capture[IP].src, self.nat_addr)
9342 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
9343 self.assertNotEqual(capture[TCP].sport, 20001)
9344 self.assertEqual(capture[TCP].dport, 10001)
9345 self.assert_packet_checksums_valid(capture)
9346 out_port = capture[TCP].sport
9348 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9349 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
9350 TCP(sport=10001, dport=out_port))
9351 self.pg0.add_stream(p)
9352 self.pg_enable_capture(self.pg_interfaces)
9354 capture = self.pg1.get_capture(1)
9355 capture = capture[0]
9356 self.assertEqual(capture[IPv6].src, aftr_ip6)
9357 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
9358 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
9359 self.assertEqual(capture[IP].dst, '192.168.1.1')
9360 self.assertEqual(capture[TCP].sport, 10001)
9361 self.assertEqual(capture[TCP].dport, 20001)
9362 self.assert_packet_checksums_valid(capture)
9365 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9366 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
9367 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
9368 ICMP(id=4000, type='echo-request'))
9369 self.pg1.add_stream(p)
9370 self.pg_enable_capture(self.pg_interfaces)
9372 capture = self.pg0.get_capture(1)
9373 capture = capture[0]
9374 self.assertFalse(capture.haslayer(IPv6))
9375 self.assertEqual(capture[IP].src, self.nat_addr)
9376 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
9377 self.assertNotEqual(capture[ICMP].id, 4000)
9378 self.assert_packet_checksums_valid(capture)
9379 out_id = capture[ICMP].id
9381 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9382 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
9383 ICMP(id=out_id, type='echo-reply'))
9384 self.pg0.add_stream(p)
9385 self.pg_enable_capture(self.pg_interfaces)
9387 capture = self.pg1.get_capture(1)
9388 capture = capture[0]
9389 self.assertEqual(capture[IPv6].src, aftr_ip6)
9390 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
9391 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
9392 self.assertEqual(capture[IP].dst, '192.168.1.1')
9393 self.assertEqual(capture[ICMP].id, 4000)
9394 self.assert_packet_checksums_valid(capture)
9396 # ping DS-Lite AFTR tunnel endpoint address
9397 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9398 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
9399 ICMPv6EchoRequest())
9400 self.pg1.add_stream(p)
9401 self.pg_enable_capture(self.pg_interfaces)
9403 capture = self.pg1.get_capture(1)
9404 capture = capture[0]
9405 self.assertEqual(capture[IPv6].src, aftr_ip6)
9406 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
9407 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
9409 b4s = self.statistics.get_counter('/dslite/total-b4s')
9410 self.assertEqual(b4s[0][0], 2)
9411 sessions = self.statistics.get_counter('/dslite/total-sessions')
9412 self.assertEqual(sessions[0][0], 3)
9415 super(TestDSlite, self).tearDown()
9417 def show_commands_at_teardown(self):
9418 self.logger.info(self.vapi.cli("show dslite pool"))
9420 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
9421 self.logger.info(self.vapi.cli("show dslite sessions"))
9424 class TestDSliteCE(MethodHolder):
9425 """ DS-Lite CE Test Cases """
9428 def setUpConstants(cls):
9429 super(TestDSliteCE, cls).setUpConstants()
9430 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
9433 def setUpClass(cls):
9434 super(TestDSliteCE, cls).setUpClass()
9437 cls.create_pg_interfaces(range(2))
9439 cls.pg0.config_ip4()
9440 cls.pg0.resolve_arp()
9442 cls.pg1.config_ip6()
9443 cls.pg1.generate_remote_hosts(1)
9444 cls.pg1.configure_ipv6_neighbors()
9447 super(TestDSliteCE, cls).tearDownClass()
9451 def tearDownClass(cls):
9452 super(TestDSliteCE, cls).tearDownClass()
9454 def test_dslite_ce(self):
9455 """ Test DS-Lite CE """
9457 nat_config = self.vapi.nat_show_config()
9458 self.assertEqual(1, nat_config.dslite_ce)
9460 b4_ip4 = '192.0.0.2'
9461 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
9462 self.vapi.dslite_set_b4_addr(ip4_addr=b4_ip4, ip6_addr=b4_ip6)
9464 aftr_ip4 = '192.0.0.1'
9465 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
9466 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
9467 self.vapi.dslite_set_aftr_addr(ip4_addr=aftr_ip4, ip6_addr=aftr_ip6)
9469 r1 = VppIpRoute(self, aftr_ip6, 128,
9470 [VppRoutePath(self.pg1.remote_ip6,
9471 self.pg1.sw_if_index)])
9475 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9476 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
9477 UDP(sport=10000, dport=20000))
9478 self.pg0.add_stream(p)
9479 self.pg_enable_capture(self.pg_interfaces)
9481 capture = self.pg1.get_capture(1)
9482 capture = capture[0]
9483 self.assertEqual(capture[IPv6].src, b4_ip6)
9484 self.assertEqual(capture[IPv6].dst, aftr_ip6)
9485 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
9486 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
9487 self.assertEqual(capture[UDP].sport, 10000)
9488 self.assertEqual(capture[UDP].dport, 20000)
9489 self.assert_packet_checksums_valid(capture)
9492 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9493 IPv6(dst=b4_ip6, src=aftr_ip6) /
9494 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
9495 UDP(sport=20000, dport=10000))
9496 self.pg1.add_stream(p)
9497 self.pg_enable_capture(self.pg_interfaces)
9499 capture = self.pg0.get_capture(1)
9500 capture = capture[0]
9501 self.assertFalse(capture.haslayer(IPv6))
9502 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
9503 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
9504 self.assertEqual(capture[UDP].sport, 20000)
9505 self.assertEqual(capture[UDP].dport, 10000)
9506 self.assert_packet_checksums_valid(capture)
9508 # ping DS-Lite B4 tunnel endpoint address
9509 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9510 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
9511 ICMPv6EchoRequest())
9512 self.pg1.add_stream(p)
9513 self.pg_enable_capture(self.pg_interfaces)
9515 capture = self.pg1.get_capture(1)
9516 capture = capture[0]
9517 self.assertEqual(capture[IPv6].src, b4_ip6)
9518 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
9519 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
9522 super(TestDSliteCE, self).tearDown()
9524 def show_commands_at_teardown(self):
9526 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
9528 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
9531 class TestNAT66(MethodHolder):
9532 """ NAT66 Test Cases """
9535 def setUpClass(cls):
9536 super(TestNAT66, cls).setUpClass()
9539 cls.nat_addr = 'fd01:ff::2'
9541 cls.create_pg_interfaces(range(2))
9542 cls.interfaces = list(cls.pg_interfaces)
9544 for i in cls.interfaces:
9547 i.configure_ipv6_neighbors()
9550 super(TestNAT66, cls).tearDownClass()
9554 def tearDownClass(cls):
9555 super(TestNAT66, cls).tearDownClass()
9557 def test_static(self):
9558 """ 1:1 NAT66 test """
9559 flags = self.config_flags.NAT_IS_INSIDE
9560 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9561 sw_if_index=self.pg0.sw_if_index)
9562 self.vapi.nat66_add_del_interface(is_add=1,
9563 sw_if_index=self.pg1.sw_if_index)
9564 self.vapi.nat66_add_del_static_mapping(
9565 local_ip_address=self.pg0.remote_ip6n,
9566 external_ip_address=self.nat_addr,
9571 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9572 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9575 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9576 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9579 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9580 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9581 ICMPv6EchoRequest())
9583 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9584 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9585 GRE() / IP() / TCP())
9587 self.pg0.add_stream(pkts)
9588 self.pg_enable_capture(self.pg_interfaces)
9590 capture = self.pg1.get_capture(len(pkts))
9591 for packet in capture:
9593 self.assertEqual(packet[IPv6].src, self.nat_addr)
9594 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9595 self.assert_packet_checksums_valid(packet)
9597 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9602 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9603 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9606 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9607 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9610 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9611 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9614 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9615 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9616 GRE() / IP() / TCP())
9618 self.pg1.add_stream(pkts)
9619 self.pg_enable_capture(self.pg_interfaces)
9621 capture = self.pg0.get_capture(len(pkts))
9622 for packet in capture:
9624 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
9625 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
9626 self.assert_packet_checksums_valid(packet)
9628 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9631 sm = self.vapi.nat66_static_mapping_dump()
9632 self.assertEqual(len(sm), 1)
9633 self.assertEqual(sm[0].total_pkts, 8)
9635 def test_check_no_translate(self):
9636 """ NAT66 translate only when egress interface is outside interface """
9637 flags = self.config_flags.NAT_IS_INSIDE
9638 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9639 sw_if_index=self.pg0.sw_if_index)
9640 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9641 sw_if_index=self.pg1.sw_if_index)
9642 self.vapi.nat66_add_del_static_mapping(
9643 local_ip_address=self.pg0.remote_ip6n,
9644 external_ip_address=self.nat_addr,
9648 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9649 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9651 self.pg0.add_stream([p])
9652 self.pg_enable_capture(self.pg_interfaces)
9654 capture = self.pg1.get_capture(1)
9657 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
9658 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9660 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9663 def clear_nat66(self):
9665 Clear NAT66 configuration.
9667 interfaces = self.vapi.nat66_interface_dump()
9668 for intf in interfaces:
9669 self.vapi.nat66_add_del_interface(is_add=0, flags=intf.flags,
9670 sw_if_index=intf.sw_if_index)
9672 static_mappings = self.vapi.nat66_static_mapping_dump()
9673 for sm in static_mappings:
9674 self.vapi.nat66_add_del_static_mapping(
9675 local_ip_address=sm.local_ip_address,
9676 external_ip_address=sm.external_ip_address, vrf_id=sm.vrf_id,
9680 super(TestNAT66, self).tearDown()
9683 def show_commands_at_teardown(self):
9684 self.logger.info(self.vapi.cli("show nat66 interfaces"))
9685 self.logger.info(self.vapi.cli("show nat66 static mappings"))
9688 if __name__ == '__main__':
9689 unittest.main(testRunner=VppTestRunner)