8 from framework import VppTestCase, VppTestRunner, running_extended_tests
11 from scapy.layers.inet import IP, TCP, UDP, ICMP
12 from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
13 from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply, \
14 ICMPv6ND_NS, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr, fragment6
15 from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
16 from scapy.layers.l2 import Ether, ARP, GRE
17 from scapy.data import IP_PROTOS
18 from scapy.packet import bind_layers, Raw
20 from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
21 from time import sleep
22 from util import ip4_range
23 from vpp_papi import mac_pton
24 from syslog_rfc5424_parser import SyslogMessage, ParseError
25 from syslog_rfc5424_parser.constants import SyslogFacility, SyslogSeverity
26 from io import BytesIO
27 from vpp_papi import VppEnum
28 from vpp_ip_route import VppIpRoute, VppRoutePath, FibPathType
29 from vpp_neighbor import VppNeighbor
30 from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \
31 IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \
33 from ipaddress import IPv6Network
34 from util import ppc, ppp
35 from socket import inet_pton, AF_INET
38 # NAT HA protocol event data
41 fields_desc = [ByteEnumField("event_type", None,
42 {1: "add", 2: "del", 3: "refresh"}),
43 ByteEnumField("protocol", None,
44 {0: "udp", 1: "tcp", 2: "icmp"}),
45 ShortField("flags", 0),
46 IPField("in_addr", None),
47 IPField("out_addr", None),
48 ShortField("in_port", None),
49 ShortField("out_port", None),
50 IPField("eh_addr", None),
51 IPField("ehn_addr", None),
52 ShortField("eh_port", None),
53 ShortField("ehn_port", None),
54 IntField("fib_index", None),
55 IntField("total_pkts", 0),
56 LongField("total_bytes", 0)]
58 def extract_padding(self, s):
62 # NAT HA protocol header
63 class HANATStateSync(Packet):
64 name = "HA NAT state sync"
65 fields_desc = [XByteField("version", 1),
66 FlagsField("flags", 0, 8, ['ACK']),
67 FieldLenField("count", None, count_of="events"),
68 IntField("sequence_number", 1),
69 IntField("thread_index", 0),
70 PacketListField("events", [], Event,
71 count_from=lambda pkt: pkt.count)]
74 class MethodHolder(VppTestCase):
75 """ NAT create capture and verify method holder """
78 def config_flags(self):
79 return VppEnum.vl_api_nat_config_flags_t
82 def SYSLOG_SEVERITY(self):
83 return VppEnum.vl_api_syslog_severity_t
85 def clear_nat44(self):
87 Clear NAT44 configuration.
89 if hasattr(self, 'pg7') and hasattr(self, 'pg8'):
90 if self.pg7.has_ip4_config:
91 self.pg7.unconfig_ip4()
93 self.vapi.nat44_forwarding_enable_disable(enable=0)
95 interfaces = self.vapi.nat44_interface_addr_dump()
96 for intf in interfaces:
97 self.vapi.nat44_add_del_interface_addr(
99 sw_if_index=intf.sw_if_index,
102 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
103 src_port=self.ipfix_src_port,
105 self.ipfix_src_port = 4739
106 self.ipfix_domain_id = 1
108 self.vapi.syslog_set_filter(
109 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_EMERG)
111 self.vapi.nat_ha_set_listener(ip_address='0.0.0.0', port=0,
113 self.vapi.nat_ha_set_failover(ip_address='0.0.0.0', port=0,
114 session_refresh_interval=10)
116 interfaces = self.vapi.nat44_interface_dump()
117 for intf in interfaces:
118 if intf.flags & self.config_flags.NAT_IS_INSIDE and \
119 intf.flags & self.config_flags.NAT_IS_OUTSIDE:
120 self.vapi.nat44_interface_add_del_feature(
121 sw_if_index=intf.sw_if_index)
122 self.vapi.nat44_interface_add_del_feature(
123 sw_if_index=intf.sw_if_index,
126 interfaces = self.vapi.nat44_interface_output_feature_dump()
127 for intf in interfaces:
128 self.vapi.nat44_interface_add_del_output_feature(
131 sw_if_index=intf.sw_if_index)
132 static_mappings = self.vapi.nat44_static_mapping_dump()
133 for sm in static_mappings:
134 self.vapi.nat44_add_del_static_mapping(
136 local_ip_address=sm.local_ip_address,
137 external_ip_address=sm.external_ip_address,
138 external_sw_if_index=sm.external_sw_if_index,
139 local_port=sm.local_port,
140 external_port=sm.external_port,
142 protocol=sm.protocol,
143 flags=sm.flags, tag=sm.tag)
145 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
146 for lb_sm in lb_static_mappings:
147 self.vapi.nat44_add_del_lb_static_mapping(
150 external_addr=lb_sm.external_addr,
151 external_port=lb_sm.external_port,
152 protocol=lb_sm.protocol,
153 local_num=0, locals=[],
156 identity_mappings = self.vapi.nat44_identity_mapping_dump()
157 for id_m in identity_mappings:
158 self.vapi.nat44_add_del_identity_mapping(
159 ip_address=id_m.ip_address,
160 sw_if_index=id_m.sw_if_index,
164 protocol=id_m.protocol)
166 addresses = self.vapi.nat44_address_dump()
167 for addr in addresses:
168 self.vapi.nat44_add_del_address_range(
169 first_ip_address=addr.ip_address,
170 last_ip_address=addr.ip_address,
171 vrf_id=0xFFFFFFFF, flags=addr.flags)
173 self.verify_no_nat44_user()
174 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
175 tcp_transitory=240, icmp=60)
176 self.vapi.nat_set_addr_and_port_alloc_alg()
177 self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
179 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
180 local_port=0, external_port=0, vrf_id=0,
181 is_add=1, external_sw_if_index=0xFFFFFFFF,
182 proto=0, tag="", flags=0):
184 Add/delete NAT44 static mapping
186 :param local_ip: Local IP address
187 :param external_ip: External IP address
188 :param local_port: Local port number (Optional)
189 :param external_port: External port number (Optional)
190 :param vrf_id: VRF ID (Default 0)
191 :param is_add: 1 if add, 0 if delete (Default add)
192 :param external_sw_if_index: External interface instead of IP address
193 :param proto: IP protocol (Mandatory if port specified)
194 :param tag: Opaque string tag
195 :param flags: NAT configuration flags
198 if not (local_port and external_port):
199 flags |= self.config_flags.NAT_IS_ADDR_ONLY
201 self.vapi.nat44_add_del_static_mapping(
203 local_ip_address=local_ip,
204 external_ip_address=external_ip,
205 external_sw_if_index=external_sw_if_index,
206 local_port=local_port,
207 external_port=external_port,
208 vrf_id=vrf_id, protocol=proto,
212 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
214 Add/delete NAT44 address
216 :param ip: IP address
217 :param is_add: 1 if add, 0 if delete (Default add)
218 :param twice_nat: twice NAT address for external hosts
220 flags = self.config_flags.NAT_IS_TWICE_NAT if twice_nat else 0
221 self.vapi.nat44_add_del_address_range(first_ip_address=ip,
227 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
229 Create packet stream for inside network
231 :param in_if: Inside interface
232 :param out_if: Outside interface
233 :param dst_ip: Destination address
234 :param ttl: TTL of generated packets
237 dst_ip = out_if.remote_ip4
241 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
242 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
243 TCP(sport=self.tcp_port_in, dport=20))
247 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
248 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
249 UDP(sport=self.udp_port_in, dport=20))
253 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
254 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
255 ICMP(id=self.icmp_id_in, type='echo-request'))
260 def compose_ip6(self, ip4, pref, plen):
262 Compose IPv4-embedded IPv6 addresses
264 :param ip4: IPv4 address
265 :param pref: IPv6 prefix
266 :param plen: IPv6 prefix length
267 :returns: IPv4-embedded IPv6 addresses
269 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
270 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
285 pref_n[10] = ip4_n[3]
289 pref_n[10] = ip4_n[2]
290 pref_n[11] = ip4_n[3]
293 pref_n[10] = ip4_n[1]
294 pref_n[11] = ip4_n[2]
295 pref_n[12] = ip4_n[3]
297 pref_n[12] = ip4_n[0]
298 pref_n[13] = ip4_n[1]
299 pref_n[14] = ip4_n[2]
300 pref_n[15] = ip4_n[3]
301 packed_pref_n = b''.join([scapy.compat.chb(x) for x in pref_n])
302 return socket.inet_ntop(socket.AF_INET6, packed_pref_n)
304 def extract_ip4(self, ip6, plen):
306 Extract IPv4 address embedded in IPv6 addresses
308 :param ip6: IPv6 address
309 :param plen: IPv6 prefix length
310 :returns: extracted IPv4 address
312 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
344 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
346 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
348 Create IPv6 packet stream for inside network
350 :param in_if: Inside interface
351 :param out_if: Outside interface
352 :param ttl: Hop Limit of generated packets
353 :param pref: NAT64 prefix
354 :param plen: NAT64 prefix length
358 dst = ''.join(['64:ff9b::', out_if.remote_ip4])
360 dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
363 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
364 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
365 TCP(sport=self.tcp_port_in, dport=20))
369 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
370 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
371 UDP(sport=self.udp_port_in, dport=20))
375 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
376 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
377 ICMPv6EchoRequest(id=self.icmp_id_in))
382 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
383 use_inside_ports=False):
385 Create packet stream for outside network
387 :param out_if: Outside interface
388 :param dst_ip: Destination IP address (Default use global NAT address)
389 :param ttl: TTL of generated packets
390 :param use_inside_ports: Use inside NAT ports as destination ports
391 instead of outside ports
394 dst_ip = self.nat_addr
395 if not use_inside_ports:
396 tcp_port = self.tcp_port_out
397 udp_port = self.udp_port_out
398 icmp_id = self.icmp_id_out
400 tcp_port = self.tcp_port_in
401 udp_port = self.udp_port_in
402 icmp_id = self.icmp_id_in
405 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
406 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
407 TCP(dport=tcp_port, sport=20))
411 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
412 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
413 UDP(dport=udp_port, sport=20))
417 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
418 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
419 ICMP(id=icmp_id, type='echo-reply'))
424 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
426 Create packet stream for outside network
428 :param out_if: Outside interface
429 :param dst_ip: Destination IP address (Default use global NAT address)
430 :param hl: HL of generated packets
434 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
435 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
436 TCP(dport=self.tcp_port_out, sport=20))
440 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
441 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
442 UDP(dport=self.udp_port_out, sport=20))
446 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
447 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
448 ICMPv6EchoReply(id=self.icmp_id_out))
453 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
454 dst_ip=None, is_ip6=False):
456 Verify captured packets on outside network
458 :param capture: Captured packets
459 :param nat_ip: Translated IP address (Default use global NAT address)
460 :param same_port: Source port number is not translated (Default False)
461 :param dst_ip: Destination IP address (Default do not verify)
462 :param is_ip6: If L3 protocol is IPv6 (Default False)
466 ICMP46 = ICMPv6EchoRequest
471 nat_ip = self.nat_addr
472 for packet in capture:
475 self.assert_packet_checksums_valid(packet)
476 self.assertEqual(packet[IP46].src, nat_ip)
477 if dst_ip is not None:
478 self.assertEqual(packet[IP46].dst, dst_ip)
479 if packet.haslayer(TCP):
481 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
484 packet[TCP].sport, self.tcp_port_in)
485 self.tcp_port_out = packet[TCP].sport
486 self.assert_packet_checksums_valid(packet)
487 elif packet.haslayer(UDP):
489 self.assertEqual(packet[UDP].sport, self.udp_port_in)
492 packet[UDP].sport, self.udp_port_in)
493 self.udp_port_out = packet[UDP].sport
496 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
498 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
499 self.icmp_id_out = packet[ICMP46].id
500 self.assert_packet_checksums_valid(packet)
502 self.logger.error(ppp("Unexpected or invalid packet "
503 "(outside network):", packet))
506 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
509 Verify captured packets on outside network
511 :param capture: Captured packets
512 :param nat_ip: Translated IP address
513 :param same_port: Source port number is not translated (Default False)
514 :param dst_ip: Destination IP address (Default do not verify)
516 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
519 def verify_capture_in(self, capture, in_if):
521 Verify captured packets on inside network
523 :param capture: Captured packets
524 :param in_if: Inside interface
526 for packet in capture:
528 self.assert_packet_checksums_valid(packet)
529 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
530 if packet.haslayer(TCP):
531 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
532 elif packet.haslayer(UDP):
533 self.assertEqual(packet[UDP].dport, self.udp_port_in)
535 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
537 self.logger.error(ppp("Unexpected or invalid packet "
538 "(inside network):", packet))
541 def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
543 Verify captured IPv6 packets on inside network
545 :param capture: Captured packets
546 :param src_ip: Source IP
547 :param dst_ip: Destination IP address
549 for packet in capture:
551 self.assertEqual(packet[IPv6].src, src_ip)
552 self.assertEqual(packet[IPv6].dst, dst_ip)
553 self.assert_packet_checksums_valid(packet)
554 if packet.haslayer(TCP):
555 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
556 elif packet.haslayer(UDP):
557 self.assertEqual(packet[UDP].dport, self.udp_port_in)
559 self.assertEqual(packet[ICMPv6EchoReply].id,
562 self.logger.error(ppp("Unexpected or invalid packet "
563 "(inside network):", packet))
566 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
568 Verify captured packet that don't have to be translated
570 :param capture: Captured packets
571 :param ingress_if: Ingress interface
572 :param egress_if: Egress interface
574 for packet in capture:
576 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
577 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
578 if packet.haslayer(TCP):
579 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
580 elif packet.haslayer(UDP):
581 self.assertEqual(packet[UDP].sport, self.udp_port_in)
583 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
585 self.logger.error(ppp("Unexpected or invalid packet "
586 "(inside network):", packet))
589 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
592 Verify captured packets with ICMP errors on outside network
594 :param capture: Captured packets
595 :param src_ip: Translated IP address or IP address of VPP
596 (Default use global NAT address)
597 :param icmp_type: Type of error ICMP packet
598 we are expecting (Default 11)
601 src_ip = self.nat_addr
602 for packet in capture:
604 self.assertEqual(packet[IP].src, src_ip)
605 self.assertEqual(packet.haslayer(ICMP), 1)
607 self.assertEqual(icmp.type, icmp_type)
608 self.assertTrue(icmp.haslayer(IPerror))
609 inner_ip = icmp[IPerror]
610 if inner_ip.haslayer(TCPerror):
611 self.assertEqual(inner_ip[TCPerror].dport,
613 elif inner_ip.haslayer(UDPerror):
614 self.assertEqual(inner_ip[UDPerror].dport,
617 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
619 self.logger.error(ppp("Unexpected or invalid packet "
620 "(outside network):", packet))
623 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
625 Verify captured packets with ICMP errors on inside network
627 :param capture: Captured packets
628 :param in_if: Inside interface
629 :param icmp_type: Type of error ICMP packet
630 we are expecting (Default 11)
632 for packet in capture:
634 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
635 self.assertEqual(packet.haslayer(ICMP), 1)
637 self.assertEqual(icmp.type, icmp_type)
638 self.assertTrue(icmp.haslayer(IPerror))
639 inner_ip = icmp[IPerror]
640 if inner_ip.haslayer(TCPerror):
641 self.assertEqual(inner_ip[TCPerror].sport,
643 elif inner_ip.haslayer(UDPerror):
644 self.assertEqual(inner_ip[UDPerror].sport,
647 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
649 self.logger.error(ppp("Unexpected or invalid packet "
650 "(inside network):", packet))
653 def create_stream_frag(self, src_if, dst, sport, dport, data,
654 proto=IP_PROTOS.tcp, echo_reply=False):
656 Create fragmented packet stream
658 :param src_if: Source interface
659 :param dst: Destination IPv4 address
660 :param sport: Source port
661 :param dport: Destination port
662 :param data: Payload data
663 :param proto: protocol (TCP, UDP, ICMP)
664 :param echo_reply: use echo_reply if protocol is ICMP
667 if proto == IP_PROTOS.tcp:
668 p = (IP(src=src_if.remote_ip4, dst=dst) /
669 TCP(sport=sport, dport=dport) /
671 p = p.__class__(scapy.compat.raw(p))
672 chksum = p[TCP].chksum
673 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
674 elif proto == IP_PROTOS.udp:
675 proto_header = UDP(sport=sport, dport=dport)
676 elif proto == IP_PROTOS.icmp:
678 proto_header = ICMP(id=sport, type='echo-request')
680 proto_header = ICMP(id=sport, type='echo-reply')
682 raise Exception("Unsupported protocol")
683 id = random.randint(0, 65535)
685 if proto == IP_PROTOS.tcp:
688 raw = Raw(data[0:16])
689 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
690 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
694 if proto == IP_PROTOS.tcp:
695 raw = Raw(data[4:20])
697 raw = Raw(data[16:32])
698 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
699 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
703 if proto == IP_PROTOS.tcp:
707 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
708 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
714 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
715 pref=None, plen=0, frag_size=128):
717 Create fragmented packet stream
719 :param src_if: Source interface
720 :param dst: Destination IPv4 address
721 :param sport: Source TCP port
722 :param dport: Destination TCP port
723 :param data: Payload data
724 :param pref: NAT64 prefix
725 :param plen: NAT64 prefix length
726 :param fragsize: size of fragments
730 dst_ip6 = ''.join(['64:ff9b::', dst])
732 dst_ip6 = self.compose_ip6(dst, pref, plen)
734 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
735 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
736 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
737 TCP(sport=sport, dport=dport) /
740 return fragment6(p, frag_size)
742 def reass_frags_and_verify(self, frags, src, dst):
744 Reassemble and verify fragmented packet
746 :param frags: Captured fragments
747 :param src: Source IPv4 address to verify
748 :param dst: Destination IPv4 address to verify
750 :returns: Reassembled IPv4 packet
754 self.assertEqual(p[IP].src, src)
755 self.assertEqual(p[IP].dst, dst)
756 self.assert_ip_checksum_valid(p)
757 buffer.seek(p[IP].frag * 8)
758 buffer.write(bytes(p[IP].payload))
759 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
760 proto=frags[0][IP].proto)
761 if ip.proto == IP_PROTOS.tcp:
762 p = (ip / TCP(buffer.getvalue()))
763 self.logger.debug(ppp("Reassembled:", p))
764 self.assert_tcp_checksum_valid(p)
765 elif ip.proto == IP_PROTOS.udp:
766 p = (ip / UDP(buffer.getvalue()[:8]) /
767 Raw(buffer.getvalue()[8:]))
768 elif ip.proto == IP_PROTOS.icmp:
769 p = (ip / ICMP(buffer.getvalue()))
772 def reass_frags_and_verify_ip6(self, frags, src, dst):
774 Reassemble and verify fragmented packet
776 :param frags: Captured fragments
777 :param src: Source IPv6 address to verify
778 :param dst: Destination IPv6 address to verify
780 :returns: Reassembled IPv6 packet
784 self.assertEqual(p[IPv6].src, src)
785 self.assertEqual(p[IPv6].dst, dst)
786 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
787 buffer.write(bytes(p[IPv6ExtHdrFragment].payload))
788 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
789 nh=frags[0][IPv6ExtHdrFragment].nh)
790 if ip.nh == IP_PROTOS.tcp:
791 p = (ip / TCP(buffer.getvalue()))
792 elif ip.nh == IP_PROTOS.udp:
793 p = (ip / UDP(buffer.getvalue()))
794 self.logger.debug(ppp("Reassembled:", p))
795 self.assert_packet_checksums_valid(p)
798 def initiate_tcp_session(self, in_if, out_if):
800 Initiates TCP session
802 :param in_if: Inside interface
803 :param out_if: Outside interface
807 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
808 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
809 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
812 self.pg_enable_capture(self.pg_interfaces)
814 capture = out_if.get_capture(1)
816 self.tcp_port_out = p[TCP].sport
818 # SYN + ACK packet out->in
819 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
820 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
821 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
824 self.pg_enable_capture(self.pg_interfaces)
829 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
830 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
831 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
834 self.pg_enable_capture(self.pg_interfaces)
836 out_if.get_capture(1)
839 self.logger.error("TCP 3 way handshake failed")
842 def verify_ipfix_nat44_ses(self, data):
844 Verify IPFIX NAT44 session create/delete event
846 :param data: Decoded IPFIX data records
848 nat44_ses_create_num = 0
849 nat44_ses_delete_num = 0
850 self.assertEqual(6, len(data))
853 self.assertIn(scapy.compat.orb(record[230]), [4, 5])
854 if scapy.compat.orb(record[230]) == 4:
855 nat44_ses_create_num += 1
857 nat44_ses_delete_num += 1
859 self.assertEqual(self.pg0.remote_ip4n, record[8])
860 # postNATSourceIPv4Address
861 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
864 self.assertEqual(struct.pack("!I", 0), record[234])
865 # protocolIdentifier/sourceTransportPort
866 # /postNAPTSourceTransportPort
867 if IP_PROTOS.icmp == scapy.compat.orb(record[4]):
868 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
869 self.assertEqual(struct.pack("!H", self.icmp_id_out),
871 elif IP_PROTOS.tcp == scapy.compat.orb(record[4]):
872 self.assertEqual(struct.pack("!H", self.tcp_port_in),
874 self.assertEqual(struct.pack("!H", self.tcp_port_out),
876 elif IP_PROTOS.udp == scapy.compat.orb(record[4]):
877 self.assertEqual(struct.pack("!H", self.udp_port_in),
879 self.assertEqual(struct.pack("!H", self.udp_port_out),
882 self.fail("Invalid protocol")
883 self.assertEqual(3, nat44_ses_create_num)
884 self.assertEqual(3, nat44_ses_delete_num)
886 def verify_ipfix_addr_exhausted(self, data):
888 Verify IPFIX NAT addresses event
890 :param data: Decoded IPFIX data records
892 self.assertEqual(1, len(data))
895 self.assertEqual(scapy.compat.orb(record[230]), 3)
897 self.assertEqual(struct.pack("!I", 0), record[283])
899 def verify_ipfix_max_sessions(self, data, limit):
901 Verify IPFIX maximum session entries exceeded event
903 :param data: Decoded IPFIX data records
904 :param limit: Number of maximum session entries that can be created.
906 self.assertEqual(1, len(data))
909 self.assertEqual(scapy.compat.orb(record[230]), 13)
910 # natQuotaExceededEvent
911 self.assertEqual(struct.pack("I", 1), record[466])
913 self.assertEqual(struct.pack("I", limit), record[471])
915 def verify_ipfix_max_bibs(self, data, limit):
917 Verify IPFIX maximum BIB entries exceeded event
919 :param data: Decoded IPFIX data records
920 :param limit: Number of maximum BIB entries that can be created.
922 self.assertEqual(1, len(data))
925 self.assertEqual(scapy.compat.orb(record[230]), 13)
926 # natQuotaExceededEvent
927 self.assertEqual(struct.pack("I", 2), record[466])
929 self.assertEqual(struct.pack("I", limit), record[472])
931 def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
933 Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
935 :param data: Decoded IPFIX data records
936 :param limit: Number of maximum fragments pending reassembly
937 :param src_addr: IPv6 source address
939 self.assertEqual(1, len(data))
942 self.assertEqual(scapy.compat.orb(record[230]), 13)
943 # natQuotaExceededEvent
944 self.assertEqual(struct.pack("I", 5), record[466])
945 # maxFragmentsPendingReassembly
946 self.assertEqual(struct.pack("I", limit), record[475])
948 self.assertEqual(src_addr, record[27])
950 def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
952 Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
954 :param data: Decoded IPFIX data records
955 :param limit: Number of maximum fragments pending reassembly
956 :param src_addr: IPv4 source address
958 self.assertEqual(1, len(data))
961 self.assertEqual(scapy.compat.orb(record[230]), 13)
962 # natQuotaExceededEvent
963 self.assertEqual(struct.pack("I", 5), record[466])
964 # maxFragmentsPendingReassembly
965 self.assertEqual(struct.pack("I", limit), record[475])
967 self.assertEqual(src_addr, record[8])
969 def verify_ipfix_bib(self, data, is_create, src_addr):
971 Verify IPFIX NAT64 BIB create and delete events
973 :param data: Decoded IPFIX data records
974 :param is_create: Create event if nonzero value otherwise delete event
975 :param src_addr: IPv6 source address
977 self.assertEqual(1, len(data))
981 self.assertEqual(scapy.compat.orb(record[230]), 10)
983 self.assertEqual(scapy.compat.orb(record[230]), 11)
985 self.assertEqual(src_addr, record[27])
986 # postNATSourceIPv4Address
987 self.assertEqual(self.nat_addr_n, record[225])
989 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
991 self.assertEqual(struct.pack("!I", 0), record[234])
992 # sourceTransportPort
993 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
994 # postNAPTSourceTransportPort
995 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
997 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
1000 Verify IPFIX NAT64 session create and delete events
1002 :param data: Decoded IPFIX data records
1003 :param is_create: Create event if nonzero value otherwise delete event
1004 :param src_addr: IPv6 source address
1005 :param dst_addr: IPv4 destination address
1006 :param dst_port: destination TCP port
1008 self.assertEqual(1, len(data))
1012 self.assertEqual(scapy.compat.orb(record[230]), 6)
1014 self.assertEqual(scapy.compat.orb(record[230]), 7)
1016 self.assertEqual(src_addr, record[27])
1017 # destinationIPv6Address
1018 self.assertEqual(socket.inet_pton(socket.AF_INET6,
1019 self.compose_ip6(dst_addr,
1023 # postNATSourceIPv4Address
1024 self.assertEqual(self.nat_addr_n, record[225])
1025 # postNATDestinationIPv4Address
1026 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
1028 # protocolIdentifier
1029 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
1031 self.assertEqual(struct.pack("!I", 0), record[234])
1032 # sourceTransportPort
1033 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1034 # postNAPTSourceTransportPort
1035 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1036 # destinationTransportPort
1037 self.assertEqual(struct.pack("!H", dst_port), record[11])
1038 # postNAPTDestinationTransportPort
1039 self.assertEqual(struct.pack("!H", dst_port), record[228])
1041 def verify_no_nat44_user(self):
1042 """ Verify that there is no NAT44 user """
1043 users = self.vapi.nat44_user_dump()
1044 self.assertEqual(len(users), 0)
1045 users = self.statistics.get_counter('/nat44/total-users')
1046 self.assertEqual(users[0][0], 0)
1047 sessions = self.statistics.get_counter('/nat44/total-sessions')
1048 self.assertEqual(sessions[0][0], 0)
1050 def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
1052 Verify IPFIX maximum entries per user exceeded event
1054 :param data: Decoded IPFIX data records
1055 :param limit: Number of maximum entries per user
1056 :param src_addr: IPv4 source address
1058 self.assertEqual(1, len(data))
1061 self.assertEqual(scapy.compat.orb(record[230]), 13)
1062 # natQuotaExceededEvent
1063 self.assertEqual(struct.pack("I", 3), record[466])
1065 self.assertEqual(struct.pack("I", limit), record[473])
1067 self.assertEqual(socket.inet_pton(socket.AF_INET, src_addr), record[8])
1069 def verify_syslog_apmap(self, data, is_add=True):
1070 message = data.decode('utf-8')
1072 message = SyslogMessage.parse(message)
1073 except ParseError as e:
1074 self.logger.error(e)
1077 self.assertEqual(message.severity, SyslogSeverity.info)
1078 self.assertEqual(message.appname, 'NAT')
1079 self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
1080 sd_params = message.sd.get('napmap')
1081 self.assertTrue(sd_params is not None)
1082 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1083 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1084 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1085 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1086 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1087 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1088 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1089 self.assertTrue(sd_params.get('SSUBIX') is not None)
1090 self.assertEqual(sd_params.get('SVLAN'), '0')
1092 def verify_syslog_sess(self, data, is_add=True, is_ip6=False):
1093 message = data.decode('utf-8')
1095 message = SyslogMessage.parse(message)
1096 except ParseError as e:
1097 self.logger.error(e)
1100 self.assertEqual(message.severity, SyslogSeverity.info)
1101 self.assertEqual(message.appname, 'NAT')
1102 self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL')
1103 sd_params = message.sd.get('nsess')
1104 self.assertTrue(sd_params is not None)
1106 self.assertEqual(sd_params.get('IATYP'), 'IPv6')
1107 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
1109 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1110 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1111 self.assertTrue(sd_params.get('SSUBIX') is not None)
1112 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1113 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1114 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1115 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1116 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1117 self.assertEqual(sd_params.get('SVLAN'), '0')
1118 self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
1119 self.assertEqual(sd_params.get('XDPORT'),
1120 "%d" % self.tcp_external_port)
1122 def verify_mss_value(self, pkt, mss):
1124 Verify TCP MSS value
1129 if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
1130 raise TypeError("Not a TCP/IP packet")
1132 for option in pkt[TCP].options:
1133 if option[0] == 'MSS':
1134 self.assertEqual(option[1], mss)
1135 self.assert_tcp_checksum_valid(pkt)
1138 def proto2layer(proto):
1139 if proto == IP_PROTOS.tcp:
1141 elif proto == IP_PROTOS.udp:
1143 elif proto == IP_PROTOS.icmp:
1146 raise Exception("Unsupported protocol")
1148 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1149 layer = self.proto2layer(proto)
1151 if proto == IP_PROTOS.tcp:
1152 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1154 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1155 self.port_in = random.randint(1025, 65535)
1158 pkts = self.create_stream_frag(self.pg0,
1159 self.pg1.remote_ip4,
1164 self.pg0.add_stream(pkts)
1165 self.pg_enable_capture(self.pg_interfaces)
1167 frags = self.pg1.get_capture(len(pkts))
1168 if not dont_translate:
1169 p = self.reass_frags_and_verify(frags,
1171 self.pg1.remote_ip4)
1173 p = self.reass_frags_and_verify(frags,
1174 self.pg0.remote_ip4,
1175 self.pg1.remote_ip4)
1176 if proto != IP_PROTOS.icmp:
1177 if not dont_translate:
1178 self.assertEqual(p[layer].dport, 20)
1179 self.assertNotEqual(p[layer].sport, self.port_in)
1181 self.assertEqual(p[layer].sport, self.port_in)
1183 if not dont_translate:
1184 self.assertNotEqual(p[layer].id, self.port_in)
1186 self.assertEqual(p[layer].id, self.port_in)
1187 self.assertEqual(data, p[Raw].load)
1190 if not dont_translate:
1191 dst_addr = self.nat_addr
1193 dst_addr = self.pg0.remote_ip4
1194 if proto != IP_PROTOS.icmp:
1196 dport = p[layer].sport
1200 pkts = self.create_stream_frag(self.pg1,
1207 self.pg1.add_stream(pkts)
1208 self.pg_enable_capture(self.pg_interfaces)
1210 frags = self.pg0.get_capture(len(pkts))
1211 p = self.reass_frags_and_verify(frags,
1212 self.pg1.remote_ip4,
1213 self.pg0.remote_ip4)
1214 if proto != IP_PROTOS.icmp:
1215 self.assertEqual(p[layer].sport, 20)
1216 self.assertEqual(p[layer].dport, self.port_in)
1218 self.assertEqual(p[layer].id, self.port_in)
1219 self.assertEqual(data, p[Raw].load)
1221 def frag_in_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1222 layer = self.proto2layer(proto)
1224 if proto == IP_PROTOS.tcp:
1225 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1227 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1228 self.port_in = random.randint(1025, 65535)
1232 pkts = self.create_stream_frag(self.pg0,
1233 self.server_out_addr,
1235 self.server_out_port,
1238 self.pg0.add_stream(pkts)
1239 self.pg_enable_capture(self.pg_interfaces)
1241 frags = self.pg1.get_capture(len(pkts))
1242 p = self.reass_frags_and_verify(frags,
1243 self.pg0.remote_ip4,
1244 self.server_in_addr)
1245 if proto != IP_PROTOS.icmp:
1246 self.assertEqual(p[layer].sport, self.port_in)
1247 self.assertEqual(p[layer].dport, self.server_in_port)
1249 self.assertEqual(p[layer].id, self.port_in)
1250 self.assertEqual(data, p[Raw].load)
1253 if proto != IP_PROTOS.icmp:
1254 pkts = self.create_stream_frag(self.pg1,
1255 self.pg0.remote_ip4,
1256 self.server_in_port,
1261 pkts = self.create_stream_frag(self.pg1,
1262 self.pg0.remote_ip4,
1268 self.pg1.add_stream(pkts)
1269 self.pg_enable_capture(self.pg_interfaces)
1271 frags = self.pg0.get_capture(len(pkts))
1272 p = self.reass_frags_and_verify(frags,
1273 self.server_out_addr,
1274 self.pg0.remote_ip4)
1275 if proto != IP_PROTOS.icmp:
1276 self.assertEqual(p[layer].sport, self.server_out_port)
1277 self.assertEqual(p[layer].dport, self.port_in)
1279 self.assertEqual(p[layer].id, self.port_in)
1280 self.assertEqual(data, p[Raw].load)
1282 def reass_hairpinning(self, proto=IP_PROTOS.tcp):
1283 layer = self.proto2layer(proto)
1285 if proto == IP_PROTOS.tcp:
1286 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1288 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1290 # send packet from host to server
1291 pkts = self.create_stream_frag(self.pg0,
1294 self.server_out_port,
1297 self.pg0.add_stream(pkts)
1298 self.pg_enable_capture(self.pg_interfaces)
1300 frags = self.pg0.get_capture(len(pkts))
1301 p = self.reass_frags_and_verify(frags,
1304 if proto != IP_PROTOS.icmp:
1305 self.assertNotEqual(p[layer].sport, self.host_in_port)
1306 self.assertEqual(p[layer].dport, self.server_in_port)
1308 self.assertNotEqual(p[layer].id, self.host_in_port)
1309 self.assertEqual(data, p[Raw].load)
1311 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1312 layer = self.proto2layer(proto)
1314 if proto == IP_PROTOS.tcp:
1315 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1317 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1318 self.port_in = random.randint(1025, 65535)
1322 pkts = self.create_stream_frag(self.pg0,
1323 self.pg1.remote_ip4,
1329 self.pg0.add_stream(pkts)
1330 self.pg_enable_capture(self.pg_interfaces)
1332 frags = self.pg1.get_capture(len(pkts))
1333 if not dont_translate:
1334 p = self.reass_frags_and_verify(frags,
1336 self.pg1.remote_ip4)
1338 p = self.reass_frags_and_verify(frags,
1339 self.pg0.remote_ip4,
1340 self.pg1.remote_ip4)
1341 if proto != IP_PROTOS.icmp:
1342 if not dont_translate:
1343 self.assertEqual(p[layer].dport, 20)
1344 self.assertNotEqual(p[layer].sport, self.port_in)
1346 self.assertEqual(p[layer].sport, self.port_in)
1348 if not dont_translate:
1349 self.assertNotEqual(p[layer].id, self.port_in)
1351 self.assertEqual(p[layer].id, self.port_in)
1352 self.assertEqual(data, p[Raw].load)
1355 if not dont_translate:
1356 dst_addr = self.nat_addr
1358 dst_addr = self.pg0.remote_ip4
1359 if proto != IP_PROTOS.icmp:
1361 dport = p[layer].sport
1365 pkts = self.create_stream_frag(self.pg1,
1373 self.pg1.add_stream(pkts)
1374 self.pg_enable_capture(self.pg_interfaces)
1376 frags = self.pg0.get_capture(len(pkts))
1377 p = self.reass_frags_and_verify(frags,
1378 self.pg1.remote_ip4,
1379 self.pg0.remote_ip4)
1380 if proto != IP_PROTOS.icmp:
1381 self.assertEqual(p[layer].sport, 20)
1382 self.assertEqual(p[layer].dport, self.port_in)
1384 self.assertEqual(p[layer].id, self.port_in)
1385 self.assertEqual(data, p[Raw].load)
1387 def frag_out_of_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1388 layer = self.proto2layer(proto)
1390 if proto == IP_PROTOS.tcp:
1391 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1393 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1394 self.port_in = random.randint(1025, 65535)
1398 pkts = self.create_stream_frag(self.pg0,
1399 self.server_out_addr,
1401 self.server_out_port,
1405 self.pg0.add_stream(pkts)
1406 self.pg_enable_capture(self.pg_interfaces)
1408 frags = self.pg1.get_capture(len(pkts))
1409 p = self.reass_frags_and_verify(frags,
1410 self.pg0.remote_ip4,
1411 self.server_in_addr)
1412 if proto != IP_PROTOS.icmp:
1413 self.assertEqual(p[layer].dport, self.server_in_port)
1414 self.assertEqual(p[layer].sport, self.port_in)
1415 self.assertEqual(p[layer].dport, self.server_in_port)
1417 self.assertEqual(p[layer].id, self.port_in)
1418 self.assertEqual(data, p[Raw].load)
1421 if proto != IP_PROTOS.icmp:
1422 pkts = self.create_stream_frag(self.pg1,
1423 self.pg0.remote_ip4,
1424 self.server_in_port,
1429 pkts = self.create_stream_frag(self.pg1,
1430 self.pg0.remote_ip4,
1437 self.pg1.add_stream(pkts)
1438 self.pg_enable_capture(self.pg_interfaces)
1440 frags = self.pg0.get_capture(len(pkts))
1441 p = self.reass_frags_and_verify(frags,
1442 self.server_out_addr,
1443 self.pg0.remote_ip4)
1444 if proto != IP_PROTOS.icmp:
1445 self.assertEqual(p[layer].sport, self.server_out_port)
1446 self.assertEqual(p[layer].dport, self.port_in)
1448 self.assertEqual(p[layer].id, self.port_in)
1449 self.assertEqual(data, p[Raw].load)
1452 class TestNAT44(MethodHolder):
1453 """ NAT44 Test Cases """
1456 def setUpClass(cls):
1457 super(TestNAT44, cls).setUpClass()
1458 cls.vapi.cli("set log class nat level debug")
1461 cls.tcp_port_in = 6303
1462 cls.tcp_port_out = 6303
1463 cls.udp_port_in = 6304
1464 cls.udp_port_out = 6304
1465 cls.icmp_id_in = 6305
1466 cls.icmp_id_out = 6305
1467 cls.nat_addr = '10.0.0.3'
1468 cls.ipfix_src_port = 4739
1469 cls.ipfix_domain_id = 1
1470 cls.tcp_external_port = 80
1471 cls.udp_external_port = 69
1473 cls.create_pg_interfaces(range(10))
1474 cls.interfaces = list(cls.pg_interfaces[0:4])
1476 for i in cls.interfaces:
1481 cls.pg0.generate_remote_hosts(3)
1482 cls.pg0.configure_ipv4_neighbors()
1484 cls.pg1.generate_remote_hosts(1)
1485 cls.pg1.configure_ipv4_neighbors()
1487 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
1488 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 10})
1489 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 20})
1491 cls.pg4._local_ip4 = "172.16.255.1"
1492 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1493 cls.pg4.set_table_ip4(10)
1494 cls.pg5._local_ip4 = "172.17.255.3"
1495 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
1496 cls.pg5.set_table_ip4(10)
1497 cls.pg6._local_ip4 = "172.16.255.1"
1498 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1499 cls.pg6.set_table_ip4(20)
1500 for i in cls.overlapping_interfaces:
1508 cls.pg9.generate_remote_hosts(2)
1509 cls.pg9.config_ip4()
1510 cls.vapi.sw_interface_add_del_address(
1511 sw_if_index=cls.pg9.sw_if_index,
1512 prefix="10.0.0.1/24")
1515 cls.pg9.resolve_arp()
1516 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1517 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1518 cls.pg9.resolve_arp()
1521 super(TestNAT44, cls).tearDownClass()
1525 def tearDownClass(cls):
1526 super(TestNAT44, cls).tearDownClass()
1528 def test_dynamic(self):
1529 """ NAT44 dynamic translation test """
1530 self.nat44_add_address(self.nat_addr)
1531 flags = self.config_flags.NAT_IS_INSIDE
1532 self.vapi.nat44_interface_add_del_feature(
1533 sw_if_index=self.pg0.sw_if_index,
1534 flags=flags, is_add=1)
1535 self.vapi.nat44_interface_add_del_feature(
1536 sw_if_index=self.pg1.sw_if_index,
1540 tcpn = self.statistics.get_err_counter(
1541 '/err/nat44-in2out-slowpath/TCP packets')
1542 udpn = self.statistics.get_err_counter(
1543 '/err/nat44-in2out-slowpath/UDP packets')
1544 icmpn = self.statistics.get_err_counter(
1545 '/err/nat44-in2out-slowpath/ICMP packets')
1546 totaln = self.statistics.get_err_counter(
1547 '/err/nat44-in2out-slowpath/good in2out packets processed')
1549 pkts = self.create_stream_in(self.pg0, self.pg1)
1550 self.pg0.add_stream(pkts)
1551 self.pg_enable_capture(self.pg_interfaces)
1553 capture = self.pg1.get_capture(len(pkts))
1554 self.verify_capture_out(capture)
1556 err = self.statistics.get_err_counter(
1557 '/err/nat44-in2out-slowpath/TCP packets')
1558 self.assertEqual(err - tcpn, 2)
1559 err = self.statistics.get_err_counter(
1560 '/err/nat44-in2out-slowpath/UDP packets')
1561 self.assertEqual(err - udpn, 1)
1562 err = self.statistics.get_err_counter(
1563 '/err/nat44-in2out-slowpath/ICMP packets')
1564 self.assertEqual(err - icmpn, 1)
1565 err = self.statistics.get_err_counter(
1566 '/err/nat44-in2out-slowpath/good in2out packets processed')
1567 self.assertEqual(err - totaln, 4)
1570 tcpn = self.statistics.get_err_counter('/err/nat44-out2in/TCP packets')
1571 udpn = self.statistics.get_err_counter('/err/nat44-out2in/UDP packets')
1572 icmpn = self.statistics.get_err_counter(
1573 '/err/nat44-out2in/ICMP packets')
1574 totaln = self.statistics.get_err_counter(
1575 '/err/nat44-out2in/good out2in packets processed')
1577 pkts = self.create_stream_out(self.pg1)
1578 self.pg1.add_stream(pkts)
1579 self.pg_enable_capture(self.pg_interfaces)
1581 capture = self.pg0.get_capture(len(pkts))
1582 self.verify_capture_in(capture, self.pg0)
1584 err = self.statistics.get_err_counter('/err/nat44-out2in/TCP packets')
1585 self.assertEqual(err - tcpn, 2)
1586 err = self.statistics.get_err_counter('/err/nat44-out2in/UDP packets')
1587 self.assertEqual(err - udpn, 1)
1588 err = self.statistics.get_err_counter('/err/nat44-out2in/ICMP packets')
1589 self.assertEqual(err - icmpn, 1)
1590 err = self.statistics.get_err_counter(
1591 '/err/nat44-out2in/good out2in packets processed')
1592 self.assertEqual(err - totaln, 4)
1594 users = self.statistics.get_counter('/nat44/total-users')
1595 self.assertEqual(users[0][0], 1)
1596 sessions = self.statistics.get_counter('/nat44/total-sessions')
1597 self.assertEqual(sessions[0][0], 3)
1599 def test_dynamic_icmp_errors_in2out_ttl_1(self):
1600 """ NAT44 handling of client packets with TTL=1 """
1602 self.nat44_add_address(self.nat_addr)
1603 flags = self.config_flags.NAT_IS_INSIDE
1604 self.vapi.nat44_interface_add_del_feature(
1605 sw_if_index=self.pg0.sw_if_index,
1606 flags=flags, is_add=1)
1607 self.vapi.nat44_interface_add_del_feature(
1608 sw_if_index=self.pg1.sw_if_index,
1611 # Client side - generate traffic
1612 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1613 self.pg0.add_stream(pkts)
1614 self.pg_enable_capture(self.pg_interfaces)
1617 # Client side - verify ICMP type 11 packets
1618 capture = self.pg0.get_capture(len(pkts))
1619 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1621 def test_dynamic_icmp_errors_out2in_ttl_1(self):
1622 """ NAT44 handling of server packets with TTL=1 """
1624 self.nat44_add_address(self.nat_addr)
1625 flags = self.config_flags.NAT_IS_INSIDE
1626 self.vapi.nat44_interface_add_del_feature(
1627 sw_if_index=self.pg0.sw_if_index,
1628 flags=flags, is_add=1)
1629 self.vapi.nat44_interface_add_del_feature(
1630 sw_if_index=self.pg1.sw_if_index,
1633 # Client side - create sessions
1634 pkts = self.create_stream_in(self.pg0, self.pg1)
1635 self.pg0.add_stream(pkts)
1636 self.pg_enable_capture(self.pg_interfaces)
1639 # Server side - generate traffic
1640 capture = self.pg1.get_capture(len(pkts))
1641 self.verify_capture_out(capture)
1642 pkts = self.create_stream_out(self.pg1, ttl=1)
1643 self.pg1.add_stream(pkts)
1644 self.pg_enable_capture(self.pg_interfaces)
1647 # Server side - verify ICMP type 11 packets
1648 capture = self.pg1.get_capture(len(pkts))
1649 self.verify_capture_out_with_icmp_errors(capture,
1650 src_ip=self.pg1.local_ip4)
1652 def test_dynamic_icmp_errors_in2out_ttl_2(self):
1653 """ NAT44 handling of error responses to client packets with TTL=2 """
1655 self.nat44_add_address(self.nat_addr)
1656 flags = self.config_flags.NAT_IS_INSIDE
1657 self.vapi.nat44_interface_add_del_feature(
1658 sw_if_index=self.pg0.sw_if_index,
1659 flags=flags, is_add=1)
1660 self.vapi.nat44_interface_add_del_feature(
1661 sw_if_index=self.pg1.sw_if_index,
1664 # Client side - generate traffic
1665 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1666 self.pg0.add_stream(pkts)
1667 self.pg_enable_capture(self.pg_interfaces)
1670 # Server side - simulate ICMP type 11 response
1671 capture = self.pg1.get_capture(len(pkts))
1672 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1673 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1674 ICMP(type=11) / packet[IP] for packet in capture]
1675 self.pg1.add_stream(pkts)
1676 self.pg_enable_capture(self.pg_interfaces)
1679 # Client side - verify ICMP type 11 packets
1680 capture = self.pg0.get_capture(len(pkts))
1681 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1683 def test_dynamic_icmp_errors_out2in_ttl_2(self):
1684 """ NAT44 handling of error responses to server packets with TTL=2 """
1686 self.nat44_add_address(self.nat_addr)
1687 flags = self.config_flags.NAT_IS_INSIDE
1688 self.vapi.nat44_interface_add_del_feature(
1689 sw_if_index=self.pg0.sw_if_index,
1690 flags=flags, is_add=1)
1691 self.vapi.nat44_interface_add_del_feature(
1692 sw_if_index=self.pg1.sw_if_index,
1695 # Client side - create sessions
1696 pkts = self.create_stream_in(self.pg0, self.pg1)
1697 self.pg0.add_stream(pkts)
1698 self.pg_enable_capture(self.pg_interfaces)
1701 # Server side - generate traffic
1702 capture = self.pg1.get_capture(len(pkts))
1703 self.verify_capture_out(capture)
1704 pkts = self.create_stream_out(self.pg1, ttl=2)
1705 self.pg1.add_stream(pkts)
1706 self.pg_enable_capture(self.pg_interfaces)
1709 # Client side - simulate ICMP type 11 response
1710 capture = self.pg0.get_capture(len(pkts))
1711 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1712 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1713 ICMP(type=11) / packet[IP] for packet in capture]
1714 self.pg0.add_stream(pkts)
1715 self.pg_enable_capture(self.pg_interfaces)
1718 # Server side - verify ICMP type 11 packets
1719 capture = self.pg1.get_capture(len(pkts))
1720 self.verify_capture_out_with_icmp_errors(capture)
1722 def test_ping_out_interface_from_outside(self):
1723 """ Ping NAT44 out interface from outside network """
1725 self.nat44_add_address(self.nat_addr)
1726 flags = self.config_flags.NAT_IS_INSIDE
1727 self.vapi.nat44_interface_add_del_feature(
1728 sw_if_index=self.pg0.sw_if_index,
1729 flags=flags, is_add=1)
1730 self.vapi.nat44_interface_add_del_feature(
1731 sw_if_index=self.pg1.sw_if_index,
1734 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1735 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1736 ICMP(id=self.icmp_id_out, type='echo-request'))
1738 self.pg1.add_stream(pkts)
1739 self.pg_enable_capture(self.pg_interfaces)
1741 capture = self.pg1.get_capture(len(pkts))
1744 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1745 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1746 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1747 self.assertEqual(packet[ICMP].type, 0) # echo reply
1749 self.logger.error(ppp("Unexpected or invalid packet "
1750 "(outside network):", packet))
1753 def test_ping_internal_host_from_outside(self):
1754 """ Ping internal host from outside network """
1756 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1757 flags = self.config_flags.NAT_IS_INSIDE
1758 self.vapi.nat44_interface_add_del_feature(
1759 sw_if_index=self.pg0.sw_if_index,
1760 flags=flags, is_add=1)
1761 self.vapi.nat44_interface_add_del_feature(
1762 sw_if_index=self.pg1.sw_if_index,
1766 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1767 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
1768 ICMP(id=self.icmp_id_out, type='echo-request'))
1769 self.pg1.add_stream(pkt)
1770 self.pg_enable_capture(self.pg_interfaces)
1772 capture = self.pg0.get_capture(1)
1773 self.verify_capture_in(capture, self.pg0)
1774 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1777 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1778 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1779 ICMP(id=self.icmp_id_in, type='echo-reply'))
1780 self.pg0.add_stream(pkt)
1781 self.pg_enable_capture(self.pg_interfaces)
1783 capture = self.pg1.get_capture(1)
1784 self.verify_capture_out(capture, same_port=True)
1785 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1787 def test_forwarding(self):
1788 """ NAT44 forwarding test """
1790 flags = self.config_flags.NAT_IS_INSIDE
1791 self.vapi.nat44_interface_add_del_feature(
1792 sw_if_index=self.pg0.sw_if_index,
1793 flags=flags, is_add=1)
1794 self.vapi.nat44_interface_add_del_feature(
1795 sw_if_index=self.pg1.sw_if_index,
1797 self.vapi.nat44_forwarding_enable_disable(enable=1)
1799 real_ip = self.pg0.remote_ip4
1800 alias_ip = self.nat_addr
1801 flags = self.config_flags.NAT_IS_ADDR_ONLY
1802 self.vapi.nat44_add_del_static_mapping(is_add=1,
1803 local_ip_address=real_ip,
1804 external_ip_address=alias_ip,
1805 external_sw_if_index=0xFFFFFFFF,
1809 # static mapping match
1811 pkts = self.create_stream_out(self.pg1)
1812 self.pg1.add_stream(pkts)
1813 self.pg_enable_capture(self.pg_interfaces)
1815 capture = self.pg0.get_capture(len(pkts))
1816 self.verify_capture_in(capture, self.pg0)
1818 pkts = self.create_stream_in(self.pg0, self.pg1)
1819 self.pg0.add_stream(pkts)
1820 self.pg_enable_capture(self.pg_interfaces)
1822 capture = self.pg1.get_capture(len(pkts))
1823 self.verify_capture_out(capture, same_port=True)
1825 # no static mapping match
1827 host0 = self.pg0.remote_hosts[0]
1828 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1830 pkts = self.create_stream_out(self.pg1,
1831 dst_ip=self.pg0.remote_ip4,
1832 use_inside_ports=True)
1833 self.pg1.add_stream(pkts)
1834 self.pg_enable_capture(self.pg_interfaces)
1836 capture = self.pg0.get_capture(len(pkts))
1837 self.verify_capture_in(capture, self.pg0)
1839 pkts = self.create_stream_in(self.pg0, self.pg1)
1840 self.pg0.add_stream(pkts)
1841 self.pg_enable_capture(self.pg_interfaces)
1843 capture = self.pg1.get_capture(len(pkts))
1844 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1847 self.pg0.remote_hosts[0] = host0
1850 self.vapi.nat44_forwarding_enable_disable(enable=0)
1851 flags = self.config_flags.NAT_IS_ADDR_ONLY
1852 self.vapi.nat44_add_del_static_mapping(
1854 local_ip_address=real_ip,
1855 external_ip_address=alias_ip,
1856 external_sw_if_index=0xFFFFFFFF,
1859 def test_static_in(self):
1860 """ 1:1 NAT initialized from inside network """
1862 nat_ip = "10.0.0.10"
1863 self.tcp_port_out = 6303
1864 self.udp_port_out = 6304
1865 self.icmp_id_out = 6305
1867 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1868 flags = self.config_flags.NAT_IS_INSIDE
1869 self.vapi.nat44_interface_add_del_feature(
1870 sw_if_index=self.pg0.sw_if_index,
1871 flags=flags, is_add=1)
1872 self.vapi.nat44_interface_add_del_feature(
1873 sw_if_index=self.pg1.sw_if_index,
1875 sm = self.vapi.nat44_static_mapping_dump()
1876 self.assertEqual(len(sm), 1)
1877 self.assertEqual(sm[0].tag, '')
1878 self.assertEqual(sm[0].protocol, 0)
1879 self.assertEqual(sm[0].local_port, 0)
1880 self.assertEqual(sm[0].external_port, 0)
1883 pkts = self.create_stream_in(self.pg0, self.pg1)
1884 self.pg0.add_stream(pkts)
1885 self.pg_enable_capture(self.pg_interfaces)
1887 capture = self.pg1.get_capture(len(pkts))
1888 self.verify_capture_out(capture, nat_ip, True)
1891 pkts = self.create_stream_out(self.pg1, nat_ip)
1892 self.pg1.add_stream(pkts)
1893 self.pg_enable_capture(self.pg_interfaces)
1895 capture = self.pg0.get_capture(len(pkts))
1896 self.verify_capture_in(capture, self.pg0)
1898 def test_static_out(self):
1899 """ 1:1 NAT initialized from outside network """
1901 nat_ip = "10.0.0.20"
1902 self.tcp_port_out = 6303
1903 self.udp_port_out = 6304
1904 self.icmp_id_out = 6305
1907 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
1908 flags = self.config_flags.NAT_IS_INSIDE
1909 self.vapi.nat44_interface_add_del_feature(
1910 sw_if_index=self.pg0.sw_if_index,
1911 flags=flags, is_add=1)
1912 self.vapi.nat44_interface_add_del_feature(
1913 sw_if_index=self.pg1.sw_if_index,
1915 sm = self.vapi.nat44_static_mapping_dump()
1916 self.assertEqual(len(sm), 1)
1917 self.assertEqual(sm[0].tag, tag)
1920 pkts = self.create_stream_out(self.pg1, nat_ip)
1921 self.pg1.add_stream(pkts)
1922 self.pg_enable_capture(self.pg_interfaces)
1924 capture = self.pg0.get_capture(len(pkts))
1925 self.verify_capture_in(capture, self.pg0)
1928 pkts = self.create_stream_in(self.pg0, self.pg1)
1929 self.pg0.add_stream(pkts)
1930 self.pg_enable_capture(self.pg_interfaces)
1932 capture = self.pg1.get_capture(len(pkts))
1933 self.verify_capture_out(capture, nat_ip, True)
1935 def test_static_with_port_in(self):
1936 """ 1:1 NAPT initialized from inside network """
1938 self.tcp_port_out = 3606
1939 self.udp_port_out = 3607
1940 self.icmp_id_out = 3608
1942 self.nat44_add_address(self.nat_addr)
1943 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1944 self.tcp_port_in, self.tcp_port_out,
1945 proto=IP_PROTOS.tcp)
1946 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1947 self.udp_port_in, self.udp_port_out,
1948 proto=IP_PROTOS.udp)
1949 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1950 self.icmp_id_in, self.icmp_id_out,
1951 proto=IP_PROTOS.icmp)
1952 flags = self.config_flags.NAT_IS_INSIDE
1953 self.vapi.nat44_interface_add_del_feature(
1954 sw_if_index=self.pg0.sw_if_index,
1955 flags=flags, is_add=1)
1956 self.vapi.nat44_interface_add_del_feature(
1957 sw_if_index=self.pg1.sw_if_index,
1961 pkts = self.create_stream_in(self.pg0, self.pg1)
1962 self.pg0.add_stream(pkts)
1963 self.pg_enable_capture(self.pg_interfaces)
1965 capture = self.pg1.get_capture(len(pkts))
1966 self.verify_capture_out(capture)
1969 pkts = self.create_stream_out(self.pg1)
1970 self.pg1.add_stream(pkts)
1971 self.pg_enable_capture(self.pg_interfaces)
1973 capture = self.pg0.get_capture(len(pkts))
1974 self.verify_capture_in(capture, self.pg0)
1976 def test_static_with_port_out(self):
1977 """ 1:1 NAPT initialized from outside network """
1979 self.tcp_port_out = 30606
1980 self.udp_port_out = 30607
1981 self.icmp_id_out = 30608
1983 self.nat44_add_address(self.nat_addr)
1984 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1985 self.tcp_port_in, self.tcp_port_out,
1986 proto=IP_PROTOS.tcp)
1987 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1988 self.udp_port_in, self.udp_port_out,
1989 proto=IP_PROTOS.udp)
1990 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1991 self.icmp_id_in, self.icmp_id_out,
1992 proto=IP_PROTOS.icmp)
1993 flags = self.config_flags.NAT_IS_INSIDE
1994 self.vapi.nat44_interface_add_del_feature(
1995 sw_if_index=self.pg0.sw_if_index,
1996 flags=flags, is_add=1)
1997 self.vapi.nat44_interface_add_del_feature(
1998 sw_if_index=self.pg1.sw_if_index,
2002 pkts = self.create_stream_out(self.pg1)
2003 self.pg1.add_stream(pkts)
2004 self.pg_enable_capture(self.pg_interfaces)
2006 capture = self.pg0.get_capture(len(pkts))
2007 self.verify_capture_in(capture, self.pg0)
2010 pkts = self.create_stream_in(self.pg0, self.pg1)
2011 self.pg0.add_stream(pkts)
2012 self.pg_enable_capture(self.pg_interfaces)
2014 capture = self.pg1.get_capture(len(pkts))
2015 self.verify_capture_out(capture)
2017 def test_static_vrf_aware(self):
2018 """ 1:1 NAT VRF awareness """
2020 nat_ip1 = "10.0.0.30"
2021 nat_ip2 = "10.0.0.40"
2022 self.tcp_port_out = 6303
2023 self.udp_port_out = 6304
2024 self.icmp_id_out = 6305
2026 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
2028 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
2030 flags = self.config_flags.NAT_IS_INSIDE
2031 self.vapi.nat44_interface_add_del_feature(
2032 sw_if_index=self.pg3.sw_if_index,
2034 self.vapi.nat44_interface_add_del_feature(
2035 sw_if_index=self.pg0.sw_if_index,
2036 flags=flags, is_add=1)
2037 self.vapi.nat44_interface_add_del_feature(
2038 sw_if_index=self.pg4.sw_if_index,
2039 flags=flags, is_add=1)
2041 # inside interface VRF match NAT44 static mapping VRF
2042 pkts = self.create_stream_in(self.pg4, self.pg3)
2043 self.pg4.add_stream(pkts)
2044 self.pg_enable_capture(self.pg_interfaces)
2046 capture = self.pg3.get_capture(len(pkts))
2047 self.verify_capture_out(capture, nat_ip1, True)
2049 # inside interface VRF don't match NAT44 static mapping VRF (packets
2051 pkts = self.create_stream_in(self.pg0, self.pg3)
2052 self.pg0.add_stream(pkts)
2053 self.pg_enable_capture(self.pg_interfaces)
2055 self.pg3.assert_nothing_captured()
2057 def test_dynamic_to_static(self):
2058 """ Switch from dynamic translation to 1:1NAT """
2059 nat_ip = "10.0.0.10"
2060 self.tcp_port_out = 6303
2061 self.udp_port_out = 6304
2062 self.icmp_id_out = 6305
2064 self.nat44_add_address(self.nat_addr)
2065 flags = self.config_flags.NAT_IS_INSIDE
2066 self.vapi.nat44_interface_add_del_feature(
2067 sw_if_index=self.pg0.sw_if_index,
2068 flags=flags, is_add=1)
2069 self.vapi.nat44_interface_add_del_feature(
2070 sw_if_index=self.pg1.sw_if_index,
2074 pkts = self.create_stream_in(self.pg0, self.pg1)
2075 self.pg0.add_stream(pkts)
2076 self.pg_enable_capture(self.pg_interfaces)
2078 capture = self.pg1.get_capture(len(pkts))
2079 self.verify_capture_out(capture)
2082 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2083 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
2084 self.assertEqual(len(sessions), 0)
2085 pkts = self.create_stream_in(self.pg0, self.pg1)
2086 self.pg0.add_stream(pkts)
2087 self.pg_enable_capture(self.pg_interfaces)
2089 capture = self.pg1.get_capture(len(pkts))
2090 self.verify_capture_out(capture, nat_ip, True)
2092 def test_identity_nat(self):
2093 """ Identity NAT """
2094 flags = self.config_flags.NAT_IS_ADDR_ONLY
2095 self.vapi.nat44_add_del_identity_mapping(
2096 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
2097 flags=flags, is_add=1)
2098 flags = self.config_flags.NAT_IS_INSIDE
2099 self.vapi.nat44_interface_add_del_feature(
2100 sw_if_index=self.pg0.sw_if_index,
2101 flags=flags, is_add=1)
2102 self.vapi.nat44_interface_add_del_feature(
2103 sw_if_index=self.pg1.sw_if_index,
2106 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2107 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2108 TCP(sport=12345, dport=56789))
2109 self.pg1.add_stream(p)
2110 self.pg_enable_capture(self.pg_interfaces)
2112 capture = self.pg0.get_capture(1)
2117 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2118 self.assertEqual(ip.src, self.pg1.remote_ip4)
2119 self.assertEqual(tcp.dport, 56789)
2120 self.assertEqual(tcp.sport, 12345)
2121 self.assert_packet_checksums_valid(p)
2123 self.logger.error(ppp("Unexpected or invalid packet:", p))
2126 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
2127 self.assertEqual(len(sessions), 0)
2128 flags = self.config_flags.NAT_IS_ADDR_ONLY
2129 self.vapi.nat44_add_del_identity_mapping(
2130 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
2131 flags=flags, vrf_id=1, is_add=1)
2132 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2133 self.assertEqual(len(identity_mappings), 2)
2135 def test_multiple_inside_interfaces(self):
2136 """ NAT44 multiple non-overlapping address space inside interfaces """
2138 self.nat44_add_address(self.nat_addr)
2139 flags = self.config_flags.NAT_IS_INSIDE
2140 self.vapi.nat44_interface_add_del_feature(
2141 sw_if_index=self.pg0.sw_if_index,
2142 flags=flags, is_add=1)
2143 self.vapi.nat44_interface_add_del_feature(
2144 sw_if_index=self.pg1.sw_if_index,
2145 flags=flags, is_add=1)
2146 self.vapi.nat44_interface_add_del_feature(
2147 sw_if_index=self.pg3.sw_if_index,
2150 # between two NAT44 inside interfaces (no translation)
2151 pkts = self.create_stream_in(self.pg0, self.pg1)
2152 self.pg0.add_stream(pkts)
2153 self.pg_enable_capture(self.pg_interfaces)
2155 capture = self.pg1.get_capture(len(pkts))
2156 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
2158 # from NAT44 inside to interface without NAT44 feature (no translation)
2159 pkts = self.create_stream_in(self.pg0, self.pg2)
2160 self.pg0.add_stream(pkts)
2161 self.pg_enable_capture(self.pg_interfaces)
2163 capture = self.pg2.get_capture(len(pkts))
2164 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2166 # in2out 1st interface
2167 pkts = self.create_stream_in(self.pg0, self.pg3)
2168 self.pg0.add_stream(pkts)
2169 self.pg_enable_capture(self.pg_interfaces)
2171 capture = self.pg3.get_capture(len(pkts))
2172 self.verify_capture_out(capture)
2174 # out2in 1st interface
2175 pkts = self.create_stream_out(self.pg3)
2176 self.pg3.add_stream(pkts)
2177 self.pg_enable_capture(self.pg_interfaces)
2179 capture = self.pg0.get_capture(len(pkts))
2180 self.verify_capture_in(capture, self.pg0)
2182 # in2out 2nd interface
2183 pkts = self.create_stream_in(self.pg1, self.pg3)
2184 self.pg1.add_stream(pkts)
2185 self.pg_enable_capture(self.pg_interfaces)
2187 capture = self.pg3.get_capture(len(pkts))
2188 self.verify_capture_out(capture)
2190 # out2in 2nd interface
2191 pkts = self.create_stream_out(self.pg3)
2192 self.pg3.add_stream(pkts)
2193 self.pg_enable_capture(self.pg_interfaces)
2195 capture = self.pg1.get_capture(len(pkts))
2196 self.verify_capture_in(capture, self.pg1)
2198 def test_inside_overlapping_interfaces(self):
2199 """ NAT44 multiple inside interfaces with overlapping address space """
2201 static_nat_ip = "10.0.0.10"
2202 self.nat44_add_address(self.nat_addr)
2203 flags = self.config_flags.NAT_IS_INSIDE
2204 self.vapi.nat44_interface_add_del_feature(
2205 sw_if_index=self.pg3.sw_if_index,
2207 self.vapi.nat44_interface_add_del_feature(
2208 sw_if_index=self.pg4.sw_if_index,
2209 flags=flags, is_add=1)
2210 self.vapi.nat44_interface_add_del_feature(
2211 sw_if_index=self.pg5.sw_if_index,
2212 flags=flags, is_add=1)
2213 self.vapi.nat44_interface_add_del_feature(
2214 sw_if_index=self.pg6.sw_if_index,
2215 flags=flags, is_add=1)
2216 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2219 # between NAT44 inside interfaces with same VRF (no translation)
2220 pkts = self.create_stream_in(self.pg4, self.pg5)
2221 self.pg4.add_stream(pkts)
2222 self.pg_enable_capture(self.pg_interfaces)
2224 capture = self.pg5.get_capture(len(pkts))
2225 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2227 # between NAT44 inside interfaces with different VRF (hairpinning)
2228 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2229 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2230 TCP(sport=1234, dport=5678))
2231 self.pg4.add_stream(p)
2232 self.pg_enable_capture(self.pg_interfaces)
2234 capture = self.pg6.get_capture(1)
2239 self.assertEqual(ip.src, self.nat_addr)
2240 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2241 self.assertNotEqual(tcp.sport, 1234)
2242 self.assertEqual(tcp.dport, 5678)
2244 self.logger.error(ppp("Unexpected or invalid packet:", p))
2247 # in2out 1st interface
2248 pkts = self.create_stream_in(self.pg4, self.pg3)
2249 self.pg4.add_stream(pkts)
2250 self.pg_enable_capture(self.pg_interfaces)
2252 capture = self.pg3.get_capture(len(pkts))
2253 self.verify_capture_out(capture)
2255 # out2in 1st interface
2256 pkts = self.create_stream_out(self.pg3)
2257 self.pg3.add_stream(pkts)
2258 self.pg_enable_capture(self.pg_interfaces)
2260 capture = self.pg4.get_capture(len(pkts))
2261 self.verify_capture_in(capture, self.pg4)
2263 # in2out 2nd interface
2264 pkts = self.create_stream_in(self.pg5, self.pg3)
2265 self.pg5.add_stream(pkts)
2266 self.pg_enable_capture(self.pg_interfaces)
2268 capture = self.pg3.get_capture(len(pkts))
2269 self.verify_capture_out(capture)
2271 # out2in 2nd interface
2272 pkts = self.create_stream_out(self.pg3)
2273 self.pg3.add_stream(pkts)
2274 self.pg_enable_capture(self.pg_interfaces)
2276 capture = self.pg5.get_capture(len(pkts))
2277 self.verify_capture_in(capture, self.pg5)
2280 addresses = self.vapi.nat44_address_dump()
2281 self.assertEqual(len(addresses), 1)
2282 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4, 10)
2283 self.assertEqual(len(sessions), 3)
2284 for session in sessions:
2285 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2286 self.assertEqual(str(session.inside_ip_address),
2287 self.pg5.remote_ip4)
2288 self.assertEqual(session.outside_ip_address,
2289 addresses[0].ip_address)
2290 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2291 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2292 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2293 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2294 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2295 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2296 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2297 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2298 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2300 # in2out 3rd interface
2301 pkts = self.create_stream_in(self.pg6, self.pg3)
2302 self.pg6.add_stream(pkts)
2303 self.pg_enable_capture(self.pg_interfaces)
2305 capture = self.pg3.get_capture(len(pkts))
2306 self.verify_capture_out(capture, static_nat_ip, True)
2308 # out2in 3rd interface
2309 pkts = self.create_stream_out(self.pg3, static_nat_ip)
2310 self.pg3.add_stream(pkts)
2311 self.pg_enable_capture(self.pg_interfaces)
2313 capture = self.pg6.get_capture(len(pkts))
2314 self.verify_capture_in(capture, self.pg6)
2316 # general user and session dump verifications
2317 users = self.vapi.nat44_user_dump()
2318 self.assertGreaterEqual(len(users), 3)
2319 addresses = self.vapi.nat44_address_dump()
2320 self.assertEqual(len(addresses), 1)
2322 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2324 for session in sessions:
2325 self.assertEqual(user.ip_address, session.inside_ip_address)
2326 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2327 self.assertTrue(session.protocol in
2328 [IP_PROTOS.tcp, IP_PROTOS.udp,
2330 self.assertFalse(session.flags &
2331 self.config_flags.NAT_IS_EXT_HOST_VALID)
2334 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4, 10)
2335 self.assertGreaterEqual(len(sessions), 4)
2336 for session in sessions:
2337 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2338 self.assertEqual(str(session.inside_ip_address),
2339 self.pg4.remote_ip4)
2340 self.assertEqual(session.outside_ip_address,
2341 addresses[0].ip_address)
2344 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4, 20)
2345 self.assertGreaterEqual(len(sessions), 3)
2346 for session in sessions:
2347 self.assertTrue(session.flags & self.config_flags.NAT_IS_STATIC)
2348 self.assertEqual(str(session.inside_ip_address),
2349 self.pg6.remote_ip4)
2350 self.assertEqual(str(session.outside_ip_address),
2352 self.assertTrue(session.inside_port in
2353 [self.tcp_port_in, self.udp_port_in,
2356 def test_hairpinning(self):
2357 """ NAT44 hairpinning - 1:1 NAPT """
2359 host = self.pg0.remote_hosts[0]
2360 server = self.pg0.remote_hosts[1]
2363 server_in_port = 5678
2364 server_out_port = 8765
2366 self.nat44_add_address(self.nat_addr)
2367 flags = self.config_flags.NAT_IS_INSIDE
2368 self.vapi.nat44_interface_add_del_feature(
2369 sw_if_index=self.pg0.sw_if_index,
2370 flags=flags, is_add=1)
2371 self.vapi.nat44_interface_add_del_feature(
2372 sw_if_index=self.pg1.sw_if_index,
2375 # add static mapping for server
2376 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2377 server_in_port, server_out_port,
2378 proto=IP_PROTOS.tcp)
2380 # send packet from host to server
2381 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2382 IP(src=host.ip4, dst=self.nat_addr) /
2383 TCP(sport=host_in_port, dport=server_out_port))
2384 self.pg0.add_stream(p)
2385 self.pg_enable_capture(self.pg_interfaces)
2387 capture = self.pg0.get_capture(1)
2392 self.assertEqual(ip.src, self.nat_addr)
2393 self.assertEqual(ip.dst, server.ip4)
2394 self.assertNotEqual(tcp.sport, host_in_port)
2395 self.assertEqual(tcp.dport, server_in_port)
2396 self.assert_packet_checksums_valid(p)
2397 host_out_port = tcp.sport
2399 self.logger.error(ppp("Unexpected or invalid packet:", p))
2402 # send reply from server to host
2403 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2404 IP(src=server.ip4, dst=self.nat_addr) /
2405 TCP(sport=server_in_port, dport=host_out_port))
2406 self.pg0.add_stream(p)
2407 self.pg_enable_capture(self.pg_interfaces)
2409 capture = self.pg0.get_capture(1)
2414 self.assertEqual(ip.src, self.nat_addr)
2415 self.assertEqual(ip.dst, host.ip4)
2416 self.assertEqual(tcp.sport, server_out_port)
2417 self.assertEqual(tcp.dport, host_in_port)
2418 self.assert_packet_checksums_valid(p)
2420 self.logger.error(ppp("Unexpected or invalid packet:", p))
2423 def test_hairpinning2(self):
2424 """ NAT44 hairpinning - 1:1 NAT"""
2426 server1_nat_ip = "10.0.0.10"
2427 server2_nat_ip = "10.0.0.11"
2428 host = self.pg0.remote_hosts[0]
2429 server1 = self.pg0.remote_hosts[1]
2430 server2 = self.pg0.remote_hosts[2]
2431 server_tcp_port = 22
2432 server_udp_port = 20
2434 self.nat44_add_address(self.nat_addr)
2435 flags = self.config_flags.NAT_IS_INSIDE
2436 self.vapi.nat44_interface_add_del_feature(
2437 sw_if_index=self.pg0.sw_if_index,
2438 flags=flags, is_add=1)
2439 self.vapi.nat44_interface_add_del_feature(
2440 sw_if_index=self.pg1.sw_if_index,
2443 # add static mapping for servers
2444 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2445 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
2449 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2450 IP(src=host.ip4, dst=server1_nat_ip) /
2451 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2453 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2454 IP(src=host.ip4, dst=server1_nat_ip) /
2455 UDP(sport=self.udp_port_in, dport=server_udp_port))
2457 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2458 IP(src=host.ip4, dst=server1_nat_ip) /
2459 ICMP(id=self.icmp_id_in, type='echo-request'))
2461 self.pg0.add_stream(pkts)
2462 self.pg_enable_capture(self.pg_interfaces)
2464 capture = self.pg0.get_capture(len(pkts))
2465 for packet in capture:
2467 self.assertEqual(packet[IP].src, self.nat_addr)
2468 self.assertEqual(packet[IP].dst, server1.ip4)
2469 if packet.haslayer(TCP):
2470 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2471 self.assertEqual(packet[TCP].dport, server_tcp_port)
2472 self.tcp_port_out = packet[TCP].sport
2473 self.assert_packet_checksums_valid(packet)
2474 elif packet.haslayer(UDP):
2475 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2476 self.assertEqual(packet[UDP].dport, server_udp_port)
2477 self.udp_port_out = packet[UDP].sport
2479 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2480 self.icmp_id_out = packet[ICMP].id
2482 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2487 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2488 IP(src=server1.ip4, dst=self.nat_addr) /
2489 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2491 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2492 IP(src=server1.ip4, dst=self.nat_addr) /
2493 UDP(sport=server_udp_port, dport=self.udp_port_out))
2495 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2496 IP(src=server1.ip4, dst=self.nat_addr) /
2497 ICMP(id=self.icmp_id_out, type='echo-reply'))
2499 self.pg0.add_stream(pkts)
2500 self.pg_enable_capture(self.pg_interfaces)
2502 capture = self.pg0.get_capture(len(pkts))
2503 for packet in capture:
2505 self.assertEqual(packet[IP].src, server1_nat_ip)
2506 self.assertEqual(packet[IP].dst, host.ip4)
2507 if packet.haslayer(TCP):
2508 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2509 self.assertEqual(packet[TCP].sport, server_tcp_port)
2510 self.assert_packet_checksums_valid(packet)
2511 elif packet.haslayer(UDP):
2512 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2513 self.assertEqual(packet[UDP].sport, server_udp_port)
2515 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2517 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2520 # server2 to server1
2522 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2523 IP(src=server2.ip4, dst=server1_nat_ip) /
2524 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2526 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2527 IP(src=server2.ip4, dst=server1_nat_ip) /
2528 UDP(sport=self.udp_port_in, dport=server_udp_port))
2530 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2531 IP(src=server2.ip4, dst=server1_nat_ip) /
2532 ICMP(id=self.icmp_id_in, type='echo-request'))
2534 self.pg0.add_stream(pkts)
2535 self.pg_enable_capture(self.pg_interfaces)
2537 capture = self.pg0.get_capture(len(pkts))
2538 for packet in capture:
2540 self.assertEqual(packet[IP].src, server2_nat_ip)
2541 self.assertEqual(packet[IP].dst, server1.ip4)
2542 if packet.haslayer(TCP):
2543 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2544 self.assertEqual(packet[TCP].dport, server_tcp_port)
2545 self.tcp_port_out = packet[TCP].sport
2546 self.assert_packet_checksums_valid(packet)
2547 elif packet.haslayer(UDP):
2548 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2549 self.assertEqual(packet[UDP].dport, server_udp_port)
2550 self.udp_port_out = packet[UDP].sport
2552 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2553 self.icmp_id_out = packet[ICMP].id
2555 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2558 # server1 to server2
2560 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2561 IP(src=server1.ip4, dst=server2_nat_ip) /
2562 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2564 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2565 IP(src=server1.ip4, dst=server2_nat_ip) /
2566 UDP(sport=server_udp_port, dport=self.udp_port_out))
2568 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2569 IP(src=server1.ip4, dst=server2_nat_ip) /
2570 ICMP(id=self.icmp_id_out, type='echo-reply'))
2572 self.pg0.add_stream(pkts)
2573 self.pg_enable_capture(self.pg_interfaces)
2575 capture = self.pg0.get_capture(len(pkts))
2576 for packet in capture:
2578 self.assertEqual(packet[IP].src, server1_nat_ip)
2579 self.assertEqual(packet[IP].dst, server2.ip4)
2580 if packet.haslayer(TCP):
2581 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2582 self.assertEqual(packet[TCP].sport, server_tcp_port)
2583 self.assert_packet_checksums_valid(packet)
2584 elif packet.haslayer(UDP):
2585 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2586 self.assertEqual(packet[UDP].sport, server_udp_port)
2588 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2590 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2593 def test_interface_addr(self):
2594 """ Acquire NAT44 addresses from interface """
2595 self.vapi.nat44_add_del_interface_addr(
2597 sw_if_index=self.pg7.sw_if_index)
2599 # no address in NAT pool
2600 addresses = self.vapi.nat44_address_dump()
2601 self.assertEqual(0, len(addresses))
2603 # configure interface address and check NAT address pool
2604 self.pg7.config_ip4()
2605 addresses = self.vapi.nat44_address_dump()
2606 self.assertEqual(1, len(addresses))
2607 self.assertEqual(str(addresses[0].ip_address), self.pg7.local_ip4)
2609 # remove interface address and check NAT address pool
2610 self.pg7.unconfig_ip4()
2611 addresses = self.vapi.nat44_address_dump()
2612 self.assertEqual(0, len(addresses))
2614 def test_interface_addr_static_mapping(self):
2615 """ Static mapping with addresses from interface """
2618 self.vapi.nat44_add_del_interface_addr(
2620 sw_if_index=self.pg7.sw_if_index)
2621 self.nat44_add_static_mapping(
2623 external_sw_if_index=self.pg7.sw_if_index,
2626 # static mappings with external interface
2627 static_mappings = self.vapi.nat44_static_mapping_dump()
2628 self.assertEqual(1, len(static_mappings))
2629 self.assertEqual(self.pg7.sw_if_index,
2630 static_mappings[0].external_sw_if_index)
2631 self.assertEqual(static_mappings[0].tag, tag)
2633 # configure interface address and check static mappings
2634 self.pg7.config_ip4()
2635 static_mappings = self.vapi.nat44_static_mapping_dump()
2636 self.assertEqual(2, len(static_mappings))
2638 for sm in static_mappings:
2639 if sm.external_sw_if_index == 0xFFFFFFFF:
2640 self.assertEqual(str(sm.external_ip_address),
2642 self.assertEqual(sm.tag, tag)
2644 self.assertTrue(resolved)
2646 # remove interface address and check static mappings
2647 self.pg7.unconfig_ip4()
2648 static_mappings = self.vapi.nat44_static_mapping_dump()
2649 self.assertEqual(1, len(static_mappings))
2650 self.assertEqual(self.pg7.sw_if_index,
2651 static_mappings[0].external_sw_if_index)
2652 self.assertEqual(static_mappings[0].tag, tag)
2654 # configure interface address again and check static mappings
2655 self.pg7.config_ip4()
2656 static_mappings = self.vapi.nat44_static_mapping_dump()
2657 self.assertEqual(2, len(static_mappings))
2659 for sm in static_mappings:
2660 if sm.external_sw_if_index == 0xFFFFFFFF:
2661 self.assertEqual(str(sm.external_ip_address),
2663 self.assertEqual(sm.tag, tag)
2665 self.assertTrue(resolved)
2667 # remove static mapping
2668 self.nat44_add_static_mapping(
2670 external_sw_if_index=self.pg7.sw_if_index,
2673 static_mappings = self.vapi.nat44_static_mapping_dump()
2674 self.assertEqual(0, len(static_mappings))
2676 def test_interface_addr_identity_nat(self):
2677 """ Identity NAT with addresses from interface """
2680 self.vapi.nat44_add_del_interface_addr(
2682 sw_if_index=self.pg7.sw_if_index)
2683 self.vapi.nat44_add_del_identity_mapping(
2685 sw_if_index=self.pg7.sw_if_index,
2687 protocol=IP_PROTOS.tcp,
2690 # identity mappings with external interface
2691 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2692 self.assertEqual(1, len(identity_mappings))
2693 self.assertEqual(self.pg7.sw_if_index,
2694 identity_mappings[0].sw_if_index)
2696 # configure interface address and check identity mappings
2697 self.pg7.config_ip4()
2698 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2700 self.assertEqual(2, len(identity_mappings))
2701 for sm in identity_mappings:
2702 if sm.sw_if_index == 0xFFFFFFFF:
2703 self.assertEqual(str(identity_mappings[0].ip_address),
2705 self.assertEqual(port, identity_mappings[0].port)
2706 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2708 self.assertTrue(resolved)
2710 # remove interface address and check identity mappings
2711 self.pg7.unconfig_ip4()
2712 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2713 self.assertEqual(1, len(identity_mappings))
2714 self.assertEqual(self.pg7.sw_if_index,
2715 identity_mappings[0].sw_if_index)
2717 def test_ipfix_nat44_sess(self):
2718 """ IPFIX logging NAT44 session created/deleted """
2719 self.ipfix_domain_id = 10
2720 self.ipfix_src_port = 20202
2721 collector_port = 30303
2722 bind_layers(UDP, IPFIX, dport=30303)
2723 self.nat44_add_address(self.nat_addr)
2724 flags = self.config_flags.NAT_IS_INSIDE
2725 self.vapi.nat44_interface_add_del_feature(
2726 sw_if_index=self.pg0.sw_if_index,
2727 flags=flags, is_add=1)
2728 self.vapi.nat44_interface_add_del_feature(
2729 sw_if_index=self.pg1.sw_if_index,
2731 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2732 src_address=self.pg3.local_ip4,
2734 template_interval=10,
2735 collector_port=collector_port)
2736 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2737 src_port=self.ipfix_src_port,
2740 pkts = self.create_stream_in(self.pg0, self.pg1)
2741 self.pg0.add_stream(pkts)
2742 self.pg_enable_capture(self.pg_interfaces)
2744 capture = self.pg1.get_capture(len(pkts))
2745 self.verify_capture_out(capture)
2746 self.nat44_add_address(self.nat_addr, is_add=0)
2747 self.vapi.ipfix_flush()
2748 capture = self.pg3.get_capture(9)
2749 ipfix = IPFIXDecoder()
2750 # first load template
2752 self.assertTrue(p.haslayer(IPFIX))
2753 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2754 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2755 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2756 self.assertEqual(p[UDP].dport, collector_port)
2757 self.assertEqual(p[IPFIX].observationDomainID,
2758 self.ipfix_domain_id)
2759 if p.haslayer(Template):
2760 ipfix.add_template(p.getlayer(Template))
2761 # verify events in data set
2763 if p.haslayer(Data):
2764 data = ipfix.decode_data_set(p.getlayer(Set))
2765 self.verify_ipfix_nat44_ses(data)
2767 def test_ipfix_addr_exhausted(self):
2768 """ IPFIX logging NAT addresses exhausted """
2769 flags = self.config_flags.NAT_IS_INSIDE
2770 self.vapi.nat44_interface_add_del_feature(
2771 sw_if_index=self.pg0.sw_if_index,
2772 flags=flags, is_add=1)
2773 self.vapi.nat44_interface_add_del_feature(
2774 sw_if_index=self.pg1.sw_if_index,
2776 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2777 src_address=self.pg3.local_ip4,
2779 template_interval=10)
2780 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2781 src_port=self.ipfix_src_port,
2784 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2785 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2787 self.pg0.add_stream(p)
2788 self.pg_enable_capture(self.pg_interfaces)
2790 self.pg1.assert_nothing_captured()
2792 self.vapi.ipfix_flush()
2793 capture = self.pg3.get_capture(9)
2794 ipfix = IPFIXDecoder()
2795 # first load template
2797 self.assertTrue(p.haslayer(IPFIX))
2798 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2799 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2800 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2801 self.assertEqual(p[UDP].dport, 4739)
2802 self.assertEqual(p[IPFIX].observationDomainID,
2803 self.ipfix_domain_id)
2804 if p.haslayer(Template):
2805 ipfix.add_template(p.getlayer(Template))
2806 # verify events in data set
2808 if p.haslayer(Data):
2809 data = ipfix.decode_data_set(p.getlayer(Set))
2810 self.verify_ipfix_addr_exhausted(data)
2812 @unittest.skipUnless(running_extended_tests, "part of extended tests")
2813 def test_ipfix_max_sessions(self):
2814 """ IPFIX logging maximum session entries exceeded """
2815 self.nat44_add_address(self.nat_addr)
2816 flags = self.config_flags.NAT_IS_INSIDE
2817 self.vapi.nat44_interface_add_del_feature(
2818 sw_if_index=self.pg0.sw_if_index,
2819 flags=flags, is_add=1)
2820 self.vapi.nat44_interface_add_del_feature(
2821 sw_if_index=self.pg1.sw_if_index,
2824 nat44_config = self.vapi.nat_show_config()
2825 max_sessions = 10 * nat44_config.translation_buckets
2828 for i in range(0, max_sessions):
2829 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2830 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2831 IP(src=src, dst=self.pg1.remote_ip4) /
2834 self.pg0.add_stream(pkts)
2835 self.pg_enable_capture(self.pg_interfaces)
2838 self.pg1.get_capture(max_sessions)
2839 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2840 src_address=self.pg3.local_ip4,
2842 template_interval=10)
2843 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2844 src_port=self.ipfix_src_port,
2847 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2848 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2850 self.pg0.add_stream(p)
2851 self.pg_enable_capture(self.pg_interfaces)
2853 self.pg1.assert_nothing_captured()
2855 self.vapi.ipfix_flush()
2856 capture = self.pg3.get_capture(9)
2857 ipfix = IPFIXDecoder()
2858 # first load template
2860 self.assertTrue(p.haslayer(IPFIX))
2861 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2862 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2863 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2864 self.assertEqual(p[UDP].dport, 4739)
2865 self.assertEqual(p[IPFIX].observationDomainID,
2866 self.ipfix_domain_id)
2867 if p.haslayer(Template):
2868 ipfix.add_template(p.getlayer(Template))
2869 # verify events in data set
2871 if p.haslayer(Data):
2872 data = ipfix.decode_data_set(p.getlayer(Set))
2873 self.verify_ipfix_max_sessions(data, max_sessions)
2875 def test_syslog_apmap(self):
2876 """ Test syslog address and port mapping creation and deletion """
2877 self.vapi.syslog_set_filter(
2878 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
2879 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
2880 self.nat44_add_address(self.nat_addr)
2881 flags = self.config_flags.NAT_IS_INSIDE
2882 self.vapi.nat44_interface_add_del_feature(
2883 sw_if_index=self.pg0.sw_if_index,
2884 flags=flags, is_add=1)
2885 self.vapi.nat44_interface_add_del_feature(
2886 sw_if_index=self.pg1.sw_if_index,
2889 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2890 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2891 TCP(sport=self.tcp_port_in, dport=20))
2892 self.pg0.add_stream(p)
2893 self.pg_enable_capture(self.pg_interfaces)
2895 capture = self.pg1.get_capture(1)
2896 self.tcp_port_out = capture[0][TCP].sport
2897 capture = self.pg3.get_capture(1)
2898 self.verify_syslog_apmap(capture[0][Raw].load)
2900 self.pg_enable_capture(self.pg_interfaces)
2902 self.nat44_add_address(self.nat_addr, is_add=0)
2903 capture = self.pg3.get_capture(1)
2904 self.verify_syslog_apmap(capture[0][Raw].load, False)
2906 def test_pool_addr_fib(self):
2907 """ NAT44 add pool addresses to FIB """
2908 static_addr = '10.0.0.10'
2909 self.nat44_add_address(self.nat_addr)
2910 flags = self.config_flags.NAT_IS_INSIDE
2911 self.vapi.nat44_interface_add_del_feature(
2912 sw_if_index=self.pg0.sw_if_index,
2913 flags=flags, is_add=1)
2914 self.vapi.nat44_interface_add_del_feature(
2915 sw_if_index=self.pg1.sw_if_index,
2917 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
2920 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2921 ARP(op=ARP.who_has, pdst=self.nat_addr,
2922 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2923 self.pg1.add_stream(p)
2924 self.pg_enable_capture(self.pg_interfaces)
2926 capture = self.pg1.get_capture(1)
2927 self.assertTrue(capture[0].haslayer(ARP))
2928 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2931 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2932 ARP(op=ARP.who_has, pdst=static_addr,
2933 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2934 self.pg1.add_stream(p)
2935 self.pg_enable_capture(self.pg_interfaces)
2937 capture = self.pg1.get_capture(1)
2938 self.assertTrue(capture[0].haslayer(ARP))
2939 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2941 # send ARP to non-NAT44 interface
2942 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2943 ARP(op=ARP.who_has, pdst=self.nat_addr,
2944 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2945 self.pg2.add_stream(p)
2946 self.pg_enable_capture(self.pg_interfaces)
2948 self.pg1.assert_nothing_captured()
2950 # remove addresses and verify
2951 self.nat44_add_address(self.nat_addr, is_add=0)
2952 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2955 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2956 ARP(op=ARP.who_has, pdst=self.nat_addr,
2957 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2958 self.pg1.add_stream(p)
2959 self.pg_enable_capture(self.pg_interfaces)
2961 self.pg1.assert_nothing_captured()
2963 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2964 ARP(op=ARP.who_has, pdst=static_addr,
2965 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2966 self.pg1.add_stream(p)
2967 self.pg_enable_capture(self.pg_interfaces)
2969 self.pg1.assert_nothing_captured()
2971 def test_vrf_mode(self):
2972 """ NAT44 tenant VRF aware address pool mode """
2976 nat_ip1 = "10.0.0.10"
2977 nat_ip2 = "10.0.0.11"
2979 self.pg0.unconfig_ip4()
2980 self.pg1.unconfig_ip4()
2981 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
2982 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
2983 self.pg0.set_table_ip4(vrf_id1)
2984 self.pg1.set_table_ip4(vrf_id2)
2985 self.pg0.config_ip4()
2986 self.pg1.config_ip4()
2987 self.pg0.resolve_arp()
2988 self.pg1.resolve_arp()
2990 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2991 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2992 flags = self.config_flags.NAT_IS_INSIDE
2993 self.vapi.nat44_interface_add_del_feature(
2994 sw_if_index=self.pg0.sw_if_index,
2995 flags=flags, is_add=1)
2996 self.vapi.nat44_interface_add_del_feature(
2997 sw_if_index=self.pg1.sw_if_index,
2998 flags=flags, is_add=1)
2999 self.vapi.nat44_interface_add_del_feature(
3000 sw_if_index=self.pg2.sw_if_index,
3005 pkts = self.create_stream_in(self.pg0, self.pg2)
3006 self.pg0.add_stream(pkts)
3007 self.pg_enable_capture(self.pg_interfaces)
3009 capture = self.pg2.get_capture(len(pkts))
3010 self.verify_capture_out(capture, nat_ip1)
3013 pkts = self.create_stream_in(self.pg1, self.pg2)
3014 self.pg1.add_stream(pkts)
3015 self.pg_enable_capture(self.pg_interfaces)
3017 capture = self.pg2.get_capture(len(pkts))
3018 self.verify_capture_out(capture, nat_ip2)
3021 self.pg0.unconfig_ip4()
3022 self.pg1.unconfig_ip4()
3023 self.pg0.set_table_ip4(0)
3024 self.pg1.set_table_ip4(0)
3025 self.pg0.config_ip4()
3026 self.pg1.config_ip4()
3027 self.pg0.resolve_arp()
3028 self.pg1.resolve_arp()
3029 self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id1})
3030 self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id2})
3032 def test_vrf_feature_independent(self):
3033 """ NAT44 tenant VRF independent address pool mode """
3035 nat_ip1 = "10.0.0.10"
3036 nat_ip2 = "10.0.0.11"
3038 self.nat44_add_address(nat_ip1)
3039 self.nat44_add_address(nat_ip2, vrf_id=99)
3040 flags = self.config_flags.NAT_IS_INSIDE
3041 self.vapi.nat44_interface_add_del_feature(
3042 sw_if_index=self.pg0.sw_if_index,
3043 flags=flags, is_add=1)
3044 self.vapi.nat44_interface_add_del_feature(
3045 sw_if_index=self.pg1.sw_if_index,
3046 flags=flags, is_add=1)
3047 self.vapi.nat44_interface_add_del_feature(
3048 sw_if_index=self.pg2.sw_if_index,
3052 pkts = self.create_stream_in(self.pg0, self.pg2)
3053 self.pg0.add_stream(pkts)
3054 self.pg_enable_capture(self.pg_interfaces)
3056 capture = self.pg2.get_capture(len(pkts))
3057 self.verify_capture_out(capture, nat_ip1)
3060 pkts = self.create_stream_in(self.pg1, self.pg2)
3061 self.pg1.add_stream(pkts)
3062 self.pg_enable_capture(self.pg_interfaces)
3064 capture = self.pg2.get_capture(len(pkts))
3065 self.verify_capture_out(capture, nat_ip1)
3067 def create_routes_and_neigbors(self):
3068 r1 = VppIpRoute(self, self.pg7.remote_ip4, 32,
3069 [VppRoutePath(self.pg7.remote_ip4,
3070 self.pg7.sw_if_index)])
3071 r2 = VppIpRoute(self, self.pg8.remote_ip4, 32,
3072 [VppRoutePath(self.pg8.remote_ip4,
3073 self.pg8.sw_if_index)])
3077 n1 = VppNeighbor(self,
3078 self.pg7.sw_if_index,
3079 self.pg7.remote_mac,
3080 self.pg7.remote_ip4,
3082 n2 = VppNeighbor(self,
3083 self.pg8.sw_if_index,
3084 self.pg8.remote_mac,
3085 self.pg8.remote_ip4,
3090 def test_dynamic_ipless_interfaces(self):
3091 """ NAT44 interfaces without configured IP address """
3092 self.create_routes_and_neigbors()
3093 self.nat44_add_address(self.nat_addr)
3094 flags = self.config_flags.NAT_IS_INSIDE
3095 self.vapi.nat44_interface_add_del_feature(
3096 sw_if_index=self.pg7.sw_if_index,
3097 flags=flags, is_add=1)
3098 self.vapi.nat44_interface_add_del_feature(
3099 sw_if_index=self.pg8.sw_if_index,
3103 pkts = self.create_stream_in(self.pg7, self.pg8)
3104 self.pg7.add_stream(pkts)
3105 self.pg_enable_capture(self.pg_interfaces)
3107 capture = self.pg8.get_capture(len(pkts))
3108 self.verify_capture_out(capture)
3111 pkts = self.create_stream_out(self.pg8, self.nat_addr)
3112 self.pg8.add_stream(pkts)
3113 self.pg_enable_capture(self.pg_interfaces)
3115 capture = self.pg7.get_capture(len(pkts))
3116 self.verify_capture_in(capture, self.pg7)
3118 def test_static_ipless_interfaces(self):
3119 """ NAT44 interfaces without configured IP address - 1:1 NAT """
3121 self.create_routes_and_neigbors()
3122 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
3123 flags = self.config_flags.NAT_IS_INSIDE
3124 self.vapi.nat44_interface_add_del_feature(
3125 sw_if_index=self.pg7.sw_if_index,
3126 flags=flags, is_add=1)
3127 self.vapi.nat44_interface_add_del_feature(
3128 sw_if_index=self.pg8.sw_if_index,
3132 pkts = self.create_stream_out(self.pg8)
3133 self.pg8.add_stream(pkts)
3134 self.pg_enable_capture(self.pg_interfaces)
3136 capture = self.pg7.get_capture(len(pkts))
3137 self.verify_capture_in(capture, self.pg7)
3140 pkts = self.create_stream_in(self.pg7, self.pg8)
3141 self.pg7.add_stream(pkts)
3142 self.pg_enable_capture(self.pg_interfaces)
3144 capture = self.pg8.get_capture(len(pkts))
3145 self.verify_capture_out(capture, self.nat_addr, True)
3147 def test_static_with_port_ipless_interfaces(self):
3148 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
3150 self.tcp_port_out = 30606
3151 self.udp_port_out = 30607
3152 self.icmp_id_out = 30608
3154 self.create_routes_and_neigbors()
3155 self.nat44_add_address(self.nat_addr)
3156 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3157 self.tcp_port_in, self.tcp_port_out,
3158 proto=IP_PROTOS.tcp)
3159 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3160 self.udp_port_in, self.udp_port_out,
3161 proto=IP_PROTOS.udp)
3162 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3163 self.icmp_id_in, self.icmp_id_out,
3164 proto=IP_PROTOS.icmp)
3165 flags = self.config_flags.NAT_IS_INSIDE
3166 self.vapi.nat44_interface_add_del_feature(
3167 sw_if_index=self.pg7.sw_if_index,
3168 flags=flags, is_add=1)
3169 self.vapi.nat44_interface_add_del_feature(
3170 sw_if_index=self.pg8.sw_if_index,
3174 pkts = self.create_stream_out(self.pg8)
3175 self.pg8.add_stream(pkts)
3176 self.pg_enable_capture(self.pg_interfaces)
3178 capture = self.pg7.get_capture(len(pkts))
3179 self.verify_capture_in(capture, self.pg7)
3182 pkts = self.create_stream_in(self.pg7, self.pg8)
3183 self.pg7.add_stream(pkts)
3184 self.pg_enable_capture(self.pg_interfaces)
3186 capture = self.pg8.get_capture(len(pkts))
3187 self.verify_capture_out(capture)
3189 def test_static_unknown_proto(self):
3190 """ 1:1 NAT translate packet with unknown protocol """
3191 nat_ip = "10.0.0.10"
3192 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
3193 flags = self.config_flags.NAT_IS_INSIDE
3194 self.vapi.nat44_interface_add_del_feature(
3195 sw_if_index=self.pg0.sw_if_index,
3196 flags=flags, is_add=1)
3197 self.vapi.nat44_interface_add_del_feature(
3198 sw_if_index=self.pg1.sw_if_index,
3202 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3203 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3205 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3206 TCP(sport=1234, dport=1234))
3207 self.pg0.add_stream(p)
3208 self.pg_enable_capture(self.pg_interfaces)
3210 p = self.pg1.get_capture(1)
3213 self.assertEqual(packet[IP].src, nat_ip)
3214 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3215 self.assertEqual(packet.haslayer(GRE), 1)
3216 self.assert_packet_checksums_valid(packet)
3218 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3222 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3223 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3225 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3226 TCP(sport=1234, dport=1234))
3227 self.pg1.add_stream(p)
3228 self.pg_enable_capture(self.pg_interfaces)
3230 p = self.pg0.get_capture(1)
3233 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3234 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3235 self.assertEqual(packet.haslayer(GRE), 1)
3236 self.assert_packet_checksums_valid(packet)
3238 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3241 def test_hairpinning_static_unknown_proto(self):
3242 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3244 host = self.pg0.remote_hosts[0]
3245 server = self.pg0.remote_hosts[1]
3247 host_nat_ip = "10.0.0.10"
3248 server_nat_ip = "10.0.0.11"
3250 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3251 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3252 flags = self.config_flags.NAT_IS_INSIDE
3253 self.vapi.nat44_interface_add_del_feature(
3254 sw_if_index=self.pg0.sw_if_index,
3255 flags=flags, is_add=1)
3256 self.vapi.nat44_interface_add_del_feature(
3257 sw_if_index=self.pg1.sw_if_index,
3261 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3262 IP(src=host.ip4, dst=server_nat_ip) /
3264 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3265 TCP(sport=1234, dport=1234))
3266 self.pg0.add_stream(p)
3267 self.pg_enable_capture(self.pg_interfaces)
3269 p = self.pg0.get_capture(1)
3272 self.assertEqual(packet[IP].src, host_nat_ip)
3273 self.assertEqual(packet[IP].dst, server.ip4)
3274 self.assertEqual(packet.haslayer(GRE), 1)
3275 self.assert_packet_checksums_valid(packet)
3277 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3281 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3282 IP(src=server.ip4, dst=host_nat_ip) /
3284 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3285 TCP(sport=1234, dport=1234))
3286 self.pg0.add_stream(p)
3287 self.pg_enable_capture(self.pg_interfaces)
3289 p = self.pg0.get_capture(1)
3292 self.assertEqual(packet[IP].src, server_nat_ip)
3293 self.assertEqual(packet[IP].dst, host.ip4)
3294 self.assertEqual(packet.haslayer(GRE), 1)
3295 self.assert_packet_checksums_valid(packet)
3297 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3300 def test_output_feature(self):
3301 """ NAT44 interface output feature (in2out postrouting) """
3302 self.nat44_add_address(self.nat_addr)
3303 flags = self.config_flags.NAT_IS_INSIDE
3304 self.vapi.nat44_interface_add_del_output_feature(
3305 is_add=1, flags=flags,
3306 sw_if_index=self.pg0.sw_if_index)
3307 self.vapi.nat44_interface_add_del_output_feature(
3308 is_add=1, flags=flags,
3309 sw_if_index=self.pg1.sw_if_index)
3310 self.vapi.nat44_interface_add_del_output_feature(
3312 sw_if_index=self.pg3.sw_if_index)
3315 pkts = self.create_stream_in(self.pg0, self.pg3)
3316 self.pg0.add_stream(pkts)
3317 self.pg_enable_capture(self.pg_interfaces)
3319 capture = self.pg3.get_capture(len(pkts))
3320 self.verify_capture_out(capture)
3323 pkts = self.create_stream_out(self.pg3)
3324 self.pg3.add_stream(pkts)
3325 self.pg_enable_capture(self.pg_interfaces)
3327 capture = self.pg0.get_capture(len(pkts))
3328 self.verify_capture_in(capture, self.pg0)
3330 # from non-NAT interface to NAT inside interface
3331 pkts = self.create_stream_in(self.pg2, self.pg0)
3332 self.pg2.add_stream(pkts)
3333 self.pg_enable_capture(self.pg_interfaces)
3335 capture = self.pg0.get_capture(len(pkts))
3336 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3338 def test_output_feature_vrf_aware(self):
3339 """ NAT44 interface output feature VRF aware (in2out postrouting) """
3340 nat_ip_vrf10 = "10.0.0.10"
3341 nat_ip_vrf20 = "10.0.0.20"
3343 r1 = VppIpRoute(self, self.pg3.remote_ip4, 32,
3344 [VppRoutePath(self.pg3.remote_ip4,
3345 self.pg3.sw_if_index)],
3347 r2 = VppIpRoute(self, self.pg3.remote_ip4, 32,
3348 [VppRoutePath(self.pg3.remote_ip4,
3349 self.pg3.sw_if_index)],
3354 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3355 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3356 flags = self.config_flags.NAT_IS_INSIDE
3357 self.vapi.nat44_interface_add_del_output_feature(
3358 is_add=1, flags=flags,
3359 sw_if_index=self.pg4.sw_if_index)
3360 self.vapi.nat44_interface_add_del_output_feature(
3361 is_add=1, flags=flags,
3362 sw_if_index=self.pg6.sw_if_index)
3363 self.vapi.nat44_interface_add_del_output_feature(
3365 sw_if_index=self.pg3.sw_if_index)
3368 pkts = self.create_stream_in(self.pg4, self.pg3)
3369 self.pg4.add_stream(pkts)
3370 self.pg_enable_capture(self.pg_interfaces)
3372 capture = self.pg3.get_capture(len(pkts))
3373 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3376 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3377 self.pg3.add_stream(pkts)
3378 self.pg_enable_capture(self.pg_interfaces)
3380 capture = self.pg4.get_capture(len(pkts))
3381 self.verify_capture_in(capture, self.pg4)
3384 pkts = self.create_stream_in(self.pg6, self.pg3)
3385 self.pg6.add_stream(pkts)
3386 self.pg_enable_capture(self.pg_interfaces)
3388 capture = self.pg3.get_capture(len(pkts))
3389 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3392 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3393 self.pg3.add_stream(pkts)
3394 self.pg_enable_capture(self.pg_interfaces)
3396 capture = self.pg6.get_capture(len(pkts))
3397 self.verify_capture_in(capture, self.pg6)
3399 def test_output_feature_hairpinning(self):
3400 """ NAT44 interface output feature hairpinning (in2out postrouting) """
3401 host = self.pg0.remote_hosts[0]
3402 server = self.pg0.remote_hosts[1]
3405 server_in_port = 5678
3406 server_out_port = 8765
3408 self.nat44_add_address(self.nat_addr)
3409 flags = self.config_flags.NAT_IS_INSIDE
3410 self.vapi.nat44_interface_add_del_output_feature(
3411 is_add=1, flags=flags,
3412 sw_if_index=self.pg0.sw_if_index)
3413 self.vapi.nat44_interface_add_del_output_feature(
3415 sw_if_index=self.pg1.sw_if_index)
3417 # add static mapping for server
3418 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3419 server_in_port, server_out_port,
3420 proto=IP_PROTOS.tcp)
3422 # send packet from host to server
3423 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3424 IP(src=host.ip4, dst=self.nat_addr) /
3425 TCP(sport=host_in_port, dport=server_out_port))
3426 self.pg0.add_stream(p)
3427 self.pg_enable_capture(self.pg_interfaces)
3429 capture = self.pg0.get_capture(1)
3434 self.assertEqual(ip.src, self.nat_addr)
3435 self.assertEqual(ip.dst, server.ip4)
3436 self.assertNotEqual(tcp.sport, host_in_port)
3437 self.assertEqual(tcp.dport, server_in_port)
3438 self.assert_packet_checksums_valid(p)
3439 host_out_port = tcp.sport
3441 self.logger.error(ppp("Unexpected or invalid packet:", p))
3444 # send reply from server to host
3445 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3446 IP(src=server.ip4, dst=self.nat_addr) /
3447 TCP(sport=server_in_port, dport=host_out_port))
3448 self.pg0.add_stream(p)
3449 self.pg_enable_capture(self.pg_interfaces)
3451 capture = self.pg0.get_capture(1)
3456 self.assertEqual(ip.src, self.nat_addr)
3457 self.assertEqual(ip.dst, host.ip4)
3458 self.assertEqual(tcp.sport, server_out_port)
3459 self.assertEqual(tcp.dport, host_in_port)
3460 self.assert_packet_checksums_valid(p)
3462 self.logger.error(ppp("Unexpected or invalid packet:", p))
3465 def test_one_armed_nat44(self):
3466 """ One armed NAT44 """
3467 remote_host = self.pg9.remote_hosts[0]
3468 local_host = self.pg9.remote_hosts[1]
3471 self.nat44_add_address(self.nat_addr)
3472 flags = self.config_flags.NAT_IS_INSIDE
3473 self.vapi.nat44_interface_add_del_feature(
3474 sw_if_index=self.pg9.sw_if_index,
3476 self.vapi.nat44_interface_add_del_feature(
3477 sw_if_index=self.pg9.sw_if_index,
3478 flags=flags, is_add=1)
3481 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3482 IP(src=local_host.ip4, dst=remote_host.ip4) /
3483 TCP(sport=12345, dport=80))
3484 self.pg9.add_stream(p)
3485 self.pg_enable_capture(self.pg_interfaces)
3487 capture = self.pg9.get_capture(1)
3492 self.assertEqual(ip.src, self.nat_addr)
3493 self.assertEqual(ip.dst, remote_host.ip4)
3494 self.assertNotEqual(tcp.sport, 12345)
3495 external_port = tcp.sport
3496 self.assertEqual(tcp.dport, 80)
3497 self.assert_packet_checksums_valid(p)
3499 self.logger.error(ppp("Unexpected or invalid packet:", p))
3503 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3504 IP(src=remote_host.ip4, dst=self.nat_addr) /
3505 TCP(sport=80, dport=external_port))
3506 self.pg9.add_stream(p)
3507 self.pg_enable_capture(self.pg_interfaces)
3509 capture = self.pg9.get_capture(1)
3514 self.assertEqual(ip.src, remote_host.ip4)
3515 self.assertEqual(ip.dst, local_host.ip4)
3516 self.assertEqual(tcp.sport, 80)
3517 self.assertEqual(tcp.dport, 12345)
3518 self.assert_packet_checksums_valid(p)
3520 self.logger.error(ppp("Unexpected or invalid packet:", p))
3523 err = self.statistics.get_err_counter(
3524 '/err/nat44-classify/next in2out')
3525 self.assertEqual(err, 1)
3526 err = self.statistics.get_err_counter(
3527 '/err/nat44-classify/next out2in')
3528 self.assertEqual(err, 1)
3530 def test_del_session(self):
3531 """ Delete NAT44 session """
3532 self.nat44_add_address(self.nat_addr)
3533 flags = self.config_flags.NAT_IS_INSIDE
3534 self.vapi.nat44_interface_add_del_feature(
3535 sw_if_index=self.pg0.sw_if_index,
3536 flags=flags, is_add=1)
3537 self.vapi.nat44_interface_add_del_feature(
3538 sw_if_index=self.pg1.sw_if_index,
3541 pkts = self.create_stream_in(self.pg0, self.pg1)
3542 self.pg0.add_stream(pkts)
3543 self.pg_enable_capture(self.pg_interfaces)
3545 self.pg1.get_capture(len(pkts))
3547 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3548 nsessions = len(sessions)
3550 self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3551 port=sessions[0].inside_port,
3552 protocol=sessions[0].protocol,
3553 flags=self.config_flags.NAT_IS_INSIDE)
3554 self.vapi.nat44_del_session(address=sessions[1].outside_ip_address,
3555 port=sessions[1].outside_port,
3556 protocol=sessions[1].protocol)
3558 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3559 self.assertEqual(nsessions - len(sessions), 2)
3561 self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3562 port=sessions[0].inside_port,
3563 protocol=sessions[0].protocol,
3564 flags=self.config_flags.NAT_IS_INSIDE)
3566 self.verify_no_nat44_user()
3568 def test_frag_in_order(self):
3569 """ NAT44 translate fragments arriving in order """
3571 self.nat44_add_address(self.nat_addr)
3572 flags = self.config_flags.NAT_IS_INSIDE
3573 self.vapi.nat44_interface_add_del_feature(
3574 sw_if_index=self.pg0.sw_if_index,
3575 flags=flags, is_add=1)
3576 self.vapi.nat44_interface_add_del_feature(
3577 sw_if_index=self.pg1.sw_if_index,
3580 self.frag_in_order(proto=IP_PROTOS.tcp)
3581 self.frag_in_order(proto=IP_PROTOS.udp)
3582 self.frag_in_order(proto=IP_PROTOS.icmp)
3584 def test_frag_forwarding(self):
3585 """ NAT44 forwarding fragment test """
3586 self.vapi.nat44_add_del_interface_addr(
3588 sw_if_index=self.pg1.sw_if_index)
3589 flags = self.config_flags.NAT_IS_INSIDE
3590 self.vapi.nat44_interface_add_del_feature(
3591 sw_if_index=self.pg0.sw_if_index,
3592 flags=flags, is_add=1)
3593 self.vapi.nat44_interface_add_del_feature(
3594 sw_if_index=self.pg1.sw_if_index,
3596 self.vapi.nat44_forwarding_enable_disable(enable=1)
3598 data = b"A" * 16 + b"B" * 16 + b"C" * 3
3599 pkts = self.create_stream_frag(self.pg1,
3600 self.pg0.remote_ip4,
3604 proto=IP_PROTOS.udp)
3605 self.pg1.add_stream(pkts)
3606 self.pg_enable_capture(self.pg_interfaces)
3608 frags = self.pg0.get_capture(len(pkts))
3609 p = self.reass_frags_and_verify(frags,
3610 self.pg1.remote_ip4,
3611 self.pg0.remote_ip4)
3612 self.assertEqual(p[UDP].sport, 4789)
3613 self.assertEqual(p[UDP].dport, 4789)
3614 self.assertEqual(data, p[Raw].load)
3616 def test_reass_hairpinning(self):
3617 """ NAT44 fragments hairpinning """
3619 self.server = self.pg0.remote_hosts[1]
3620 self.host_in_port = random.randint(1025, 65535)
3621 self.server_in_port = random.randint(1025, 65535)
3622 self.server_out_port = random.randint(1025, 65535)
3624 self.nat44_add_address(self.nat_addr)
3625 flags = self.config_flags.NAT_IS_INSIDE
3626 self.vapi.nat44_interface_add_del_feature(
3627 sw_if_index=self.pg0.sw_if_index,
3628 flags=flags, is_add=1)
3629 self.vapi.nat44_interface_add_del_feature(
3630 sw_if_index=self.pg1.sw_if_index,
3632 # add static mapping for server
3633 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3634 self.server_in_port,
3635 self.server_out_port,
3636 proto=IP_PROTOS.tcp)
3637 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3638 self.server_in_port,
3639 self.server_out_port,
3640 proto=IP_PROTOS.udp)
3641 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
3643 self.reass_hairpinning(proto=IP_PROTOS.tcp)
3644 self.reass_hairpinning(proto=IP_PROTOS.udp)
3645 self.reass_hairpinning(proto=IP_PROTOS.icmp)
3647 def test_frag_out_of_order(self):
3648 """ NAT44 translate fragments arriving out of order """
3650 self.nat44_add_address(self.nat_addr)
3651 flags = self.config_flags.NAT_IS_INSIDE
3652 self.vapi.nat44_interface_add_del_feature(
3653 sw_if_index=self.pg0.sw_if_index,
3654 flags=flags, is_add=1)
3655 self.vapi.nat44_interface_add_del_feature(
3656 sw_if_index=self.pg1.sw_if_index,
3659 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3660 self.frag_out_of_order(proto=IP_PROTOS.udp)
3661 self.frag_out_of_order(proto=IP_PROTOS.icmp)
3663 def test_port_restricted(self):
3664 """ Port restricted NAT44 (MAP-E CE) """
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,
3673 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3678 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3679 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3680 TCP(sport=4567, dport=22))
3681 self.pg0.add_stream(p)
3682 self.pg_enable_capture(self.pg_interfaces)
3684 capture = self.pg1.get_capture(1)
3689 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3690 self.assertEqual(ip.src, self.nat_addr)
3691 self.assertEqual(tcp.dport, 22)
3692 self.assertNotEqual(tcp.sport, 4567)
3693 self.assertEqual((tcp.sport >> 6) & 63, 10)
3694 self.assert_packet_checksums_valid(p)
3696 self.logger.error(ppp("Unexpected or invalid packet:", p))
3699 def test_port_range(self):
3700 """ External address port range """
3701 self.nat44_add_address(self.nat_addr)
3702 flags = self.config_flags.NAT_IS_INSIDE
3703 self.vapi.nat44_interface_add_del_feature(
3704 sw_if_index=self.pg0.sw_if_index,
3705 flags=flags, is_add=1)
3706 self.vapi.nat44_interface_add_del_feature(
3707 sw_if_index=self.pg1.sw_if_index,
3709 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3714 for port in range(0, 5):
3715 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3716 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3717 TCP(sport=1125 + port))
3719 self.pg0.add_stream(pkts)
3720 self.pg_enable_capture(self.pg_interfaces)
3722 capture = self.pg1.get_capture(3)
3725 self.assertGreaterEqual(tcp.sport, 1025)
3726 self.assertLessEqual(tcp.sport, 1027)
3728 def test_multiple_outside_vrf(self):
3729 """ Multiple outside VRF """
3733 self.pg1.unconfig_ip4()
3734 self.pg2.unconfig_ip4()
3735 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
3736 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
3737 self.pg1.set_table_ip4(vrf_id1)
3738 self.pg2.set_table_ip4(vrf_id2)
3739 self.pg1.config_ip4()
3740 self.pg2.config_ip4()
3741 self.pg1.resolve_arp()
3742 self.pg2.resolve_arp()
3744 self.nat44_add_address(self.nat_addr)
3745 flags = self.config_flags.NAT_IS_INSIDE
3746 self.vapi.nat44_interface_add_del_feature(
3747 sw_if_index=self.pg0.sw_if_index,
3748 flags=flags, is_add=1)
3749 self.vapi.nat44_interface_add_del_feature(
3750 sw_if_index=self.pg1.sw_if_index,
3752 self.vapi.nat44_interface_add_del_feature(
3753 sw_if_index=self.pg2.sw_if_index,
3758 pkts = self.create_stream_in(self.pg0, self.pg1)
3759 self.pg0.add_stream(pkts)
3760 self.pg_enable_capture(self.pg_interfaces)
3762 capture = self.pg1.get_capture(len(pkts))
3763 self.verify_capture_out(capture, self.nat_addr)
3765 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3766 self.pg1.add_stream(pkts)
3767 self.pg_enable_capture(self.pg_interfaces)
3769 capture = self.pg0.get_capture(len(pkts))
3770 self.verify_capture_in(capture, self.pg0)
3772 self.tcp_port_in = 60303
3773 self.udp_port_in = 60304
3774 self.icmp_id_in = 60305
3777 pkts = self.create_stream_in(self.pg0, self.pg2)
3778 self.pg0.add_stream(pkts)
3779 self.pg_enable_capture(self.pg_interfaces)
3781 capture = self.pg2.get_capture(len(pkts))
3782 self.verify_capture_out(capture, self.nat_addr)
3784 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3785 self.pg2.add_stream(pkts)
3786 self.pg_enable_capture(self.pg_interfaces)
3788 capture = self.pg0.get_capture(len(pkts))
3789 self.verify_capture_in(capture, self.pg0)
3792 self.nat44_add_address(self.nat_addr, is_add=0)
3793 self.pg1.unconfig_ip4()
3794 self.pg2.unconfig_ip4()
3795 self.pg1.set_table_ip4(0)
3796 self.pg2.set_table_ip4(0)
3797 self.pg1.config_ip4()
3798 self.pg2.config_ip4()
3799 self.pg1.resolve_arp()
3800 self.pg2.resolve_arp()
3802 @unittest.skipUnless(running_extended_tests, "part of extended tests")
3803 def test_session_timeout(self):
3804 """ NAT44 session timeouts """
3805 self.nat44_add_address(self.nat_addr)
3806 flags = self.config_flags.NAT_IS_INSIDE
3807 self.vapi.nat44_interface_add_del_feature(
3808 sw_if_index=self.pg0.sw_if_index,
3809 flags=flags, is_add=1)
3810 self.vapi.nat44_interface_add_del_feature(
3811 sw_if_index=self.pg1.sw_if_index,
3813 self.vapi.nat_set_timeouts(udp=5, tcp_established=7440,
3814 tcp_transitory=240, icmp=60)
3818 for i in range(0, max_sessions):
3819 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3820 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3821 IP(src=src, dst=self.pg1.remote_ip4) /
3822 UDP(sport=1025, dport=53))
3824 self.pg0.add_stream(pkts)
3825 self.pg_enable_capture(self.pg_interfaces)
3827 self.pg1.get_capture(max_sessions)
3832 for i in range(0, max_sessions):
3833 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3834 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3835 IP(src=src, dst=self.pg1.remote_ip4) /
3836 UDP(sport=1026, dport=53))
3838 self.pg0.add_stream(pkts)
3839 self.pg_enable_capture(self.pg_interfaces)
3841 self.pg1.get_capture(max_sessions)
3844 users = self.vapi.nat44_user_dump()
3846 nsessions = nsessions + user.nsessions
3847 self.assertLess(nsessions, 2 * max_sessions)
3849 def test_mss_clamping(self):
3850 """ TCP MSS clamping """
3851 self.nat44_add_address(self.nat_addr)
3852 flags = self.config_flags.NAT_IS_INSIDE
3853 self.vapi.nat44_interface_add_del_feature(
3854 sw_if_index=self.pg0.sw_if_index,
3855 flags=flags, is_add=1)
3856 self.vapi.nat44_interface_add_del_feature(
3857 sw_if_index=self.pg1.sw_if_index,
3860 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3861 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3862 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3863 flags="S", options=[('MSS', 1400)]))
3865 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3866 self.pg0.add_stream(p)
3867 self.pg_enable_capture(self.pg_interfaces)
3869 capture = self.pg1.get_capture(1)
3870 # Negotiated MSS value greater than configured - changed
3871 self.verify_mss_value(capture[0], 1000)
3873 self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
3874 self.pg0.add_stream(p)
3875 self.pg_enable_capture(self.pg_interfaces)
3877 capture = self.pg1.get_capture(1)
3878 # MSS clamping disabled - negotiated MSS unchanged
3879 self.verify_mss_value(capture[0], 1400)
3881 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3882 self.pg0.add_stream(p)
3883 self.pg_enable_capture(self.pg_interfaces)
3885 capture = self.pg1.get_capture(1)
3886 # Negotiated MSS value smaller than configured - unchanged
3887 self.verify_mss_value(capture[0], 1400)
3889 @unittest.skipUnless(running_extended_tests, "part of extended tests")
3890 def test_ha_send(self):
3891 """ Send HA session synchronization events (active) """
3892 self.nat44_add_address(self.nat_addr)
3893 flags = self.config_flags.NAT_IS_INSIDE
3894 self.vapi.nat44_interface_add_del_feature(
3895 sw_if_index=self.pg0.sw_if_index,
3896 flags=flags, is_add=1)
3897 self.vapi.nat44_interface_add_del_feature(
3898 sw_if_index=self.pg1.sw_if_index,
3900 self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
3903 self.vapi.nat_ha_set_failover(ip_address=self.pg3.remote_ip4,
3904 port=12346, session_refresh_interval=10)
3905 bind_layers(UDP, HANATStateSync, sport=12345)
3908 pkts = self.create_stream_in(self.pg0, self.pg1)
3909 self.pg0.add_stream(pkts)
3910 self.pg_enable_capture(self.pg_interfaces)
3912 capture = self.pg1.get_capture(len(pkts))
3913 self.verify_capture_out(capture)
3914 # active send HA events
3915 self.vapi.nat_ha_flush()
3916 stats = self.statistics.get_counter('/nat44/ha/add-event-send')
3917 self.assertEqual(stats[0][0], 3)
3918 capture = self.pg3.get_capture(1)
3920 self.assert_packet_checksums_valid(p)
3924 hanat = p[HANATStateSync]
3926 self.logger.error(ppp("Invalid packet:", p))
3929 self.assertEqual(ip.src, self.pg3.local_ip4)
3930 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3931 self.assertEqual(udp.sport, 12345)
3932 self.assertEqual(udp.dport, 12346)
3933 self.assertEqual(hanat.version, 1)
3934 self.assertEqual(hanat.thread_index, 0)
3935 self.assertEqual(hanat.count, 3)
3936 seq = hanat.sequence_number
3937 for event in hanat.events:
3938 self.assertEqual(event.event_type, 1)
3939 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
3940 self.assertEqual(event.out_addr, self.nat_addr)
3941 self.assertEqual(event.fib_index, 0)
3943 # ACK received events
3944 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3945 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3946 UDP(sport=12346, dport=12345) /
3947 HANATStateSync(sequence_number=seq, flags='ACK'))
3948 self.pg3.add_stream(ack)
3950 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3951 self.assertEqual(stats[0][0], 1)
3953 # delete one session
3954 self.pg_enable_capture(self.pg_interfaces)
3955 self.vapi.nat44_del_session(address=self.pg0.remote_ip4,
3956 port=self.tcp_port_in,
3957 protocol=IP_PROTOS.tcp,
3958 flags=self.config_flags.NAT_IS_INSIDE)
3959 self.vapi.nat_ha_flush()
3960 stats = self.statistics.get_counter('/nat44/ha/del-event-send')
3961 self.assertEqual(stats[0][0], 1)
3962 capture = self.pg3.get_capture(1)
3965 hanat = p[HANATStateSync]
3967 self.logger.error(ppp("Invalid packet:", p))
3970 self.assertGreater(hanat.sequence_number, seq)
3972 # do not send ACK, active retry send HA event again
3973 self.pg_enable_capture(self.pg_interfaces)
3975 stats = self.statistics.get_counter('/nat44/ha/retry-count')
3976 self.assertEqual(stats[0][0], 3)
3977 stats = self.statistics.get_counter('/nat44/ha/missed-count')
3978 self.assertEqual(stats[0][0], 1)
3979 capture = self.pg3.get_capture(3)
3980 for packet in capture:
3981 self.assertEqual(packet, p)
3983 # session counters refresh
3984 pkts = self.create_stream_out(self.pg1)
3985 self.pg1.add_stream(pkts)
3986 self.pg_enable_capture(self.pg_interfaces)
3988 self.pg0.get_capture(2)
3989 self.vapi.nat_ha_flush()
3990 stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
3991 self.assertEqual(stats[0][0], 2)
3992 capture = self.pg3.get_capture(1)
3994 self.assert_packet_checksums_valid(p)
3998 hanat = p[HANATStateSync]
4000 self.logger.error(ppp("Invalid packet:", p))
4003 self.assertEqual(ip.src, self.pg3.local_ip4)
4004 self.assertEqual(ip.dst, self.pg3.remote_ip4)
4005 self.assertEqual(udp.sport, 12345)
4006 self.assertEqual(udp.dport, 12346)
4007 self.assertEqual(hanat.version, 1)
4008 self.assertEqual(hanat.count, 2)
4009 seq = hanat.sequence_number
4010 for event in hanat.events:
4011 self.assertEqual(event.event_type, 3)
4012 self.assertEqual(event.out_addr, self.nat_addr)
4013 self.assertEqual(event.fib_index, 0)
4014 self.assertEqual(event.total_pkts, 2)
4015 self.assertGreater(event.total_bytes, 0)
4017 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4018 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4019 UDP(sport=12346, dport=12345) /
4020 HANATStateSync(sequence_number=seq, flags='ACK'))
4021 self.pg3.add_stream(ack)
4023 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
4024 self.assertEqual(stats[0][0], 2)
4026 def test_ha_recv(self):
4027 """ Receive HA session synchronization events (passive) """
4028 self.nat44_add_address(self.nat_addr)
4029 flags = self.config_flags.NAT_IS_INSIDE
4030 self.vapi.nat44_interface_add_del_feature(
4031 sw_if_index=self.pg0.sw_if_index,
4032 flags=flags, is_add=1)
4033 self.vapi.nat44_interface_add_del_feature(
4034 sw_if_index=self.pg1.sw_if_index,
4036 self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
4039 bind_layers(UDP, HANATStateSync, sport=12345)
4041 self.tcp_port_out = random.randint(1025, 65535)
4042 self.udp_port_out = random.randint(1025, 65535)
4044 # send HA session add events to failover/passive
4045 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4046 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4047 UDP(sport=12346, dport=12345) /
4048 HANATStateSync(sequence_number=1, events=[
4049 Event(event_type='add', protocol='tcp',
4050 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4051 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4052 eh_addr=self.pg1.remote_ip4,
4053 ehn_addr=self.pg1.remote_ip4,
4054 eh_port=self.tcp_external_port,
4055 ehn_port=self.tcp_external_port, fib_index=0),
4056 Event(event_type='add', protocol='udp',
4057 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4058 in_port=self.udp_port_in, out_port=self.udp_port_out,
4059 eh_addr=self.pg1.remote_ip4,
4060 ehn_addr=self.pg1.remote_ip4,
4061 eh_port=self.udp_external_port,
4062 ehn_port=self.udp_external_port, fib_index=0)]))
4064 self.pg3.add_stream(p)
4065 self.pg_enable_capture(self.pg_interfaces)
4068 capture = self.pg3.get_capture(1)
4071 hanat = p[HANATStateSync]
4073 self.logger.error(ppp("Invalid packet:", p))
4076 self.assertEqual(hanat.sequence_number, 1)
4077 self.assertEqual(hanat.flags, 'ACK')
4078 self.assertEqual(hanat.version, 1)
4079 self.assertEqual(hanat.thread_index, 0)
4080 stats = self.statistics.get_counter('/nat44/ha/ack-send')
4081 self.assertEqual(stats[0][0], 1)
4082 stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
4083 self.assertEqual(stats[0][0], 2)
4084 users = self.statistics.get_counter('/nat44/total-users')
4085 self.assertEqual(users[0][0], 1)
4086 sessions = self.statistics.get_counter('/nat44/total-sessions')
4087 self.assertEqual(sessions[0][0], 2)
4088 users = self.vapi.nat44_user_dump()
4089 self.assertEqual(len(users), 1)
4090 self.assertEqual(str(users[0].ip_address),
4091 self.pg0.remote_ip4)
4092 # there should be 2 sessions created by HA
4093 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4095 self.assertEqual(len(sessions), 2)
4096 for session in sessions:
4097 self.assertEqual(str(session.inside_ip_address),
4098 self.pg0.remote_ip4)
4099 self.assertEqual(str(session.outside_ip_address),
4101 self.assertIn(session.inside_port,
4102 [self.tcp_port_in, self.udp_port_in])
4103 self.assertIn(session.outside_port,
4104 [self.tcp_port_out, self.udp_port_out])
4105 self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
4107 # send HA session delete event to failover/passive
4108 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4109 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4110 UDP(sport=12346, dport=12345) /
4111 HANATStateSync(sequence_number=2, events=[
4112 Event(event_type='del', protocol='udp',
4113 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4114 in_port=self.udp_port_in, out_port=self.udp_port_out,
4115 eh_addr=self.pg1.remote_ip4,
4116 ehn_addr=self.pg1.remote_ip4,
4117 eh_port=self.udp_external_port,
4118 ehn_port=self.udp_external_port, fib_index=0)]))
4120 self.pg3.add_stream(p)
4121 self.pg_enable_capture(self.pg_interfaces)
4124 capture = self.pg3.get_capture(1)
4127 hanat = p[HANATStateSync]
4129 self.logger.error(ppp("Invalid packet:", p))
4132 self.assertEqual(hanat.sequence_number, 2)
4133 self.assertEqual(hanat.flags, 'ACK')
4134 self.assertEqual(hanat.version, 1)
4135 users = self.vapi.nat44_user_dump()
4136 self.assertEqual(len(users), 1)
4137 self.assertEqual(str(users[0].ip_address),
4138 self.pg0.remote_ip4)
4139 # now we should have only 1 session, 1 deleted by HA
4140 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4142 self.assertEqual(len(sessions), 1)
4143 stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
4144 self.assertEqual(stats[0][0], 1)
4146 stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
4147 self.assertEqual(stats, 2)
4149 # send HA session refresh event to failover/passive
4150 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4151 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4152 UDP(sport=12346, dport=12345) /
4153 HANATStateSync(sequence_number=3, events=[
4154 Event(event_type='refresh', protocol='tcp',
4155 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4156 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4157 eh_addr=self.pg1.remote_ip4,
4158 ehn_addr=self.pg1.remote_ip4,
4159 eh_port=self.tcp_external_port,
4160 ehn_port=self.tcp_external_port, fib_index=0,
4161 total_bytes=1024, total_pkts=2)]))
4162 self.pg3.add_stream(p)
4163 self.pg_enable_capture(self.pg_interfaces)
4166 capture = self.pg3.get_capture(1)
4169 hanat = p[HANATStateSync]
4171 self.logger.error(ppp("Invalid packet:", p))
4174 self.assertEqual(hanat.sequence_number, 3)
4175 self.assertEqual(hanat.flags, 'ACK')
4176 self.assertEqual(hanat.version, 1)
4177 users = self.vapi.nat44_user_dump()
4178 self.assertEqual(len(users), 1)
4179 self.assertEqual(str(users[0].ip_address),
4180 self.pg0.remote_ip4)
4181 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4183 self.assertEqual(len(sessions), 1)
4184 session = sessions[0]
4185 self.assertEqual(session.total_bytes, 1024)
4186 self.assertEqual(session.total_pkts, 2)
4187 stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
4188 self.assertEqual(stats[0][0], 1)
4190 stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
4191 self.assertEqual(stats, 3)
4193 # send packet to test session created by HA
4194 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4195 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4196 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
4197 self.pg1.add_stream(p)
4198 self.pg_enable_capture(self.pg_interfaces)
4200 capture = self.pg0.get_capture(1)
4206 self.logger.error(ppp("Invalid packet:", p))
4209 self.assertEqual(ip.src, self.pg1.remote_ip4)
4210 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4211 self.assertEqual(tcp.sport, self.tcp_external_port)
4212 self.assertEqual(tcp.dport, self.tcp_port_in)
4215 super(TestNAT44, self).tearDown()
4217 self.vapi.cli("clear logging")
4219 def show_commands_at_teardown(self):
4220 self.logger.info(self.vapi.cli("show nat44 addresses"))
4221 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4222 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4223 self.logger.info(self.vapi.cli("show nat44 interface address"))
4224 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
4225 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
4226 self.logger.info(self.vapi.cli("show nat timeouts"))
4228 self.vapi.cli("show nat addr-port-assignment-alg"))
4229 self.logger.info(self.vapi.cli("show nat ha"))
4232 class TestNAT44EndpointDependent2(MethodHolder):
4233 """ Endpoint-Dependent session test cases """
4238 def setUpConstants(cls):
4239 super(TestNAT44EndpointDependent2, cls).setUpConstants()
4240 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent",
4241 "translation", "hash", "buckets", "1",
4242 "icmp", "timeout", str(cls.icmp_timeout), "}"])
4245 def setUpClass(cls):
4246 super(TestNAT44EndpointDependent2, cls).setUpClass()
4248 translation_buckets = 1
4249 cls.max_translations = 10 * translation_buckets
4251 cls.create_pg_interfaces(range(2))
4252 cls.interfaces = list(cls.pg_interfaces[0:2])
4254 for i in cls.interfaces:
4259 cls.pg0.generate_remote_hosts(1)
4260 cls.pg0.configure_ipv4_neighbors()
4262 cls.pg1.generate_remote_hosts(1)
4263 cls.pg1.configure_ipv4_neighbors()
4266 super(TestNAT44EndpointDependent2, cls).tearDownClass()
4269 def create_icmp_stream(self, in_if, out_if, count):
4271 Create ICMP packet stream for inside network
4273 :param in_if: Inside interface
4274 :param out_if: Outside interface
4275 :param count: Number of packets
4278 self.assertTrue(count > 0)
4279 icmp_id = random.randint(0, 65535 - (count - 1))
4282 for i in range(count):
4283 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4284 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=64) /
4285 ICMP(id=icmp_id + i, type='echo-request'))
4289 def send_pkts(self, pkts, expected=None):
4290 self.pg0.add_stream(pkts)
4291 self.pg_enable_capture(self.pg_interfaces)
4293 return self.pg1.get_capture(
4294 len(pkts) if expected is None else expected)
4296 def test_session_cleanup(self):
4297 """ NAT44 session cleanup test """
4299 self.nat44_add_address(self.pg1.local_ip4)
4300 flags = self.config_flags.NAT_IS_INSIDE
4301 self.vapi.nat44_interface_add_del_feature(
4302 sw_if_index=self.pg0.sw_if_index,
4303 flags=flags, is_add=1)
4304 self.vapi.nat44_interface_add_del_feature(
4305 sw_if_index=self.pg1.sw_if_index,
4308 nat_config = self.vapi.nat_show_config()
4309 self.assertEqual(1, nat_config.endpoint_dependent)
4311 pkts = self.create_icmp_stream(self.pg0, self.pg1,
4312 self.max_translations + 2)
4316 self.send_pkts(pkts[0:self.max_translations])
4318 # false positive test
4319 self.send_pkts(pkts[self.max_translations:sz - 1], 0)
4321 sleep(self.icmp_timeout)
4324 self.send_pkts(pkts[self.max_translations + 1:sz])
4327 class TestNAT44EndpointDependent(MethodHolder):
4328 """ Endpoint-Dependent mapping and filtering test cases """
4331 def setUpConstants(cls):
4332 super(TestNAT44EndpointDependent, cls).setUpConstants()
4333 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4336 def setUpClass(cls):
4337 super(TestNAT44EndpointDependent, cls).setUpClass()
4338 cls.vapi.cli("set log class nat level debug")
4340 cls.tcp_port_in = 6303
4341 cls.tcp_port_out = 6303
4342 cls.udp_port_in = 6304
4343 cls.udp_port_out = 6304
4344 cls.icmp_id_in = 6305
4345 cls.icmp_id_out = 6305
4346 cls.nat_addr = '10.0.0.3'
4347 cls.ipfix_src_port = 4739
4348 cls.ipfix_domain_id = 1
4349 cls.tcp_external_port = 80
4351 cls.create_pg_interfaces(range(9))
4352 cls.interfaces = list(cls.pg_interfaces[0:3])
4354 for i in cls.interfaces:
4359 cls.pg0.generate_remote_hosts(3)
4360 cls.pg0.configure_ipv4_neighbors()
4364 cls.pg4.generate_remote_hosts(2)
4365 cls.pg4.config_ip4()
4366 cls.vapi.sw_interface_add_del_address(
4367 sw_if_index=cls.pg4.sw_if_index,
4368 prefix="10.0.0.1/24")
4371 cls.pg4.resolve_arp()
4372 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4373 cls.pg4.resolve_arp()
4375 zero_ip4 = socket.inet_pton(socket.AF_INET, "0.0.0.0")
4376 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 1})
4378 cls.pg5._local_ip4 = "10.1.1.1"
4379 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4380 cls.pg5.set_table_ip4(1)
4381 cls.pg5.config_ip4()
4383 r1 = VppIpRoute(cls, cls.pg5.remote_ip4, 32,
4384 [VppRoutePath("0.0.0.0",
4385 cls.pg5.sw_if_index)],
4390 cls.pg6._local_ip4 = "10.1.2.1"
4391 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4392 cls.pg6.set_table_ip4(1)
4393 cls.pg6.config_ip4()
4396 r2 = VppIpRoute(cls, cls.pg6.remote_ip4, 32,
4397 [VppRoutePath("0.0.0.0",
4398 cls.pg6.sw_if_index)],
4401 r3 = VppIpRoute(cls, cls.pg6.remote_ip4, 16,
4402 [VppRoutePath("0.0.0.0",
4407 r4 = VppIpRoute(cls, "0.0.0.0", 0,
4408 [VppRoutePath("0.0.0.0", 0xffffffff,
4412 r5 = VppIpRoute(cls, "0.0.0.0", 0,
4413 [VppRoutePath(cls.pg1.local_ip4,
4414 cls.pg1.sw_if_index)],
4421 cls.pg5.resolve_arp()
4422 cls.pg6.resolve_arp()
4425 cls.pg7.config_ip4()
4426 cls.pg7.resolve_arp()
4427 cls.pg7.generate_remote_hosts(3)
4428 cls.pg7.configure_ipv4_neighbors()
4431 cls.pg8.config_ip4()
4432 cls.pg8.resolve_arp()
4435 super(TestNAT44EndpointDependent, cls).tearDownClass()
4439 def tearDownClass(cls):
4440 super(TestNAT44EndpointDependent, cls).tearDownClass()
4442 def test_frag_in_order(self):
4443 """ NAT44 translate fragments arriving in order """
4444 self.nat44_add_address(self.nat_addr)
4445 flags = self.config_flags.NAT_IS_INSIDE
4446 self.vapi.nat44_interface_add_del_feature(
4447 sw_if_index=self.pg0.sw_if_index,
4448 flags=flags, is_add=1)
4449 self.vapi.nat44_interface_add_del_feature(
4450 sw_if_index=self.pg1.sw_if_index,
4452 self.frag_in_order(proto=IP_PROTOS.tcp)
4453 self.frag_in_order(proto=IP_PROTOS.udp)
4454 self.frag_in_order(proto=IP_PROTOS.icmp)
4456 def test_frag_in_order_dont_translate(self):
4457 """ NAT44 don't translate fragments arriving in order """
4458 flags = self.config_flags.NAT_IS_INSIDE
4459 self.vapi.nat44_interface_add_del_feature(
4460 sw_if_index=self.pg0.sw_if_index,
4461 flags=flags, is_add=1)
4462 self.vapi.nat44_interface_add_del_feature(
4463 sw_if_index=self.pg1.sw_if_index,
4465 self.vapi.nat44_forwarding_enable_disable(enable=True)
4466 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4468 def test_frag_out_of_order(self):
4469 """ NAT44 translate fragments arriving out of order """
4470 self.nat44_add_address(self.nat_addr)
4471 flags = self.config_flags.NAT_IS_INSIDE
4472 self.vapi.nat44_interface_add_del_feature(
4473 sw_if_index=self.pg0.sw_if_index,
4474 flags=flags, is_add=1)
4475 self.vapi.nat44_interface_add_del_feature(
4476 sw_if_index=self.pg1.sw_if_index,
4478 self.frag_out_of_order(proto=IP_PROTOS.tcp)
4479 self.frag_out_of_order(proto=IP_PROTOS.udp)
4480 self.frag_out_of_order(proto=IP_PROTOS.icmp)
4482 def test_frag_out_of_order_dont_translate(self):
4483 """ NAT44 don't translate fragments arriving out of order """
4484 flags = self.config_flags.NAT_IS_INSIDE
4485 self.vapi.nat44_interface_add_del_feature(
4486 sw_if_index=self.pg0.sw_if_index,
4487 flags=flags, is_add=1)
4488 self.vapi.nat44_interface_add_del_feature(
4489 sw_if_index=self.pg1.sw_if_index,
4491 self.vapi.nat44_forwarding_enable_disable(enable=True)
4492 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4494 def test_frag_in_order_in_plus_out(self):
4495 """ in+out interface fragments in order """
4496 flags = self.config_flags.NAT_IS_INSIDE
4497 self.vapi.nat44_interface_add_del_feature(
4498 sw_if_index=self.pg0.sw_if_index,
4500 self.vapi.nat44_interface_add_del_feature(
4501 sw_if_index=self.pg0.sw_if_index,
4502 flags=flags, is_add=1)
4503 self.vapi.nat44_interface_add_del_feature(
4504 sw_if_index=self.pg1.sw_if_index,
4506 self.vapi.nat44_interface_add_del_feature(
4507 sw_if_index=self.pg1.sw_if_index,
4508 flags=flags, is_add=1)
4510 self.server = self.pg1.remote_hosts[0]
4512 self.server_in_addr = self.server.ip4
4513 self.server_out_addr = '11.11.11.11'
4514 self.server_in_port = random.randint(1025, 65535)
4515 self.server_out_port = random.randint(1025, 65535)
4517 self.nat44_add_address(self.server_out_addr)
4519 # add static mappings for server
4520 self.nat44_add_static_mapping(self.server_in_addr,
4521 self.server_out_addr,
4522 self.server_in_port,
4523 self.server_out_port,
4524 proto=IP_PROTOS.tcp)
4525 self.nat44_add_static_mapping(self.server_in_addr,
4526 self.server_out_addr,
4527 self.server_in_port,
4528 self.server_out_port,
4529 proto=IP_PROTOS.udp)
4530 self.nat44_add_static_mapping(self.server_in_addr,
4531 self.server_out_addr,
4532 proto=IP_PROTOS.icmp)
4534 self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4535 self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4536 self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4538 def test_frag_out_of_order_in_plus_out(self):
4539 """ in+out interface fragments out of order """
4540 flags = self.config_flags.NAT_IS_INSIDE
4541 self.vapi.nat44_interface_add_del_feature(
4542 sw_if_index=self.pg0.sw_if_index,
4544 self.vapi.nat44_interface_add_del_feature(
4545 sw_if_index=self.pg0.sw_if_index,
4546 flags=flags, is_add=1)
4547 self.vapi.nat44_interface_add_del_feature(
4548 sw_if_index=self.pg1.sw_if_index,
4550 self.vapi.nat44_interface_add_del_feature(
4551 sw_if_index=self.pg1.sw_if_index,
4552 flags=flags, is_add=1)
4554 self.server = self.pg1.remote_hosts[0]
4556 self.server_in_addr = self.server.ip4
4557 self.server_out_addr = '11.11.11.11'
4558 self.server_in_port = random.randint(1025, 65535)
4559 self.server_out_port = random.randint(1025, 65535)
4561 self.nat44_add_address(self.server_out_addr)
4563 # add static mappings for server
4564 self.nat44_add_static_mapping(self.server_in_addr,
4565 self.server_out_addr,
4566 self.server_in_port,
4567 self.server_out_port,
4568 proto=IP_PROTOS.tcp)
4569 self.nat44_add_static_mapping(self.server_in_addr,
4570 self.server_out_addr,
4571 self.server_in_port,
4572 self.server_out_port,
4573 proto=IP_PROTOS.udp)
4574 self.nat44_add_static_mapping(self.server_in_addr,
4575 self.server_out_addr,
4576 proto=IP_PROTOS.icmp)
4578 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4579 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4580 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4582 def test_reass_hairpinning(self):
4583 """ NAT44 fragments hairpinning """
4584 self.server = self.pg0.remote_hosts[1]
4585 self.host_in_port = random.randint(1025, 65535)
4586 self.server_in_port = random.randint(1025, 65535)
4587 self.server_out_port = random.randint(1025, 65535)
4589 self.nat44_add_address(self.nat_addr)
4590 flags = self.config_flags.NAT_IS_INSIDE
4591 self.vapi.nat44_interface_add_del_feature(
4592 sw_if_index=self.pg0.sw_if_index,
4593 flags=flags, is_add=1)
4594 self.vapi.nat44_interface_add_del_feature(
4595 sw_if_index=self.pg1.sw_if_index,
4597 # add static mapping for server
4598 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4599 self.server_in_port,
4600 self.server_out_port,
4601 proto=IP_PROTOS.tcp)
4602 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4603 self.server_in_port,
4604 self.server_out_port,
4605 proto=IP_PROTOS.udp)
4606 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
4608 self.reass_hairpinning(proto=IP_PROTOS.tcp)
4609 self.reass_hairpinning(proto=IP_PROTOS.udp)
4610 self.reass_hairpinning(proto=IP_PROTOS.icmp)
4612 def test_dynamic(self):
4613 """ NAT44 dynamic translation test """
4615 self.nat44_add_address(self.nat_addr)
4616 flags = self.config_flags.NAT_IS_INSIDE
4617 self.vapi.nat44_interface_add_del_feature(
4618 sw_if_index=self.pg0.sw_if_index,
4619 flags=flags, is_add=1)
4620 self.vapi.nat44_interface_add_del_feature(
4621 sw_if_index=self.pg1.sw_if_index,
4624 nat_config = self.vapi.nat_show_config()
4625 self.assertEqual(1, nat_config.endpoint_dependent)
4628 tcpn = self.statistics.get_err_counter(
4629 '/err/nat44-ed-in2out-slowpath/TCP packets')
4630 udpn = self.statistics.get_err_counter(
4631 '/err/nat44-ed-in2out-slowpath/UDP packets')
4632 icmpn = self.statistics.get_err_counter(
4633 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4634 totaln = self.statistics.get_err_counter(
4635 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4637 pkts = self.create_stream_in(self.pg0, self.pg1)
4638 self.pg0.add_stream(pkts)
4639 self.pg_enable_capture(self.pg_interfaces)
4641 capture = self.pg1.get_capture(len(pkts))
4642 self.verify_capture_out(capture)
4644 err = self.statistics.get_err_counter(
4645 '/err/nat44-ed-in2out-slowpath/TCP packets')
4646 self.assertEqual(err - tcpn, 2)
4647 err = self.statistics.get_err_counter(
4648 '/err/nat44-ed-in2out-slowpath/UDP packets')
4649 self.assertEqual(err - udpn, 1)
4650 err = self.statistics.get_err_counter(
4651 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4652 self.assertEqual(err - icmpn, 1)
4653 err = self.statistics.get_err_counter(
4654 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4655 self.assertEqual(err - totaln, 4)
4658 tcpn = self.statistics.get_err_counter(
4659 '/err/nat44-ed-out2in/TCP packets')
4660 udpn = self.statistics.get_err_counter(
4661 '/err/nat44-ed-out2in/UDP packets')
4662 icmpn = self.statistics.get_err_counter(
4663 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4664 totaln = self.statistics.get_err_counter(
4665 '/err/nat44-ed-out2in/good out2in packets processed')
4667 pkts = self.create_stream_out(self.pg1)
4668 self.pg1.add_stream(pkts)
4669 self.pg_enable_capture(self.pg_interfaces)
4671 capture = self.pg0.get_capture(len(pkts))
4672 self.verify_capture_in(capture, self.pg0)
4674 err = self.statistics.get_err_counter(
4675 '/err/nat44-ed-out2in/TCP packets')
4676 self.assertEqual(err - tcpn, 2)
4677 err = self.statistics.get_err_counter(
4678 '/err/nat44-ed-out2in/UDP packets')
4679 self.assertEqual(err - udpn, 1)
4680 err = self.statistics.get_err_counter(
4681 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4682 self.assertEqual(err - icmpn, 1)
4683 err = self.statistics.get_err_counter(
4684 '/err/nat44-ed-out2in/good out2in packets processed')
4685 self.assertEqual(err - totaln, 3)
4687 users = self.statistics.get_counter('/nat44/total-users')
4688 self.assertEqual(users[0][0], 1)
4689 sessions = self.statistics.get_counter('/nat44/total-sessions')
4690 self.assertEqual(sessions[0][0], 3)
4692 def test_dynamic_output_feature_vrf(self):
4693 """ NAT44 dynamic translation test: output-feature, VRF"""
4695 # other then default (0)
4698 self.nat44_add_address(self.nat_addr)
4699 flags = self.config_flags.NAT_IS_INSIDE
4700 self.vapi.nat44_interface_add_del_output_feature(
4701 sw_if_index=self.pg7.sw_if_index,
4702 flags=flags, is_add=1)
4703 self.vapi.nat44_interface_add_del_output_feature(
4704 sw_if_index=self.pg8.sw_if_index,
4708 self.vapi.ip_table_add_del(is_add=1,
4709 table={'table_id': new_vrf_id})
4711 self.pg7.unconfig_ip4()
4712 self.pg7.set_table_ip4(new_vrf_id)
4713 self.pg7.config_ip4()
4714 self.pg7.resolve_arp()
4716 self.pg8.unconfig_ip4()
4717 self.pg8.set_table_ip4(new_vrf_id)
4718 self.pg8.config_ip4()
4719 self.pg8.resolve_arp()
4721 nat_config = self.vapi.nat_show_config()
4722 self.assertEqual(1, nat_config.endpoint_dependent)
4725 tcpn = self.statistics.get_err_counter(
4726 '/err/nat44-ed-in2out-slowpath/TCP packets')
4727 udpn = self.statistics.get_err_counter(
4728 '/err/nat44-ed-in2out-slowpath/UDP packets')
4729 icmpn = self.statistics.get_err_counter(
4730 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4731 totaln = self.statistics.get_err_counter(
4732 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4734 pkts = self.create_stream_in(self.pg7, self.pg8)
4735 self.pg7.add_stream(pkts)
4736 self.pg_enable_capture(self.pg_interfaces)
4738 capture = self.pg8.get_capture(len(pkts))
4739 self.verify_capture_out(capture)
4741 err = self.statistics.get_err_counter(
4742 '/err/nat44-ed-in2out-slowpath/TCP packets')
4743 self.assertEqual(err - tcpn, 2)
4744 err = self.statistics.get_err_counter(
4745 '/err/nat44-ed-in2out-slowpath/UDP packets')
4746 self.assertEqual(err - udpn, 1)
4747 err = self.statistics.get_err_counter(
4748 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4749 self.assertEqual(err - icmpn, 1)
4750 err = self.statistics.get_err_counter(
4751 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4752 self.assertEqual(err - totaln, 4)
4755 tcpn = self.statistics.get_err_counter(
4756 '/err/nat44-ed-out2in/TCP packets')
4757 udpn = self.statistics.get_err_counter(
4758 '/err/nat44-ed-out2in/UDP packets')
4759 icmpn = self.statistics.get_err_counter(
4760 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4761 totaln = self.statistics.get_err_counter(
4762 '/err/nat44-ed-out2in/good out2in packets processed')
4764 pkts = self.create_stream_out(self.pg8)
4765 self.pg8.add_stream(pkts)
4766 self.pg_enable_capture(self.pg_interfaces)
4768 capture = self.pg7.get_capture(len(pkts))
4769 self.verify_capture_in(capture, self.pg7)
4771 err = self.statistics.get_err_counter(
4772 '/err/nat44-ed-out2in/TCP packets')
4773 self.assertEqual(err - tcpn, 2)
4774 err = self.statistics.get_err_counter(
4775 '/err/nat44-ed-out2in/UDP packets')
4776 self.assertEqual(err - udpn, 1)
4777 err = self.statistics.get_err_counter(
4778 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4779 self.assertEqual(err - icmpn, 1)
4780 err = self.statistics.get_err_counter(
4781 '/err/nat44-ed-out2in/good out2in packets processed')
4782 self.assertEqual(err - totaln, 3)
4784 users = self.statistics.get_counter('/nat44/total-users')
4785 self.assertEqual(users[0][0], 1)
4786 sessions = self.statistics.get_counter('/nat44/total-sessions')
4787 self.assertEqual(sessions[0][0], 3)
4790 self.pg7.unconfig_ip4()
4791 self.pg7.set_table_ip4(1)
4792 self.pg7.config_ip4()
4793 self.pg7.resolve_arp()
4795 self.pg8.unconfig_ip4()
4796 self.pg8.set_table_ip4(1)
4797 self.pg8.config_ip4()
4798 self.pg8.resolve_arp()
4800 self.vapi.ip_table_add_del(is_add=0,
4801 table={'table_id': new_vrf_id})
4803 def test_forwarding(self):
4804 """ NAT44 forwarding test """
4806 flags = self.config_flags.NAT_IS_INSIDE
4807 self.vapi.nat44_interface_add_del_feature(
4808 sw_if_index=self.pg0.sw_if_index,
4809 flags=flags, is_add=1)
4810 self.vapi.nat44_interface_add_del_feature(
4811 sw_if_index=self.pg1.sw_if_index,
4813 self.vapi.nat44_forwarding_enable_disable(enable=1)
4815 real_ip = self.pg0.remote_ip4
4816 alias_ip = self.nat_addr
4817 flags = self.config_flags.NAT_IS_ADDR_ONLY
4818 self.vapi.nat44_add_del_static_mapping(is_add=1,
4819 local_ip_address=real_ip,
4820 external_ip_address=alias_ip,
4821 external_sw_if_index=0xFFFFFFFF,
4825 # in2out - static mapping match
4827 pkts = self.create_stream_out(self.pg1)
4828 self.pg1.add_stream(pkts)
4829 self.pg_enable_capture(self.pg_interfaces)
4831 capture = self.pg0.get_capture(len(pkts))
4832 self.verify_capture_in(capture, self.pg0)
4834 pkts = self.create_stream_in(self.pg0, self.pg1)
4835 self.pg0.add_stream(pkts)
4836 self.pg_enable_capture(self.pg_interfaces)
4838 capture = self.pg1.get_capture(len(pkts))
4839 self.verify_capture_out(capture, same_port=True)
4841 # in2out - no static mapping match
4843 host0 = self.pg0.remote_hosts[0]
4844 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4846 pkts = self.create_stream_out(self.pg1,
4847 dst_ip=self.pg0.remote_ip4,
4848 use_inside_ports=True)
4849 self.pg1.add_stream(pkts)
4850 self.pg_enable_capture(self.pg_interfaces)
4852 capture = self.pg0.get_capture(len(pkts))
4853 self.verify_capture_in(capture, self.pg0)
4855 pkts = self.create_stream_in(self.pg0, self.pg1)
4856 self.pg0.add_stream(pkts)
4857 self.pg_enable_capture(self.pg_interfaces)
4859 capture = self.pg1.get_capture(len(pkts))
4860 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4863 self.pg0.remote_hosts[0] = host0
4865 user = self.pg0.remote_hosts[1]
4866 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4867 self.assertEqual(len(sessions), 3)
4868 self.assertTrue(sessions[0].flags &
4869 self.config_flags.NAT_IS_EXT_HOST_VALID)
4870 self.vapi.nat44_del_session(
4871 address=sessions[0].inside_ip_address,
4872 port=sessions[0].inside_port,
4873 protocol=sessions[0].protocol,
4874 flags=(self.config_flags.NAT_IS_INSIDE |
4875 self.config_flags.NAT_IS_EXT_HOST_VALID),
4876 ext_host_address=sessions[0].ext_host_address,
4877 ext_host_port=sessions[0].ext_host_port)
4878 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4879 self.assertEqual(len(sessions), 2)
4882 self.vapi.nat44_forwarding_enable_disable(enable=0)
4883 flags = self.config_flags.NAT_IS_ADDR_ONLY
4884 self.vapi.nat44_add_del_static_mapping(
4886 local_ip_address=real_ip,
4887 external_ip_address=alias_ip,
4888 external_sw_if_index=0xFFFFFFFF,
4891 def test_static_lb(self):
4892 """ NAT44 local service load balancing """
4893 external_addr_n = self.nat_addr
4896 server1 = self.pg0.remote_hosts[0]
4897 server2 = self.pg0.remote_hosts[1]
4899 locals = [{'addr': server1.ip4,
4903 {'addr': server2.ip4,
4908 self.nat44_add_address(self.nat_addr)
4909 self.vapi.nat44_add_del_lb_static_mapping(
4911 external_addr=external_addr_n,
4912 external_port=external_port,
4913 protocol=IP_PROTOS.tcp,
4914 local_num=len(locals),
4916 flags = self.config_flags.NAT_IS_INSIDE
4917 self.vapi.nat44_interface_add_del_feature(
4918 sw_if_index=self.pg0.sw_if_index,
4919 flags=flags, is_add=1)
4920 self.vapi.nat44_interface_add_del_feature(
4921 sw_if_index=self.pg1.sw_if_index,
4924 # from client to service
4925 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4926 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4927 TCP(sport=12345, dport=external_port))
4928 self.pg1.add_stream(p)
4929 self.pg_enable_capture(self.pg_interfaces)
4931 capture = self.pg0.get_capture(1)
4937 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4938 if ip.dst == server1.ip4:
4942 self.assertEqual(tcp.dport, local_port)
4943 self.assert_packet_checksums_valid(p)
4945 self.logger.error(ppp("Unexpected or invalid packet:", p))
4948 # from service back to client
4949 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4950 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4951 TCP(sport=local_port, dport=12345))
4952 self.pg0.add_stream(p)
4953 self.pg_enable_capture(self.pg_interfaces)
4955 capture = self.pg1.get_capture(1)
4960 self.assertEqual(ip.src, self.nat_addr)
4961 self.assertEqual(tcp.sport, external_port)
4962 self.assert_packet_checksums_valid(p)
4964 self.logger.error(ppp("Unexpected or invalid packet:", p))
4967 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
4968 self.assertEqual(len(sessions), 1)
4969 self.assertTrue(sessions[0].flags &
4970 self.config_flags.NAT_IS_EXT_HOST_VALID)
4971 self.vapi.nat44_del_session(
4972 address=sessions[0].inside_ip_address,
4973 port=sessions[0].inside_port,
4974 protocol=sessions[0].protocol,
4975 flags=(self.config_flags.NAT_IS_INSIDE |
4976 self.config_flags.NAT_IS_EXT_HOST_VALID),
4977 ext_host_address=sessions[0].ext_host_address,
4978 ext_host_port=sessions[0].ext_host_port)
4979 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
4980 self.assertEqual(len(sessions), 0)
4982 @unittest.skipUnless(running_extended_tests, "part of extended tests")
4983 def test_static_lb_multi_clients(self):
4984 """ NAT44 local service load balancing - multiple clients"""
4986 external_addr = self.nat_addr
4989 server1 = self.pg0.remote_hosts[0]
4990 server2 = self.pg0.remote_hosts[1]
4991 server3 = self.pg0.remote_hosts[2]
4993 locals = [{'addr': server1.ip4,
4997 {'addr': server2.ip4,
5002 self.nat44_add_address(self.nat_addr)
5003 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
5004 external_addr=external_addr,
5005 external_port=external_port,
5006 protocol=IP_PROTOS.tcp,
5007 local_num=len(locals),
5009 flags = self.config_flags.NAT_IS_INSIDE
5010 self.vapi.nat44_interface_add_del_feature(
5011 sw_if_index=self.pg0.sw_if_index,
5012 flags=flags, is_add=1)
5013 self.vapi.nat44_interface_add_del_feature(
5014 sw_if_index=self.pg1.sw_if_index,
5019 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
5021 for client in clients:
5022 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5023 IP(src=client, dst=self.nat_addr) /
5024 TCP(sport=12345, dport=external_port))
5026 self.pg1.add_stream(pkts)
5027 self.pg_enable_capture(self.pg_interfaces)
5029 capture = self.pg0.get_capture(len(pkts))
5031 if p[IP].dst == server1.ip4:
5035 self.assertGreater(server1_n, server2_n)
5038 'addr': server3.ip4,
5045 self.vapi.nat44_lb_static_mapping_add_del_local(
5047 external_addr=external_addr,
5048 external_port=external_port,
5050 protocol=IP_PROTOS.tcp)
5054 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
5056 for client in clients:
5057 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5058 IP(src=client, dst=self.nat_addr) /
5059 TCP(sport=12346, dport=external_port))
5061 self.assertGreater(len(pkts), 0)
5062 self.pg1.add_stream(pkts)
5063 self.pg_enable_capture(self.pg_interfaces)
5065 capture = self.pg0.get_capture(len(pkts))
5067 if p[IP].dst == server1.ip4:
5069 elif p[IP].dst == server2.ip4:
5073 self.assertGreater(server1_n, 0)
5074 self.assertGreater(server2_n, 0)
5075 self.assertGreater(server3_n, 0)
5078 'addr': server2.ip4,
5084 # remove one back-end
5085 self.vapi.nat44_lb_static_mapping_add_del_local(
5087 external_addr=external_addr,
5088 external_port=external_port,
5090 protocol=IP_PROTOS.tcp)
5094 self.pg1.add_stream(pkts)
5095 self.pg_enable_capture(self.pg_interfaces)
5097 capture = self.pg0.get_capture(len(pkts))
5099 if p[IP].dst == server1.ip4:
5101 elif p[IP].dst == server2.ip4:
5105 self.assertGreater(server1_n, 0)
5106 self.assertEqual(server2_n, 0)
5107 self.assertGreater(server3_n, 0)
5109 def test_static_lb_2(self):
5110 """ NAT44 local service load balancing (asymmetrical rule) """
5111 external_addr = self.nat_addr
5114 server1 = self.pg0.remote_hosts[0]
5115 server2 = self.pg0.remote_hosts[1]
5117 locals = [{'addr': server1.ip4,
5121 {'addr': server2.ip4,
5126 self.vapi.nat44_forwarding_enable_disable(enable=1)
5127 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5128 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5129 external_addr=external_addr,
5130 external_port=external_port,
5131 protocol=IP_PROTOS.tcp,
5132 local_num=len(locals),
5134 flags = self.config_flags.NAT_IS_INSIDE
5135 self.vapi.nat44_interface_add_del_feature(
5136 sw_if_index=self.pg0.sw_if_index,
5137 flags=flags, is_add=1)
5138 self.vapi.nat44_interface_add_del_feature(
5139 sw_if_index=self.pg1.sw_if_index,
5142 # from client to service
5143 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5144 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5145 TCP(sport=12345, dport=external_port))
5146 self.pg1.add_stream(p)
5147 self.pg_enable_capture(self.pg_interfaces)
5149 capture = self.pg0.get_capture(1)
5155 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
5156 if ip.dst == server1.ip4:
5160 self.assertEqual(tcp.dport, local_port)
5161 self.assert_packet_checksums_valid(p)
5163 self.logger.error(ppp("Unexpected or invalid packet:", p))
5166 # from service back to client
5167 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
5168 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
5169 TCP(sport=local_port, dport=12345))
5170 self.pg0.add_stream(p)
5171 self.pg_enable_capture(self.pg_interfaces)
5173 capture = self.pg1.get_capture(1)
5178 self.assertEqual(ip.src, self.nat_addr)
5179 self.assertEqual(tcp.sport, external_port)
5180 self.assert_packet_checksums_valid(p)
5182 self.logger.error(ppp("Unexpected or invalid packet:", p))
5185 # from client to server (no translation)
5186 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5187 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
5188 TCP(sport=12346, dport=local_port))
5189 self.pg1.add_stream(p)
5190 self.pg_enable_capture(self.pg_interfaces)
5192 capture = self.pg0.get_capture(1)
5198 self.assertEqual(ip.dst, server1.ip4)
5199 self.assertEqual(tcp.dport, local_port)
5200 self.assert_packet_checksums_valid(p)
5202 self.logger.error(ppp("Unexpected or invalid packet:", p))
5205 # from service back to client (no translation)
5206 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
5207 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
5208 TCP(sport=local_port, dport=12346))
5209 self.pg0.add_stream(p)
5210 self.pg_enable_capture(self.pg_interfaces)
5212 capture = self.pg1.get_capture(1)
5217 self.assertEqual(ip.src, server1.ip4)
5218 self.assertEqual(tcp.sport, local_port)
5219 self.assert_packet_checksums_valid(p)
5221 self.logger.error(ppp("Unexpected or invalid packet:", p))
5224 def test_lb_affinity(self):
5225 """ NAT44 local service load balancing affinity """
5226 external_addr = self.nat_addr
5229 server1 = self.pg0.remote_hosts[0]
5230 server2 = self.pg0.remote_hosts[1]
5232 locals = [{'addr': server1.ip4,
5236 {'addr': server2.ip4,
5241 self.nat44_add_address(self.nat_addr)
5242 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
5243 external_addr=external_addr,
5244 external_port=external_port,
5245 protocol=IP_PROTOS.tcp,
5247 local_num=len(locals),
5249 flags = self.config_flags.NAT_IS_INSIDE
5250 self.vapi.nat44_interface_add_del_feature(
5251 sw_if_index=self.pg0.sw_if_index,
5252 flags=flags, is_add=1)
5253 self.vapi.nat44_interface_add_del_feature(
5254 sw_if_index=self.pg1.sw_if_index,
5257 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5258 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5259 TCP(sport=1025, dport=external_port))
5260 self.pg1.add_stream(p)
5261 self.pg_enable_capture(self.pg_interfaces)
5263 capture = self.pg0.get_capture(1)
5264 backend = capture[0][IP].dst
5266 sessions = self.vapi.nat44_user_session_dump(backend, 0)
5267 self.assertEqual(len(sessions), 1)
5268 self.assertTrue(sessions[0].flags &
5269 self.config_flags.NAT_IS_EXT_HOST_VALID)
5270 self.vapi.nat44_del_session(
5271 address=sessions[0].inside_ip_address,
5272 port=sessions[0].inside_port,
5273 protocol=sessions[0].protocol,
5274 flags=(self.config_flags.NAT_IS_INSIDE |
5275 self.config_flags.NAT_IS_EXT_HOST_VALID),
5276 ext_host_address=sessions[0].ext_host_address,
5277 ext_host_port=sessions[0].ext_host_port)
5280 for port in range(1030, 1100):
5281 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5282 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5283 TCP(sport=port, dport=external_port))
5285 self.pg1.add_stream(pkts)
5286 self.pg_enable_capture(self.pg_interfaces)
5288 capture = self.pg0.get_capture(len(pkts))
5290 self.assertEqual(p[IP].dst, backend)
5292 def test_unknown_proto(self):
5293 """ NAT44 translate packet with unknown protocol """
5294 self.nat44_add_address(self.nat_addr)
5295 flags = self.config_flags.NAT_IS_INSIDE
5296 self.vapi.nat44_interface_add_del_feature(
5297 sw_if_index=self.pg0.sw_if_index,
5298 flags=flags, is_add=1)
5299 self.vapi.nat44_interface_add_del_feature(
5300 sw_if_index=self.pg1.sw_if_index,
5304 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5305 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5306 TCP(sport=self.tcp_port_in, dport=20))
5307 self.pg0.add_stream(p)
5308 self.pg_enable_capture(self.pg_interfaces)
5310 p = self.pg1.get_capture(1)
5312 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5313 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5315 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5316 TCP(sport=1234, dport=1234))
5317 self.pg0.add_stream(p)
5318 self.pg_enable_capture(self.pg_interfaces)
5320 p = self.pg1.get_capture(1)
5323 self.assertEqual(packet[IP].src, self.nat_addr)
5324 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5325 self.assertEqual(packet.haslayer(GRE), 1)
5326 self.assert_packet_checksums_valid(packet)
5328 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5332 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5333 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5335 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5336 TCP(sport=1234, dport=1234))
5337 self.pg1.add_stream(p)
5338 self.pg_enable_capture(self.pg_interfaces)
5340 p = self.pg0.get_capture(1)
5343 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
5344 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
5345 self.assertEqual(packet.haslayer(GRE), 1)
5346 self.assert_packet_checksums_valid(packet)
5348 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5351 def test_hairpinning_unknown_proto(self):
5352 """ NAT44 translate packet with unknown protocol - hairpinning """
5353 host = self.pg0.remote_hosts[0]
5354 server = self.pg0.remote_hosts[1]
5356 server_out_port = 8765
5357 server_nat_ip = "10.0.0.11"
5359 self.nat44_add_address(self.nat_addr)
5360 flags = self.config_flags.NAT_IS_INSIDE
5361 self.vapi.nat44_interface_add_del_feature(
5362 sw_if_index=self.pg0.sw_if_index,
5363 flags=flags, is_add=1)
5364 self.vapi.nat44_interface_add_del_feature(
5365 sw_if_index=self.pg1.sw_if_index,
5368 # add static mapping for server
5369 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
5372 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
5373 IP(src=host.ip4, dst=server_nat_ip) /
5374 TCP(sport=host_in_port, dport=server_out_port))
5375 self.pg0.add_stream(p)
5376 self.pg_enable_capture(self.pg_interfaces)
5378 self.pg0.get_capture(1)
5380 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5381 IP(src=host.ip4, dst=server_nat_ip) /
5383 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5384 TCP(sport=1234, dport=1234))
5385 self.pg0.add_stream(p)
5386 self.pg_enable_capture(self.pg_interfaces)
5388 p = self.pg0.get_capture(1)
5391 self.assertEqual(packet[IP].src, self.nat_addr)
5392 self.assertEqual(packet[IP].dst, server.ip4)
5393 self.assertEqual(packet.haslayer(GRE), 1)
5394 self.assert_packet_checksums_valid(packet)
5396 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5400 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5401 IP(src=server.ip4, dst=self.nat_addr) /
5403 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5404 TCP(sport=1234, dport=1234))
5405 self.pg0.add_stream(p)
5406 self.pg_enable_capture(self.pg_interfaces)
5408 p = self.pg0.get_capture(1)
5411 self.assertEqual(packet[IP].src, server_nat_ip)
5412 self.assertEqual(packet[IP].dst, host.ip4)
5413 self.assertEqual(packet.haslayer(GRE), 1)
5414 self.assert_packet_checksums_valid(packet)
5416 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5419 def test_output_feature_and_service(self):
5420 """ NAT44 interface output feature and services """
5421 external_addr = '1.2.3.4'
5425 self.vapi.nat44_forwarding_enable_disable(enable=1)
5426 self.nat44_add_address(self.nat_addr)
5427 flags = self.config_flags.NAT_IS_ADDR_ONLY
5428 self.vapi.nat44_add_del_identity_mapping(
5429 ip_address=self.pg1.remote_ip4, sw_if_index=0xFFFFFFFF,
5430 flags=flags, is_add=1)
5431 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5432 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5433 local_port, external_port,
5434 proto=IP_PROTOS.tcp, flags=flags)
5435 flags = self.config_flags.NAT_IS_INSIDE
5436 self.vapi.nat44_interface_add_del_feature(
5437 sw_if_index=self.pg0.sw_if_index,
5439 self.vapi.nat44_interface_add_del_feature(
5440 sw_if_index=self.pg0.sw_if_index,
5441 flags=flags, is_add=1)
5442 self.vapi.nat44_interface_add_del_output_feature(
5444 sw_if_index=self.pg1.sw_if_index)
5446 # from client to service
5447 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5448 IP(src=self.pg1.remote_ip4, dst=external_addr) /
5449 TCP(sport=12345, dport=external_port))
5450 self.pg1.add_stream(p)
5451 self.pg_enable_capture(self.pg_interfaces)
5453 capture = self.pg0.get_capture(1)
5458 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5459 self.assertEqual(tcp.dport, local_port)
5460 self.assert_packet_checksums_valid(p)
5462 self.logger.error(ppp("Unexpected or invalid packet:", p))
5465 # from service back to client
5466 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5467 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5468 TCP(sport=local_port, dport=12345))
5469 self.pg0.add_stream(p)
5470 self.pg_enable_capture(self.pg_interfaces)
5472 capture = self.pg1.get_capture(1)
5477 self.assertEqual(ip.src, external_addr)
5478 self.assertEqual(tcp.sport, external_port)
5479 self.assert_packet_checksums_valid(p)
5481 self.logger.error(ppp("Unexpected or invalid packet:", p))
5484 # from local network host to external network
5485 pkts = self.create_stream_in(self.pg0, self.pg1)
5486 self.pg0.add_stream(pkts)
5487 self.pg_enable_capture(self.pg_interfaces)
5489 capture = self.pg1.get_capture(len(pkts))
5490 self.verify_capture_out(capture)
5491 pkts = self.create_stream_in(self.pg0, self.pg1)
5492 self.pg0.add_stream(pkts)
5493 self.pg_enable_capture(self.pg_interfaces)
5495 capture = self.pg1.get_capture(len(pkts))
5496 self.verify_capture_out(capture)
5498 # from external network back to local network host
5499 pkts = self.create_stream_out(self.pg1)
5500 self.pg1.add_stream(pkts)
5501 self.pg_enable_capture(self.pg_interfaces)
5503 capture = self.pg0.get_capture(len(pkts))
5504 self.verify_capture_in(capture, self.pg0)
5506 def test_output_feature_and_service2(self):
5507 """ NAT44 interface output feature and service host direct access """
5508 self.vapi.nat44_forwarding_enable_disable(enable=1)
5509 self.nat44_add_address(self.nat_addr)
5510 self.vapi.nat44_interface_add_del_output_feature(
5512 sw_if_index=self.pg1.sw_if_index)
5514 # session initiated from service host - translate
5515 pkts = self.create_stream_in(self.pg0, self.pg1)
5516 self.pg0.add_stream(pkts)
5517 self.pg_enable_capture(self.pg_interfaces)
5519 capture = self.pg1.get_capture(len(pkts))
5520 self.verify_capture_out(capture)
5522 pkts = self.create_stream_out(self.pg1)
5523 self.pg1.add_stream(pkts)
5524 self.pg_enable_capture(self.pg_interfaces)
5526 capture = self.pg0.get_capture(len(pkts))
5527 self.verify_capture_in(capture, self.pg0)
5529 # session initiated from remote host - do not translate
5530 self.tcp_port_in = 60303
5531 self.udp_port_in = 60304
5532 self.icmp_id_in = 60305
5533 pkts = self.create_stream_out(self.pg1,
5534 self.pg0.remote_ip4,
5535 use_inside_ports=True)
5536 self.pg1.add_stream(pkts)
5537 self.pg_enable_capture(self.pg_interfaces)
5539 capture = self.pg0.get_capture(len(pkts))
5540 self.verify_capture_in(capture, self.pg0)
5542 pkts = self.create_stream_in(self.pg0, self.pg1)
5543 self.pg0.add_stream(pkts)
5544 self.pg_enable_capture(self.pg_interfaces)
5546 capture = self.pg1.get_capture(len(pkts))
5547 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5550 def test_output_feature_and_service3(self):
5551 """ NAT44 interface output feature and DST NAT """
5552 external_addr = '1.2.3.4'
5556 self.vapi.nat44_forwarding_enable_disable(enable=1)
5557 self.nat44_add_address(self.nat_addr)
5558 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5559 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5560 local_port, external_port,
5561 proto=IP_PROTOS.tcp, flags=flags)
5562 flags = self.config_flags.NAT_IS_INSIDE
5563 self.vapi.nat44_interface_add_del_feature(
5564 sw_if_index=self.pg0.sw_if_index,
5566 self.vapi.nat44_interface_add_del_feature(
5567 sw_if_index=self.pg0.sw_if_index,
5568 flags=flags, is_add=1)
5569 self.vapi.nat44_interface_add_del_output_feature(
5571 sw_if_index=self.pg1.sw_if_index)
5573 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5574 IP(src=self.pg0.remote_ip4, dst=external_addr) /
5575 TCP(sport=12345, dport=external_port))
5576 self.pg0.add_stream(p)
5577 self.pg_enable_capture(self.pg_interfaces)
5579 capture = self.pg1.get_capture(1)
5584 self.assertEqual(ip.src, self.pg0.remote_ip4)
5585 self.assertEqual(tcp.sport, 12345)
5586 self.assertEqual(ip.dst, self.pg1.remote_ip4)
5587 self.assertEqual(tcp.dport, local_port)
5588 self.assert_packet_checksums_valid(p)
5590 self.logger.error(ppp("Unexpected or invalid packet:", p))
5593 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5594 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5595 TCP(sport=local_port, dport=12345))
5596 self.pg1.add_stream(p)
5597 self.pg_enable_capture(self.pg_interfaces)
5599 capture = self.pg0.get_capture(1)
5604 self.assertEqual(ip.src, external_addr)
5605 self.assertEqual(tcp.sport, external_port)
5606 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5607 self.assertEqual(tcp.dport, 12345)
5608 self.assert_packet_checksums_valid(p)
5610 self.logger.error(ppp("Unexpected or invalid packet:", p))
5613 def test_next_src_nat(self):
5614 """ On way back forward packet to nat44-in2out node. """
5615 twice_nat_addr = '10.0.1.3'
5618 post_twice_nat_port = 0
5620 self.vapi.nat44_forwarding_enable_disable(enable=1)
5621 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5622 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5623 self.config_flags.NAT_IS_SELF_TWICE_NAT)
5624 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5625 local_port, external_port,
5626 proto=IP_PROTOS.tcp, vrf_id=1,
5628 self.vapi.nat44_interface_add_del_feature(
5629 sw_if_index=self.pg6.sw_if_index,
5632 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5633 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5634 TCP(sport=12345, dport=external_port))
5635 self.pg6.add_stream(p)
5636 self.pg_enable_capture(self.pg_interfaces)
5638 capture = self.pg6.get_capture(1)
5643 self.assertEqual(ip.src, twice_nat_addr)
5644 self.assertNotEqual(tcp.sport, 12345)
5645 post_twice_nat_port = tcp.sport
5646 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5647 self.assertEqual(tcp.dport, local_port)
5648 self.assert_packet_checksums_valid(p)
5650 self.logger.error(ppp("Unexpected or invalid packet:", p))
5653 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5654 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5655 TCP(sport=local_port, dport=post_twice_nat_port))
5656 self.pg6.add_stream(p)
5657 self.pg_enable_capture(self.pg_interfaces)
5659 capture = self.pg6.get_capture(1)
5664 self.assertEqual(ip.src, self.pg1.remote_ip4)
5665 self.assertEqual(tcp.sport, external_port)
5666 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5667 self.assertEqual(tcp.dport, 12345)
5668 self.assert_packet_checksums_valid(p)
5670 self.logger.error(ppp("Unexpected or invalid packet:", p))
5673 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5675 twice_nat_addr = '10.0.1.3'
5683 port_in1 = port_in + 1
5684 port_in2 = port_in + 2
5689 server1 = self.pg0.remote_hosts[0]
5690 server2 = self.pg0.remote_hosts[1]
5702 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5705 self.nat44_add_address(self.nat_addr)
5706 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5710 flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
5712 flags |= self.config_flags.NAT_IS_TWICE_NAT
5715 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5717 proto=IP_PROTOS.tcp,
5720 locals = [{'addr': server1.ip4,
5724 {'addr': server2.ip4,
5728 out_addr = self.nat_addr
5730 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5731 external_addr=out_addr,
5732 external_port=port_out,
5733 protocol=IP_PROTOS.tcp,
5734 local_num=len(locals),
5736 flags = self.config_flags.NAT_IS_INSIDE
5737 self.vapi.nat44_interface_add_del_feature(
5738 sw_if_index=pg0.sw_if_index,
5739 flags=flags, is_add=1)
5740 self.vapi.nat44_interface_add_del_feature(
5741 sw_if_index=pg1.sw_if_index,
5748 assert client_id is not None
5750 client = self.pg0.remote_hosts[0]
5751 elif client_id == 2:
5752 client = self.pg0.remote_hosts[1]
5754 client = pg1.remote_hosts[0]
5755 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5756 IP(src=client.ip4, dst=self.nat_addr) /
5757 TCP(sport=eh_port_out, dport=port_out))
5759 self.pg_enable_capture(self.pg_interfaces)
5761 capture = pg0.get_capture(1)
5767 if ip.dst == server1.ip4:
5773 self.assertEqual(ip.dst, server.ip4)
5775 self.assertIn(tcp.dport, [port_in1, port_in2])
5777 self.assertEqual(tcp.dport, port_in)
5779 self.assertEqual(ip.src, twice_nat_addr)
5780 self.assertNotEqual(tcp.sport, eh_port_out)
5782 self.assertEqual(ip.src, client.ip4)
5783 self.assertEqual(tcp.sport, eh_port_out)
5785 eh_port_in = tcp.sport
5786 saved_port_in = tcp.dport
5787 self.assert_packet_checksums_valid(p)
5789 self.logger.error(ppp("Unexpected or invalid packet:", p))
5792 p = (Ether(src=server.mac, dst=pg0.local_mac) /
5793 IP(src=server.ip4, dst=eh_addr_in) /
5794 TCP(sport=saved_port_in, dport=eh_port_in))
5796 self.pg_enable_capture(self.pg_interfaces)
5798 capture = pg1.get_capture(1)
5803 self.assertEqual(ip.dst, client.ip4)
5804 self.assertEqual(ip.src, self.nat_addr)
5805 self.assertEqual(tcp.dport, eh_port_out)
5806 self.assertEqual(tcp.sport, port_out)
5807 self.assert_packet_checksums_valid(p)
5809 self.logger.error(ppp("Unexpected or invalid packet:", p))
5813 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5814 self.assertEqual(len(sessions), 1)
5815 self.assertTrue(sessions[0].flags &
5816 self.config_flags.NAT_IS_EXT_HOST_VALID)
5817 self.assertTrue(sessions[0].flags &
5818 self.config_flags.NAT_IS_TWICE_NAT)
5819 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
5820 self.vapi.nat44_del_session(
5821 address=sessions[0].inside_ip_address,
5822 port=sessions[0].inside_port,
5823 protocol=sessions[0].protocol,
5824 flags=(self.config_flags.NAT_IS_INSIDE |
5825 self.config_flags.NAT_IS_EXT_HOST_VALID),
5826 ext_host_address=sessions[0].ext_host_nat_address,
5827 ext_host_port=sessions[0].ext_host_nat_port)
5828 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5829 self.assertEqual(len(sessions), 0)
5831 def test_twice_nat(self):
5833 self.twice_nat_common()
5835 def test_self_twice_nat_positive(self):
5836 """ Self Twice NAT44 (positive test) """
5837 self.twice_nat_common(self_twice_nat=True, same_pg=True)
5839 def test_self_twice_nat_negative(self):
5840 """ Self Twice NAT44 (negative test) """
5841 self.twice_nat_common(self_twice_nat=True)
5843 def test_twice_nat_lb(self):
5844 """ Twice NAT44 local service load balancing """
5845 self.twice_nat_common(lb=True)
5847 def test_self_twice_nat_lb_positive(self):
5848 """ Self Twice NAT44 local service load balancing (positive test) """
5849 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5852 def test_self_twice_nat_lb_negative(self):
5853 """ Self Twice NAT44 local service load balancing (negative test) """
5854 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5857 def test_twice_nat_interface_addr(self):
5858 """ Acquire twice NAT44 addresses from interface """
5859 flags = self.config_flags.NAT_IS_TWICE_NAT
5860 self.vapi.nat44_add_del_interface_addr(
5862 sw_if_index=self.pg3.sw_if_index,
5865 # no address in NAT pool
5866 adresses = self.vapi.nat44_address_dump()
5867 self.assertEqual(0, len(adresses))
5869 # configure interface address and check NAT address pool
5870 self.pg3.config_ip4()
5871 adresses = self.vapi.nat44_address_dump()
5872 self.assertEqual(1, len(adresses))
5873 self.assertEqual(str(adresses[0].ip_address),
5875 self.assertEqual(adresses[0].flags, flags)
5877 # remove interface address and check NAT address pool
5878 self.pg3.unconfig_ip4()
5879 adresses = self.vapi.nat44_address_dump()
5880 self.assertEqual(0, len(adresses))
5882 def test_tcp_close(self):
5883 """ Close TCP session from inside network - output feature """
5884 self.vapi.nat44_forwarding_enable_disable(enable=1)
5885 self.nat44_add_address(self.pg1.local_ip4)
5886 twice_nat_addr = '10.0.1.3'
5887 service_ip = '192.168.16.150'
5888 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5889 flags = self.config_flags.NAT_IS_INSIDE
5890 self.vapi.nat44_interface_add_del_feature(
5891 sw_if_index=self.pg0.sw_if_index,
5893 self.vapi.nat44_interface_add_del_feature(
5894 sw_if_index=self.pg0.sw_if_index,
5895 flags=flags, is_add=1)
5896 self.vapi.nat44_interface_add_del_output_feature(
5898 sw_if_index=self.pg1.sw_if_index)
5899 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5900 self.config_flags.NAT_IS_TWICE_NAT)
5901 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5905 proto=IP_PROTOS.tcp,
5907 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5908 start_sessnum = len(sessions)
5910 # SYN packet out->in
5911 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5912 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5913 TCP(sport=33898, dport=80, flags="S"))
5914 self.pg1.add_stream(p)
5915 self.pg_enable_capture(self.pg_interfaces)
5917 capture = self.pg0.get_capture(1)
5919 tcp_port = p[TCP].sport
5921 # SYN + ACK packet in->out
5922 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5923 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5924 TCP(sport=80, dport=tcp_port, flags="SA"))
5925 self.pg0.add_stream(p)
5926 self.pg_enable_capture(self.pg_interfaces)
5928 self.pg1.get_capture(1)
5930 # ACK packet out->in
5931 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5932 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5933 TCP(sport=33898, dport=80, flags="A"))
5934 self.pg1.add_stream(p)
5935 self.pg_enable_capture(self.pg_interfaces)
5937 self.pg0.get_capture(1)
5939 # FIN packet in -> out
5940 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5941 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5942 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5943 self.pg0.add_stream(p)
5944 self.pg_enable_capture(self.pg_interfaces)
5946 self.pg1.get_capture(1)
5948 # FIN+ACK packet out -> in
5949 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5950 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5951 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5952 self.pg1.add_stream(p)
5953 self.pg_enable_capture(self.pg_interfaces)
5955 self.pg0.get_capture(1)
5957 # ACK packet in -> out
5958 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5959 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5960 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5961 self.pg0.add_stream(p)
5962 self.pg_enable_capture(self.pg_interfaces)
5964 self.pg1.get_capture(1)
5966 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4,
5968 self.assertEqual(len(sessions) - start_sessnum, 0)
5970 def test_tcp_session_close_in(self):
5971 """ Close TCP session from inside network """
5972 self.tcp_port_out = 10505
5973 self.nat44_add_address(self.nat_addr)
5974 flags = self.config_flags.NAT_IS_TWICE_NAT
5975 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5979 proto=IP_PROTOS.tcp,
5981 flags = self.config_flags.NAT_IS_INSIDE
5982 self.vapi.nat44_interface_add_del_feature(
5983 sw_if_index=self.pg0.sw_if_index,
5984 flags=flags, is_add=1)
5985 self.vapi.nat44_interface_add_del_feature(
5986 sw_if_index=self.pg1.sw_if_index,
5989 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5990 start_sessnum = len(sessions)
5992 self.initiate_tcp_session(self.pg0, self.pg1)
5994 # FIN packet in -> out
5995 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5996 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5997 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5998 flags="FA", seq=100, ack=300))
5999 self.pg0.add_stream(p)
6000 self.pg_enable_capture(self.pg_interfaces)
6002 self.pg1.get_capture(1)
6006 # ACK packet out -> in
6007 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6008 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6009 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6010 flags="A", seq=300, ack=101))
6013 # FIN packet out -> in
6014 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6015 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6016 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6017 flags="FA", seq=300, ack=101))
6020 self.pg1.add_stream(pkts)
6021 self.pg_enable_capture(self.pg_interfaces)
6023 self.pg0.get_capture(2)
6025 # ACK packet in -> out
6026 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6027 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6028 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6029 flags="A", seq=101, ack=301))
6030 self.pg0.add_stream(p)
6031 self.pg_enable_capture(self.pg_interfaces)
6033 self.pg1.get_capture(1)
6035 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4,
6037 self.assertEqual(len(sessions) - start_sessnum, 0)
6039 def test_tcp_session_close_out(self):
6040 """ Close TCP session from outside network """
6041 self.tcp_port_out = 10505
6042 self.nat44_add_address(self.nat_addr)
6043 flags = self.config_flags.NAT_IS_TWICE_NAT
6044 self.nat44_add_static_mapping(self.pg0.remote_ip4,
6048 proto=IP_PROTOS.tcp,
6050 flags = self.config_flags.NAT_IS_INSIDE
6051 self.vapi.nat44_interface_add_del_feature(
6052 sw_if_index=self.pg0.sw_if_index,
6053 flags=flags, is_add=1)
6054 self.vapi.nat44_interface_add_del_feature(
6055 sw_if_index=self.pg1.sw_if_index,
6058 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6059 start_sessnum = len(sessions)
6061 self.initiate_tcp_session(self.pg0, self.pg1)
6063 # FIN packet out -> in
6064 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6065 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6066 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6067 flags="FA", seq=100, ack=300))
6068 self.pg1.add_stream(p)
6069 self.pg_enable_capture(self.pg_interfaces)
6071 self.pg0.get_capture(1)
6073 # FIN+ACK packet in -> out
6074 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6075 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6076 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6077 flags="FA", seq=300, ack=101))
6079 self.pg0.add_stream(p)
6080 self.pg_enable_capture(self.pg_interfaces)
6082 self.pg1.get_capture(1)
6084 # ACK packet out -> in
6085 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6086 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6087 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6088 flags="A", seq=101, ack=301))
6089 self.pg1.add_stream(p)
6090 self.pg_enable_capture(self.pg_interfaces)
6092 self.pg0.get_capture(1)
6094 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4,
6096 self.assertEqual(len(sessions) - start_sessnum, 0)
6098 def test_tcp_session_close_simultaneous(self):
6099 """ Close TCP session from inside network """
6100 self.tcp_port_out = 10505
6101 self.nat44_add_address(self.nat_addr)
6102 flags = self.config_flags.NAT_IS_TWICE_NAT
6103 self.nat44_add_static_mapping(self.pg0.remote_ip4,
6107 proto=IP_PROTOS.tcp,
6109 flags = self.config_flags.NAT_IS_INSIDE
6110 self.vapi.nat44_interface_add_del_feature(
6111 sw_if_index=self.pg0.sw_if_index,
6112 flags=flags, is_add=1)
6113 self.vapi.nat44_interface_add_del_feature(
6114 sw_if_index=self.pg1.sw_if_index,
6117 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6118 start_sessnum = len(sessions)
6120 self.initiate_tcp_session(self.pg0, self.pg1)
6122 # FIN packet in -> out
6123 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6124 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6125 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6126 flags="FA", seq=100, ack=300))
6127 self.pg0.add_stream(p)
6128 self.pg_enable_capture(self.pg_interfaces)
6130 self.pg1.get_capture(1)
6132 # FIN packet out -> in
6133 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6134 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6135 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6136 flags="FA", seq=300, ack=100))
6137 self.pg1.add_stream(p)
6138 self.pg_enable_capture(self.pg_interfaces)
6140 self.pg0.get_capture(1)
6142 # ACK packet in -> out
6143 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6144 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6145 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6146 flags="A", seq=101, ack=301))
6147 self.pg0.add_stream(p)
6148 self.pg_enable_capture(self.pg_interfaces)
6150 self.pg1.get_capture(1)
6152 # ACK packet out -> in
6153 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6154 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6155 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6156 flags="A", seq=301, ack=101))
6157 self.pg1.add_stream(p)
6158 self.pg_enable_capture(self.pg_interfaces)
6160 self.pg0.get_capture(1)
6162 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4,
6164 self.assertEqual(len(sessions) - start_sessnum, 0)
6166 def test_one_armed_nat44_static(self):
6167 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
6168 remote_host = self.pg4.remote_hosts[0]
6169 local_host = self.pg4.remote_hosts[1]
6174 self.vapi.nat44_forwarding_enable_disable(enable=1)
6175 self.nat44_add_address(self.nat_addr, twice_nat=1)
6176 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
6177 self.config_flags.NAT_IS_TWICE_NAT)
6178 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
6179 local_port, external_port,
6180 proto=IP_PROTOS.tcp, flags=flags)
6181 flags = self.config_flags.NAT_IS_INSIDE
6182 self.vapi.nat44_interface_add_del_feature(
6183 sw_if_index=self.pg4.sw_if_index,
6185 self.vapi.nat44_interface_add_del_feature(
6186 sw_if_index=self.pg4.sw_if_index,
6187 flags=flags, is_add=1)
6189 # from client to service
6190 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6191 IP(src=remote_host.ip4, dst=self.nat_addr) /
6192 TCP(sport=12345, dport=external_port))
6193 self.pg4.add_stream(p)
6194 self.pg_enable_capture(self.pg_interfaces)
6196 capture = self.pg4.get_capture(1)
6201 self.assertEqual(ip.dst, local_host.ip4)
6202 self.assertEqual(ip.src, self.nat_addr)
6203 self.assertEqual(tcp.dport, local_port)
6204 self.assertNotEqual(tcp.sport, 12345)
6205 eh_port_in = tcp.sport
6206 self.assert_packet_checksums_valid(p)
6208 self.logger.error(ppp("Unexpected or invalid packet:", p))
6211 # from service back to client
6212 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6213 IP(src=local_host.ip4, dst=self.nat_addr) /
6214 TCP(sport=local_port, dport=eh_port_in))
6215 self.pg4.add_stream(p)
6216 self.pg_enable_capture(self.pg_interfaces)
6218 capture = self.pg4.get_capture(1)
6223 self.assertEqual(ip.src, self.nat_addr)
6224 self.assertEqual(ip.dst, remote_host.ip4)
6225 self.assertEqual(tcp.sport, external_port)
6226 self.assertEqual(tcp.dport, 12345)
6227 self.assert_packet_checksums_valid(p)
6229 self.logger.error(ppp("Unexpected or invalid packet:", p))
6232 def test_static_with_port_out2(self):
6233 """ 1:1 NAPT asymmetrical rule """
6238 self.vapi.nat44_forwarding_enable_disable(enable=1)
6239 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6240 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
6241 local_port, external_port,
6242 proto=IP_PROTOS.tcp, flags=flags)
6243 flags = self.config_flags.NAT_IS_INSIDE
6244 self.vapi.nat44_interface_add_del_feature(
6245 sw_if_index=self.pg0.sw_if_index,
6246 flags=flags, is_add=1)
6247 self.vapi.nat44_interface_add_del_feature(
6248 sw_if_index=self.pg1.sw_if_index,
6251 # from client to service
6252 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6253 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6254 TCP(sport=12345, dport=external_port))
6255 self.pg1.add_stream(p)
6256 self.pg_enable_capture(self.pg_interfaces)
6258 capture = self.pg0.get_capture(1)
6263 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6264 self.assertEqual(tcp.dport, local_port)
6265 self.assert_packet_checksums_valid(p)
6267 self.logger.error(ppp("Unexpected or invalid packet:", p))
6271 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6272 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6273 ICMP(type=11) / capture[0][IP])
6274 self.pg0.add_stream(p)
6275 self.pg_enable_capture(self.pg_interfaces)
6277 capture = self.pg1.get_capture(1)
6280 self.assertEqual(p[IP].src, self.nat_addr)
6282 self.assertEqual(inner.dst, self.nat_addr)
6283 self.assertEqual(inner[TCPerror].dport, external_port)
6285 self.logger.error(ppp("Unexpected or invalid packet:", p))
6288 # from service back to client
6289 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6290 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6291 TCP(sport=local_port, dport=12345))
6292 self.pg0.add_stream(p)
6293 self.pg_enable_capture(self.pg_interfaces)
6295 capture = self.pg1.get_capture(1)
6300 self.assertEqual(ip.src, self.nat_addr)
6301 self.assertEqual(tcp.sport, external_port)
6302 self.assert_packet_checksums_valid(p)
6304 self.logger.error(ppp("Unexpected or invalid packet:", p))
6308 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6309 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6310 ICMP(type=11) / capture[0][IP])
6311 self.pg1.add_stream(p)
6312 self.pg_enable_capture(self.pg_interfaces)
6314 capture = self.pg0.get_capture(1)
6317 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
6319 self.assertEqual(inner.src, self.pg0.remote_ip4)
6320 self.assertEqual(inner[TCPerror].sport, local_port)
6322 self.logger.error(ppp("Unexpected or invalid packet:", p))
6325 # from client to server (no translation)
6326 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6327 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
6328 TCP(sport=12346, dport=local_port))
6329 self.pg1.add_stream(p)
6330 self.pg_enable_capture(self.pg_interfaces)
6332 capture = self.pg0.get_capture(1)
6337 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6338 self.assertEqual(tcp.dport, local_port)
6339 self.assert_packet_checksums_valid(p)
6341 self.logger.error(ppp("Unexpected or invalid packet:", p))
6344 # from service back to client (no translation)
6345 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6346 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6347 TCP(sport=local_port, dport=12346))
6348 self.pg0.add_stream(p)
6349 self.pg_enable_capture(self.pg_interfaces)
6351 capture = self.pg1.get_capture(1)
6356 self.assertEqual(ip.src, self.pg0.remote_ip4)
6357 self.assertEqual(tcp.sport, local_port)
6358 self.assert_packet_checksums_valid(p)
6360 self.logger.error(ppp("Unexpected or invalid packet:", p))
6363 def test_output_feature(self):
6364 """ NAT44 interface output feature (in2out postrouting) """
6365 self.vapi.nat44_forwarding_enable_disable(enable=1)
6366 self.nat44_add_address(self.nat_addr)
6367 self.vapi.nat44_interface_add_del_feature(
6368 sw_if_index=self.pg0.sw_if_index,
6370 self.vapi.nat44_interface_add_del_output_feature(
6372 sw_if_index=self.pg1.sw_if_index)
6375 pkts = self.create_stream_in(self.pg0, self.pg1)
6376 self.pg0.add_stream(pkts)
6377 self.pg_enable_capture(self.pg_interfaces)
6379 capture = self.pg1.get_capture(len(pkts))
6380 self.verify_capture_out(capture)
6383 pkts = self.create_stream_out(self.pg1)
6384 self.pg1.add_stream(pkts)
6385 self.pg_enable_capture(self.pg_interfaces)
6387 capture = self.pg0.get_capture(len(pkts))
6388 self.verify_capture_in(capture, self.pg0)
6390 def test_output_feature_stateful_acl(self):
6391 """ NAT44 endpoint-dependent output feature works with stateful ACL """
6392 self.nat44_add_address(self.nat_addr)
6393 self.vapi.nat44_interface_add_del_output_feature(
6394 sw_if_index=self.pg0.sw_if_index,
6395 flags=self.config_flags.NAT_IS_INSIDE,
6397 self.vapi.nat44_interface_add_del_output_feature(
6398 sw_if_index=self.pg1.sw_if_index,
6399 flags=self.config_flags.NAT_IS_OUTSIDE,
6402 # First ensure that the NAT is working sans ACL
6404 # send packets out2in, no sessions yet so packets should drop
6405 pkts_out2in = self.create_stream_out(self.pg1)
6406 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
6408 # send packets into inside intf, ensure received via outside intf
6409 pkts_in2out = self.create_stream_in(self.pg0, self.pg1)
6410 capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
6412 self.verify_capture_out(capture)
6414 # send out2in again, with sessions created it should work now
6415 pkts_out2in = self.create_stream_out(self.pg1)
6416 capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
6418 self.verify_capture_in(capture, self.pg0)
6420 # Create an ACL blocking everything
6421 out2in_deny_rule = {
6424 'src_ip_addr': inet_pton(AF_INET, "0.0.0.0"),
6425 'src_ip_prefix_len': 0,
6426 'dst_ip_addr': inet_pton(AF_INET, "0.0.0.0"),
6427 'dst_ip_prefix_len': 0,
6428 'srcport_or_icmptype_first': 0,
6429 'srcport_or_icmptype_last': 65535,
6430 'dstport_or_icmpcode_first': 0,
6431 'dstport_or_icmpcode_last': 65535,
6434 out2in_rules = [out2in_deny_rule]
6435 res = self.vapi.acl_add_replace(0xffffffff, out2in_rules)
6436 self.assertEqual(res.retval, 0, "error adding out2in ACL")
6437 out2in_acl = res.acl_index
6439 # apply as input acl on interface and confirm it blocks everything
6440 self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg1.sw_if_index,
6443 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
6445 # create an ACL to permit/reflect everything
6446 in2out_reflect_rule = {
6449 'src_ip_addr': inet_pton(AF_INET, "0.0.0.0"),
6450 'src_ip_prefix_len': 0,
6451 'dst_ip_addr': inet_pton(AF_INET, "0.0.0.0"),
6452 'dst_ip_prefix_len': 0,
6453 'srcport_or_icmptype_first': 0,
6454 'srcport_or_icmptype_last': 65535,
6455 'dstport_or_icmpcode_first': 0,
6456 'dstport_or_icmpcode_last': 65535,
6459 in2out_rules = [in2out_reflect_rule]
6460 res = self.vapi.acl_add_replace(0xffffffff, in2out_rules)
6461 self.assertEqual(res.retval, 0, "error adding in2out ACL")
6462 in2out_acl = res.acl_index
6465 self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg1.sw_if_index,
6467 acls=[out2in_acl, in2out_acl])
6468 # send in2out to generate ACL state (NAT state was created earlier)
6469 capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
6471 self.verify_capture_out(capture)
6473 # send out2in again. ACL state exists so it should work now.
6474 # TCP packets with the syn flag set also need the ack flag
6475 for p in pkts_out2in:
6476 if p.haslayer(TCP) and p[TCP].flags & 0x02:
6477 p[TCP].flags |= 0x10
6478 capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
6480 self.verify_capture_in(capture, self.pg0)
6481 self.logger.info(self.vapi.cli("show trace"))
6484 # Remove ACLs from interface
6485 self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg1.sw_if_index,
6489 self.vapi.acl_del(acl_index=out2in_acl, expected_retval=0)
6490 self.vapi.acl_del(acl_index=in2out_acl, expected_retval=0)
6492 def test_multiple_vrf(self):
6493 """ Multiple VRF setup """
6494 external_addr = '1.2.3.4'
6499 self.vapi.nat44_forwarding_enable_disable(enable=1)
6500 self.nat44_add_address(self.nat_addr)
6501 flags = self.config_flags.NAT_IS_INSIDE
6502 self.vapi.nat44_interface_add_del_feature(
6503 sw_if_index=self.pg0.sw_if_index,
6505 self.vapi.nat44_interface_add_del_feature(
6506 sw_if_index=self.pg0.sw_if_index,
6507 flags=flags, is_add=1)
6508 self.vapi.nat44_interface_add_del_output_feature(
6510 sw_if_index=self.pg1.sw_if_index)
6511 self.vapi.nat44_interface_add_del_feature(
6512 sw_if_index=self.pg5.sw_if_index,
6514 self.vapi.nat44_interface_add_del_feature(
6515 sw_if_index=self.pg5.sw_if_index,
6516 flags=flags, is_add=1)
6517 self.vapi.nat44_interface_add_del_feature(
6518 sw_if_index=self.pg6.sw_if_index,
6520 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6521 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
6522 local_port, external_port, vrf_id=1,
6523 proto=IP_PROTOS.tcp, flags=flags)
6524 self.nat44_add_static_mapping(
6525 self.pg0.remote_ip4,
6526 external_sw_if_index=self.pg0.sw_if_index,
6527 local_port=local_port,
6529 external_port=external_port,
6530 proto=IP_PROTOS.tcp,
6534 # from client to service (both VRF1)
6535 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6536 IP(src=self.pg6.remote_ip4, dst=external_addr) /
6537 TCP(sport=12345, dport=external_port))
6538 self.pg6.add_stream(p)
6539 self.pg_enable_capture(self.pg_interfaces)
6541 capture = self.pg5.get_capture(1)
6546 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6547 self.assertEqual(tcp.dport, local_port)
6548 self.assert_packet_checksums_valid(p)
6550 self.logger.error(ppp("Unexpected or invalid packet:", p))
6553 # from service back to client (both VRF1)
6554 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6555 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6556 TCP(sport=local_port, dport=12345))
6557 self.pg5.add_stream(p)
6558 self.pg_enable_capture(self.pg_interfaces)
6560 capture = self.pg6.get_capture(1)
6565 self.assertEqual(ip.src, external_addr)
6566 self.assertEqual(tcp.sport, external_port)
6567 self.assert_packet_checksums_valid(p)
6569 self.logger.error(ppp("Unexpected or invalid packet:", p))
6572 # dynamic NAT from VRF1 to VRF0 (output-feature)
6573 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6574 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6575 TCP(sport=2345, dport=22))
6576 self.pg5.add_stream(p)
6577 self.pg_enable_capture(self.pg_interfaces)
6579 capture = self.pg1.get_capture(1)
6584 self.assertEqual(ip.src, self.nat_addr)
6585 self.assertNotEqual(tcp.sport, 2345)
6586 self.assert_packet_checksums_valid(p)
6589 self.logger.error(ppp("Unexpected or invalid packet:", p))
6592 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6593 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6594 TCP(sport=22, dport=port))
6595 self.pg1.add_stream(p)
6596 self.pg_enable_capture(self.pg_interfaces)
6598 capture = self.pg5.get_capture(1)
6603 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6604 self.assertEqual(tcp.dport, 2345)
6605 self.assert_packet_checksums_valid(p)
6607 self.logger.error(ppp("Unexpected or invalid packet:", p))
6610 # from client VRF1 to service VRF0
6611 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6612 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6613 TCP(sport=12346, dport=external_port))
6614 self.pg6.add_stream(p)
6615 self.pg_enable_capture(self.pg_interfaces)
6617 capture = self.pg0.get_capture(1)
6622 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6623 self.assertEqual(tcp.dport, local_port)
6624 self.assert_packet_checksums_valid(p)
6626 self.logger.error(ppp("Unexpected or invalid packet:", p))
6629 # from service VRF0 back to client VRF1
6630 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6631 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6632 TCP(sport=local_port, dport=12346))
6633 self.pg0.add_stream(p)
6634 self.pg_enable_capture(self.pg_interfaces)
6636 capture = self.pg6.get_capture(1)
6641 self.assertEqual(ip.src, self.pg0.local_ip4)
6642 self.assertEqual(tcp.sport, external_port)
6643 self.assert_packet_checksums_valid(p)
6645 self.logger.error(ppp("Unexpected or invalid packet:", p))
6648 # from client VRF0 to service VRF1
6649 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6650 IP(src=self.pg0.remote_ip4, dst=external_addr) /
6651 TCP(sport=12347, dport=external_port))
6652 self.pg0.add_stream(p)
6653 self.pg_enable_capture(self.pg_interfaces)
6655 capture = self.pg5.get_capture(1)
6660 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6661 self.assertEqual(tcp.dport, local_port)
6662 self.assert_packet_checksums_valid(p)
6664 self.logger.error(ppp("Unexpected or invalid packet:", p))
6667 # from service VRF1 back to client VRF0
6668 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6669 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6670 TCP(sport=local_port, dport=12347))
6671 self.pg5.add_stream(p)
6672 self.pg_enable_capture(self.pg_interfaces)
6674 capture = self.pg0.get_capture(1)
6679 self.assertEqual(ip.src, external_addr)
6680 self.assertEqual(tcp.sport, external_port)
6681 self.assert_packet_checksums_valid(p)
6683 self.logger.error(ppp("Unexpected or invalid packet:", p))
6686 # from client to server (both VRF1, no translation)
6687 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6688 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6689 TCP(sport=12348, dport=local_port))
6690 self.pg6.add_stream(p)
6691 self.pg_enable_capture(self.pg_interfaces)
6693 capture = self.pg5.get_capture(1)
6698 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6699 self.assertEqual(tcp.dport, local_port)
6700 self.assert_packet_checksums_valid(p)
6702 self.logger.error(ppp("Unexpected or invalid packet:", p))
6705 # from server back to client (both VRF1, no translation)
6706 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6707 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6708 TCP(sport=local_port, dport=12348))
6709 self.pg5.add_stream(p)
6710 self.pg_enable_capture(self.pg_interfaces)
6712 capture = self.pg6.get_capture(1)
6717 self.assertEqual(ip.src, self.pg5.remote_ip4)
6718 self.assertEqual(tcp.sport, local_port)
6719 self.assert_packet_checksums_valid(p)
6721 self.logger.error(ppp("Unexpected or invalid packet:", p))
6724 # from client VRF1 to server VRF0 (no translation)
6725 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6726 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6727 TCP(sport=local_port, dport=12349))
6728 self.pg0.add_stream(p)
6729 self.pg_enable_capture(self.pg_interfaces)
6731 capture = self.pg6.get_capture(1)
6736 self.assertEqual(ip.src, self.pg0.remote_ip4)
6737 self.assertEqual(tcp.sport, local_port)
6738 self.assert_packet_checksums_valid(p)
6740 self.logger.error(ppp("Unexpected or invalid packet:", p))
6743 # from server VRF0 back to client VRF1 (no translation)
6744 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6745 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6746 TCP(sport=local_port, dport=12349))
6747 self.pg0.add_stream(p)
6748 self.pg_enable_capture(self.pg_interfaces)
6750 capture = self.pg6.get_capture(1)
6755 self.assertEqual(ip.src, self.pg0.remote_ip4)
6756 self.assertEqual(tcp.sport, local_port)
6757 self.assert_packet_checksums_valid(p)
6759 self.logger.error(ppp("Unexpected or invalid packet:", p))
6762 # from client VRF0 to server VRF1 (no translation)
6763 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6764 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6765 TCP(sport=12344, dport=local_port))
6766 self.pg0.add_stream(p)
6767 self.pg_enable_capture(self.pg_interfaces)
6769 capture = self.pg5.get_capture(1)
6774 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6775 self.assertEqual(tcp.dport, local_port)
6776 self.assert_packet_checksums_valid(p)
6778 self.logger.error(ppp("Unexpected or invalid packet:", p))
6781 # from server VRF1 back to client VRF0 (no translation)
6782 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6783 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6784 TCP(sport=local_port, dport=12344))
6785 self.pg5.add_stream(p)
6786 self.pg_enable_capture(self.pg_interfaces)
6788 capture = self.pg0.get_capture(1)
6793 self.assertEqual(ip.src, self.pg5.remote_ip4)
6794 self.assertEqual(tcp.sport, local_port)
6795 self.assert_packet_checksums_valid(p)
6797 self.logger.error(ppp("Unexpected or invalid packet:", p))
6800 @unittest.skipUnless(running_extended_tests, "part of extended tests")
6801 def test_session_timeout(self):
6802 """ NAT44 session timeouts """
6803 self.nat44_add_address(self.nat_addr)
6804 flags = self.config_flags.NAT_IS_INSIDE
6805 self.vapi.nat44_interface_add_del_feature(
6806 sw_if_index=self.pg0.sw_if_index,
6807 flags=flags, is_add=1)
6808 self.vapi.nat44_interface_add_del_feature(
6809 sw_if_index=self.pg1.sw_if_index,
6811 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6812 tcp_transitory=240, icmp=5)
6816 for i in range(0, max_sessions):
6817 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6818 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6819 IP(src=src, dst=self.pg1.remote_ip4) /
6820 ICMP(id=1025, type='echo-request'))
6822 self.pg0.add_stream(pkts)
6823 self.pg_enable_capture(self.pg_interfaces)
6825 self.pg1.get_capture(max_sessions)
6830 for i in range(0, max_sessions):
6831 src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6832 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6833 IP(src=src, dst=self.pg1.remote_ip4) /
6834 ICMP(id=1026, type='echo-request'))
6836 self.pg0.add_stream(pkts)
6837 self.pg_enable_capture(self.pg_interfaces)
6839 self.pg1.get_capture(max_sessions)
6842 users = self.vapi.nat44_user_dump()
6844 nsessions = nsessions + user.nsessions
6845 self.assertLess(nsessions, 2 * max_sessions)
6847 @unittest.skipUnless(running_extended_tests, "part of extended tests")
6848 def test_session_rst_timeout(self):
6849 """ NAT44 session RST timeouts """
6850 self.nat44_add_address(self.nat_addr)
6851 flags = self.config_flags.NAT_IS_INSIDE
6852 self.vapi.nat44_interface_add_del_feature(
6853 sw_if_index=self.pg0.sw_if_index,
6854 flags=flags, is_add=1)
6855 self.vapi.nat44_interface_add_del_feature(
6856 sw_if_index=self.pg1.sw_if_index,
6858 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6859 tcp_transitory=5, icmp=60)
6861 self.initiate_tcp_session(self.pg0, self.pg1)
6862 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6863 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6864 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6866 self.pg0.add_stream(p)
6867 self.pg_enable_capture(self.pg_interfaces)
6869 self.pg1.get_capture(1)
6873 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6874 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6875 TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6877 self.pg0.add_stream(p)
6878 self.pg_enable_capture(self.pg_interfaces)
6880 self.pg1.get_capture(1)
6883 users = self.vapi.nat44_user_dump()
6884 self.assertEqual(len(users), 1)
6885 self.assertEqual(str(users[0].ip_address),
6886 self.pg0.remote_ip4)
6887 self.assertEqual(users[0].nsessions, 1)
6889 def test_syslog_sess(self):
6890 """ Test syslog session creation and deletion """
6891 self.vapi.syslog_set_filter(
6892 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
6893 self.vapi.syslog_set_sender(self.pg2.local_ip4, self.pg2.remote_ip4)
6894 self.nat44_add_address(self.nat_addr)
6895 flags = self.config_flags.NAT_IS_INSIDE
6896 self.vapi.nat44_interface_add_del_feature(
6897 sw_if_index=self.pg0.sw_if_index,
6898 flags=flags, is_add=1)
6899 self.vapi.nat44_interface_add_del_feature(
6900 sw_if_index=self.pg1.sw_if_index,
6903 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6904 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6905 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6906 self.pg0.add_stream(p)
6907 self.pg_enable_capture(self.pg_interfaces)
6909 capture = self.pg1.get_capture(1)
6910 self.tcp_port_out = capture[0][TCP].sport
6911 capture = self.pg2.get_capture(1)
6912 self.verify_syslog_sess(capture[0][Raw].load)
6914 self.pg_enable_capture(self.pg_interfaces)
6916 self.nat44_add_address(self.nat_addr, is_add=0)
6917 capture = self.pg2.get_capture(1)
6918 self.verify_syslog_sess(capture[0][Raw].load, False)
6921 super(TestNAT44EndpointDependent, self).tearDown()
6922 if not self.vpp_dead:
6924 self.vapi.cli("clear logging")
6926 def show_commands_at_teardown(self):
6927 self.logger.info(self.vapi.cli("show nat44 addresses"))
6928 self.logger.info(self.vapi.cli("show nat44 interfaces"))
6929 self.logger.info(self.vapi.cli("show nat44 static mappings"))
6930 self.logger.info(self.vapi.cli("show nat44 interface address"))
6931 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
6932 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
6933 self.logger.info(self.vapi.cli("show nat timeouts"))
6936 class TestNAT44Out2InDPO(MethodHolder):
6937 """ NAT44 Test Cases using out2in DPO """
6940 def setUpConstants(cls):
6941 super(TestNAT44Out2InDPO, cls).setUpConstants()
6942 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
6945 def setUpClass(cls):
6946 super(TestNAT44Out2InDPO, cls).setUpClass()
6947 cls.vapi.cli("set log class nat level debug")
6950 cls.tcp_port_in = 6303
6951 cls.tcp_port_out = 6303
6952 cls.udp_port_in = 6304
6953 cls.udp_port_out = 6304
6954 cls.icmp_id_in = 6305
6955 cls.icmp_id_out = 6305
6956 cls.nat_addr = '10.0.0.3'
6957 cls.dst_ip4 = '192.168.70.1'
6959 cls.create_pg_interfaces(range(2))
6962 cls.pg0.config_ip4()
6963 cls.pg0.resolve_arp()
6966 cls.pg1.config_ip6()
6967 cls.pg1.resolve_ndp()
6969 r1 = VppIpRoute(cls, "::", 0,
6970 [VppRoutePath(cls.pg1.remote_ip6,
6971 cls.pg1.sw_if_index)],
6976 super(TestNAT44Out2InDPO, cls).tearDownClass()
6980 def tearDownClass(cls):
6981 super(TestNAT44Out2InDPO, cls).tearDownClass()
6983 def configure_xlat(self):
6984 self.dst_ip6_pfx = '1:2:3::'
6985 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6987 self.dst_ip6_pfx_len = 96
6988 self.src_ip6_pfx = '4:5:6::'
6989 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6991 self.src_ip6_pfx_len = 96
6992 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
6993 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
6994 '\x00\x00\x00\x00', 0)
6996 @unittest.skip('Temporary disabled')
6997 def test_464xlat_ce(self):
6998 """ Test 464XLAT CE with NAT44 """
7000 nat_config = self.vapi.nat_show_config()
7001 self.assertEqual(1, nat_config.out2in_dpo)
7003 self.configure_xlat()
7005 flags = self.config_flags.NAT_IS_INSIDE
7006 self.vapi.nat44_interface_add_del_feature(
7007 sw_if_index=self.pg0.sw_if_index,
7008 flags=flags, is_add=1)
7009 self.vapi.nat44_add_del_address_range(first_ip_address=self.nat_addr_n,
7010 last_ip_address=self.nat_addr_n,
7011 vrf_id=0xFFFFFFFF, is_add=1)
7013 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7014 self.dst_ip6_pfx_len)
7015 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
7016 self.src_ip6_pfx_len)
7019 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7020 self.pg0.add_stream(pkts)
7021 self.pg_enable_capture(self.pg_interfaces)
7023 capture = self.pg1.get_capture(len(pkts))
7024 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
7027 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
7029 self.pg1.add_stream(pkts)
7030 self.pg_enable_capture(self.pg_interfaces)
7032 capture = self.pg0.get_capture(len(pkts))
7033 self.verify_capture_in(capture, self.pg0)
7035 self.vapi.nat44_interface_add_del_feature(
7036 sw_if_index=self.pg0.sw_if_index,
7038 self.vapi.nat44_add_del_address_range(
7039 first_ip_address=self.nat_addr_n,
7040 last_ip_address=self.nat_addr_n,
7043 @unittest.skip('Temporary disabled')
7044 def test_464xlat_ce_no_nat(self):
7045 """ Test 464XLAT CE without NAT44 """
7047 self.configure_xlat()
7049 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7050 self.dst_ip6_pfx_len)
7051 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
7052 self.src_ip6_pfx_len)
7054 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7055 self.pg0.add_stream(pkts)
7056 self.pg_enable_capture(self.pg_interfaces)
7058 capture = self.pg1.get_capture(len(pkts))
7059 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
7060 nat_ip=out_dst_ip6, same_port=True)
7062 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
7063 self.pg1.add_stream(pkts)
7064 self.pg_enable_capture(self.pg_interfaces)
7066 capture = self.pg0.get_capture(len(pkts))
7067 self.verify_capture_in(capture, self.pg0)
7070 class TestDeterministicNAT(MethodHolder):
7071 """ Deterministic NAT Test Cases """
7074 def setUpConstants(cls):
7075 super(TestDeterministicNAT, cls).setUpConstants()
7076 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
7079 def setUpClass(cls):
7080 super(TestDeterministicNAT, cls).setUpClass()
7081 cls.vapi.cli("set log class nat level debug")
7084 cls.tcp_port_in = 6303
7085 cls.tcp_external_port = 6303
7086 cls.udp_port_in = 6304
7087 cls.udp_external_port = 6304
7088 cls.icmp_id_in = 6305
7089 cls.nat_addr = '10.0.0.3'
7091 cls.create_pg_interfaces(range(3))
7092 cls.interfaces = list(cls.pg_interfaces)
7094 for i in cls.interfaces:
7099 cls.pg0.generate_remote_hosts(2)
7100 cls.pg0.configure_ipv4_neighbors()
7103 super(TestDeterministicNAT, cls).tearDownClass()
7107 def tearDownClass(cls):
7108 super(TestDeterministicNAT, cls).tearDownClass()
7110 def create_stream_in(self, in_if, out_if, ttl=64):
7112 Create packet stream for inside network
7114 :param in_if: Inside interface
7115 :param out_if: Outside interface
7116 :param ttl: TTL of generated packets
7120 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7121 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7122 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
7126 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7127 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7128 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
7132 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7133 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7134 ICMP(id=self.icmp_id_in, type='echo-request'))
7139 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
7141 Create packet stream for outside network
7143 :param out_if: Outside interface
7144 :param dst_ip: Destination IP address (Default use global NAT address)
7145 :param ttl: TTL of generated packets
7148 dst_ip = self.nat_addr
7151 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7152 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7153 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
7157 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7158 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7159 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
7163 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7164 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7165 ICMP(id=self.icmp_external_id, type='echo-reply'))
7170 def verify_capture_out(self, capture, nat_ip=None):
7172 Verify captured packets on outside network
7174 :param capture: Captured packets
7175 :param nat_ip: Translated IP address (Default use global NAT address)
7176 :param same_port: Source port number is not translated (Default False)
7179 nat_ip = self.nat_addr
7180 for packet in capture:
7182 self.assertEqual(packet[IP].src, nat_ip)
7183 if packet.haslayer(TCP):
7184 self.tcp_port_out = packet[TCP].sport
7185 elif packet.haslayer(UDP):
7186 self.udp_port_out = packet[UDP].sport
7188 self.icmp_external_id = packet[ICMP].id
7190 self.logger.error(ppp("Unexpected or invalid packet "
7191 "(outside network):", packet))
7194 def test_deterministic_mode(self):
7195 """ NAT plugin run deterministic mode """
7196 in_addr = '172.16.255.0'
7197 out_addr = '172.17.255.50'
7198 in_addr_t = '172.16.255.20'
7202 nat_config = self.vapi.nat_show_config()
7203 self.assertEqual(1, nat_config.deterministic)
7205 self.vapi.nat_det_add_del_map(is_add=1, in_addr=in_addr,
7206 in_plen=in_plen, out_addr=out_addr,
7209 rep1 = self.vapi.nat_det_forward(in_addr_t)
7210 self.assertEqual(str(rep1.out_addr), out_addr)
7211 rep2 = self.vapi.nat_det_reverse(rep1.out_port_hi, out_addr)
7213 self.assertEqual(str(rep2.in_addr), in_addr_t)
7215 deterministic_mappings = self.vapi.nat_det_map_dump()
7216 self.assertEqual(len(deterministic_mappings), 1)
7217 dsm = deterministic_mappings[0]
7218 self.assertEqual(in_addr, str(dsm.in_addr))
7219 self.assertEqual(in_plen, dsm.in_plen)
7220 self.assertEqual(out_addr, str(dsm.out_addr))
7221 self.assertEqual(out_plen, dsm.out_plen)
7223 self.clear_nat_det()
7224 deterministic_mappings = self.vapi.nat_det_map_dump()
7225 self.assertEqual(len(deterministic_mappings), 0)
7227 def test_set_timeouts(self):
7228 """ Set deterministic NAT timeouts """
7229 timeouts_before = self.vapi.nat_get_timeouts()
7231 self.vapi.nat_set_timeouts(
7232 udp=timeouts_before.udp + 10,
7233 tcp_established=timeouts_before.tcp_established + 10,
7234 tcp_transitory=timeouts_before.tcp_transitory + 10,
7235 icmp=timeouts_before.icmp + 10)
7237 timeouts_after = self.vapi.nat_get_timeouts()
7239 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
7240 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
7241 self.assertNotEqual(timeouts_before.tcp_established,
7242 timeouts_after.tcp_established)
7243 self.assertNotEqual(timeouts_before.tcp_transitory,
7244 timeouts_after.tcp_transitory)
7246 def test_det_in(self):
7247 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
7249 nat_ip = "10.0.0.10"
7251 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7253 out_addr=socket.inet_aton(nat_ip),
7256 flags = self.config_flags.NAT_IS_INSIDE
7257 self.vapi.nat44_interface_add_del_feature(
7258 sw_if_index=self.pg0.sw_if_index,
7259 flags=flags, is_add=1)
7260 self.vapi.nat44_interface_add_del_feature(
7261 sw_if_index=self.pg1.sw_if_index,
7265 pkts = self.create_stream_in(self.pg0, self.pg1)
7266 self.pg0.add_stream(pkts)
7267 self.pg_enable_capture(self.pg_interfaces)
7269 capture = self.pg1.get_capture(len(pkts))
7270 self.verify_capture_out(capture, nat_ip)
7273 pkts = self.create_stream_out(self.pg1, nat_ip)
7274 self.pg1.add_stream(pkts)
7275 self.pg_enable_capture(self.pg_interfaces)
7277 capture = self.pg0.get_capture(len(pkts))
7278 self.verify_capture_in(capture, self.pg0)
7281 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4)
7282 self.assertEqual(len(sessions), 3)
7286 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7287 self.assertEqual(s.in_port, self.tcp_port_in)
7288 self.assertEqual(s.out_port, self.tcp_port_out)
7289 self.assertEqual(s.ext_port, self.tcp_external_port)
7293 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7294 self.assertEqual(s.in_port, self.udp_port_in)
7295 self.assertEqual(s.out_port, self.udp_port_out)
7296 self.assertEqual(s.ext_port, self.udp_external_port)
7300 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7301 self.assertEqual(s.in_port, self.icmp_id_in)
7302 self.assertEqual(s.out_port, self.icmp_external_id)
7304 def test_multiple_users(self):
7305 """ Deterministic NAT multiple users """
7307 nat_ip = "10.0.0.10"
7309 external_port = 6303
7311 host0 = self.pg0.remote_hosts[0]
7312 host1 = self.pg0.remote_hosts[1]
7314 self.vapi.nat_det_add_del_map(is_add=1, in_addr=host0.ip4, in_plen=24,
7315 out_addr=socket.inet_aton(nat_ip),
7317 flags = self.config_flags.NAT_IS_INSIDE
7318 self.vapi.nat44_interface_add_del_feature(
7319 sw_if_index=self.pg0.sw_if_index,
7320 flags=flags, is_add=1)
7321 self.vapi.nat44_interface_add_del_feature(
7322 sw_if_index=self.pg1.sw_if_index,
7326 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
7327 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
7328 TCP(sport=port_in, dport=external_port))
7329 self.pg0.add_stream(p)
7330 self.pg_enable_capture(self.pg_interfaces)
7332 capture = self.pg1.get_capture(1)
7337 self.assertEqual(ip.src, nat_ip)
7338 self.assertEqual(ip.dst, self.pg1.remote_ip4)
7339 self.assertEqual(tcp.dport, external_port)
7340 port_out0 = tcp.sport
7342 self.logger.error(ppp("Unexpected or invalid packet:", p))
7346 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
7347 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
7348 TCP(sport=port_in, dport=external_port))
7349 self.pg0.add_stream(p)
7350 self.pg_enable_capture(self.pg_interfaces)
7352 capture = self.pg1.get_capture(1)
7357 self.assertEqual(ip.src, nat_ip)
7358 self.assertEqual(ip.dst, self.pg1.remote_ip4)
7359 self.assertEqual(tcp.dport, external_port)
7360 port_out1 = tcp.sport
7362 self.logger.error(ppp("Unexpected or invalid packet:", p))
7365 dms = self.vapi.nat_det_map_dump()
7366 self.assertEqual(1, len(dms))
7367 self.assertEqual(2, dms[0].ses_num)
7370 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7371 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
7372 TCP(sport=external_port, dport=port_out0))
7373 self.pg1.add_stream(p)
7374 self.pg_enable_capture(self.pg_interfaces)
7376 capture = self.pg0.get_capture(1)
7381 self.assertEqual(ip.src, self.pg1.remote_ip4)
7382 self.assertEqual(ip.dst, host0.ip4)
7383 self.assertEqual(tcp.dport, port_in)
7384 self.assertEqual(tcp.sport, external_port)
7386 self.logger.error(ppp("Unexpected or invalid packet:", p))
7390 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7391 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
7392 TCP(sport=external_port, dport=port_out1))
7393 self.pg1.add_stream(p)
7394 self.pg_enable_capture(self.pg_interfaces)
7396 capture = self.pg0.get_capture(1)
7401 self.assertEqual(ip.src, self.pg1.remote_ip4)
7402 self.assertEqual(ip.dst, host1.ip4)
7403 self.assertEqual(tcp.dport, port_in)
7404 self.assertEqual(tcp.sport, external_port)
7406 self.logger.error(ppp("Unexpected or invalid packet", p))
7409 # session close api test
7410 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
7412 self.pg1.remote_ip4,
7414 dms = self.vapi.nat_det_map_dump()
7415 self.assertEqual(dms[0].ses_num, 1)
7417 self.vapi.nat_det_close_session_in(host0.ip4,
7419 self.pg1.remote_ip4,
7421 dms = self.vapi.nat_det_map_dump()
7422 self.assertEqual(dms[0].ses_num, 0)
7424 def test_tcp_session_close_detection_in(self):
7425 """ Deterministic NAT TCP session close from inside network """
7426 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7428 out_addr=socket.inet_aton(self.nat_addr),
7430 flags = self.config_flags.NAT_IS_INSIDE
7431 self.vapi.nat44_interface_add_del_feature(
7432 sw_if_index=self.pg0.sw_if_index,
7433 flags=flags, is_add=1)
7434 self.vapi.nat44_interface_add_del_feature(
7435 sw_if_index=self.pg1.sw_if_index,
7438 self.initiate_tcp_session(self.pg0, self.pg1)
7440 # close the session from inside
7442 # FIN packet in -> out
7443 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7444 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7445 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7447 self.pg0.add_stream(p)
7448 self.pg_enable_capture(self.pg_interfaces)
7450 self.pg1.get_capture(1)
7454 # ACK packet out -> in
7455 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7456 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7457 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7461 # FIN packet out -> in
7462 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7463 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7464 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7468 self.pg1.add_stream(pkts)
7469 self.pg_enable_capture(self.pg_interfaces)
7471 self.pg0.get_capture(2)
7473 # ACK packet in -> out
7474 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7475 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7476 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7478 self.pg0.add_stream(p)
7479 self.pg_enable_capture(self.pg_interfaces)
7481 self.pg1.get_capture(1)
7483 # Check if deterministic NAT44 closed the session
7484 dms = self.vapi.nat_det_map_dump()
7485 self.assertEqual(0, dms[0].ses_num)
7487 self.logger.error("TCP session termination failed")
7490 def test_tcp_session_close_detection_out(self):
7491 """ Deterministic NAT TCP session close from outside network """
7492 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7494 out_addr=socket.inet_aton(self.nat_addr),
7496 flags = self.config_flags.NAT_IS_INSIDE
7497 self.vapi.nat44_interface_add_del_feature(
7498 sw_if_index=self.pg0.sw_if_index,
7499 flags=flags, is_add=1)
7500 self.vapi.nat44_interface_add_del_feature(
7501 sw_if_index=self.pg1.sw_if_index,
7504 self.initiate_tcp_session(self.pg0, self.pg1)
7506 # close the session from outside
7508 # FIN packet out -> in
7509 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7510 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7511 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7513 self.pg1.add_stream(p)
7514 self.pg_enable_capture(self.pg_interfaces)
7516 self.pg0.get_capture(1)
7520 # ACK packet in -> out
7521 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7522 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7523 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7527 # ACK packet in -> out
7528 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7529 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7530 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7534 self.pg0.add_stream(pkts)
7535 self.pg_enable_capture(self.pg_interfaces)
7537 self.pg1.get_capture(2)
7539 # ACK packet out -> in
7540 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7541 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7542 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7544 self.pg1.add_stream(p)
7545 self.pg_enable_capture(self.pg_interfaces)
7547 self.pg0.get_capture(1)
7549 # Check if deterministic NAT44 closed the session
7550 dms = self.vapi.nat_det_map_dump()
7551 self.assertEqual(0, dms[0].ses_num)
7553 self.logger.error("TCP session termination failed")
7556 @unittest.skipUnless(running_extended_tests, "part of extended tests")
7557 def test_session_timeout(self):
7558 """ Deterministic NAT session timeouts """
7559 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7561 out_addr=socket.inet_aton(self.nat_addr),
7563 flags = self.config_flags.NAT_IS_INSIDE
7564 self.vapi.nat44_interface_add_del_feature(
7565 sw_if_index=self.pg0.sw_if_index,
7566 flags=flags, is_add=1)
7567 self.vapi.nat44_interface_add_del_feature(
7568 sw_if_index=self.pg1.sw_if_index,
7571 self.initiate_tcp_session(self.pg0, self.pg1)
7572 self.vapi.nat_set_timeouts(udp=5, tcp_established=5, tcp_transitory=5,
7574 pkts = self.create_stream_in(self.pg0, self.pg1)
7575 self.pg0.add_stream(pkts)
7576 self.pg_enable_capture(self.pg_interfaces)
7578 capture = self.pg1.get_capture(len(pkts))
7581 dms = self.vapi.nat_det_map_dump()
7582 self.assertEqual(0, dms[0].ses_num)
7584 @unittest.skipUnless(running_extended_tests, "part of extended tests")
7585 def test_session_limit_per_user(self):
7586 """ Deterministic NAT maximum sessions per user limit """
7587 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7589 out_addr=socket.inet_aton(self.nat_addr),
7591 flags = self.config_flags.NAT_IS_INSIDE
7592 self.vapi.nat44_interface_add_del_feature(
7593 sw_if_index=self.pg0.sw_if_index,
7594 flags=flags, is_add=1)
7595 self.vapi.nat44_interface_add_del_feature(
7596 sw_if_index=self.pg1.sw_if_index,
7598 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4,
7599 src_address=self.pg2.local_ip4,
7601 template_interval=10)
7602 self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7606 for port in range(1025, 2025):
7607 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7608 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7609 UDP(sport=port, dport=port))
7612 self.pg0.add_stream(pkts)
7613 self.pg_enable_capture(self.pg_interfaces)
7615 capture = self.pg1.get_capture(len(pkts))
7617 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7618 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7619 UDP(sport=3001, dport=3002))
7620 self.pg0.add_stream(p)
7621 self.pg_enable_capture(self.pg_interfaces)
7623 capture = self.pg1.assert_nothing_captured()
7625 # verify ICMP error packet
7626 capture = self.pg0.get_capture(1)
7628 self.assertTrue(p.haslayer(ICMP))
7630 self.assertEqual(icmp.type, 3)
7631 self.assertEqual(icmp.code, 1)
7632 self.assertTrue(icmp.haslayer(IPerror))
7633 inner_ip = icmp[IPerror]
7634 self.assertEqual(inner_ip[UDPerror].sport, 3001)
7635 self.assertEqual(inner_ip[UDPerror].dport, 3002)
7637 dms = self.vapi.nat_det_map_dump()
7639 self.assertEqual(1000, dms[0].ses_num)
7641 # verify IPFIX logging
7642 self.vapi.ipfix_flush()
7644 capture = self.pg2.get_capture(2)
7645 ipfix = IPFIXDecoder()
7646 # first load template
7648 self.assertTrue(p.haslayer(IPFIX))
7649 if p.haslayer(Template):
7650 ipfix.add_template(p.getlayer(Template))
7651 # verify events in data set
7653 if p.haslayer(Data):
7654 data = ipfix.decode_data_set(p.getlayer(Set))
7655 self.verify_ipfix_max_entries_per_user(data,
7657 self.pg0.remote_ip4)
7659 def clear_nat_det(self):
7661 Clear deterministic NAT configuration.
7663 self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7665 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
7666 tcp_transitory=240, icmp=60)
7667 deterministic_mappings = self.vapi.nat_det_map_dump()
7668 for dsm in deterministic_mappings:
7669 self.vapi.nat_det_add_del_map(is_add=0, in_addr=dsm.in_addr,
7670 in_plen=dsm.in_plen,
7671 out_addr=dsm.out_addr,
7672 out_plen=dsm.out_plen)
7674 interfaces = self.vapi.nat44_interface_dump()
7675 for intf in interfaces:
7676 self.vapi.nat44_interface_add_del_feature(
7677 sw_if_index=intf.sw_if_index,
7681 super(TestDeterministicNAT, self).tearDown()
7682 if not self.vpp_dead:
7683 self.clear_nat_det()
7685 def show_commands_at_teardown(self):
7686 self.logger.info(self.vapi.cli("show nat44 interfaces"))
7687 self.logger.info(self.vapi.cli("show nat timeouts"))
7689 self.vapi.cli("show nat44 deterministic mappings"))
7691 self.vapi.cli("show nat44 deterministic sessions"))
7694 class TestNAT64(MethodHolder):
7695 """ NAT64 Test Cases """
7698 def setUpConstants(cls):
7699 super(TestNAT64, cls).setUpConstants()
7700 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
7701 "nat64 st hash buckets 256", "}"])
7704 def setUpClass(cls):
7705 super(TestNAT64, cls).setUpClass()
7708 cls.tcp_port_in = 6303
7709 cls.tcp_port_out = 6303
7710 cls.udp_port_in = 6304
7711 cls.udp_port_out = 6304
7712 cls.icmp_id_in = 6305
7713 cls.icmp_id_out = 6305
7714 cls.tcp_external_port = 80
7715 cls.nat_addr = '10.0.0.3'
7716 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
7718 cls.vrf1_nat_addr = '10.0.10.3'
7719 cls.ipfix_src_port = 4739
7720 cls.ipfix_domain_id = 1
7722 cls.create_pg_interfaces(range(6))
7723 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
7724 cls.ip6_interfaces.append(cls.pg_interfaces[2])
7725 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
7727 cls.vapi.ip_table_add_del(is_add=1,
7728 table={'table_id': cls.vrf1_id,
7731 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
7733 cls.pg0.generate_remote_hosts(2)
7735 for i in cls.ip6_interfaces:
7738 i.configure_ipv6_neighbors()
7740 for i in cls.ip4_interfaces:
7746 cls.pg3.config_ip4()
7747 cls.pg3.resolve_arp()
7748 cls.pg3.config_ip6()
7749 cls.pg3.configure_ipv6_neighbors()
7752 cls.pg5.config_ip6()
7755 super(TestNAT64, cls).tearDownClass()
7759 def tearDownClass(cls):
7760 super(TestNAT64, cls).tearDownClass()
7762 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
7763 """ NAT64 inside interface handles Neighbor Advertisement """
7765 flags = self.config_flags.NAT_IS_INSIDE
7766 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7767 sw_if_index=self.pg5.sw_if_index)
7770 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7771 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7772 ICMPv6EchoRequest())
7774 self.pg5.add_stream(pkts)
7775 self.pg_enable_capture(self.pg_interfaces)
7778 # Wait for Neighbor Solicitation
7779 capture = self.pg5.get_capture(len(pkts))
7782 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7783 self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
7784 tgt = packet[ICMPv6ND_NS].tgt
7786 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7789 # Send Neighbor Advertisement
7790 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7791 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7792 ICMPv6ND_NA(tgt=tgt) /
7793 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
7795 self.pg5.add_stream(pkts)
7796 self.pg_enable_capture(self.pg_interfaces)
7799 # Try to send ping again
7801 self.pg5.add_stream(pkts)
7802 self.pg_enable_capture(self.pg_interfaces)
7805 # Wait for ping reply
7806 capture = self.pg5.get_capture(len(pkts))
7809 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7810 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
7811 self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
7813 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7816 def test_pool(self):
7817 """ Add/delete address to NAT64 pool """
7818 nat_addr = '1.2.3.4'
7820 self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7822 vrf_id=0xFFFFFFFF, is_add=1)
7824 addresses = self.vapi.nat64_pool_addr_dump()
7825 self.assertEqual(len(addresses), 1)
7826 self.assertEqual(str(addresses[0].address), nat_addr)
7828 self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7830 vrf_id=0xFFFFFFFF, is_add=0)
7832 addresses = self.vapi.nat64_pool_addr_dump()
7833 self.assertEqual(len(addresses), 0)
7835 def test_interface(self):
7836 """ Enable/disable NAT64 feature on the interface """
7837 flags = self.config_flags.NAT_IS_INSIDE
7838 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7839 sw_if_index=self.pg0.sw_if_index)
7840 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7841 sw_if_index=self.pg1.sw_if_index)
7843 interfaces = self.vapi.nat64_interface_dump()
7844 self.assertEqual(len(interfaces), 2)
7847 for intf in interfaces:
7848 if intf.sw_if_index == self.pg0.sw_if_index:
7849 self.assertEqual(intf.flags, self.config_flags.NAT_IS_INSIDE)
7851 elif intf.sw_if_index == self.pg1.sw_if_index:
7852 self.assertEqual(intf.flags, self.config_flags.NAT_IS_OUTSIDE)
7854 self.assertTrue(pg0_found)
7855 self.assertTrue(pg1_found)
7857 features = self.vapi.cli("show interface features pg0")
7858 self.assertIn('nat64-in2out', features)
7859 features = self.vapi.cli("show interface features pg1")
7860 self.assertIn('nat64-out2in', features)
7862 self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7863 sw_if_index=self.pg0.sw_if_index)
7864 self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7865 sw_if_index=self.pg1.sw_if_index)
7867 interfaces = self.vapi.nat64_interface_dump()
7868 self.assertEqual(len(interfaces), 0)
7870 def test_static_bib(self):
7871 """ Add/delete static BIB entry """
7872 in_addr = '2001:db8:85a3::8a2e:370:7334'
7873 out_addr = '10.1.1.3'
7876 proto = IP_PROTOS.tcp
7878 self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7879 i_port=in_port, o_port=out_port,
7880 proto=proto, vrf_id=0, is_add=1)
7881 bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
7884 if bibe.flags & self.config_flags.NAT_IS_STATIC:
7886 self.assertEqual(str(bibe.i_addr), in_addr)
7887 self.assertEqual(str(bibe.o_addr), out_addr)
7888 self.assertEqual(bibe.i_port, in_port)
7889 self.assertEqual(bibe.o_port, out_port)
7890 self.assertEqual(static_bib_num, 1)
7891 bibs = self.statistics.get_counter('/nat64/total-bibs')
7892 self.assertEqual(bibs[0][0], 1)
7894 self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7895 i_port=in_port, o_port=out_port,
7896 proto=proto, vrf_id=0, is_add=0)
7897 bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
7900 if bibe.flags & self.config_flags.NAT_IS_STATIC:
7902 self.assertEqual(static_bib_num, 0)
7903 bibs = self.statistics.get_counter('/nat64/total-bibs')
7904 self.assertEqual(bibs[0][0], 0)
7906 def test_set_timeouts(self):
7907 """ Set NAT64 timeouts """
7908 # verify default values
7909 timeouts = self.vapi.nat_get_timeouts()
7910 self.assertEqual(timeouts.udp, 300)
7911 self.assertEqual(timeouts.icmp, 60)
7912 self.assertEqual(timeouts.tcp_transitory, 240)
7913 self.assertEqual(timeouts.tcp_established, 7440)
7915 # set and verify custom values
7916 self.vapi.nat_set_timeouts(udp=200, tcp_established=7450,
7917 tcp_transitory=250, icmp=30)
7918 timeouts = self.vapi.nat_get_timeouts()
7919 self.assertEqual(timeouts.udp, 200)
7920 self.assertEqual(timeouts.icmp, 30)
7921 self.assertEqual(timeouts.tcp_transitory, 250)
7922 self.assertEqual(timeouts.tcp_established, 7450)
7924 def test_dynamic(self):
7925 """ NAT64 dynamic translation test """
7926 self.tcp_port_in = 6303
7927 self.udp_port_in = 6304
7928 self.icmp_id_in = 6305
7930 ses_num_start = self.nat64_get_ses_num()
7932 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
7933 end_addr=self.nat_addr,
7936 flags = self.config_flags.NAT_IS_INSIDE
7937 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7938 sw_if_index=self.pg0.sw_if_index)
7939 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7940 sw_if_index=self.pg1.sw_if_index)
7943 tcpn = self.statistics.get_err_counter('/err/nat64-in2out/TCP packets')
7944 udpn = self.statistics.get_err_counter('/err/nat64-in2out/UDP packets')
7945 icmpn = self.statistics.get_err_counter(
7946 '/err/nat64-in2out/ICMP packets')
7947 totaln = self.statistics.get_err_counter(
7948 '/err/nat64-in2out/good in2out packets processed')
7950 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7951 self.pg0.add_stream(pkts)
7952 self.pg_enable_capture(self.pg_interfaces)
7954 capture = self.pg1.get_capture(len(pkts))
7955 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7956 dst_ip=self.pg1.remote_ip4)
7958 err = self.statistics.get_err_counter('/err/nat64-in2out/TCP packets')
7959 self.assertEqual(err - tcpn, 1)
7960 err = self.statistics.get_err_counter('/err/nat64-in2out/UDP packets')
7961 self.assertEqual(err - udpn, 1)
7962 err = self.statistics.get_err_counter('/err/nat64-in2out/ICMP packets')
7963 self.assertEqual(err - icmpn, 1)
7964 err = self.statistics.get_err_counter(
7965 '/err/nat64-in2out/good in2out packets processed')
7966 self.assertEqual(err - totaln, 3)
7969 tcpn = self.statistics.get_err_counter('/err/nat64-out2in/TCP packets')
7970 udpn = self.statistics.get_err_counter('/err/nat64-out2in/UDP packets')
7971 icmpn = self.statistics.get_err_counter(
7972 '/err/nat64-out2in/ICMP packets')
7973 totaln = self.statistics.get_err_counter(
7974 '/err/nat64-out2in/good out2in packets processed')
7976 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7977 self.pg1.add_stream(pkts)
7978 self.pg_enable_capture(self.pg_interfaces)
7980 capture = self.pg0.get_capture(len(pkts))
7981 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7982 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7984 err = self.statistics.get_err_counter('/err/nat64-out2in/TCP packets')
7985 self.assertEqual(err - tcpn, 2)
7986 err = self.statistics.get_err_counter('/err/nat64-out2in/UDP packets')
7987 self.assertEqual(err - udpn, 1)
7988 err = self.statistics.get_err_counter('/err/nat64-out2in/ICMP packets')
7989 self.assertEqual(err - icmpn, 1)
7990 err = self.statistics.get_err_counter(
7991 '/err/nat64-out2in/good out2in packets processed')
7992 self.assertEqual(err - totaln, 4)
7994 bibs = self.statistics.get_counter('/nat64/total-bibs')
7995 self.assertEqual(bibs[0][0], 3)
7996 sessions = self.statistics.get_counter('/nat64/total-sessions')
7997 self.assertEqual(sessions[0][0], 3)
8000 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8001 self.pg0.add_stream(pkts)
8002 self.pg_enable_capture(self.pg_interfaces)
8004 capture = self.pg1.get_capture(len(pkts))
8005 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8006 dst_ip=self.pg1.remote_ip4)
8009 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8010 self.pg1.add_stream(pkts)
8011 self.pg_enable_capture(self.pg_interfaces)
8013 capture = self.pg0.get_capture(len(pkts))
8014 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8016 ses_num_end = self.nat64_get_ses_num()
8018 self.assertEqual(ses_num_end - ses_num_start, 3)
8020 # tenant with specific VRF
8021 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
8022 end_addr=self.vrf1_nat_addr,
8023 vrf_id=self.vrf1_id, is_add=1)
8024 flags = self.config_flags.NAT_IS_INSIDE
8025 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8026 sw_if_index=self.pg2.sw_if_index)
8028 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
8029 self.pg2.add_stream(pkts)
8030 self.pg_enable_capture(self.pg_interfaces)
8032 capture = self.pg1.get_capture(len(pkts))
8033 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
8034 dst_ip=self.pg1.remote_ip4)
8036 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
8037 self.pg1.add_stream(pkts)
8038 self.pg_enable_capture(self.pg_interfaces)
8040 capture = self.pg2.get_capture(len(pkts))
8041 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
8043 def test_static(self):
8044 """ NAT64 static translation test """
8045 self.tcp_port_in = 60303
8046 self.udp_port_in = 60304
8047 self.icmp_id_in = 60305
8048 self.tcp_port_out = 60303
8049 self.udp_port_out = 60304
8050 self.icmp_id_out = 60305
8052 ses_num_start = self.nat64_get_ses_num()
8054 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8055 end_addr=self.nat_addr,
8058 flags = self.config_flags.NAT_IS_INSIDE
8059 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8060 sw_if_index=self.pg0.sw_if_index)
8061 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8062 sw_if_index=self.pg1.sw_if_index)
8064 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8065 o_addr=self.nat_addr,
8066 i_port=self.tcp_port_in,
8067 o_port=self.tcp_port_out,
8068 proto=IP_PROTOS.tcp, vrf_id=0,
8070 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8071 o_addr=self.nat_addr,
8072 i_port=self.udp_port_in,
8073 o_port=self.udp_port_out,
8074 proto=IP_PROTOS.udp, vrf_id=0,
8076 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8077 o_addr=self.nat_addr,
8078 i_port=self.icmp_id_in,
8079 o_port=self.icmp_id_out,
8080 proto=IP_PROTOS.icmp, vrf_id=0,
8084 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8085 self.pg0.add_stream(pkts)
8086 self.pg_enable_capture(self.pg_interfaces)
8088 capture = self.pg1.get_capture(len(pkts))
8089 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8090 dst_ip=self.pg1.remote_ip4, same_port=True)
8093 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8094 self.pg1.add_stream(pkts)
8095 self.pg_enable_capture(self.pg_interfaces)
8097 capture = self.pg0.get_capture(len(pkts))
8098 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8099 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8101 ses_num_end = self.nat64_get_ses_num()
8103 self.assertEqual(ses_num_end - ses_num_start, 3)
8105 @unittest.skipUnless(running_extended_tests, "part of extended tests")
8106 def test_session_timeout(self):
8107 """ NAT64 session timeout """
8108 self.icmp_id_in = 1234
8109 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8110 end_addr=self.nat_addr,
8113 flags = self.config_flags.NAT_IS_INSIDE
8114 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8115 sw_if_index=self.pg0.sw_if_index)
8116 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8117 sw_if_index=self.pg1.sw_if_index)
8118 self.vapi.nat_set_timeouts(udp=300, tcp_established=5,
8122 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8123 self.pg0.add_stream(pkts)
8124 self.pg_enable_capture(self.pg_interfaces)
8126 capture = self.pg1.get_capture(len(pkts))
8128 ses_num_before_timeout = self.nat64_get_ses_num()
8132 # ICMP and TCP session after timeout
8133 ses_num_after_timeout = self.nat64_get_ses_num()
8134 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
8136 def test_icmp_error(self):
8137 """ NAT64 ICMP Error message translation """
8138 self.tcp_port_in = 6303
8139 self.udp_port_in = 6304
8140 self.icmp_id_in = 6305
8142 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8143 end_addr=self.nat_addr,
8146 flags = self.config_flags.NAT_IS_INSIDE
8147 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8148 sw_if_index=self.pg0.sw_if_index)
8149 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8150 sw_if_index=self.pg1.sw_if_index)
8152 # send some packets to create sessions
8153 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8154 self.pg0.add_stream(pkts)
8155 self.pg_enable_capture(self.pg_interfaces)
8157 capture_ip4 = self.pg1.get_capture(len(pkts))
8158 self.verify_capture_out(capture_ip4,
8159 nat_ip=self.nat_addr,
8160 dst_ip=self.pg1.remote_ip4)
8162 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8163 self.pg1.add_stream(pkts)
8164 self.pg_enable_capture(self.pg_interfaces)
8166 capture_ip6 = self.pg0.get_capture(len(pkts))
8167 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8168 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
8169 self.pg0.remote_ip6)
8172 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8173 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
8174 ICMPv6DestUnreach(code=1) /
8175 packet[IPv6] for packet in capture_ip6]
8176 self.pg0.add_stream(pkts)
8177 self.pg_enable_capture(self.pg_interfaces)
8179 capture = self.pg1.get_capture(len(pkts))
8180 for packet in capture:
8182 self.assertEqual(packet[IP].src, self.nat_addr)
8183 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
8184 self.assertEqual(packet[ICMP].type, 3)
8185 self.assertEqual(packet[ICMP].code, 13)
8186 inner = packet[IPerror]
8187 self.assertEqual(inner.src, self.pg1.remote_ip4)
8188 self.assertEqual(inner.dst, self.nat_addr)
8189 self.assert_packet_checksums_valid(packet)
8190 if inner.haslayer(TCPerror):
8191 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
8192 elif inner.haslayer(UDPerror):
8193 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
8195 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
8197 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8201 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8202 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8203 ICMP(type=3, code=13) /
8204 packet[IP] for packet in capture_ip4]
8205 self.pg1.add_stream(pkts)
8206 self.pg_enable_capture(self.pg_interfaces)
8208 capture = self.pg0.get_capture(len(pkts))
8209 for packet in capture:
8211 self.assertEqual(packet[IPv6].src, ip.src)
8212 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8213 icmp = packet[ICMPv6DestUnreach]
8214 self.assertEqual(icmp.code, 1)
8215 inner = icmp[IPerror6]
8216 self.assertEqual(inner.src, self.pg0.remote_ip6)
8217 self.assertEqual(inner.dst, ip.src)
8218 self.assert_icmpv6_checksum_valid(packet)
8219 if inner.haslayer(TCPerror):
8220 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
8221 elif inner.haslayer(UDPerror):
8222 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
8224 self.assertEqual(inner[ICMPv6EchoRequest].id,
8227 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8230 def test_hairpinning(self):
8231 """ NAT64 hairpinning """
8233 client = self.pg0.remote_hosts[0]
8234 server = self.pg0.remote_hosts[1]
8235 server_tcp_in_port = 22
8236 server_tcp_out_port = 4022
8237 server_udp_in_port = 23
8238 server_udp_out_port = 4023
8239 client_tcp_in_port = 1234
8240 client_udp_in_port = 1235
8241 client_tcp_out_port = 0
8242 client_udp_out_port = 0
8243 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8244 nat_addr_ip6 = ip.src
8246 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8247 end_addr=self.nat_addr,
8250 flags = self.config_flags.NAT_IS_INSIDE
8251 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8252 sw_if_index=self.pg0.sw_if_index)
8253 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8254 sw_if_index=self.pg1.sw_if_index)
8256 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8257 o_addr=self.nat_addr,
8258 i_port=server_tcp_in_port,
8259 o_port=server_tcp_out_port,
8260 proto=IP_PROTOS.tcp, vrf_id=0,
8262 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8263 o_addr=self.nat_addr,
8264 i_port=server_udp_in_port,
8265 o_port=server_udp_out_port,
8266 proto=IP_PROTOS.udp, vrf_id=0,
8271 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8272 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8273 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8275 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8276 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8277 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
8279 self.pg0.add_stream(pkts)
8280 self.pg_enable_capture(self.pg_interfaces)
8282 capture = self.pg0.get_capture(len(pkts))
8283 for packet in capture:
8285 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8286 self.assertEqual(packet[IPv6].dst, server.ip6)
8287 self.assert_packet_checksums_valid(packet)
8288 if packet.haslayer(TCP):
8289 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
8290 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
8291 client_tcp_out_port = packet[TCP].sport
8293 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
8294 self.assertEqual(packet[UDP].dport, server_udp_in_port)
8295 client_udp_out_port = packet[UDP].sport
8297 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8302 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8303 IPv6(src=server.ip6, dst=nat_addr_ip6) /
8304 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
8306 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8307 IPv6(src=server.ip6, dst=nat_addr_ip6) /
8308 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
8310 self.pg0.add_stream(pkts)
8311 self.pg_enable_capture(self.pg_interfaces)
8313 capture = self.pg0.get_capture(len(pkts))
8314 for packet in capture:
8316 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8317 self.assertEqual(packet[IPv6].dst, client.ip6)
8318 self.assert_packet_checksums_valid(packet)
8319 if packet.haslayer(TCP):
8320 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
8321 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
8323 self.assertEqual(packet[UDP].sport, server_udp_out_port)
8324 self.assertEqual(packet[UDP].dport, client_udp_in_port)
8326 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8331 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8332 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8333 ICMPv6DestUnreach(code=1) /
8334 packet[IPv6] for packet in capture]
8335 self.pg0.add_stream(pkts)
8336 self.pg_enable_capture(self.pg_interfaces)
8338 capture = self.pg0.get_capture(len(pkts))
8339 for packet in capture:
8341 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8342 self.assertEqual(packet[IPv6].dst, server.ip6)
8343 icmp = packet[ICMPv6DestUnreach]
8344 self.assertEqual(icmp.code, 1)
8345 inner = icmp[IPerror6]
8346 self.assertEqual(inner.src, server.ip6)
8347 self.assertEqual(inner.dst, nat_addr_ip6)
8348 self.assert_packet_checksums_valid(packet)
8349 if inner.haslayer(TCPerror):
8350 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
8351 self.assertEqual(inner[TCPerror].dport,
8352 client_tcp_out_port)
8354 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
8355 self.assertEqual(inner[UDPerror].dport,
8356 client_udp_out_port)
8358 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8361 def test_prefix(self):
8362 """ NAT64 Network-Specific Prefix """
8364 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8365 end_addr=self.nat_addr,
8368 flags = self.config_flags.NAT_IS_INSIDE
8369 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8370 sw_if_index=self.pg0.sw_if_index)
8371 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8372 sw_if_index=self.pg1.sw_if_index)
8373 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
8374 end_addr=self.vrf1_nat_addr,
8375 vrf_id=self.vrf1_id, is_add=1)
8376 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8377 sw_if_index=self.pg2.sw_if_index)
8380 global_pref64 = "2001:db8::"
8381 global_pref64_len = 32
8382 global_pref64_str = "{}/{}".format(global_pref64, global_pref64_len)
8383 self.vapi.nat64_add_del_prefix(prefix=global_pref64_str, vrf_id=0,
8386 prefix = self.vapi.nat64_prefix_dump()
8387 self.assertEqual(len(prefix), 1)
8388 self.assertEqual(str(prefix[0].prefix), global_pref64_str)
8389 self.assertEqual(prefix[0].vrf_id, 0)
8391 # Add tenant specific prefix
8392 vrf1_pref64 = "2001:db8:122:300::"
8393 vrf1_pref64_len = 56
8394 vrf1_pref64_str = "{}/{}".format(vrf1_pref64, vrf1_pref64_len)
8395 self.vapi.nat64_add_del_prefix(prefix=vrf1_pref64_str,
8396 vrf_id=self.vrf1_id, is_add=1)
8398 prefix = self.vapi.nat64_prefix_dump()
8399 self.assertEqual(len(prefix), 2)
8402 pkts = self.create_stream_in_ip6(self.pg0,
8405 plen=global_pref64_len)
8406 self.pg0.add_stream(pkts)
8407 self.pg_enable_capture(self.pg_interfaces)
8409 capture = self.pg1.get_capture(len(pkts))
8410 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8411 dst_ip=self.pg1.remote_ip4)
8413 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8414 self.pg1.add_stream(pkts)
8415 self.pg_enable_capture(self.pg_interfaces)
8417 capture = self.pg0.get_capture(len(pkts))
8418 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8421 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
8423 # Tenant specific prefix
8424 pkts = self.create_stream_in_ip6(self.pg2,
8427 plen=vrf1_pref64_len)
8428 self.pg2.add_stream(pkts)
8429 self.pg_enable_capture(self.pg_interfaces)
8431 capture = self.pg1.get_capture(len(pkts))
8432 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
8433 dst_ip=self.pg1.remote_ip4)
8435 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
8436 self.pg1.add_stream(pkts)
8437 self.pg_enable_capture(self.pg_interfaces)
8439 capture = self.pg2.get_capture(len(pkts))
8440 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8443 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
8445 def test_unknown_proto(self):
8446 """ NAT64 translate packet with unknown protocol """
8448 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8449 end_addr=self.nat_addr,
8452 flags = self.config_flags.NAT_IS_INSIDE
8453 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8454 sw_if_index=self.pg0.sw_if_index)
8455 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8456 sw_if_index=self.pg1.sw_if_index)
8457 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8460 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8461 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
8462 TCP(sport=self.tcp_port_in, dport=20))
8463 self.pg0.add_stream(p)
8464 self.pg_enable_capture(self.pg_interfaces)
8466 p = self.pg1.get_capture(1)
8468 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8469 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
8471 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8472 TCP(sport=1234, dport=1234))
8473 self.pg0.add_stream(p)
8474 self.pg_enable_capture(self.pg_interfaces)
8476 p = self.pg1.get_capture(1)
8479 self.assertEqual(packet[IP].src, self.nat_addr)
8480 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
8481 self.assertEqual(packet.haslayer(GRE), 1)
8482 self.assert_packet_checksums_valid(packet)
8484 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8488 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8489 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8491 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8492 TCP(sport=1234, dport=1234))
8493 self.pg1.add_stream(p)
8494 self.pg_enable_capture(self.pg_interfaces)
8496 p = self.pg0.get_capture(1)
8499 self.assertEqual(packet[IPv6].src, remote_ip6)
8500 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8501 self.assertEqual(packet[IPv6].nh, 47)
8503 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8506 def test_hairpinning_unknown_proto(self):
8507 """ NAT64 translate packet with unknown protocol - hairpinning """
8509 client = self.pg0.remote_hosts[0]
8510 server = self.pg0.remote_hosts[1]
8511 server_tcp_in_port = 22
8512 server_tcp_out_port = 4022
8513 client_tcp_in_port = 1234
8514 client_tcp_out_port = 1235
8515 server_nat_ip = "10.0.0.100"
8516 client_nat_ip = "10.0.0.110"
8517 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
8518 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
8520 self.vapi.nat64_add_del_pool_addr_range(start_addr=server_nat_ip,
8521 end_addr=client_nat_ip,
8524 flags = self.config_flags.NAT_IS_INSIDE
8525 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8526 sw_if_index=self.pg0.sw_if_index)
8527 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8528 sw_if_index=self.pg1.sw_if_index)
8530 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8531 o_addr=server_nat_ip,
8532 i_port=server_tcp_in_port,
8533 o_port=server_tcp_out_port,
8534 proto=IP_PROTOS.tcp, vrf_id=0,
8537 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8538 o_addr=server_nat_ip, i_port=0,
8540 proto=IP_PROTOS.gre, vrf_id=0,
8543 self.vapi.nat64_add_del_static_bib(i_addr=client.ip6n,
8544 o_addr=client_nat_ip,
8545 i_port=client_tcp_in_port,
8546 o_port=client_tcp_out_port,
8547 proto=IP_PROTOS.tcp, vrf_id=0,
8551 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8552 IPv6(src=client.ip6, dst=server_nat_ip6) /
8553 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8554 self.pg0.add_stream(p)
8555 self.pg_enable_capture(self.pg_interfaces)
8557 p = self.pg0.get_capture(1)
8559 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8560 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
8562 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8563 TCP(sport=1234, dport=1234))
8564 self.pg0.add_stream(p)
8565 self.pg_enable_capture(self.pg_interfaces)
8567 p = self.pg0.get_capture(1)
8570 self.assertEqual(packet[IPv6].src, client_nat_ip6)
8571 self.assertEqual(packet[IPv6].dst, server.ip6)
8572 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
8574 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8578 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8579 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
8581 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8582 TCP(sport=1234, dport=1234))
8583 self.pg0.add_stream(p)
8584 self.pg_enable_capture(self.pg_interfaces)
8586 p = self.pg0.get_capture(1)
8589 self.assertEqual(packet[IPv6].src, server_nat_ip6)
8590 self.assertEqual(packet[IPv6].dst, client.ip6)
8591 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
8593 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8596 def test_one_armed_nat64(self):
8597 """ One armed NAT64 """
8599 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
8603 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8604 end_addr=self.nat_addr,
8607 flags = self.config_flags.NAT_IS_INSIDE
8608 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8609 sw_if_index=self.pg3.sw_if_index)
8610 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8611 sw_if_index=self.pg3.sw_if_index)
8614 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8615 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
8616 TCP(sport=12345, dport=80))
8617 self.pg3.add_stream(p)
8618 self.pg_enable_capture(self.pg_interfaces)
8620 capture = self.pg3.get_capture(1)
8625 self.assertEqual(ip.src, self.nat_addr)
8626 self.assertEqual(ip.dst, self.pg3.remote_ip4)
8627 self.assertNotEqual(tcp.sport, 12345)
8628 external_port = tcp.sport
8629 self.assertEqual(tcp.dport, 80)
8630 self.assert_packet_checksums_valid(p)
8632 self.logger.error(ppp("Unexpected or invalid packet:", p))
8636 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8637 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
8638 TCP(sport=80, dport=external_port))
8639 self.pg3.add_stream(p)
8640 self.pg_enable_capture(self.pg_interfaces)
8642 capture = self.pg3.get_capture(1)
8647 self.assertEqual(ip.src, remote_host_ip6)
8648 self.assertEqual(ip.dst, self.pg3.remote_ip6)
8649 self.assertEqual(tcp.sport, 80)
8650 self.assertEqual(tcp.dport, 12345)
8651 self.assert_packet_checksums_valid(p)
8653 self.logger.error(ppp("Unexpected or invalid packet:", p))
8656 def test_frag_in_order(self):
8657 """ NAT64 translate fragments arriving in order """
8658 self.tcp_port_in = random.randint(1025, 65535)
8660 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8661 end_addr=self.nat_addr,
8664 flags = self.config_flags.NAT_IS_INSIDE
8665 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8666 sw_if_index=self.pg0.sw_if_index)
8667 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8668 sw_if_index=self.pg1.sw_if_index)
8672 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8673 self.tcp_port_in, 20, data)
8674 self.pg0.add_stream(pkts)
8675 self.pg_enable_capture(self.pg_interfaces)
8677 frags = self.pg1.get_capture(len(pkts))
8678 p = self.reass_frags_and_verify(frags,
8680 self.pg1.remote_ip4)
8681 self.assertEqual(p[TCP].dport, 20)
8682 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8683 self.tcp_port_out = p[TCP].sport
8684 self.assertEqual(data, p[Raw].load)
8687 data = b"A" * 4 + b"b" * 16 + b"C" * 3
8688 pkts = self.create_stream_frag(self.pg1,
8693 self.pg1.add_stream(pkts)
8694 self.pg_enable_capture(self.pg_interfaces)
8696 frags = self.pg0.get_capture(len(pkts))
8697 self.logger.debug(ppc("Captured:", frags))
8698 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8699 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8700 self.assertEqual(p[TCP].sport, 20)
8701 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8702 self.assertEqual(data, p[Raw].load)
8704 def test_reass_hairpinning(self):
8705 """ NAT64 fragments hairpinning """
8707 server = self.pg0.remote_hosts[1]
8708 server_in_port = random.randint(1025, 65535)
8709 server_out_port = random.randint(1025, 65535)
8710 client_in_port = random.randint(1025, 65535)
8711 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8712 nat_addr_ip6 = ip.src
8714 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8715 end_addr=self.nat_addr,
8718 flags = self.config_flags.NAT_IS_INSIDE
8719 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8720 sw_if_index=self.pg0.sw_if_index)
8721 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8722 sw_if_index=self.pg1.sw_if_index)
8724 # add static BIB entry for server
8725 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8726 o_addr=self.nat_addr,
8727 i_port=server_in_port,
8728 o_port=server_out_port,
8729 proto=IP_PROTOS.tcp, vrf_id=0,
8732 # send packet from host to server
8733 pkts = self.create_stream_frag_ip6(self.pg0,
8738 self.pg0.add_stream(pkts)
8739 self.pg_enable_capture(self.pg_interfaces)
8741 frags = self.pg0.get_capture(len(pkts))
8742 self.logger.debug(ppc("Captured:", frags))
8743 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
8744 self.assertNotEqual(p[TCP].sport, client_in_port)
8745 self.assertEqual(p[TCP].dport, server_in_port)
8746 self.assertEqual(data, p[Raw].load)
8748 def test_frag_out_of_order(self):
8749 """ NAT64 translate fragments arriving out of order """
8750 self.tcp_port_in = random.randint(1025, 65535)
8752 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8753 end_addr=self.nat_addr,
8756 flags = self.config_flags.NAT_IS_INSIDE
8757 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8758 sw_if_index=self.pg0.sw_if_index)
8759 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8760 sw_if_index=self.pg1.sw_if_index)
8764 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8765 self.tcp_port_in, 20, data)
8767 self.pg0.add_stream(pkts)
8768 self.pg_enable_capture(self.pg_interfaces)
8770 frags = self.pg1.get_capture(len(pkts))
8771 p = self.reass_frags_and_verify(frags,
8773 self.pg1.remote_ip4)
8774 self.assertEqual(p[TCP].dport, 20)
8775 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8776 self.tcp_port_out = p[TCP].sport
8777 self.assertEqual(data, p[Raw].load)
8780 data = b"A" * 4 + b"B" * 16 + b"C" * 3
8781 pkts = self.create_stream_frag(self.pg1,
8787 self.pg1.add_stream(pkts)
8788 self.pg_enable_capture(self.pg_interfaces)
8790 frags = self.pg0.get_capture(len(pkts))
8791 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8792 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8793 self.assertEqual(p[TCP].sport, 20)
8794 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8795 self.assertEqual(data, p[Raw].load)
8797 def test_interface_addr(self):
8798 """ Acquire NAT64 pool addresses from interface """
8799 self.vapi.nat64_add_del_interface_addr(
8801 sw_if_index=self.pg4.sw_if_index)
8803 # no address in NAT64 pool
8804 addresses = self.vapi.nat44_address_dump()
8805 self.assertEqual(0, len(addresses))
8807 # configure interface address and check NAT64 address pool
8808 self.pg4.config_ip4()
8809 addresses = self.vapi.nat64_pool_addr_dump()
8810 self.assertEqual(len(addresses), 1)
8812 self.assertEqual(str(addresses[0].address),
8815 # remove interface address and check NAT64 address pool
8816 self.pg4.unconfig_ip4()
8817 addresses = self.vapi.nat64_pool_addr_dump()
8818 self.assertEqual(0, len(addresses))
8820 @unittest.skipUnless(running_extended_tests, "part of extended tests")
8821 def test_ipfix_max_bibs_sessions(self):
8822 """ IPFIX logging maximum session and BIB entries exceeded """
8825 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8829 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8830 end_addr=self.nat_addr,
8833 flags = self.config_flags.NAT_IS_INSIDE
8834 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8835 sw_if_index=self.pg0.sw_if_index)
8836 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8837 sw_if_index=self.pg1.sw_if_index)
8841 for i in range(0, max_bibs):
8842 src = "fd01:aa::%x" % (i)
8843 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8844 IPv6(src=src, dst=remote_host_ip6) /
8845 TCP(sport=12345, dport=80))
8847 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8848 IPv6(src=src, dst=remote_host_ip6) /
8849 TCP(sport=12345, dport=22))
8851 self.pg0.add_stream(pkts)
8852 self.pg_enable_capture(self.pg_interfaces)
8854 self.pg1.get_capture(max_sessions)
8856 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
8857 src_address=self.pg3.local_ip4,
8859 template_interval=10)
8860 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8861 src_port=self.ipfix_src_port,
8864 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8865 IPv6(src=src, dst=remote_host_ip6) /
8866 TCP(sport=12345, dport=25))
8867 self.pg0.add_stream(p)
8868 self.pg_enable_capture(self.pg_interfaces)
8870 self.pg1.assert_nothing_captured()
8872 self.vapi.ipfix_flush()
8873 capture = self.pg3.get_capture(9)
8874 ipfix = IPFIXDecoder()
8875 # first load template
8877 self.assertTrue(p.haslayer(IPFIX))
8878 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8879 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8880 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8881 self.assertEqual(p[UDP].dport, 4739)
8882 self.assertEqual(p[IPFIX].observationDomainID,
8883 self.ipfix_domain_id)
8884 if p.haslayer(Template):
8885 ipfix.add_template(p.getlayer(Template))
8886 # verify events in data set
8888 if p.haslayer(Data):
8889 data = ipfix.decode_data_set(p.getlayer(Set))
8890 self.verify_ipfix_max_sessions(data, max_sessions)
8892 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8893 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8894 TCP(sport=12345, dport=80))
8895 self.pg0.add_stream(p)
8896 self.pg_enable_capture(self.pg_interfaces)
8898 self.pg1.assert_nothing_captured()
8900 self.vapi.ipfix_flush()
8901 capture = self.pg3.get_capture(1)
8902 # verify events in data set
8904 self.assertTrue(p.haslayer(IPFIX))
8905 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8906 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8907 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8908 self.assertEqual(p[UDP].dport, 4739)
8909 self.assertEqual(p[IPFIX].observationDomainID,
8910 self.ipfix_domain_id)
8911 if p.haslayer(Data):
8912 data = ipfix.decode_data_set(p.getlayer(Set))
8913 self.verify_ipfix_max_bibs(data, max_bibs)
8915 def test_ipfix_bib_ses(self):
8916 """ IPFIX logging NAT64 BIB/session create and delete events """
8917 self.tcp_port_in = random.randint(1025, 65535)
8918 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8922 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8923 end_addr=self.nat_addr,
8926 flags = self.config_flags.NAT_IS_INSIDE
8927 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8928 sw_if_index=self.pg0.sw_if_index)
8929 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8930 sw_if_index=self.pg1.sw_if_index)
8931 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
8932 src_address=self.pg3.local_ip4,
8934 template_interval=10)
8935 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8936 src_port=self.ipfix_src_port,
8940 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8941 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8942 TCP(sport=self.tcp_port_in, dport=25))
8943 self.pg0.add_stream(p)
8944 self.pg_enable_capture(self.pg_interfaces)
8946 p = self.pg1.get_capture(1)
8947 self.tcp_port_out = p[0][TCP].sport
8948 self.vapi.ipfix_flush()
8949 capture = self.pg3.get_capture(10)
8950 ipfix = IPFIXDecoder()
8951 # first load template
8953 self.assertTrue(p.haslayer(IPFIX))
8954 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8955 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8956 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8957 self.assertEqual(p[UDP].dport, 4739)
8958 self.assertEqual(p[IPFIX].observationDomainID,
8959 self.ipfix_domain_id)
8960 if p.haslayer(Template):
8961 ipfix.add_template(p.getlayer(Template))
8962 # verify events in data set
8964 if p.haslayer(Data):
8965 data = ipfix.decode_data_set(p.getlayer(Set))
8966 if scapy.compat.orb(data[0][230]) == 10:
8967 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
8968 elif scapy.compat.orb(data[0][230]) == 6:
8969 self.verify_ipfix_nat64_ses(data,
8971 self.pg0.remote_ip6n,
8972 self.pg1.remote_ip4,
8975 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8978 self.pg_enable_capture(self.pg_interfaces)
8979 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8980 end_addr=self.nat_addr,
8983 self.vapi.ipfix_flush()
8984 capture = self.pg3.get_capture(2)
8985 # verify events in data set
8987 self.assertTrue(p.haslayer(IPFIX))
8988 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8989 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8990 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8991 self.assertEqual(p[UDP].dport, 4739)
8992 self.assertEqual(p[IPFIX].observationDomainID,
8993 self.ipfix_domain_id)
8994 if p.haslayer(Data):
8995 data = ipfix.decode_data_set(p.getlayer(Set))
8996 if scapy.compat.orb(data[0][230]) == 11:
8997 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
8998 elif scapy.compat.orb(data[0][230]) == 7:
8999 self.verify_ipfix_nat64_ses(data,
9001 self.pg0.remote_ip6n,
9002 self.pg1.remote_ip4,
9005 self.logger.error(ppp("Unexpected or invalid packet: ", p))
9007 def test_syslog_sess(self):
9008 """ Test syslog session creation and deletion """
9009 self.tcp_port_in = random.randint(1025, 65535)
9010 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
9014 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9015 end_addr=self.nat_addr,
9018 flags = self.config_flags.NAT_IS_INSIDE
9019 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
9020 sw_if_index=self.pg0.sw_if_index)
9021 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
9022 sw_if_index=self.pg1.sw_if_index)
9023 self.vapi.syslog_set_filter(
9024 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
9025 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
9027 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
9028 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
9029 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
9030 self.pg0.add_stream(p)
9031 self.pg_enable_capture(self.pg_interfaces)
9033 p = self.pg1.get_capture(1)
9034 self.tcp_port_out = p[0][TCP].sport
9035 capture = self.pg3.get_capture(1)
9036 self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
9038 self.pg_enable_capture(self.pg_interfaces)
9040 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9041 end_addr=self.nat_addr,
9044 capture = self.pg3.get_capture(1)
9045 self.verify_syslog_sess(capture[0][Raw].load, False, True)
9047 def nat64_get_ses_num(self):
9049 Return number of active NAT64 sessions.
9051 st = self.vapi.nat64_st_dump(proto=255)
9054 def clear_nat64(self):
9056 Clear NAT64 configuration.
9058 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
9059 src_port=self.ipfix_src_port,
9061 self.ipfix_src_port = 4739
9062 self.ipfix_domain_id = 1
9064 self.vapi.syslog_set_filter(
9065 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_EMERG)
9067 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
9068 tcp_transitory=240, icmp=60)
9070 interfaces = self.vapi.nat64_interface_dump()
9071 for intf in interfaces:
9072 self.vapi.nat64_add_del_interface(is_add=0, flags=intf.flags,
9073 sw_if_index=intf.sw_if_index)
9075 bib = self.vapi.nat64_bib_dump(proto=255)
9077 if bibe.flags & self.config_flags.NAT_IS_STATIC:
9078 self.vapi.nat64_add_del_static_bib(i_addr=bibe.i_addr,
9086 adresses = self.vapi.nat64_pool_addr_dump()
9087 for addr in adresses:
9088 self.vapi.nat64_add_del_pool_addr_range(start_addr=addr.address,
9089 end_addr=addr.address,
9093 prefixes = self.vapi.nat64_prefix_dump()
9094 for prefix in prefixes:
9095 self.vapi.nat64_add_del_prefix(prefix=str(prefix.prefix),
9096 vrf_id=prefix.vrf_id, is_add=0)
9098 bibs = self.statistics.get_counter('/nat64/total-bibs')
9099 self.assertEqual(bibs[0][0], 0)
9100 sessions = self.statistics.get_counter('/nat64/total-sessions')
9101 self.assertEqual(sessions[0][0], 0)
9104 super(TestNAT64, self).tearDown()
9105 if not self.vpp_dead:
9108 def show_commands_at_teardown(self):
9109 self.logger.info(self.vapi.cli("show nat64 pool"))
9110 self.logger.info(self.vapi.cli("show nat64 interfaces"))
9111 self.logger.info(self.vapi.cli("show nat64 prefix"))
9112 self.logger.info(self.vapi.cli("show nat64 bib all"))
9113 self.logger.info(self.vapi.cli("show nat64 session table all"))
9116 class TestNAT66(MethodHolder):
9117 """ NAT66 Test Cases """
9120 def setUpClass(cls):
9121 super(TestNAT66, cls).setUpClass()
9124 cls.nat_addr = 'fd01:ff::2'
9126 cls.create_pg_interfaces(range(2))
9127 cls.interfaces = list(cls.pg_interfaces)
9129 for i in cls.interfaces:
9132 i.configure_ipv6_neighbors()
9135 super(TestNAT66, cls).tearDownClass()
9139 def tearDownClass(cls):
9140 super(TestNAT66, cls).tearDownClass()
9142 def test_static(self):
9143 """ 1:1 NAT66 test """
9144 flags = self.config_flags.NAT_IS_INSIDE
9145 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9146 sw_if_index=self.pg0.sw_if_index)
9147 self.vapi.nat66_add_del_interface(is_add=1,
9148 sw_if_index=self.pg1.sw_if_index)
9149 self.vapi.nat66_add_del_static_mapping(
9150 local_ip_address=self.pg0.remote_ip6n,
9151 external_ip_address=self.nat_addr,
9156 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9157 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9160 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9161 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9164 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9165 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9166 ICMPv6EchoRequest())
9168 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9169 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9170 GRE() / IP() / TCP())
9172 self.pg0.add_stream(pkts)
9173 self.pg_enable_capture(self.pg_interfaces)
9175 capture = self.pg1.get_capture(len(pkts))
9177 for packet in capture:
9179 self.assertEqual(packet[IPv6].src, self.nat_addr)
9180 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9181 self.assert_packet_checksums_valid(packet)
9183 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9188 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9189 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9192 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9193 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9196 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9197 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9200 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9201 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9202 GRE() / IP() / TCP())
9204 self.pg1.add_stream(pkts)
9205 self.pg_enable_capture(self.pg_interfaces)
9207 capture = self.pg0.get_capture(len(pkts))
9208 for packet in capture:
9210 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
9211 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
9212 self.assert_packet_checksums_valid(packet)
9214 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9217 sm = self.vapi.nat66_static_mapping_dump()
9218 self.assertEqual(len(sm), 1)
9219 self.assertEqual(sm[0].total_pkts, 8)
9221 def test_check_no_translate(self):
9222 """ NAT66 translate only when egress interface is outside interface """
9223 flags = self.config_flags.NAT_IS_INSIDE
9224 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9225 sw_if_index=self.pg0.sw_if_index)
9226 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9227 sw_if_index=self.pg1.sw_if_index)
9228 self.vapi.nat66_add_del_static_mapping(
9229 local_ip_address=self.pg0.remote_ip6n,
9230 external_ip_address=self.nat_addr,
9234 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9235 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9237 self.pg0.add_stream([p])
9238 self.pg_enable_capture(self.pg_interfaces)
9240 capture = self.pg1.get_capture(1)
9243 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
9244 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9246 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9249 def clear_nat66(self):
9251 Clear NAT66 configuration.
9253 interfaces = self.vapi.nat66_interface_dump()
9254 for intf in interfaces:
9255 self.vapi.nat66_add_del_interface(is_add=0, flags=intf.flags,
9256 sw_if_index=intf.sw_if_index)
9258 static_mappings = self.vapi.nat66_static_mapping_dump()
9259 for sm in static_mappings:
9260 self.vapi.nat66_add_del_static_mapping(
9261 local_ip_address=sm.local_ip_address,
9262 external_ip_address=sm.external_ip_address, vrf_id=sm.vrf_id,
9266 super(TestNAT66, self).tearDown()
9269 def show_commands_at_teardown(self):
9270 self.logger.info(self.vapi.cli("show nat66 interfaces"))
9271 self.logger.info(self.vapi.cli("show nat66 static mappings"))
9274 if __name__ == '__main__':
9275 unittest.main(testRunner=VppTestRunner)