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, self.pg1.remote_ip4,
1159 self.port_in, 20, data, proto)
1160 self.pg0.add_stream(pkts)
1161 self.pg_enable_capture(self.pg_interfaces)
1163 frags = self.pg1.get_capture(len(pkts))
1164 if not dont_translate:
1165 p = self.reass_frags_and_verify(frags,
1167 self.pg1.remote_ip4)
1169 p = self.reass_frags_and_verify(frags,
1170 self.pg0.remote_ip4,
1171 self.pg1.remote_ip4)
1172 if proto != IP_PROTOS.icmp:
1173 if not dont_translate:
1174 self.assertEqual(p[layer].dport, 20)
1175 self.assertNotEqual(p[layer].sport, self.port_in)
1177 self.assertEqual(p[layer].sport, self.port_in)
1179 if not dont_translate:
1180 self.assertNotEqual(p[layer].id, self.port_in)
1182 self.assertEqual(p[layer].id, self.port_in)
1183 self.assertEqual(data, p[Raw].load)
1186 if not dont_translate:
1187 dst_addr = self.nat_addr
1189 dst_addr = self.pg0.remote_ip4
1190 if proto != IP_PROTOS.icmp:
1192 dport = p[layer].sport
1196 pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport, data,
1197 proto, echo_reply=True)
1198 self.pg1.add_stream(pkts)
1199 self.pg_enable_capture(self.pg_interfaces)
1201 frags = self.pg0.get_capture(len(pkts))
1202 p = self.reass_frags_and_verify(frags,
1203 self.pg1.remote_ip4,
1204 self.pg0.remote_ip4)
1205 if proto != IP_PROTOS.icmp:
1206 self.assertEqual(p[layer].sport, 20)
1207 self.assertEqual(p[layer].dport, self.port_in)
1209 self.assertEqual(p[layer].id, self.port_in)
1210 self.assertEqual(data, p[Raw].load)
1212 def frag_in_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1213 layer = self.proto2layer(proto)
1215 if proto == IP_PROTOS.tcp:
1216 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1218 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1219 self.port_in = random.randint(1025, 65535)
1223 pkts = self.create_stream_frag(self.pg0, self.server_out_addr,
1224 self.port_in, self.server_out_port,
1226 self.pg0.add_stream(pkts)
1227 self.pg_enable_capture(self.pg_interfaces)
1229 frags = self.pg1.get_capture(len(pkts))
1230 p = self.reass_frags_and_verify(frags,
1231 self.pg0.remote_ip4,
1232 self.server_in_addr)
1233 if proto != IP_PROTOS.icmp:
1234 self.assertEqual(p[layer].sport, self.port_in)
1235 self.assertEqual(p[layer].dport, self.server_in_port)
1237 self.assertEqual(p[layer].id, self.port_in)
1238 self.assertEqual(data, p[Raw].load)
1241 if proto != IP_PROTOS.icmp:
1242 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1243 self.server_in_port,
1244 p[layer].sport, data, proto)
1246 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1247 p[layer].id, 0, data, proto,
1249 self.pg1.add_stream(pkts)
1250 self.pg_enable_capture(self.pg_interfaces)
1252 frags = self.pg0.get_capture(len(pkts))
1253 p = self.reass_frags_and_verify(frags,
1254 self.server_out_addr,
1255 self.pg0.remote_ip4)
1256 if proto != IP_PROTOS.icmp:
1257 self.assertEqual(p[layer].sport, self.server_out_port)
1258 self.assertEqual(p[layer].dport, self.port_in)
1260 self.assertEqual(p[layer].id, self.port_in)
1261 self.assertEqual(data, p[Raw].load)
1263 def reass_hairpinning(self, proto=IP_PROTOS.tcp):
1264 layer = self.proto2layer(proto)
1266 if proto == IP_PROTOS.tcp:
1267 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1269 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1271 # send packet from host to server
1272 pkts = self.create_stream_frag(self.pg0,
1275 self.server_out_port,
1278 self.pg0.add_stream(pkts)
1279 self.pg_enable_capture(self.pg_interfaces)
1281 frags = self.pg0.get_capture(len(pkts))
1282 p = self.reass_frags_and_verify(frags,
1285 if proto != IP_PROTOS.icmp:
1286 self.assertNotEqual(p[layer].sport, self.host_in_port)
1287 self.assertEqual(p[layer].dport, self.server_in_port)
1289 self.assertNotEqual(p[layer].id, self.host_in_port)
1290 self.assertEqual(data, p[Raw].load)
1292 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1293 layer = self.proto2layer(proto)
1295 if proto == IP_PROTOS.tcp:
1296 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1298 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1299 self.port_in = random.randint(1025, 65535)
1303 pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
1304 self.port_in, 20, data, proto)
1306 self.pg0.add_stream(pkts)
1307 self.pg_enable_capture(self.pg_interfaces)
1309 frags = self.pg1.get_capture(len(pkts))
1310 if not dont_translate:
1311 p = self.reass_frags_and_verify(frags,
1313 self.pg1.remote_ip4)
1315 p = self.reass_frags_and_verify(frags,
1316 self.pg0.remote_ip4,
1317 self.pg1.remote_ip4)
1318 if proto != IP_PROTOS.icmp:
1319 if not dont_translate:
1320 self.assertEqual(p[layer].dport, 20)
1321 self.assertNotEqual(p[layer].sport, self.port_in)
1323 self.assertEqual(p[layer].sport, self.port_in)
1325 if not dont_translate:
1326 self.assertNotEqual(p[layer].id, self.port_in)
1328 self.assertEqual(p[layer].id, self.port_in)
1329 self.assertEqual(data, p[Raw].load)
1332 if not dont_translate:
1333 dst_addr = self.nat_addr
1335 dst_addr = self.pg0.remote_ip4
1336 if proto != IP_PROTOS.icmp:
1338 dport = p[layer].sport
1342 pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport,
1343 data, proto, echo_reply=True)
1345 self.pg1.add_stream(pkts)
1346 self.pg_enable_capture(self.pg_interfaces)
1348 frags = self.pg0.get_capture(len(pkts))
1349 p = self.reass_frags_and_verify(frags,
1350 self.pg1.remote_ip4,
1351 self.pg0.remote_ip4)
1352 if proto != IP_PROTOS.icmp:
1353 self.assertEqual(p[layer].sport, 20)
1354 self.assertEqual(p[layer].dport, self.port_in)
1356 self.assertEqual(p[layer].id, self.port_in)
1357 self.assertEqual(data, p[Raw].load)
1359 def frag_out_of_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1360 layer = self.proto2layer(proto)
1362 if proto == IP_PROTOS.tcp:
1363 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1365 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1366 self.port_in = random.randint(1025, 65535)
1370 pkts = self.create_stream_frag(self.pg0, self.server_out_addr,
1371 self.port_in, self.server_out_port,
1374 self.pg0.add_stream(pkts)
1375 self.pg_enable_capture(self.pg_interfaces)
1377 frags = self.pg1.get_capture(len(pkts))
1378 p = self.reass_frags_and_verify(frags,
1379 self.pg0.remote_ip4,
1380 self.server_in_addr)
1381 if proto != IP_PROTOS.icmp:
1382 self.assertEqual(p[layer].dport, self.server_in_port)
1383 self.assertEqual(p[layer].sport, self.port_in)
1384 self.assertEqual(p[layer].dport, self.server_in_port)
1386 self.assertEqual(p[layer].id, self.port_in)
1387 self.assertEqual(data, p[Raw].load)
1390 if proto != IP_PROTOS.icmp:
1391 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1392 self.server_in_port,
1393 p[layer].sport, data, proto)
1395 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
1396 p[layer].id, 0, data, proto,
1399 self.pg1.add_stream(pkts)
1400 self.pg_enable_capture(self.pg_interfaces)
1402 frags = self.pg0.get_capture(len(pkts))
1403 p = self.reass_frags_and_verify(frags,
1404 self.server_out_addr,
1405 self.pg0.remote_ip4)
1406 if proto != IP_PROTOS.icmp:
1407 self.assertEqual(p[layer].sport, self.server_out_port)
1408 self.assertEqual(p[layer].dport, self.port_in)
1410 self.assertEqual(p[layer].id, self.port_in)
1411 self.assertEqual(data, p[Raw].load)
1414 class TestNAT44(MethodHolder):
1415 """ NAT44 Test Cases """
1418 def setUpClass(cls):
1419 super(TestNAT44, cls).setUpClass()
1420 cls.vapi.cli("set log class nat level debug")
1422 cls.tcp_port_in = 6303
1423 cls.tcp_port_out = 6303
1424 cls.udp_port_in = 6304
1425 cls.udp_port_out = 6304
1426 cls.icmp_id_in = 6305
1427 cls.icmp_id_out = 6305
1428 cls.nat_addr = '10.0.0.3'
1429 cls.ipfix_src_port = 4739
1430 cls.ipfix_domain_id = 1
1431 cls.tcp_external_port = 80
1432 cls.udp_external_port = 69
1434 cls.create_pg_interfaces(range(10))
1435 cls.interfaces = list(cls.pg_interfaces[0:4])
1437 for i in cls.interfaces:
1442 cls.pg0.generate_remote_hosts(3)
1443 cls.pg0.configure_ipv4_neighbors()
1445 cls.pg1.generate_remote_hosts(1)
1446 cls.pg1.configure_ipv4_neighbors()
1448 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
1449 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 10})
1450 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 20})
1452 cls.pg4._local_ip4 = "172.16.255.1"
1453 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1454 cls.pg4.set_table_ip4(10)
1455 cls.pg5._local_ip4 = "172.17.255.3"
1456 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
1457 cls.pg5.set_table_ip4(10)
1458 cls.pg6._local_ip4 = "172.16.255.1"
1459 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1460 cls.pg6.set_table_ip4(20)
1461 for i in cls.overlapping_interfaces:
1469 cls.pg9.generate_remote_hosts(2)
1470 cls.pg9.config_ip4()
1471 cls.vapi.sw_interface_add_del_address(
1472 sw_if_index=cls.pg9.sw_if_index,
1473 prefix="10.0.0.1/24")
1476 cls.pg9.resolve_arp()
1477 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1478 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1479 cls.pg9.resolve_arp()
1482 def tearDownClass(cls):
1483 super(TestNAT44, cls).tearDownClass()
1485 def test_dynamic(self):
1486 """ NAT44 dynamic translation test """
1487 self.nat44_add_address(self.nat_addr)
1488 flags = self.config_flags.NAT_IS_INSIDE
1489 self.vapi.nat44_interface_add_del_feature(
1490 sw_if_index=self.pg0.sw_if_index,
1491 flags=flags, is_add=1)
1492 self.vapi.nat44_interface_add_del_feature(
1493 sw_if_index=self.pg1.sw_if_index,
1497 tcpn = self.statistics.get_err_counter(
1498 '/err/nat44-in2out-slowpath/TCP packets')
1499 udpn = self.statistics.get_err_counter(
1500 '/err/nat44-in2out-slowpath/UDP packets')
1501 icmpn = self.statistics.get_err_counter(
1502 '/err/nat44-in2out-slowpath/ICMP packets')
1503 totaln = self.statistics.get_err_counter(
1504 '/err/nat44-in2out-slowpath/good in2out packets processed')
1506 pkts = self.create_stream_in(self.pg0, self.pg1)
1507 self.pg0.add_stream(pkts)
1508 self.pg_enable_capture(self.pg_interfaces)
1510 capture = self.pg1.get_capture(len(pkts))
1511 self.verify_capture_out(capture)
1513 err = self.statistics.get_err_counter(
1514 '/err/nat44-in2out-slowpath/TCP packets')
1515 self.assertEqual(err - tcpn, 2)
1516 err = self.statistics.get_err_counter(
1517 '/err/nat44-in2out-slowpath/UDP packets')
1518 self.assertEqual(err - udpn, 1)
1519 err = self.statistics.get_err_counter(
1520 '/err/nat44-in2out-slowpath/ICMP packets')
1521 self.assertEqual(err - icmpn, 1)
1522 err = self.statistics.get_err_counter(
1523 '/err/nat44-in2out-slowpath/good in2out packets processed')
1524 self.assertEqual(err - totaln, 4)
1527 tcpn = self.statistics.get_err_counter('/err/nat44-out2in/TCP packets')
1528 udpn = self.statistics.get_err_counter('/err/nat44-out2in/UDP packets')
1529 icmpn = self.statistics.get_err_counter(
1530 '/err/nat44-out2in/ICMP packets')
1531 totaln = self.statistics.get_err_counter(
1532 '/err/nat44-out2in/good out2in packets processed')
1534 pkts = self.create_stream_out(self.pg1)
1535 self.pg1.add_stream(pkts)
1536 self.pg_enable_capture(self.pg_interfaces)
1538 capture = self.pg0.get_capture(len(pkts))
1539 self.verify_capture_in(capture, self.pg0)
1541 err = self.statistics.get_err_counter('/err/nat44-out2in/TCP packets')
1542 self.assertEqual(err - tcpn, 2)
1543 err = self.statistics.get_err_counter('/err/nat44-out2in/UDP packets')
1544 self.assertEqual(err - udpn, 1)
1545 err = self.statistics.get_err_counter('/err/nat44-out2in/ICMP packets')
1546 self.assertEqual(err - icmpn, 1)
1547 err = self.statistics.get_err_counter(
1548 '/err/nat44-out2in/good out2in packets processed')
1549 self.assertEqual(err - totaln, 4)
1551 users = self.statistics.get_counter('/nat44/total-users')
1552 self.assertEqual(users[0][0], 1)
1553 sessions = self.statistics.get_counter('/nat44/total-sessions')
1554 self.assertEqual(sessions[0][0], 3)
1556 def test_dynamic_icmp_errors_in2out_ttl_1(self):
1557 """ NAT44 handling of client packets with TTL=1 """
1559 self.nat44_add_address(self.nat_addr)
1560 flags = self.config_flags.NAT_IS_INSIDE
1561 self.vapi.nat44_interface_add_del_feature(
1562 sw_if_index=self.pg0.sw_if_index,
1563 flags=flags, is_add=1)
1564 self.vapi.nat44_interface_add_del_feature(
1565 sw_if_index=self.pg1.sw_if_index,
1568 # Client side - generate traffic
1569 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1570 self.pg0.add_stream(pkts)
1571 self.pg_enable_capture(self.pg_interfaces)
1574 # Client side - verify ICMP type 11 packets
1575 capture = self.pg0.get_capture(len(pkts))
1576 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1578 def test_dynamic_icmp_errors_out2in_ttl_1(self):
1579 """ NAT44 handling of server packets with TTL=1 """
1581 self.nat44_add_address(self.nat_addr)
1582 flags = self.config_flags.NAT_IS_INSIDE
1583 self.vapi.nat44_interface_add_del_feature(
1584 sw_if_index=self.pg0.sw_if_index,
1585 flags=flags, is_add=1)
1586 self.vapi.nat44_interface_add_del_feature(
1587 sw_if_index=self.pg1.sw_if_index,
1590 # Client side - create sessions
1591 pkts = self.create_stream_in(self.pg0, self.pg1)
1592 self.pg0.add_stream(pkts)
1593 self.pg_enable_capture(self.pg_interfaces)
1596 # Server side - generate traffic
1597 capture = self.pg1.get_capture(len(pkts))
1598 self.verify_capture_out(capture)
1599 pkts = self.create_stream_out(self.pg1, ttl=1)
1600 self.pg1.add_stream(pkts)
1601 self.pg_enable_capture(self.pg_interfaces)
1604 # Server side - verify ICMP type 11 packets
1605 capture = self.pg1.get_capture(len(pkts))
1606 self.verify_capture_out_with_icmp_errors(capture,
1607 src_ip=self.pg1.local_ip4)
1609 def test_dynamic_icmp_errors_in2out_ttl_2(self):
1610 """ NAT44 handling of error responses to client packets with TTL=2 """
1612 self.nat44_add_address(self.nat_addr)
1613 flags = self.config_flags.NAT_IS_INSIDE
1614 self.vapi.nat44_interface_add_del_feature(
1615 sw_if_index=self.pg0.sw_if_index,
1616 flags=flags, is_add=1)
1617 self.vapi.nat44_interface_add_del_feature(
1618 sw_if_index=self.pg1.sw_if_index,
1621 # Client side - generate traffic
1622 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1623 self.pg0.add_stream(pkts)
1624 self.pg_enable_capture(self.pg_interfaces)
1627 # Server side - simulate ICMP type 11 response
1628 capture = self.pg1.get_capture(len(pkts))
1629 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1630 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1631 ICMP(type=11) / packet[IP] for packet in capture]
1632 self.pg1.add_stream(pkts)
1633 self.pg_enable_capture(self.pg_interfaces)
1636 # Client side - verify ICMP type 11 packets
1637 capture = self.pg0.get_capture(len(pkts))
1638 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1640 def test_dynamic_icmp_errors_out2in_ttl_2(self):
1641 """ NAT44 handling of error responses to server packets with TTL=2 """
1643 self.nat44_add_address(self.nat_addr)
1644 flags = self.config_flags.NAT_IS_INSIDE
1645 self.vapi.nat44_interface_add_del_feature(
1646 sw_if_index=self.pg0.sw_if_index,
1647 flags=flags, is_add=1)
1648 self.vapi.nat44_interface_add_del_feature(
1649 sw_if_index=self.pg1.sw_if_index,
1652 # Client side - create sessions
1653 pkts = self.create_stream_in(self.pg0, self.pg1)
1654 self.pg0.add_stream(pkts)
1655 self.pg_enable_capture(self.pg_interfaces)
1658 # Server side - generate traffic
1659 capture = self.pg1.get_capture(len(pkts))
1660 self.verify_capture_out(capture)
1661 pkts = self.create_stream_out(self.pg1, ttl=2)
1662 self.pg1.add_stream(pkts)
1663 self.pg_enable_capture(self.pg_interfaces)
1666 # Client side - simulate ICMP type 11 response
1667 capture = self.pg0.get_capture(len(pkts))
1668 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1669 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1670 ICMP(type=11) / packet[IP] for packet in capture]
1671 self.pg0.add_stream(pkts)
1672 self.pg_enable_capture(self.pg_interfaces)
1675 # Server side - verify ICMP type 11 packets
1676 capture = self.pg1.get_capture(len(pkts))
1677 self.verify_capture_out_with_icmp_errors(capture)
1679 def test_ping_out_interface_from_outside(self):
1680 """ Ping NAT44 out interface from outside network """
1682 self.nat44_add_address(self.nat_addr)
1683 flags = self.config_flags.NAT_IS_INSIDE
1684 self.vapi.nat44_interface_add_del_feature(
1685 sw_if_index=self.pg0.sw_if_index,
1686 flags=flags, is_add=1)
1687 self.vapi.nat44_interface_add_del_feature(
1688 sw_if_index=self.pg1.sw_if_index,
1691 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1692 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1693 ICMP(id=self.icmp_id_out, type='echo-request'))
1695 self.pg1.add_stream(pkts)
1696 self.pg_enable_capture(self.pg_interfaces)
1698 capture = self.pg1.get_capture(len(pkts))
1701 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1702 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1703 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1704 self.assertEqual(packet[ICMP].type, 0) # echo reply
1706 self.logger.error(ppp("Unexpected or invalid packet "
1707 "(outside network):", packet))
1710 def test_ping_internal_host_from_outside(self):
1711 """ Ping internal host from outside network """
1713 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1714 flags = self.config_flags.NAT_IS_INSIDE
1715 self.vapi.nat44_interface_add_del_feature(
1716 sw_if_index=self.pg0.sw_if_index,
1717 flags=flags, is_add=1)
1718 self.vapi.nat44_interface_add_del_feature(
1719 sw_if_index=self.pg1.sw_if_index,
1723 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1724 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
1725 ICMP(id=self.icmp_id_out, type='echo-request'))
1726 self.pg1.add_stream(pkt)
1727 self.pg_enable_capture(self.pg_interfaces)
1729 capture = self.pg0.get_capture(1)
1730 self.verify_capture_in(capture, self.pg0)
1731 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1734 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1735 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1736 ICMP(id=self.icmp_id_in, type='echo-reply'))
1737 self.pg0.add_stream(pkt)
1738 self.pg_enable_capture(self.pg_interfaces)
1740 capture = self.pg1.get_capture(1)
1741 self.verify_capture_out(capture, same_port=True)
1742 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1744 def test_forwarding(self):
1745 """ NAT44 forwarding test """
1747 flags = self.config_flags.NAT_IS_INSIDE
1748 self.vapi.nat44_interface_add_del_feature(
1749 sw_if_index=self.pg0.sw_if_index,
1750 flags=flags, is_add=1)
1751 self.vapi.nat44_interface_add_del_feature(
1752 sw_if_index=self.pg1.sw_if_index,
1754 self.vapi.nat44_forwarding_enable_disable(enable=1)
1756 real_ip = self.pg0.remote_ip4
1757 alias_ip = self.nat_addr
1758 flags = self.config_flags.NAT_IS_ADDR_ONLY
1759 self.vapi.nat44_add_del_static_mapping(is_add=1,
1760 local_ip_address=real_ip,
1761 external_ip_address=alias_ip,
1762 external_sw_if_index=0xFFFFFFFF,
1766 # static mapping match
1768 pkts = self.create_stream_out(self.pg1)
1769 self.pg1.add_stream(pkts)
1770 self.pg_enable_capture(self.pg_interfaces)
1772 capture = self.pg0.get_capture(len(pkts))
1773 self.verify_capture_in(capture, self.pg0)
1775 pkts = self.create_stream_in(self.pg0, self.pg1)
1776 self.pg0.add_stream(pkts)
1777 self.pg_enable_capture(self.pg_interfaces)
1779 capture = self.pg1.get_capture(len(pkts))
1780 self.verify_capture_out(capture, same_port=True)
1782 # no static mapping match
1784 host0 = self.pg0.remote_hosts[0]
1785 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1787 pkts = self.create_stream_out(self.pg1,
1788 dst_ip=self.pg0.remote_ip4,
1789 use_inside_ports=True)
1790 self.pg1.add_stream(pkts)
1791 self.pg_enable_capture(self.pg_interfaces)
1793 capture = self.pg0.get_capture(len(pkts))
1794 self.verify_capture_in(capture, self.pg0)
1796 pkts = self.create_stream_in(self.pg0, self.pg1)
1797 self.pg0.add_stream(pkts)
1798 self.pg_enable_capture(self.pg_interfaces)
1800 capture = self.pg1.get_capture(len(pkts))
1801 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1804 self.pg0.remote_hosts[0] = host0
1807 self.vapi.nat44_forwarding_enable_disable(enable=0)
1808 flags = self.config_flags.NAT_IS_ADDR_ONLY
1809 self.vapi.nat44_add_del_static_mapping(
1811 local_ip_address=real_ip,
1812 external_ip_address=alias_ip,
1813 external_sw_if_index=0xFFFFFFFF,
1816 def test_static_in(self):
1817 """ 1:1 NAT initialized from inside network """
1819 nat_ip = "10.0.0.10"
1820 self.tcp_port_out = 6303
1821 self.udp_port_out = 6304
1822 self.icmp_id_out = 6305
1824 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1825 flags = self.config_flags.NAT_IS_INSIDE
1826 self.vapi.nat44_interface_add_del_feature(
1827 sw_if_index=self.pg0.sw_if_index,
1828 flags=flags, is_add=1)
1829 self.vapi.nat44_interface_add_del_feature(
1830 sw_if_index=self.pg1.sw_if_index,
1832 sm = self.vapi.nat44_static_mapping_dump()
1833 self.assertEqual(len(sm), 1)
1834 self.assertEqual(sm[0].tag, '')
1835 self.assertEqual(sm[0].protocol, 0)
1836 self.assertEqual(sm[0].local_port, 0)
1837 self.assertEqual(sm[0].external_port, 0)
1840 pkts = self.create_stream_in(self.pg0, self.pg1)
1841 self.pg0.add_stream(pkts)
1842 self.pg_enable_capture(self.pg_interfaces)
1844 capture = self.pg1.get_capture(len(pkts))
1845 self.verify_capture_out(capture, nat_ip, True)
1848 pkts = self.create_stream_out(self.pg1, nat_ip)
1849 self.pg1.add_stream(pkts)
1850 self.pg_enable_capture(self.pg_interfaces)
1852 capture = self.pg0.get_capture(len(pkts))
1853 self.verify_capture_in(capture, self.pg0)
1855 def test_static_out(self):
1856 """ 1:1 NAT initialized from outside network """
1858 nat_ip = "10.0.0.20"
1859 self.tcp_port_out = 6303
1860 self.udp_port_out = 6304
1861 self.icmp_id_out = 6305
1864 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
1865 flags = self.config_flags.NAT_IS_INSIDE
1866 self.vapi.nat44_interface_add_del_feature(
1867 sw_if_index=self.pg0.sw_if_index,
1868 flags=flags, is_add=1)
1869 self.vapi.nat44_interface_add_del_feature(
1870 sw_if_index=self.pg1.sw_if_index,
1872 sm = self.vapi.nat44_static_mapping_dump()
1873 self.assertEqual(len(sm), 1)
1874 self.assertEqual(sm[0].tag, tag)
1877 pkts = self.create_stream_out(self.pg1, nat_ip)
1878 self.pg1.add_stream(pkts)
1879 self.pg_enable_capture(self.pg_interfaces)
1881 capture = self.pg0.get_capture(len(pkts))
1882 self.verify_capture_in(capture, self.pg0)
1885 pkts = self.create_stream_in(self.pg0, self.pg1)
1886 self.pg0.add_stream(pkts)
1887 self.pg_enable_capture(self.pg_interfaces)
1889 capture = self.pg1.get_capture(len(pkts))
1890 self.verify_capture_out(capture, nat_ip, True)
1892 def test_static_with_port_in(self):
1893 """ 1:1 NAPT initialized from inside network """
1895 self.tcp_port_out = 3606
1896 self.udp_port_out = 3607
1897 self.icmp_id_out = 3608
1899 self.nat44_add_address(self.nat_addr)
1900 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1901 self.tcp_port_in, self.tcp_port_out,
1902 proto=IP_PROTOS.tcp)
1903 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1904 self.udp_port_in, self.udp_port_out,
1905 proto=IP_PROTOS.udp)
1906 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1907 self.icmp_id_in, self.icmp_id_out,
1908 proto=IP_PROTOS.icmp)
1909 flags = self.config_flags.NAT_IS_INSIDE
1910 self.vapi.nat44_interface_add_del_feature(
1911 sw_if_index=self.pg0.sw_if_index,
1912 flags=flags, is_add=1)
1913 self.vapi.nat44_interface_add_del_feature(
1914 sw_if_index=self.pg1.sw_if_index,
1918 pkts = self.create_stream_in(self.pg0, self.pg1)
1919 self.pg0.add_stream(pkts)
1920 self.pg_enable_capture(self.pg_interfaces)
1922 capture = self.pg1.get_capture(len(pkts))
1923 self.verify_capture_out(capture)
1926 pkts = self.create_stream_out(self.pg1)
1927 self.pg1.add_stream(pkts)
1928 self.pg_enable_capture(self.pg_interfaces)
1930 capture = self.pg0.get_capture(len(pkts))
1931 self.verify_capture_in(capture, self.pg0)
1933 def test_static_with_port_out(self):
1934 """ 1:1 NAPT initialized from outside network """
1936 self.tcp_port_out = 30606
1937 self.udp_port_out = 30607
1938 self.icmp_id_out = 30608
1940 self.nat44_add_address(self.nat_addr)
1941 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1942 self.tcp_port_in, self.tcp_port_out,
1943 proto=IP_PROTOS.tcp)
1944 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1945 self.udp_port_in, self.udp_port_out,
1946 proto=IP_PROTOS.udp)
1947 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1948 self.icmp_id_in, self.icmp_id_out,
1949 proto=IP_PROTOS.icmp)
1950 flags = self.config_flags.NAT_IS_INSIDE
1951 self.vapi.nat44_interface_add_del_feature(
1952 sw_if_index=self.pg0.sw_if_index,
1953 flags=flags, is_add=1)
1954 self.vapi.nat44_interface_add_del_feature(
1955 sw_if_index=self.pg1.sw_if_index,
1959 pkts = self.create_stream_out(self.pg1)
1960 self.pg1.add_stream(pkts)
1961 self.pg_enable_capture(self.pg_interfaces)
1963 capture = self.pg0.get_capture(len(pkts))
1964 self.verify_capture_in(capture, self.pg0)
1967 pkts = self.create_stream_in(self.pg0, self.pg1)
1968 self.pg0.add_stream(pkts)
1969 self.pg_enable_capture(self.pg_interfaces)
1971 capture = self.pg1.get_capture(len(pkts))
1972 self.verify_capture_out(capture)
1974 def test_static_vrf_aware(self):
1975 """ 1:1 NAT VRF awareness """
1977 nat_ip1 = "10.0.0.30"
1978 nat_ip2 = "10.0.0.40"
1979 self.tcp_port_out = 6303
1980 self.udp_port_out = 6304
1981 self.icmp_id_out = 6305
1983 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1985 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1987 flags = self.config_flags.NAT_IS_INSIDE
1988 self.vapi.nat44_interface_add_del_feature(
1989 sw_if_index=self.pg3.sw_if_index,
1991 self.vapi.nat44_interface_add_del_feature(
1992 sw_if_index=self.pg0.sw_if_index,
1993 flags=flags, is_add=1)
1994 self.vapi.nat44_interface_add_del_feature(
1995 sw_if_index=self.pg4.sw_if_index,
1996 flags=flags, is_add=1)
1998 # inside interface VRF match NAT44 static mapping VRF
1999 pkts = self.create_stream_in(self.pg4, self.pg3)
2000 self.pg4.add_stream(pkts)
2001 self.pg_enable_capture(self.pg_interfaces)
2003 capture = self.pg3.get_capture(len(pkts))
2004 self.verify_capture_out(capture, nat_ip1, True)
2006 # inside interface VRF don't match NAT44 static mapping VRF (packets
2008 pkts = self.create_stream_in(self.pg0, self.pg3)
2009 self.pg0.add_stream(pkts)
2010 self.pg_enable_capture(self.pg_interfaces)
2012 self.pg3.assert_nothing_captured()
2014 def test_dynamic_to_static(self):
2015 """ Switch from dynamic translation to 1:1NAT """
2016 nat_ip = "10.0.0.10"
2017 self.tcp_port_out = 6303
2018 self.udp_port_out = 6304
2019 self.icmp_id_out = 6305
2021 self.nat44_add_address(self.nat_addr)
2022 flags = self.config_flags.NAT_IS_INSIDE
2023 self.vapi.nat44_interface_add_del_feature(
2024 sw_if_index=self.pg0.sw_if_index,
2025 flags=flags, is_add=1)
2026 self.vapi.nat44_interface_add_del_feature(
2027 sw_if_index=self.pg1.sw_if_index,
2031 pkts = self.create_stream_in(self.pg0, self.pg1)
2032 self.pg0.add_stream(pkts)
2033 self.pg_enable_capture(self.pg_interfaces)
2035 capture = self.pg1.get_capture(len(pkts))
2036 self.verify_capture_out(capture)
2039 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2040 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
2041 self.assertEqual(len(sessions), 0)
2042 pkts = self.create_stream_in(self.pg0, self.pg1)
2043 self.pg0.add_stream(pkts)
2044 self.pg_enable_capture(self.pg_interfaces)
2046 capture = self.pg1.get_capture(len(pkts))
2047 self.verify_capture_out(capture, nat_ip, True)
2049 def test_identity_nat(self):
2050 """ Identity NAT """
2051 flags = self.config_flags.NAT_IS_ADDR_ONLY
2052 self.vapi.nat44_add_del_identity_mapping(
2053 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
2054 flags=flags, is_add=1)
2055 flags = self.config_flags.NAT_IS_INSIDE
2056 self.vapi.nat44_interface_add_del_feature(
2057 sw_if_index=self.pg0.sw_if_index,
2058 flags=flags, is_add=1)
2059 self.vapi.nat44_interface_add_del_feature(
2060 sw_if_index=self.pg1.sw_if_index,
2063 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2064 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2065 TCP(sport=12345, dport=56789))
2066 self.pg1.add_stream(p)
2067 self.pg_enable_capture(self.pg_interfaces)
2069 capture = self.pg0.get_capture(1)
2074 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2075 self.assertEqual(ip.src, self.pg1.remote_ip4)
2076 self.assertEqual(tcp.dport, 56789)
2077 self.assertEqual(tcp.sport, 12345)
2078 self.assert_packet_checksums_valid(p)
2080 self.logger.error(ppp("Unexpected or invalid packet:", p))
2083 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
2084 self.assertEqual(len(sessions), 0)
2085 flags = self.config_flags.NAT_IS_ADDR_ONLY
2086 self.vapi.nat44_add_del_identity_mapping(
2087 ip_address=self.pg0.remote_ip4, sw_if_index=0xFFFFFFFF,
2088 flags=flags, vrf_id=1, is_add=1)
2089 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2090 self.assertEqual(len(identity_mappings), 2)
2092 def test_multiple_inside_interfaces(self):
2093 """ NAT44 multiple non-overlapping address space inside interfaces """
2095 self.nat44_add_address(self.nat_addr)
2096 flags = self.config_flags.NAT_IS_INSIDE
2097 self.vapi.nat44_interface_add_del_feature(
2098 sw_if_index=self.pg0.sw_if_index,
2099 flags=flags, is_add=1)
2100 self.vapi.nat44_interface_add_del_feature(
2101 sw_if_index=self.pg1.sw_if_index,
2102 flags=flags, is_add=1)
2103 self.vapi.nat44_interface_add_del_feature(
2104 sw_if_index=self.pg3.sw_if_index,
2107 # between two NAT44 inside interfaces (no translation)
2108 pkts = self.create_stream_in(self.pg0, self.pg1)
2109 self.pg0.add_stream(pkts)
2110 self.pg_enable_capture(self.pg_interfaces)
2112 capture = self.pg1.get_capture(len(pkts))
2113 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
2115 # from NAT44 inside to interface without NAT44 feature (no translation)
2116 pkts = self.create_stream_in(self.pg0, self.pg2)
2117 self.pg0.add_stream(pkts)
2118 self.pg_enable_capture(self.pg_interfaces)
2120 capture = self.pg2.get_capture(len(pkts))
2121 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2123 # in2out 1st interface
2124 pkts = self.create_stream_in(self.pg0, self.pg3)
2125 self.pg0.add_stream(pkts)
2126 self.pg_enable_capture(self.pg_interfaces)
2128 capture = self.pg3.get_capture(len(pkts))
2129 self.verify_capture_out(capture)
2131 # out2in 1st interface
2132 pkts = self.create_stream_out(self.pg3)
2133 self.pg3.add_stream(pkts)
2134 self.pg_enable_capture(self.pg_interfaces)
2136 capture = self.pg0.get_capture(len(pkts))
2137 self.verify_capture_in(capture, self.pg0)
2139 # in2out 2nd interface
2140 pkts = self.create_stream_in(self.pg1, self.pg3)
2141 self.pg1.add_stream(pkts)
2142 self.pg_enable_capture(self.pg_interfaces)
2144 capture = self.pg3.get_capture(len(pkts))
2145 self.verify_capture_out(capture)
2147 # out2in 2nd interface
2148 pkts = self.create_stream_out(self.pg3)
2149 self.pg3.add_stream(pkts)
2150 self.pg_enable_capture(self.pg_interfaces)
2152 capture = self.pg1.get_capture(len(pkts))
2153 self.verify_capture_in(capture, self.pg1)
2155 def test_inside_overlapping_interfaces(self):
2156 """ NAT44 multiple inside interfaces with overlapping address space """
2158 static_nat_ip = "10.0.0.10"
2159 self.nat44_add_address(self.nat_addr)
2160 flags = self.config_flags.NAT_IS_INSIDE
2161 self.vapi.nat44_interface_add_del_feature(
2162 sw_if_index=self.pg3.sw_if_index,
2164 self.vapi.nat44_interface_add_del_feature(
2165 sw_if_index=self.pg4.sw_if_index,
2166 flags=flags, is_add=1)
2167 self.vapi.nat44_interface_add_del_feature(
2168 sw_if_index=self.pg5.sw_if_index,
2169 flags=flags, is_add=1)
2170 self.vapi.nat44_interface_add_del_feature(
2171 sw_if_index=self.pg6.sw_if_index,
2172 flags=flags, is_add=1)
2173 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2176 # between NAT44 inside interfaces with same VRF (no translation)
2177 pkts = self.create_stream_in(self.pg4, self.pg5)
2178 self.pg4.add_stream(pkts)
2179 self.pg_enable_capture(self.pg_interfaces)
2181 capture = self.pg5.get_capture(len(pkts))
2182 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2184 # between NAT44 inside interfaces with different VRF (hairpinning)
2185 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2186 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2187 TCP(sport=1234, dport=5678))
2188 self.pg4.add_stream(p)
2189 self.pg_enable_capture(self.pg_interfaces)
2191 capture = self.pg6.get_capture(1)
2196 self.assertEqual(ip.src, self.nat_addr)
2197 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2198 self.assertNotEqual(tcp.sport, 1234)
2199 self.assertEqual(tcp.dport, 5678)
2201 self.logger.error(ppp("Unexpected or invalid packet:", p))
2204 # in2out 1st interface
2205 pkts = self.create_stream_in(self.pg4, self.pg3)
2206 self.pg4.add_stream(pkts)
2207 self.pg_enable_capture(self.pg_interfaces)
2209 capture = self.pg3.get_capture(len(pkts))
2210 self.verify_capture_out(capture)
2212 # out2in 1st interface
2213 pkts = self.create_stream_out(self.pg3)
2214 self.pg3.add_stream(pkts)
2215 self.pg_enable_capture(self.pg_interfaces)
2217 capture = self.pg4.get_capture(len(pkts))
2218 self.verify_capture_in(capture, self.pg4)
2220 # in2out 2nd interface
2221 pkts = self.create_stream_in(self.pg5, self.pg3)
2222 self.pg5.add_stream(pkts)
2223 self.pg_enable_capture(self.pg_interfaces)
2225 capture = self.pg3.get_capture(len(pkts))
2226 self.verify_capture_out(capture)
2228 # out2in 2nd interface
2229 pkts = self.create_stream_out(self.pg3)
2230 self.pg3.add_stream(pkts)
2231 self.pg_enable_capture(self.pg_interfaces)
2233 capture = self.pg5.get_capture(len(pkts))
2234 self.verify_capture_in(capture, self.pg5)
2237 addresses = self.vapi.nat44_address_dump()
2238 self.assertEqual(len(addresses), 1)
2239 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4, 10)
2240 self.assertEqual(len(sessions), 3)
2241 for session in sessions:
2242 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2243 self.assertEqual(str(session.inside_ip_address),
2244 self.pg5.remote_ip4)
2245 self.assertEqual(session.outside_ip_address,
2246 addresses[0].ip_address)
2247 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2248 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2249 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2250 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2251 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2252 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2253 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2254 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2255 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2257 # in2out 3rd interface
2258 pkts = self.create_stream_in(self.pg6, self.pg3)
2259 self.pg6.add_stream(pkts)
2260 self.pg_enable_capture(self.pg_interfaces)
2262 capture = self.pg3.get_capture(len(pkts))
2263 self.verify_capture_out(capture, static_nat_ip, True)
2265 # out2in 3rd interface
2266 pkts = self.create_stream_out(self.pg3, static_nat_ip)
2267 self.pg3.add_stream(pkts)
2268 self.pg_enable_capture(self.pg_interfaces)
2270 capture = self.pg6.get_capture(len(pkts))
2271 self.verify_capture_in(capture, self.pg6)
2273 # general user and session dump verifications
2274 users = self.vapi.nat44_user_dump()
2275 self.assertGreaterEqual(len(users), 3)
2276 addresses = self.vapi.nat44_address_dump()
2277 self.assertEqual(len(addresses), 1)
2279 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2281 for session in sessions:
2282 self.assertEqual(user.ip_address, session.inside_ip_address)
2283 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2284 self.assertTrue(session.protocol in
2285 [IP_PROTOS.tcp, IP_PROTOS.udp,
2287 self.assertFalse(session.flags &
2288 self.config_flags.NAT_IS_EXT_HOST_VALID)
2291 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4, 10)
2292 self.assertGreaterEqual(len(sessions), 4)
2293 for session in sessions:
2294 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2295 self.assertEqual(str(session.inside_ip_address),
2296 self.pg4.remote_ip4)
2297 self.assertEqual(session.outside_ip_address,
2298 addresses[0].ip_address)
2301 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4, 20)
2302 self.assertGreaterEqual(len(sessions), 3)
2303 for session in sessions:
2304 self.assertTrue(session.flags & self.config_flags.NAT_IS_STATIC)
2305 self.assertEqual(str(session.inside_ip_address),
2306 self.pg6.remote_ip4)
2307 self.assertEqual(str(session.outside_ip_address),
2309 self.assertTrue(session.inside_port in
2310 [self.tcp_port_in, self.udp_port_in,
2313 def test_hairpinning(self):
2314 """ NAT44 hairpinning - 1:1 NAPT """
2316 host = self.pg0.remote_hosts[0]
2317 server = self.pg0.remote_hosts[1]
2320 server_in_port = 5678
2321 server_out_port = 8765
2323 self.nat44_add_address(self.nat_addr)
2324 flags = self.config_flags.NAT_IS_INSIDE
2325 self.vapi.nat44_interface_add_del_feature(
2326 sw_if_index=self.pg0.sw_if_index,
2327 flags=flags, is_add=1)
2328 self.vapi.nat44_interface_add_del_feature(
2329 sw_if_index=self.pg1.sw_if_index,
2332 # add static mapping for server
2333 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2334 server_in_port, server_out_port,
2335 proto=IP_PROTOS.tcp)
2337 # send packet from host to server
2338 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2339 IP(src=host.ip4, dst=self.nat_addr) /
2340 TCP(sport=host_in_port, dport=server_out_port))
2341 self.pg0.add_stream(p)
2342 self.pg_enable_capture(self.pg_interfaces)
2344 capture = self.pg0.get_capture(1)
2349 self.assertEqual(ip.src, self.nat_addr)
2350 self.assertEqual(ip.dst, server.ip4)
2351 self.assertNotEqual(tcp.sport, host_in_port)
2352 self.assertEqual(tcp.dport, server_in_port)
2353 self.assert_packet_checksums_valid(p)
2354 host_out_port = tcp.sport
2356 self.logger.error(ppp("Unexpected or invalid packet:", p))
2359 # send reply from server to host
2360 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2361 IP(src=server.ip4, dst=self.nat_addr) /
2362 TCP(sport=server_in_port, dport=host_out_port))
2363 self.pg0.add_stream(p)
2364 self.pg_enable_capture(self.pg_interfaces)
2366 capture = self.pg0.get_capture(1)
2371 self.assertEqual(ip.src, self.nat_addr)
2372 self.assertEqual(ip.dst, host.ip4)
2373 self.assertEqual(tcp.sport, server_out_port)
2374 self.assertEqual(tcp.dport, host_in_port)
2375 self.assert_packet_checksums_valid(p)
2377 self.logger.error(ppp("Unexpected or invalid packet:", p))
2380 def test_hairpinning2(self):
2381 """ NAT44 hairpinning - 1:1 NAT"""
2383 server1_nat_ip = "10.0.0.10"
2384 server2_nat_ip = "10.0.0.11"
2385 host = self.pg0.remote_hosts[0]
2386 server1 = self.pg0.remote_hosts[1]
2387 server2 = self.pg0.remote_hosts[2]
2388 server_tcp_port = 22
2389 server_udp_port = 20
2391 self.nat44_add_address(self.nat_addr)
2392 flags = self.config_flags.NAT_IS_INSIDE
2393 self.vapi.nat44_interface_add_del_feature(
2394 sw_if_index=self.pg0.sw_if_index,
2395 flags=flags, is_add=1)
2396 self.vapi.nat44_interface_add_del_feature(
2397 sw_if_index=self.pg1.sw_if_index,
2400 # add static mapping for servers
2401 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2402 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
2406 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2407 IP(src=host.ip4, dst=server1_nat_ip) /
2408 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2410 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2411 IP(src=host.ip4, dst=server1_nat_ip) /
2412 UDP(sport=self.udp_port_in, dport=server_udp_port))
2414 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2415 IP(src=host.ip4, dst=server1_nat_ip) /
2416 ICMP(id=self.icmp_id_in, type='echo-request'))
2418 self.pg0.add_stream(pkts)
2419 self.pg_enable_capture(self.pg_interfaces)
2421 capture = self.pg0.get_capture(len(pkts))
2422 for packet in capture:
2424 self.assertEqual(packet[IP].src, self.nat_addr)
2425 self.assertEqual(packet[IP].dst, server1.ip4)
2426 if packet.haslayer(TCP):
2427 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2428 self.assertEqual(packet[TCP].dport, server_tcp_port)
2429 self.tcp_port_out = packet[TCP].sport
2430 self.assert_packet_checksums_valid(packet)
2431 elif packet.haslayer(UDP):
2432 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2433 self.assertEqual(packet[UDP].dport, server_udp_port)
2434 self.udp_port_out = packet[UDP].sport
2436 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2437 self.icmp_id_out = packet[ICMP].id
2439 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2444 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2445 IP(src=server1.ip4, dst=self.nat_addr) /
2446 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2448 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2449 IP(src=server1.ip4, dst=self.nat_addr) /
2450 UDP(sport=server_udp_port, dport=self.udp_port_out))
2452 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2453 IP(src=server1.ip4, dst=self.nat_addr) /
2454 ICMP(id=self.icmp_id_out, type='echo-reply'))
2456 self.pg0.add_stream(pkts)
2457 self.pg_enable_capture(self.pg_interfaces)
2459 capture = self.pg0.get_capture(len(pkts))
2460 for packet in capture:
2462 self.assertEqual(packet[IP].src, server1_nat_ip)
2463 self.assertEqual(packet[IP].dst, host.ip4)
2464 if packet.haslayer(TCP):
2465 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2466 self.assertEqual(packet[TCP].sport, server_tcp_port)
2467 self.assert_packet_checksums_valid(packet)
2468 elif packet.haslayer(UDP):
2469 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2470 self.assertEqual(packet[UDP].sport, server_udp_port)
2472 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2474 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2477 # server2 to server1
2479 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2480 IP(src=server2.ip4, dst=server1_nat_ip) /
2481 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2483 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2484 IP(src=server2.ip4, dst=server1_nat_ip) /
2485 UDP(sport=self.udp_port_in, dport=server_udp_port))
2487 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2488 IP(src=server2.ip4, dst=server1_nat_ip) /
2489 ICMP(id=self.icmp_id_in, type='echo-request'))
2491 self.pg0.add_stream(pkts)
2492 self.pg_enable_capture(self.pg_interfaces)
2494 capture = self.pg0.get_capture(len(pkts))
2495 for packet in capture:
2497 self.assertEqual(packet[IP].src, server2_nat_ip)
2498 self.assertEqual(packet[IP].dst, server1.ip4)
2499 if packet.haslayer(TCP):
2500 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2501 self.assertEqual(packet[TCP].dport, server_tcp_port)
2502 self.tcp_port_out = packet[TCP].sport
2503 self.assert_packet_checksums_valid(packet)
2504 elif packet.haslayer(UDP):
2505 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2506 self.assertEqual(packet[UDP].dport, server_udp_port)
2507 self.udp_port_out = packet[UDP].sport
2509 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2510 self.icmp_id_out = packet[ICMP].id
2512 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2515 # server1 to server2
2517 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2518 IP(src=server1.ip4, dst=server2_nat_ip) /
2519 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2521 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2522 IP(src=server1.ip4, dst=server2_nat_ip) /
2523 UDP(sport=server_udp_port, dport=self.udp_port_out))
2525 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2526 IP(src=server1.ip4, dst=server2_nat_ip) /
2527 ICMP(id=self.icmp_id_out, type='echo-reply'))
2529 self.pg0.add_stream(pkts)
2530 self.pg_enable_capture(self.pg_interfaces)
2532 capture = self.pg0.get_capture(len(pkts))
2533 for packet in capture:
2535 self.assertEqual(packet[IP].src, server1_nat_ip)
2536 self.assertEqual(packet[IP].dst, server2.ip4)
2537 if packet.haslayer(TCP):
2538 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2539 self.assertEqual(packet[TCP].sport, server_tcp_port)
2540 self.assert_packet_checksums_valid(packet)
2541 elif packet.haslayer(UDP):
2542 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2543 self.assertEqual(packet[UDP].sport, server_udp_port)
2545 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2547 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2550 def test_interface_addr(self):
2551 """ Acquire NAT44 addresses from interface """
2552 self.vapi.nat44_add_del_interface_addr(
2554 sw_if_index=self.pg7.sw_if_index)
2556 # no address in NAT pool
2557 addresses = self.vapi.nat44_address_dump()
2558 self.assertEqual(0, len(addresses))
2560 # configure interface address and check NAT address pool
2561 self.pg7.config_ip4()
2562 addresses = self.vapi.nat44_address_dump()
2563 self.assertEqual(1, len(addresses))
2564 self.assertEqual(str(addresses[0].ip_address), self.pg7.local_ip4)
2566 # remove interface address and check NAT address pool
2567 self.pg7.unconfig_ip4()
2568 addresses = self.vapi.nat44_address_dump()
2569 self.assertEqual(0, len(addresses))
2571 def test_interface_addr_static_mapping(self):
2572 """ Static mapping with addresses from interface """
2575 self.vapi.nat44_add_del_interface_addr(
2577 sw_if_index=self.pg7.sw_if_index)
2578 self.nat44_add_static_mapping(
2580 external_sw_if_index=self.pg7.sw_if_index,
2583 # static mappings with external interface
2584 static_mappings = self.vapi.nat44_static_mapping_dump()
2585 self.assertEqual(1, len(static_mappings))
2586 self.assertEqual(self.pg7.sw_if_index,
2587 static_mappings[0].external_sw_if_index)
2588 self.assertEqual(static_mappings[0].tag, tag)
2590 # configure interface address and check static mappings
2591 self.pg7.config_ip4()
2592 static_mappings = self.vapi.nat44_static_mapping_dump()
2593 self.assertEqual(2, len(static_mappings))
2595 for sm in static_mappings:
2596 if sm.external_sw_if_index == 0xFFFFFFFF:
2597 self.assertEqual(str(sm.external_ip_address),
2599 self.assertEqual(sm.tag, tag)
2601 self.assertTrue(resolved)
2603 # remove interface address and check static mappings
2604 self.pg7.unconfig_ip4()
2605 static_mappings = self.vapi.nat44_static_mapping_dump()
2606 self.assertEqual(1, len(static_mappings))
2607 self.assertEqual(self.pg7.sw_if_index,
2608 static_mappings[0].external_sw_if_index)
2609 self.assertEqual(static_mappings[0].tag, tag)
2611 # configure interface address again and check static mappings
2612 self.pg7.config_ip4()
2613 static_mappings = self.vapi.nat44_static_mapping_dump()
2614 self.assertEqual(2, len(static_mappings))
2616 for sm in static_mappings:
2617 if sm.external_sw_if_index == 0xFFFFFFFF:
2618 self.assertEqual(str(sm.external_ip_address),
2620 self.assertEqual(sm.tag, tag)
2622 self.assertTrue(resolved)
2624 # remove static mapping
2625 self.nat44_add_static_mapping(
2627 external_sw_if_index=self.pg7.sw_if_index,
2630 static_mappings = self.vapi.nat44_static_mapping_dump()
2631 self.assertEqual(0, len(static_mappings))
2633 def test_interface_addr_identity_nat(self):
2634 """ Identity NAT with addresses from interface """
2637 self.vapi.nat44_add_del_interface_addr(
2639 sw_if_index=self.pg7.sw_if_index)
2640 self.vapi.nat44_add_del_identity_mapping(
2642 sw_if_index=self.pg7.sw_if_index,
2644 protocol=IP_PROTOS.tcp,
2647 # identity mappings with external interface
2648 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2649 self.assertEqual(1, len(identity_mappings))
2650 self.assertEqual(self.pg7.sw_if_index,
2651 identity_mappings[0].sw_if_index)
2653 # configure interface address and check identity mappings
2654 self.pg7.config_ip4()
2655 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2657 self.assertEqual(2, len(identity_mappings))
2658 for sm in identity_mappings:
2659 if sm.sw_if_index == 0xFFFFFFFF:
2660 self.assertEqual(str(identity_mappings[0].ip_address),
2662 self.assertEqual(port, identity_mappings[0].port)
2663 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2665 self.assertTrue(resolved)
2667 # remove interface address and check identity mappings
2668 self.pg7.unconfig_ip4()
2669 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2670 self.assertEqual(1, len(identity_mappings))
2671 self.assertEqual(self.pg7.sw_if_index,
2672 identity_mappings[0].sw_if_index)
2674 def test_ipfix_nat44_sess(self):
2675 """ IPFIX logging NAT44 session created/deleted """
2676 self.ipfix_domain_id = 10
2677 self.ipfix_src_port = 20202
2678 collector_port = 30303
2679 bind_layers(UDP, IPFIX, dport=30303)
2680 self.nat44_add_address(self.nat_addr)
2681 flags = self.config_flags.NAT_IS_INSIDE
2682 self.vapi.nat44_interface_add_del_feature(
2683 sw_if_index=self.pg0.sw_if_index,
2684 flags=flags, is_add=1)
2685 self.vapi.nat44_interface_add_del_feature(
2686 sw_if_index=self.pg1.sw_if_index,
2688 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2689 src_address=self.pg3.local_ip4,
2691 template_interval=10,
2692 collector_port=collector_port)
2693 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2694 src_port=self.ipfix_src_port,
2697 pkts = self.create_stream_in(self.pg0, self.pg1)
2698 self.pg0.add_stream(pkts)
2699 self.pg_enable_capture(self.pg_interfaces)
2701 capture = self.pg1.get_capture(len(pkts))
2702 self.verify_capture_out(capture)
2703 self.nat44_add_address(self.nat_addr, is_add=0)
2704 self.vapi.ipfix_flush()
2705 capture = self.pg3.get_capture(9)
2706 ipfix = IPFIXDecoder()
2707 # first load template
2709 self.assertTrue(p.haslayer(IPFIX))
2710 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2711 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2712 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2713 self.assertEqual(p[UDP].dport, collector_port)
2714 self.assertEqual(p[IPFIX].observationDomainID,
2715 self.ipfix_domain_id)
2716 if p.haslayer(Template):
2717 ipfix.add_template(p.getlayer(Template))
2718 # verify events in data set
2720 if p.haslayer(Data):
2721 data = ipfix.decode_data_set(p.getlayer(Set))
2722 self.verify_ipfix_nat44_ses(data)
2724 def test_ipfix_addr_exhausted(self):
2725 """ IPFIX logging NAT addresses exhausted """
2726 flags = self.config_flags.NAT_IS_INSIDE
2727 self.vapi.nat44_interface_add_del_feature(
2728 sw_if_index=self.pg0.sw_if_index,
2729 flags=flags, is_add=1)
2730 self.vapi.nat44_interface_add_del_feature(
2731 sw_if_index=self.pg1.sw_if_index,
2733 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2734 src_address=self.pg3.local_ip4,
2736 template_interval=10)
2737 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2738 src_port=self.ipfix_src_port,
2741 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2742 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2744 self.pg0.add_stream(p)
2745 self.pg_enable_capture(self.pg_interfaces)
2747 self.pg1.assert_nothing_captured()
2749 self.vapi.ipfix_flush()
2750 capture = self.pg3.get_capture(9)
2751 ipfix = IPFIXDecoder()
2752 # first load template
2754 self.assertTrue(p.haslayer(IPFIX))
2755 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2756 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2757 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2758 self.assertEqual(p[UDP].dport, 4739)
2759 self.assertEqual(p[IPFIX].observationDomainID,
2760 self.ipfix_domain_id)
2761 if p.haslayer(Template):
2762 ipfix.add_template(p.getlayer(Template))
2763 # verify events in data set
2765 if p.haslayer(Data):
2766 data = ipfix.decode_data_set(p.getlayer(Set))
2767 self.verify_ipfix_addr_exhausted(data)
2769 @unittest.skipUnless(running_extended_tests, "part of extended tests")
2770 def test_ipfix_max_sessions(self):
2771 """ IPFIX logging maximum session entries exceeded """
2772 self.nat44_add_address(self.nat_addr)
2773 flags = self.config_flags.NAT_IS_INSIDE
2774 self.vapi.nat44_interface_add_del_feature(
2775 sw_if_index=self.pg0.sw_if_index,
2776 flags=flags, is_add=1)
2777 self.vapi.nat44_interface_add_del_feature(
2778 sw_if_index=self.pg1.sw_if_index,
2781 nat44_config = self.vapi.nat_show_config()
2782 max_sessions = 10 * nat44_config.translation_buckets
2785 for i in range(0, max_sessions):
2786 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2787 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2788 IP(src=src, dst=self.pg1.remote_ip4) /
2791 self.pg0.add_stream(pkts)
2792 self.pg_enable_capture(self.pg_interfaces)
2795 self.pg1.get_capture(max_sessions)
2796 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
2797 src_address=self.pg3.local_ip4,
2799 template_interval=10)
2800 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2801 src_port=self.ipfix_src_port,
2804 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2805 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2807 self.pg0.add_stream(p)
2808 self.pg_enable_capture(self.pg_interfaces)
2810 self.pg1.assert_nothing_captured()
2812 self.vapi.ipfix_flush()
2813 capture = self.pg3.get_capture(9)
2814 ipfix = IPFIXDecoder()
2815 # first load template
2817 self.assertTrue(p.haslayer(IPFIX))
2818 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2819 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2820 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2821 self.assertEqual(p[UDP].dport, 4739)
2822 self.assertEqual(p[IPFIX].observationDomainID,
2823 self.ipfix_domain_id)
2824 if p.haslayer(Template):
2825 ipfix.add_template(p.getlayer(Template))
2826 # verify events in data set
2828 if p.haslayer(Data):
2829 data = ipfix.decode_data_set(p.getlayer(Set))
2830 self.verify_ipfix_max_sessions(data, max_sessions)
2832 def test_syslog_apmap(self):
2833 """ Test syslog address and port mapping creation and deletion """
2834 self.vapi.syslog_set_filter(
2835 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
2836 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
2837 self.nat44_add_address(self.nat_addr)
2838 flags = self.config_flags.NAT_IS_INSIDE
2839 self.vapi.nat44_interface_add_del_feature(
2840 sw_if_index=self.pg0.sw_if_index,
2841 flags=flags, is_add=1)
2842 self.vapi.nat44_interface_add_del_feature(
2843 sw_if_index=self.pg1.sw_if_index,
2846 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2847 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2848 TCP(sport=self.tcp_port_in, dport=20))
2849 self.pg0.add_stream(p)
2850 self.pg_enable_capture(self.pg_interfaces)
2852 capture = self.pg1.get_capture(1)
2853 self.tcp_port_out = capture[0][TCP].sport
2854 capture = self.pg3.get_capture(1)
2855 self.verify_syslog_apmap(capture[0][Raw].load)
2857 self.pg_enable_capture(self.pg_interfaces)
2859 self.nat44_add_address(self.nat_addr, is_add=0)
2860 capture = self.pg3.get_capture(1)
2861 self.verify_syslog_apmap(capture[0][Raw].load, False)
2863 def test_pool_addr_fib(self):
2864 """ NAT44 add pool addresses to FIB """
2865 static_addr = '10.0.0.10'
2866 self.nat44_add_address(self.nat_addr)
2867 flags = self.config_flags.NAT_IS_INSIDE
2868 self.vapi.nat44_interface_add_del_feature(
2869 sw_if_index=self.pg0.sw_if_index,
2870 flags=flags, is_add=1)
2871 self.vapi.nat44_interface_add_del_feature(
2872 sw_if_index=self.pg1.sw_if_index,
2874 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
2877 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2878 ARP(op=ARP.who_has, pdst=self.nat_addr,
2879 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2880 self.pg1.add_stream(p)
2881 self.pg_enable_capture(self.pg_interfaces)
2883 capture = self.pg1.get_capture(1)
2884 self.assertTrue(capture[0].haslayer(ARP))
2885 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2888 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2889 ARP(op=ARP.who_has, pdst=static_addr,
2890 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2891 self.pg1.add_stream(p)
2892 self.pg_enable_capture(self.pg_interfaces)
2894 capture = self.pg1.get_capture(1)
2895 self.assertTrue(capture[0].haslayer(ARP))
2896 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2898 # send ARP to non-NAT44 interface
2899 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2900 ARP(op=ARP.who_has, pdst=self.nat_addr,
2901 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2902 self.pg2.add_stream(p)
2903 self.pg_enable_capture(self.pg_interfaces)
2905 self.pg1.assert_nothing_captured()
2907 # remove addresses and verify
2908 self.nat44_add_address(self.nat_addr, is_add=0)
2909 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2912 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2913 ARP(op=ARP.who_has, pdst=self.nat_addr,
2914 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2915 self.pg1.add_stream(p)
2916 self.pg_enable_capture(self.pg_interfaces)
2918 self.pg1.assert_nothing_captured()
2920 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2921 ARP(op=ARP.who_has, pdst=static_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 self.pg1.assert_nothing_captured()
2928 def test_vrf_mode(self):
2929 """ NAT44 tenant VRF aware address pool mode """
2933 nat_ip1 = "10.0.0.10"
2934 nat_ip2 = "10.0.0.11"
2936 self.pg0.unconfig_ip4()
2937 self.pg1.unconfig_ip4()
2938 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
2939 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
2940 self.pg0.set_table_ip4(vrf_id1)
2941 self.pg1.set_table_ip4(vrf_id2)
2942 self.pg0.config_ip4()
2943 self.pg1.config_ip4()
2944 self.pg0.resolve_arp()
2945 self.pg1.resolve_arp()
2947 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2948 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2949 flags = self.config_flags.NAT_IS_INSIDE
2950 self.vapi.nat44_interface_add_del_feature(
2951 sw_if_index=self.pg0.sw_if_index,
2952 flags=flags, is_add=1)
2953 self.vapi.nat44_interface_add_del_feature(
2954 sw_if_index=self.pg1.sw_if_index,
2955 flags=flags, is_add=1)
2956 self.vapi.nat44_interface_add_del_feature(
2957 sw_if_index=self.pg2.sw_if_index,
2962 pkts = self.create_stream_in(self.pg0, self.pg2)
2963 self.pg0.add_stream(pkts)
2964 self.pg_enable_capture(self.pg_interfaces)
2966 capture = self.pg2.get_capture(len(pkts))
2967 self.verify_capture_out(capture, nat_ip1)
2970 pkts = self.create_stream_in(self.pg1, self.pg2)
2971 self.pg1.add_stream(pkts)
2972 self.pg_enable_capture(self.pg_interfaces)
2974 capture = self.pg2.get_capture(len(pkts))
2975 self.verify_capture_out(capture, nat_ip2)
2978 self.pg0.unconfig_ip4()
2979 self.pg1.unconfig_ip4()
2980 self.pg0.set_table_ip4(0)
2981 self.pg1.set_table_ip4(0)
2982 self.pg0.config_ip4()
2983 self.pg1.config_ip4()
2984 self.pg0.resolve_arp()
2985 self.pg1.resolve_arp()
2986 self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id1})
2987 self.vapi.ip_table_add_del(is_add=0, table={'table_id': vrf_id2})
2989 def test_vrf_feature_independent(self):
2990 """ NAT44 tenant VRF independent address pool mode """
2992 nat_ip1 = "10.0.0.10"
2993 nat_ip2 = "10.0.0.11"
2995 self.nat44_add_address(nat_ip1)
2996 self.nat44_add_address(nat_ip2, vrf_id=99)
2997 flags = self.config_flags.NAT_IS_INSIDE
2998 self.vapi.nat44_interface_add_del_feature(
2999 sw_if_index=self.pg0.sw_if_index,
3000 flags=flags, is_add=1)
3001 self.vapi.nat44_interface_add_del_feature(
3002 sw_if_index=self.pg1.sw_if_index,
3003 flags=flags, is_add=1)
3004 self.vapi.nat44_interface_add_del_feature(
3005 sw_if_index=self.pg2.sw_if_index,
3009 pkts = self.create_stream_in(self.pg0, self.pg2)
3010 self.pg0.add_stream(pkts)
3011 self.pg_enable_capture(self.pg_interfaces)
3013 capture = self.pg2.get_capture(len(pkts))
3014 self.verify_capture_out(capture, nat_ip1)
3017 pkts = self.create_stream_in(self.pg1, self.pg2)
3018 self.pg1.add_stream(pkts)
3019 self.pg_enable_capture(self.pg_interfaces)
3021 capture = self.pg2.get_capture(len(pkts))
3022 self.verify_capture_out(capture, nat_ip1)
3024 def create_routes_and_neigbors(self):
3025 r1 = VppIpRoute(self, self.pg7.remote_ip4, 32,
3026 [VppRoutePath(self.pg7.remote_ip4,
3027 self.pg7.sw_if_index)])
3028 r2 = VppIpRoute(self, self.pg8.remote_ip4, 32,
3029 [VppRoutePath(self.pg8.remote_ip4,
3030 self.pg8.sw_if_index)])
3034 n1 = VppNeighbor(self,
3035 self.pg7.sw_if_index,
3036 self.pg7.remote_mac,
3037 self.pg7.remote_ip4,
3039 n2 = VppNeighbor(self,
3040 self.pg8.sw_if_index,
3041 self.pg8.remote_mac,
3042 self.pg8.remote_ip4,
3047 def test_dynamic_ipless_interfaces(self):
3048 """ NAT44 interfaces without configured IP address """
3049 self.create_routes_and_neigbors()
3050 self.nat44_add_address(self.nat_addr)
3051 flags = self.config_flags.NAT_IS_INSIDE
3052 self.vapi.nat44_interface_add_del_feature(
3053 sw_if_index=self.pg7.sw_if_index,
3054 flags=flags, is_add=1)
3055 self.vapi.nat44_interface_add_del_feature(
3056 sw_if_index=self.pg8.sw_if_index,
3060 pkts = self.create_stream_in(self.pg7, self.pg8)
3061 self.pg7.add_stream(pkts)
3062 self.pg_enable_capture(self.pg_interfaces)
3064 capture = self.pg8.get_capture(len(pkts))
3065 self.verify_capture_out(capture)
3068 pkts = self.create_stream_out(self.pg8, self.nat_addr)
3069 self.pg8.add_stream(pkts)
3070 self.pg_enable_capture(self.pg_interfaces)
3072 capture = self.pg7.get_capture(len(pkts))
3073 self.verify_capture_in(capture, self.pg7)
3075 def test_static_ipless_interfaces(self):
3076 """ NAT44 interfaces without configured IP address - 1:1 NAT """
3078 self.create_routes_and_neigbors()
3079 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
3080 flags = self.config_flags.NAT_IS_INSIDE
3081 self.vapi.nat44_interface_add_del_feature(
3082 sw_if_index=self.pg7.sw_if_index,
3083 flags=flags, is_add=1)
3084 self.vapi.nat44_interface_add_del_feature(
3085 sw_if_index=self.pg8.sw_if_index,
3089 pkts = self.create_stream_out(self.pg8)
3090 self.pg8.add_stream(pkts)
3091 self.pg_enable_capture(self.pg_interfaces)
3093 capture = self.pg7.get_capture(len(pkts))
3094 self.verify_capture_in(capture, self.pg7)
3097 pkts = self.create_stream_in(self.pg7, self.pg8)
3098 self.pg7.add_stream(pkts)
3099 self.pg_enable_capture(self.pg_interfaces)
3101 capture = self.pg8.get_capture(len(pkts))
3102 self.verify_capture_out(capture, self.nat_addr, True)
3104 def test_static_with_port_ipless_interfaces(self):
3105 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
3107 self.tcp_port_out = 30606
3108 self.udp_port_out = 30607
3109 self.icmp_id_out = 30608
3111 self.create_routes_and_neigbors()
3112 self.nat44_add_address(self.nat_addr)
3113 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3114 self.tcp_port_in, self.tcp_port_out,
3115 proto=IP_PROTOS.tcp)
3116 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3117 self.udp_port_in, self.udp_port_out,
3118 proto=IP_PROTOS.udp)
3119 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3120 self.icmp_id_in, self.icmp_id_out,
3121 proto=IP_PROTOS.icmp)
3122 flags = self.config_flags.NAT_IS_INSIDE
3123 self.vapi.nat44_interface_add_del_feature(
3124 sw_if_index=self.pg7.sw_if_index,
3125 flags=flags, is_add=1)
3126 self.vapi.nat44_interface_add_del_feature(
3127 sw_if_index=self.pg8.sw_if_index,
3131 pkts = self.create_stream_out(self.pg8)
3132 self.pg8.add_stream(pkts)
3133 self.pg_enable_capture(self.pg_interfaces)
3135 capture = self.pg7.get_capture(len(pkts))
3136 self.verify_capture_in(capture, self.pg7)
3139 pkts = self.create_stream_in(self.pg7, self.pg8)
3140 self.pg7.add_stream(pkts)
3141 self.pg_enable_capture(self.pg_interfaces)
3143 capture = self.pg8.get_capture(len(pkts))
3144 self.verify_capture_out(capture)
3146 def test_static_unknown_proto(self):
3147 """ 1:1 NAT translate packet with unknown protocol """
3148 nat_ip = "10.0.0.10"
3149 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
3150 flags = self.config_flags.NAT_IS_INSIDE
3151 self.vapi.nat44_interface_add_del_feature(
3152 sw_if_index=self.pg0.sw_if_index,
3153 flags=flags, is_add=1)
3154 self.vapi.nat44_interface_add_del_feature(
3155 sw_if_index=self.pg1.sw_if_index,
3159 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3160 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3162 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3163 TCP(sport=1234, dport=1234))
3164 self.pg0.add_stream(p)
3165 self.pg_enable_capture(self.pg_interfaces)
3167 p = self.pg1.get_capture(1)
3170 self.assertEqual(packet[IP].src, nat_ip)
3171 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3172 self.assertEqual(packet.haslayer(GRE), 1)
3173 self.assert_packet_checksums_valid(packet)
3175 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3179 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3180 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3182 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3183 TCP(sport=1234, dport=1234))
3184 self.pg1.add_stream(p)
3185 self.pg_enable_capture(self.pg_interfaces)
3187 p = self.pg0.get_capture(1)
3190 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3191 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3192 self.assertEqual(packet.haslayer(GRE), 1)
3193 self.assert_packet_checksums_valid(packet)
3195 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3198 def test_hairpinning_static_unknown_proto(self):
3199 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3201 host = self.pg0.remote_hosts[0]
3202 server = self.pg0.remote_hosts[1]
3204 host_nat_ip = "10.0.0.10"
3205 server_nat_ip = "10.0.0.11"
3207 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3208 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3209 flags = self.config_flags.NAT_IS_INSIDE
3210 self.vapi.nat44_interface_add_del_feature(
3211 sw_if_index=self.pg0.sw_if_index,
3212 flags=flags, is_add=1)
3213 self.vapi.nat44_interface_add_del_feature(
3214 sw_if_index=self.pg1.sw_if_index,
3218 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3219 IP(src=host.ip4, dst=server_nat_ip) /
3221 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3222 TCP(sport=1234, dport=1234))
3223 self.pg0.add_stream(p)
3224 self.pg_enable_capture(self.pg_interfaces)
3226 p = self.pg0.get_capture(1)
3229 self.assertEqual(packet[IP].src, host_nat_ip)
3230 self.assertEqual(packet[IP].dst, server.ip4)
3231 self.assertEqual(packet.haslayer(GRE), 1)
3232 self.assert_packet_checksums_valid(packet)
3234 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3238 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3239 IP(src=server.ip4, dst=host_nat_ip) /
3241 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3242 TCP(sport=1234, dport=1234))
3243 self.pg0.add_stream(p)
3244 self.pg_enable_capture(self.pg_interfaces)
3246 p = self.pg0.get_capture(1)
3249 self.assertEqual(packet[IP].src, server_nat_ip)
3250 self.assertEqual(packet[IP].dst, host.ip4)
3251 self.assertEqual(packet.haslayer(GRE), 1)
3252 self.assert_packet_checksums_valid(packet)
3254 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3257 def test_output_feature(self):
3258 """ NAT44 interface output feature (in2out postrouting) """
3259 self.nat44_add_address(self.nat_addr)
3260 flags = self.config_flags.NAT_IS_INSIDE
3261 self.vapi.nat44_interface_add_del_output_feature(
3262 is_add=1, flags=flags,
3263 sw_if_index=self.pg0.sw_if_index)
3264 self.vapi.nat44_interface_add_del_output_feature(
3265 is_add=1, flags=flags,
3266 sw_if_index=self.pg1.sw_if_index)
3267 self.vapi.nat44_interface_add_del_output_feature(
3269 sw_if_index=self.pg3.sw_if_index)
3272 pkts = self.create_stream_in(self.pg0, self.pg3)
3273 self.pg0.add_stream(pkts)
3274 self.pg_enable_capture(self.pg_interfaces)
3276 capture = self.pg3.get_capture(len(pkts))
3277 self.verify_capture_out(capture)
3280 pkts = self.create_stream_out(self.pg3)
3281 self.pg3.add_stream(pkts)
3282 self.pg_enable_capture(self.pg_interfaces)
3284 capture = self.pg0.get_capture(len(pkts))
3285 self.verify_capture_in(capture, self.pg0)
3287 # from non-NAT interface to NAT inside interface
3288 pkts = self.create_stream_in(self.pg2, self.pg0)
3289 self.pg2.add_stream(pkts)
3290 self.pg_enable_capture(self.pg_interfaces)
3292 capture = self.pg0.get_capture(len(pkts))
3293 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3295 def test_output_feature_vrf_aware(self):
3296 """ NAT44 interface output feature VRF aware (in2out postrouting) """
3297 nat_ip_vrf10 = "10.0.0.10"
3298 nat_ip_vrf20 = "10.0.0.20"
3300 r1 = VppIpRoute(self, self.pg3.remote_ip4, 32,
3301 [VppRoutePath(self.pg3.remote_ip4,
3302 self.pg3.sw_if_index)],
3304 r2 = VppIpRoute(self, self.pg3.remote_ip4, 32,
3305 [VppRoutePath(self.pg3.remote_ip4,
3306 self.pg3.sw_if_index)],
3311 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3312 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3313 flags = self.config_flags.NAT_IS_INSIDE
3314 self.vapi.nat44_interface_add_del_output_feature(
3315 is_add=1, flags=flags,
3316 sw_if_index=self.pg4.sw_if_index)
3317 self.vapi.nat44_interface_add_del_output_feature(
3318 is_add=1, flags=flags,
3319 sw_if_index=self.pg6.sw_if_index)
3320 self.vapi.nat44_interface_add_del_output_feature(
3322 sw_if_index=self.pg3.sw_if_index)
3325 pkts = self.create_stream_in(self.pg4, self.pg3)
3326 self.pg4.add_stream(pkts)
3327 self.pg_enable_capture(self.pg_interfaces)
3329 capture = self.pg3.get_capture(len(pkts))
3330 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3333 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3334 self.pg3.add_stream(pkts)
3335 self.pg_enable_capture(self.pg_interfaces)
3337 capture = self.pg4.get_capture(len(pkts))
3338 self.verify_capture_in(capture, self.pg4)
3341 pkts = self.create_stream_in(self.pg6, self.pg3)
3342 self.pg6.add_stream(pkts)
3343 self.pg_enable_capture(self.pg_interfaces)
3345 capture = self.pg3.get_capture(len(pkts))
3346 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3349 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3350 self.pg3.add_stream(pkts)
3351 self.pg_enable_capture(self.pg_interfaces)
3353 capture = self.pg6.get_capture(len(pkts))
3354 self.verify_capture_in(capture, self.pg6)
3356 def test_output_feature_hairpinning(self):
3357 """ NAT44 interface output feature hairpinning (in2out postrouting) """
3358 host = self.pg0.remote_hosts[0]
3359 server = self.pg0.remote_hosts[1]
3362 server_in_port = 5678
3363 server_out_port = 8765
3365 self.nat44_add_address(self.nat_addr)
3366 flags = self.config_flags.NAT_IS_INSIDE
3367 self.vapi.nat44_interface_add_del_output_feature(
3368 is_add=1, flags=flags,
3369 sw_if_index=self.pg0.sw_if_index)
3370 self.vapi.nat44_interface_add_del_output_feature(
3372 sw_if_index=self.pg1.sw_if_index)
3374 # add static mapping for server
3375 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3376 server_in_port, server_out_port,
3377 proto=IP_PROTOS.tcp)
3379 # send packet from host to server
3380 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3381 IP(src=host.ip4, dst=self.nat_addr) /
3382 TCP(sport=host_in_port, dport=server_out_port))
3383 self.pg0.add_stream(p)
3384 self.pg_enable_capture(self.pg_interfaces)
3386 capture = self.pg0.get_capture(1)
3391 self.assertEqual(ip.src, self.nat_addr)
3392 self.assertEqual(ip.dst, server.ip4)
3393 self.assertNotEqual(tcp.sport, host_in_port)
3394 self.assertEqual(tcp.dport, server_in_port)
3395 self.assert_packet_checksums_valid(p)
3396 host_out_port = tcp.sport
3398 self.logger.error(ppp("Unexpected or invalid packet:", p))
3401 # send reply from server to host
3402 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3403 IP(src=server.ip4, dst=self.nat_addr) /
3404 TCP(sport=server_in_port, dport=host_out_port))
3405 self.pg0.add_stream(p)
3406 self.pg_enable_capture(self.pg_interfaces)
3408 capture = self.pg0.get_capture(1)
3413 self.assertEqual(ip.src, self.nat_addr)
3414 self.assertEqual(ip.dst, host.ip4)
3415 self.assertEqual(tcp.sport, server_out_port)
3416 self.assertEqual(tcp.dport, host_in_port)
3417 self.assert_packet_checksums_valid(p)
3419 self.logger.error(ppp("Unexpected or invalid packet:", p))
3422 def test_one_armed_nat44(self):
3423 """ One armed NAT44 """
3424 remote_host = self.pg9.remote_hosts[0]
3425 local_host = self.pg9.remote_hosts[1]
3428 self.nat44_add_address(self.nat_addr)
3429 flags = self.config_flags.NAT_IS_INSIDE
3430 self.vapi.nat44_interface_add_del_feature(
3431 sw_if_index=self.pg9.sw_if_index,
3433 self.vapi.nat44_interface_add_del_feature(
3434 sw_if_index=self.pg9.sw_if_index,
3435 flags=flags, is_add=1)
3438 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3439 IP(src=local_host.ip4, dst=remote_host.ip4) /
3440 TCP(sport=12345, dport=80))
3441 self.pg9.add_stream(p)
3442 self.pg_enable_capture(self.pg_interfaces)
3444 capture = self.pg9.get_capture(1)
3449 self.assertEqual(ip.src, self.nat_addr)
3450 self.assertEqual(ip.dst, remote_host.ip4)
3451 self.assertNotEqual(tcp.sport, 12345)
3452 external_port = tcp.sport
3453 self.assertEqual(tcp.dport, 80)
3454 self.assert_packet_checksums_valid(p)
3456 self.logger.error(ppp("Unexpected or invalid packet:", p))
3460 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3461 IP(src=remote_host.ip4, dst=self.nat_addr) /
3462 TCP(sport=80, dport=external_port))
3463 self.pg9.add_stream(p)
3464 self.pg_enable_capture(self.pg_interfaces)
3466 capture = self.pg9.get_capture(1)
3471 self.assertEqual(ip.src, remote_host.ip4)
3472 self.assertEqual(ip.dst, local_host.ip4)
3473 self.assertEqual(tcp.sport, 80)
3474 self.assertEqual(tcp.dport, 12345)
3475 self.assert_packet_checksums_valid(p)
3477 self.logger.error(ppp("Unexpected or invalid packet:", p))
3480 err = self.statistics.get_err_counter(
3481 '/err/nat44-classify/next in2out')
3482 self.assertEqual(err, 1)
3483 err = self.statistics.get_err_counter(
3484 '/err/nat44-classify/next out2in')
3485 self.assertEqual(err, 1)
3487 def test_del_session(self):
3488 """ Delete NAT44 session """
3489 self.nat44_add_address(self.nat_addr)
3490 flags = self.config_flags.NAT_IS_INSIDE
3491 self.vapi.nat44_interface_add_del_feature(
3492 sw_if_index=self.pg0.sw_if_index,
3493 flags=flags, is_add=1)
3494 self.vapi.nat44_interface_add_del_feature(
3495 sw_if_index=self.pg1.sw_if_index,
3498 pkts = self.create_stream_in(self.pg0, self.pg1)
3499 self.pg0.add_stream(pkts)
3500 self.pg_enable_capture(self.pg_interfaces)
3502 self.pg1.get_capture(len(pkts))
3504 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3505 nsessions = len(sessions)
3507 self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3508 port=sessions[0].inside_port,
3509 protocol=sessions[0].protocol,
3510 flags=self.config_flags.NAT_IS_INSIDE)
3511 self.vapi.nat44_del_session(address=sessions[1].outside_ip_address,
3512 port=sessions[1].outside_port,
3513 protocol=sessions[1].protocol)
3515 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3516 self.assertEqual(nsessions - len(sessions), 2)
3518 self.vapi.nat44_del_session(address=sessions[0].inside_ip_address,
3519 port=sessions[0].inside_port,
3520 protocol=sessions[0].protocol,
3521 flags=self.config_flags.NAT_IS_INSIDE)
3523 self.verify_no_nat44_user()
3525 def test_frag_in_order(self):
3526 """ NAT44 translate fragments arriving in order """
3528 self.nat44_add_address(self.nat_addr)
3529 flags = self.config_flags.NAT_IS_INSIDE
3530 self.vapi.nat44_interface_add_del_feature(
3531 sw_if_index=self.pg0.sw_if_index,
3532 flags=flags, is_add=1)
3533 self.vapi.nat44_interface_add_del_feature(
3534 sw_if_index=self.pg1.sw_if_index,
3537 self.frag_in_order(proto=IP_PROTOS.tcp)
3538 self.frag_in_order(proto=IP_PROTOS.udp)
3539 self.frag_in_order(proto=IP_PROTOS.icmp)
3541 def test_frag_forwarding(self):
3542 """ NAT44 forwarding fragment test """
3543 self.vapi.nat44_add_del_interface_addr(
3545 sw_if_index=self.pg1.sw_if_index)
3546 flags = self.config_flags.NAT_IS_INSIDE
3547 self.vapi.nat44_interface_add_del_feature(
3548 sw_if_index=self.pg0.sw_if_index,
3549 flags=flags, is_add=1)
3550 self.vapi.nat44_interface_add_del_feature(
3551 sw_if_index=self.pg1.sw_if_index,
3553 self.vapi.nat44_forwarding_enable_disable(enable=1)
3555 data = b"A" * 16 + b"B" * 16 + b"C" * 3
3556 pkts = self.create_stream_frag(self.pg1,
3557 self.pg0.remote_ip4,
3561 proto=IP_PROTOS.udp)
3562 self.pg1.add_stream(pkts)
3563 self.pg_enable_capture(self.pg_interfaces)
3565 frags = self.pg0.get_capture(len(pkts))
3566 p = self.reass_frags_and_verify(frags,
3567 self.pg1.remote_ip4,
3568 self.pg0.remote_ip4)
3569 self.assertEqual(p[UDP].sport, 4789)
3570 self.assertEqual(p[UDP].dport, 4789)
3571 self.assertEqual(data, p[Raw].load)
3573 def test_reass_hairpinning(self):
3574 """ NAT44 fragments hairpinning """
3576 self.server = self.pg0.remote_hosts[1]
3577 self.host_in_port = random.randint(1025, 65535)
3578 self.server_in_port = random.randint(1025, 65535)
3579 self.server_out_port = random.randint(1025, 65535)
3581 self.nat44_add_address(self.nat_addr)
3582 flags = self.config_flags.NAT_IS_INSIDE
3583 self.vapi.nat44_interface_add_del_feature(
3584 sw_if_index=self.pg0.sw_if_index,
3585 flags=flags, is_add=1)
3586 self.vapi.nat44_interface_add_del_feature(
3587 sw_if_index=self.pg1.sw_if_index,
3589 # add static mapping for server
3590 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3591 self.server_in_port,
3592 self.server_out_port,
3593 proto=IP_PROTOS.tcp)
3594 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3595 self.server_in_port,
3596 self.server_out_port,
3597 proto=IP_PROTOS.udp)
3598 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
3600 self.reass_hairpinning(proto=IP_PROTOS.tcp)
3601 self.reass_hairpinning(proto=IP_PROTOS.udp)
3602 self.reass_hairpinning(proto=IP_PROTOS.icmp)
3604 def test_frag_out_of_order(self):
3605 """ NAT44 translate fragments arriving out of order """
3607 self.nat44_add_address(self.nat_addr)
3608 flags = self.config_flags.NAT_IS_INSIDE
3609 self.vapi.nat44_interface_add_del_feature(
3610 sw_if_index=self.pg0.sw_if_index,
3611 flags=flags, is_add=1)
3612 self.vapi.nat44_interface_add_del_feature(
3613 sw_if_index=self.pg1.sw_if_index,
3616 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3617 self.frag_out_of_order(proto=IP_PROTOS.udp)
3618 self.frag_out_of_order(proto=IP_PROTOS.icmp)
3620 def test_port_restricted(self):
3621 """ Port restricted NAT44 (MAP-E CE) """
3622 self.nat44_add_address(self.nat_addr)
3623 flags = self.config_flags.NAT_IS_INSIDE
3624 self.vapi.nat44_interface_add_del_feature(
3625 sw_if_index=self.pg0.sw_if_index,
3626 flags=flags, is_add=1)
3627 self.vapi.nat44_interface_add_del_feature(
3628 sw_if_index=self.pg1.sw_if_index,
3630 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3635 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3636 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3637 TCP(sport=4567, dport=22))
3638 self.pg0.add_stream(p)
3639 self.pg_enable_capture(self.pg_interfaces)
3641 capture = self.pg1.get_capture(1)
3646 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3647 self.assertEqual(ip.src, self.nat_addr)
3648 self.assertEqual(tcp.dport, 22)
3649 self.assertNotEqual(tcp.sport, 4567)
3650 self.assertEqual((tcp.sport >> 6) & 63, 10)
3651 self.assert_packet_checksums_valid(p)
3653 self.logger.error(ppp("Unexpected or invalid packet:", p))
3656 def test_port_range(self):
3657 """ External address port range """
3658 self.nat44_add_address(self.nat_addr)
3659 flags = self.config_flags.NAT_IS_INSIDE
3660 self.vapi.nat44_interface_add_del_feature(
3661 sw_if_index=self.pg0.sw_if_index,
3662 flags=flags, is_add=1)
3663 self.vapi.nat44_interface_add_del_feature(
3664 sw_if_index=self.pg1.sw_if_index,
3666 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3671 for port in range(0, 5):
3672 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3673 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3674 TCP(sport=1125 + port))
3676 self.pg0.add_stream(pkts)
3677 self.pg_enable_capture(self.pg_interfaces)
3679 capture = self.pg1.get_capture(3)
3682 self.assertGreaterEqual(tcp.sport, 1025)
3683 self.assertLessEqual(tcp.sport, 1027)
3685 def test_multiple_outside_vrf(self):
3686 """ Multiple outside VRF """
3690 self.pg1.unconfig_ip4()
3691 self.pg2.unconfig_ip4()
3692 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id1})
3693 self.vapi.ip_table_add_del(is_add=1, table={'table_id': vrf_id2})
3694 self.pg1.set_table_ip4(vrf_id1)
3695 self.pg2.set_table_ip4(vrf_id2)
3696 self.pg1.config_ip4()
3697 self.pg2.config_ip4()
3698 self.pg1.resolve_arp()
3699 self.pg2.resolve_arp()
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.nat44_interface_add_del_feature(
3710 sw_if_index=self.pg2.sw_if_index,
3715 pkts = self.create_stream_in(self.pg0, self.pg1)
3716 self.pg0.add_stream(pkts)
3717 self.pg_enable_capture(self.pg_interfaces)
3719 capture = self.pg1.get_capture(len(pkts))
3720 self.verify_capture_out(capture, self.nat_addr)
3722 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3723 self.pg1.add_stream(pkts)
3724 self.pg_enable_capture(self.pg_interfaces)
3726 capture = self.pg0.get_capture(len(pkts))
3727 self.verify_capture_in(capture, self.pg0)
3729 self.tcp_port_in = 60303
3730 self.udp_port_in = 60304
3731 self.icmp_id_in = 60305
3734 pkts = self.create_stream_in(self.pg0, self.pg2)
3735 self.pg0.add_stream(pkts)
3736 self.pg_enable_capture(self.pg_interfaces)
3738 capture = self.pg2.get_capture(len(pkts))
3739 self.verify_capture_out(capture, self.nat_addr)
3741 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3742 self.pg2.add_stream(pkts)
3743 self.pg_enable_capture(self.pg_interfaces)
3745 capture = self.pg0.get_capture(len(pkts))
3746 self.verify_capture_in(capture, self.pg0)
3749 self.nat44_add_address(self.nat_addr, is_add=0)
3750 self.pg1.unconfig_ip4()
3751 self.pg2.unconfig_ip4()
3752 self.pg1.set_table_ip4(0)
3753 self.pg2.set_table_ip4(0)
3754 self.pg1.config_ip4()
3755 self.pg2.config_ip4()
3756 self.pg1.resolve_arp()
3757 self.pg2.resolve_arp()
3759 @unittest.skipUnless(running_extended_tests, "part of extended tests")
3760 def test_session_timeout(self):
3761 """ NAT44 session timeouts """
3762 self.nat44_add_address(self.nat_addr)
3763 flags = self.config_flags.NAT_IS_INSIDE
3764 self.vapi.nat44_interface_add_del_feature(
3765 sw_if_index=self.pg0.sw_if_index,
3766 flags=flags, is_add=1)
3767 self.vapi.nat44_interface_add_del_feature(
3768 sw_if_index=self.pg1.sw_if_index,
3770 self.vapi.nat_set_timeouts(udp=5, tcp_established=7440,
3771 tcp_transitory=240, icmp=60)
3775 for i in range(0, max_sessions):
3776 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3777 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3778 IP(src=src, dst=self.pg1.remote_ip4) /
3779 UDP(sport=1025, dport=53))
3781 self.pg0.add_stream(pkts)
3782 self.pg_enable_capture(self.pg_interfaces)
3784 self.pg1.get_capture(max_sessions)
3789 for i in range(0, max_sessions):
3790 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3791 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3792 IP(src=src, dst=self.pg1.remote_ip4) /
3793 UDP(sport=1026, dport=53))
3795 self.pg0.add_stream(pkts)
3796 self.pg_enable_capture(self.pg_interfaces)
3798 self.pg1.get_capture(max_sessions)
3801 users = self.vapi.nat44_user_dump()
3803 nsessions = nsessions + user.nsessions
3804 self.assertLess(nsessions, 2 * max_sessions)
3806 def test_mss_clamping(self):
3807 """ TCP MSS clamping """
3808 self.nat44_add_address(self.nat_addr)
3809 flags = self.config_flags.NAT_IS_INSIDE
3810 self.vapi.nat44_interface_add_del_feature(
3811 sw_if_index=self.pg0.sw_if_index,
3812 flags=flags, is_add=1)
3813 self.vapi.nat44_interface_add_del_feature(
3814 sw_if_index=self.pg1.sw_if_index,
3817 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3818 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3819 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3820 flags="S", options=[('MSS', 1400)]))
3822 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3823 self.pg0.add_stream(p)
3824 self.pg_enable_capture(self.pg_interfaces)
3826 capture = self.pg1.get_capture(1)
3827 # Negotiated MSS value greater than configured - changed
3828 self.verify_mss_value(capture[0], 1000)
3830 self.vapi.nat_set_mss_clamping(enable=0, mss_value=1500)
3831 self.pg0.add_stream(p)
3832 self.pg_enable_capture(self.pg_interfaces)
3834 capture = self.pg1.get_capture(1)
3835 # MSS clamping disabled - negotiated MSS unchanged
3836 self.verify_mss_value(capture[0], 1400)
3838 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3839 self.pg0.add_stream(p)
3840 self.pg_enable_capture(self.pg_interfaces)
3842 capture = self.pg1.get_capture(1)
3843 # Negotiated MSS value smaller than configured - unchanged
3844 self.verify_mss_value(capture[0], 1400)
3846 @unittest.skipUnless(running_extended_tests, "part of extended tests")
3847 def test_ha_send(self):
3848 """ Send HA session synchronization events (active) """
3849 self.nat44_add_address(self.nat_addr)
3850 flags = self.config_flags.NAT_IS_INSIDE
3851 self.vapi.nat44_interface_add_del_feature(
3852 sw_if_index=self.pg0.sw_if_index,
3853 flags=flags, is_add=1)
3854 self.vapi.nat44_interface_add_del_feature(
3855 sw_if_index=self.pg1.sw_if_index,
3857 self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
3860 self.vapi.nat_ha_set_failover(ip_address=self.pg3.remote_ip4,
3861 port=12346, session_refresh_interval=10)
3862 bind_layers(UDP, HANATStateSync, sport=12345)
3865 pkts = self.create_stream_in(self.pg0, self.pg1)
3866 self.pg0.add_stream(pkts)
3867 self.pg_enable_capture(self.pg_interfaces)
3869 capture = self.pg1.get_capture(len(pkts))
3870 self.verify_capture_out(capture)
3871 # active send HA events
3872 self.vapi.nat_ha_flush()
3873 stats = self.statistics.get_counter('/nat44/ha/add-event-send')
3874 self.assertEqual(stats[0][0], 3)
3875 capture = self.pg3.get_capture(1)
3877 self.assert_packet_checksums_valid(p)
3881 hanat = p[HANATStateSync]
3883 self.logger.error(ppp("Invalid packet:", p))
3886 self.assertEqual(ip.src, self.pg3.local_ip4)
3887 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3888 self.assertEqual(udp.sport, 12345)
3889 self.assertEqual(udp.dport, 12346)
3890 self.assertEqual(hanat.version, 1)
3891 self.assertEqual(hanat.thread_index, 0)
3892 self.assertEqual(hanat.count, 3)
3893 seq = hanat.sequence_number
3894 for event in hanat.events:
3895 self.assertEqual(event.event_type, 1)
3896 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
3897 self.assertEqual(event.out_addr, self.nat_addr)
3898 self.assertEqual(event.fib_index, 0)
3900 # ACK received events
3901 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3902 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3903 UDP(sport=12346, dport=12345) /
3904 HANATStateSync(sequence_number=seq, flags='ACK'))
3905 self.pg3.add_stream(ack)
3907 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3908 self.assertEqual(stats[0][0], 1)
3910 # delete one session
3911 self.pg_enable_capture(self.pg_interfaces)
3912 self.vapi.nat44_del_session(address=self.pg0.remote_ip4,
3913 port=self.tcp_port_in,
3914 protocol=IP_PROTOS.tcp,
3915 flags=self.config_flags.NAT_IS_INSIDE)
3916 self.vapi.nat_ha_flush()
3917 stats = self.statistics.get_counter('/nat44/ha/del-event-send')
3918 self.assertEqual(stats[0][0], 1)
3919 capture = self.pg3.get_capture(1)
3922 hanat = p[HANATStateSync]
3924 self.logger.error(ppp("Invalid packet:", p))
3927 self.assertGreater(hanat.sequence_number, seq)
3929 # do not send ACK, active retry send HA event again
3930 self.pg_enable_capture(self.pg_interfaces)
3932 stats = self.statistics.get_counter('/nat44/ha/retry-count')
3933 self.assertEqual(stats[0][0], 3)
3934 stats = self.statistics.get_counter('/nat44/ha/missed-count')
3935 self.assertEqual(stats[0][0], 1)
3936 capture = self.pg3.get_capture(3)
3937 for packet in capture:
3938 self.assertEqual(packet, p)
3940 # session counters refresh
3941 pkts = self.create_stream_out(self.pg1)
3942 self.pg1.add_stream(pkts)
3943 self.pg_enable_capture(self.pg_interfaces)
3945 self.pg0.get_capture(2)
3946 self.vapi.nat_ha_flush()
3947 stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
3948 self.assertEqual(stats[0][0], 2)
3949 capture = self.pg3.get_capture(1)
3951 self.assert_packet_checksums_valid(p)
3955 hanat = p[HANATStateSync]
3957 self.logger.error(ppp("Invalid packet:", p))
3960 self.assertEqual(ip.src, self.pg3.local_ip4)
3961 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3962 self.assertEqual(udp.sport, 12345)
3963 self.assertEqual(udp.dport, 12346)
3964 self.assertEqual(hanat.version, 1)
3965 self.assertEqual(hanat.count, 2)
3966 seq = hanat.sequence_number
3967 for event in hanat.events:
3968 self.assertEqual(event.event_type, 3)
3969 self.assertEqual(event.out_addr, self.nat_addr)
3970 self.assertEqual(event.fib_index, 0)
3971 self.assertEqual(event.total_pkts, 2)
3972 self.assertGreater(event.total_bytes, 0)
3974 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3975 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3976 UDP(sport=12346, dport=12345) /
3977 HANATStateSync(sequence_number=seq, flags='ACK'))
3978 self.pg3.add_stream(ack)
3980 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3981 self.assertEqual(stats[0][0], 2)
3983 def test_ha_recv(self):
3984 """ Receive HA session synchronization events (passive) """
3985 self.nat44_add_address(self.nat_addr)
3986 flags = self.config_flags.NAT_IS_INSIDE
3987 self.vapi.nat44_interface_add_del_feature(
3988 sw_if_index=self.pg0.sw_if_index,
3989 flags=flags, is_add=1)
3990 self.vapi.nat44_interface_add_del_feature(
3991 sw_if_index=self.pg1.sw_if_index,
3993 self.vapi.nat_ha_set_listener(ip_address=self.pg3.local_ip4,
3996 bind_layers(UDP, HANATStateSync, sport=12345)
3998 self.tcp_port_out = random.randint(1025, 65535)
3999 self.udp_port_out = random.randint(1025, 65535)
4001 # send HA session add events to failover/passive
4002 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4003 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4004 UDP(sport=12346, dport=12345) /
4005 HANATStateSync(sequence_number=1, events=[
4006 Event(event_type='add', protocol='tcp',
4007 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4008 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4009 eh_addr=self.pg1.remote_ip4,
4010 ehn_addr=self.pg1.remote_ip4,
4011 eh_port=self.tcp_external_port,
4012 ehn_port=self.tcp_external_port, fib_index=0),
4013 Event(event_type='add', protocol='udp',
4014 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4015 in_port=self.udp_port_in, out_port=self.udp_port_out,
4016 eh_addr=self.pg1.remote_ip4,
4017 ehn_addr=self.pg1.remote_ip4,
4018 eh_port=self.udp_external_port,
4019 ehn_port=self.udp_external_port, fib_index=0)]))
4021 self.pg3.add_stream(p)
4022 self.pg_enable_capture(self.pg_interfaces)
4025 capture = self.pg3.get_capture(1)
4028 hanat = p[HANATStateSync]
4030 self.logger.error(ppp("Invalid packet:", p))
4033 self.assertEqual(hanat.sequence_number, 1)
4034 self.assertEqual(hanat.flags, 'ACK')
4035 self.assertEqual(hanat.version, 1)
4036 self.assertEqual(hanat.thread_index, 0)
4037 stats = self.statistics.get_counter('/nat44/ha/ack-send')
4038 self.assertEqual(stats[0][0], 1)
4039 stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
4040 self.assertEqual(stats[0][0], 2)
4041 users = self.statistics.get_counter('/nat44/total-users')
4042 self.assertEqual(users[0][0], 1)
4043 sessions = self.statistics.get_counter('/nat44/total-sessions')
4044 self.assertEqual(sessions[0][0], 2)
4045 users = self.vapi.nat44_user_dump()
4046 self.assertEqual(len(users), 1)
4047 self.assertEqual(str(users[0].ip_address),
4048 self.pg0.remote_ip4)
4049 # there should be 2 sessions created by HA
4050 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4052 self.assertEqual(len(sessions), 2)
4053 for session in sessions:
4054 self.assertEqual(str(session.inside_ip_address),
4055 self.pg0.remote_ip4)
4056 self.assertEqual(str(session.outside_ip_address),
4058 self.assertIn(session.inside_port,
4059 [self.tcp_port_in, self.udp_port_in])
4060 self.assertIn(session.outside_port,
4061 [self.tcp_port_out, self.udp_port_out])
4062 self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
4064 # send HA session delete event to failover/passive
4065 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4066 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4067 UDP(sport=12346, dport=12345) /
4068 HANATStateSync(sequence_number=2, events=[
4069 Event(event_type='del', protocol='udp',
4070 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4071 in_port=self.udp_port_in, out_port=self.udp_port_out,
4072 eh_addr=self.pg1.remote_ip4,
4073 ehn_addr=self.pg1.remote_ip4,
4074 eh_port=self.udp_external_port,
4075 ehn_port=self.udp_external_port, fib_index=0)]))
4077 self.pg3.add_stream(p)
4078 self.pg_enable_capture(self.pg_interfaces)
4081 capture = self.pg3.get_capture(1)
4084 hanat = p[HANATStateSync]
4086 self.logger.error(ppp("Invalid packet:", p))
4089 self.assertEqual(hanat.sequence_number, 2)
4090 self.assertEqual(hanat.flags, 'ACK')
4091 self.assertEqual(hanat.version, 1)
4092 users = self.vapi.nat44_user_dump()
4093 self.assertEqual(len(users), 1)
4094 self.assertEqual(str(users[0].ip_address),
4095 self.pg0.remote_ip4)
4096 # now we should have only 1 session, 1 deleted by HA
4097 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4099 self.assertEqual(len(sessions), 1)
4100 stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
4101 self.assertEqual(stats[0][0], 1)
4103 stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
4104 self.assertEqual(stats, 2)
4106 # send HA session refresh event to failover/passive
4107 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4108 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4109 UDP(sport=12346, dport=12345) /
4110 HANATStateSync(sequence_number=3, events=[
4111 Event(event_type='refresh', protocol='tcp',
4112 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4113 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4114 eh_addr=self.pg1.remote_ip4,
4115 ehn_addr=self.pg1.remote_ip4,
4116 eh_port=self.tcp_external_port,
4117 ehn_port=self.tcp_external_port, fib_index=0,
4118 total_bytes=1024, total_pkts=2)]))
4119 self.pg3.add_stream(p)
4120 self.pg_enable_capture(self.pg_interfaces)
4123 capture = self.pg3.get_capture(1)
4126 hanat = p[HANATStateSync]
4128 self.logger.error(ppp("Invalid packet:", p))
4131 self.assertEqual(hanat.sequence_number, 3)
4132 self.assertEqual(hanat.flags, 'ACK')
4133 self.assertEqual(hanat.version, 1)
4134 users = self.vapi.nat44_user_dump()
4135 self.assertEqual(len(users), 1)
4136 self.assertEqual(str(users[0].ip_address),
4137 self.pg0.remote_ip4)
4138 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4140 self.assertEqual(len(sessions), 1)
4141 session = sessions[0]
4142 self.assertEqual(session.total_bytes, 1024)
4143 self.assertEqual(session.total_pkts, 2)
4144 stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
4145 self.assertEqual(stats[0][0], 1)
4147 stats = self.statistics.get_err_counter('/err/nat-ha/pkts-processed')
4148 self.assertEqual(stats, 3)
4150 # send packet to test session created by HA
4151 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4152 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4153 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
4154 self.pg1.add_stream(p)
4155 self.pg_enable_capture(self.pg_interfaces)
4157 capture = self.pg0.get_capture(1)
4163 self.logger.error(ppp("Invalid packet:", p))
4166 self.assertEqual(ip.src, self.pg1.remote_ip4)
4167 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4168 self.assertEqual(tcp.sport, self.tcp_external_port)
4169 self.assertEqual(tcp.dport, self.tcp_port_in)
4172 super(TestNAT44, self).tearDown()
4174 self.vapi.cli("clear logging")
4176 def show_commands_at_teardown(self):
4177 self.logger.info(self.vapi.cli("show nat44 addresses"))
4178 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4179 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4180 self.logger.info(self.vapi.cli("show nat44 interface address"))
4181 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
4182 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
4183 self.logger.info(self.vapi.cli("show nat timeouts"))
4185 self.vapi.cli("show nat addr-port-assignment-alg"))
4186 self.logger.info(self.vapi.cli("show nat ha"))
4189 class TestNAT44EndpointDependent2(MethodHolder):
4190 """ Endpoint-Dependent session test cases """
4195 def setUpConstants(cls):
4196 super(TestNAT44EndpointDependent2, cls).setUpConstants()
4197 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent",
4198 "translation", "hash", "buckets", "1",
4199 "icmp", "timeout", str(cls.icmp_timeout), "}"])
4202 def setUpClass(cls):
4203 super(TestNAT44EndpointDependent2, cls).setUpClass()
4204 translation_buckets = 1
4205 cls.max_translations = 10 * translation_buckets
4207 cls.create_pg_interfaces(range(2))
4208 cls.interfaces = list(cls.pg_interfaces[0:2])
4210 for i in cls.interfaces:
4215 cls.pg0.generate_remote_hosts(1)
4216 cls.pg0.configure_ipv4_neighbors()
4218 cls.pg1.generate_remote_hosts(1)
4219 cls.pg1.configure_ipv4_neighbors()
4222 def tearDownClass(cls):
4223 super(TestNAT44EndpointDependent2, cls).tearDownClass()
4225 def create_icmp_stream(self, in_if, out_if, count):
4227 Create ICMP packet stream for inside network
4229 :param in_if: Inside interface
4230 :param out_if: Outside interface
4231 :param count: Number of packets
4234 self.assertTrue(count > 0)
4235 icmp_id = random.randint(0, 65535 - (count - 1))
4238 for i in range(count):
4239 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
4240 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=64) /
4241 ICMP(id=icmp_id + i, type='echo-request'))
4245 def send_pkts(self, pkts, expected=None):
4246 self.pg0.add_stream(pkts)
4247 self.pg_enable_capture(self.pg_interfaces)
4249 return self.pg1.get_capture(
4250 len(pkts) if expected is None else expected)
4252 def test_session_cleanup(self):
4253 """ NAT44 session cleanup test """
4255 self.nat44_add_address(self.pg1.local_ip4)
4256 flags = self.config_flags.NAT_IS_INSIDE
4257 self.vapi.nat44_interface_add_del_feature(
4258 sw_if_index=self.pg0.sw_if_index,
4259 flags=flags, is_add=1)
4260 self.vapi.nat44_interface_add_del_feature(
4261 sw_if_index=self.pg1.sw_if_index,
4264 nat_config = self.vapi.nat_show_config()
4265 self.assertEqual(1, nat_config.endpoint_dependent)
4267 pkts = self.create_icmp_stream(self.pg0, self.pg1,
4268 self.max_translations + 2)
4272 self.send_pkts(pkts[0:self.max_translations])
4274 # false positive test
4275 self.send_pkts(pkts[self.max_translations:sz - 1], 0)
4277 sleep(self.icmp_timeout)
4280 self.send_pkts(pkts[self.max_translations + 1:sz])
4283 class TestNAT44EndpointDependent(MethodHolder):
4284 """ Endpoint-Dependent mapping and filtering test cases """
4287 def setUpConstants(cls):
4288 super(TestNAT44EndpointDependent, cls).setUpConstants()
4289 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4292 def setUpClass(cls):
4293 super(TestNAT44EndpointDependent, cls).setUpClass()
4294 cls.vapi.cli("set log class nat level debug")
4296 cls.tcp_port_in = 6303
4297 cls.tcp_port_out = 6303
4298 cls.udp_port_in = 6304
4299 cls.udp_port_out = 6304
4300 cls.icmp_id_in = 6305
4301 cls.icmp_id_out = 6305
4302 cls.nat_addr = '10.0.0.3'
4303 cls.ipfix_src_port = 4739
4304 cls.ipfix_domain_id = 1
4305 cls.tcp_external_port = 80
4307 cls.create_pg_interfaces(range(9))
4308 cls.interfaces = list(cls.pg_interfaces[0:3])
4310 for i in cls.interfaces:
4315 cls.pg0.generate_remote_hosts(3)
4316 cls.pg0.configure_ipv4_neighbors()
4320 cls.pg4.generate_remote_hosts(2)
4321 cls.pg4.config_ip4()
4322 cls.vapi.sw_interface_add_del_address(
4323 sw_if_index=cls.pg4.sw_if_index,
4324 prefix="10.0.0.1/24")
4327 cls.pg4.resolve_arp()
4328 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4329 cls.pg4.resolve_arp()
4331 zero_ip4 = socket.inet_pton(socket.AF_INET, "0.0.0.0")
4332 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 1})
4334 cls.pg5._local_ip4 = "10.1.1.1"
4335 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4336 cls.pg5.set_table_ip4(1)
4337 cls.pg5.config_ip4()
4339 r1 = VppIpRoute(cls, cls.pg5.remote_ip4, 32,
4340 [VppRoutePath("0.0.0.0",
4341 cls.pg5.sw_if_index)],
4346 cls.pg6._local_ip4 = "10.1.2.1"
4347 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4348 cls.pg6.set_table_ip4(1)
4349 cls.pg6.config_ip4()
4352 r2 = VppIpRoute(cls, cls.pg6.remote_ip4, 32,
4353 [VppRoutePath("0.0.0.0",
4354 cls.pg6.sw_if_index)],
4357 r3 = VppIpRoute(cls, cls.pg6.remote_ip4, 16,
4358 [VppRoutePath("0.0.0.0",
4363 r4 = VppIpRoute(cls, "0.0.0.0", 0,
4364 [VppRoutePath("0.0.0.0", 0xffffffff,
4368 r5 = VppIpRoute(cls, "0.0.0.0", 0,
4369 [VppRoutePath(cls.pg1.local_ip4,
4370 cls.pg1.sw_if_index)],
4377 cls.pg5.resolve_arp()
4378 cls.pg6.resolve_arp()
4381 cls.pg7.config_ip4()
4382 cls.pg7.resolve_arp()
4383 cls.pg7.generate_remote_hosts(3)
4384 cls.pg7.configure_ipv4_neighbors()
4387 cls.pg8.config_ip4()
4388 cls.pg8.resolve_arp()
4391 super(TestNAT44EndpointDependent, self).setUp()
4392 self.vapi.nat_set_timeouts(
4393 udp=300, tcp_established=7440, tcp_transitory=240, icmp=60)
4396 def tearDownClass(cls):
4397 super(TestNAT44EndpointDependent, cls).tearDownClass()
4399 def test_frag_in_order(self):
4400 """ NAT44 translate fragments arriving in order """
4401 self.nat44_add_address(self.nat_addr)
4402 flags = self.config_flags.NAT_IS_INSIDE
4403 self.vapi.nat44_interface_add_del_feature(
4404 sw_if_index=self.pg0.sw_if_index,
4405 flags=flags, is_add=1)
4406 self.vapi.nat44_interface_add_del_feature(
4407 sw_if_index=self.pg1.sw_if_index,
4409 self.frag_in_order(proto=IP_PROTOS.tcp)
4410 self.frag_in_order(proto=IP_PROTOS.udp)
4411 self.frag_in_order(proto=IP_PROTOS.icmp)
4413 def test_frag_in_order_dont_translate(self):
4414 """ NAT44 don't translate fragments arriving in order """
4415 flags = self.config_flags.NAT_IS_INSIDE
4416 self.vapi.nat44_interface_add_del_feature(
4417 sw_if_index=self.pg0.sw_if_index,
4418 flags=flags, is_add=1)
4419 self.vapi.nat44_interface_add_del_feature(
4420 sw_if_index=self.pg1.sw_if_index,
4422 self.vapi.nat44_forwarding_enable_disable(enable=True)
4423 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4425 def test_frag_out_of_order(self):
4426 """ NAT44 translate fragments arriving out of order """
4427 self.nat44_add_address(self.nat_addr)
4428 flags = self.config_flags.NAT_IS_INSIDE
4429 self.vapi.nat44_interface_add_del_feature(
4430 sw_if_index=self.pg0.sw_if_index,
4431 flags=flags, is_add=1)
4432 self.vapi.nat44_interface_add_del_feature(
4433 sw_if_index=self.pg1.sw_if_index,
4435 self.frag_out_of_order(proto=IP_PROTOS.tcp)
4436 self.frag_out_of_order(proto=IP_PROTOS.udp)
4437 self.frag_out_of_order(proto=IP_PROTOS.icmp)
4439 def test_frag_out_of_order_dont_translate(self):
4440 """ NAT44 don't translate fragments arriving out of order """
4441 flags = self.config_flags.NAT_IS_INSIDE
4442 self.vapi.nat44_interface_add_del_feature(
4443 sw_if_index=self.pg0.sw_if_index,
4444 flags=flags, is_add=1)
4445 self.vapi.nat44_interface_add_del_feature(
4446 sw_if_index=self.pg1.sw_if_index,
4448 self.vapi.nat44_forwarding_enable_disable(enable=True)
4449 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4451 def test_frag_in_order_in_plus_out(self):
4452 """ in+out interface fragments in order """
4453 flags = self.config_flags.NAT_IS_INSIDE
4454 self.vapi.nat44_interface_add_del_feature(
4455 sw_if_index=self.pg0.sw_if_index,
4457 self.vapi.nat44_interface_add_del_feature(
4458 sw_if_index=self.pg0.sw_if_index,
4459 flags=flags, is_add=1)
4460 self.vapi.nat44_interface_add_del_feature(
4461 sw_if_index=self.pg1.sw_if_index,
4463 self.vapi.nat44_interface_add_del_feature(
4464 sw_if_index=self.pg1.sw_if_index,
4465 flags=flags, is_add=1)
4467 self.server = self.pg1.remote_hosts[0]
4469 self.server_in_addr = self.server.ip4
4470 self.server_out_addr = '11.11.11.11'
4471 self.server_in_port = random.randint(1025, 65535)
4472 self.server_out_port = random.randint(1025, 65535)
4474 self.nat44_add_address(self.server_out_addr)
4476 # add static mappings for server
4477 self.nat44_add_static_mapping(self.server_in_addr,
4478 self.server_out_addr,
4479 self.server_in_port,
4480 self.server_out_port,
4481 proto=IP_PROTOS.tcp)
4482 self.nat44_add_static_mapping(self.server_in_addr,
4483 self.server_out_addr,
4484 self.server_in_port,
4485 self.server_out_port,
4486 proto=IP_PROTOS.udp)
4487 self.nat44_add_static_mapping(self.server_in_addr,
4488 self.server_out_addr,
4489 proto=IP_PROTOS.icmp)
4491 self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4492 self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4493 self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4495 def test_frag_out_of_order_in_plus_out(self):
4496 """ in+out interface fragments out of order """
4497 flags = self.config_flags.NAT_IS_INSIDE
4498 self.vapi.nat44_interface_add_del_feature(
4499 sw_if_index=self.pg0.sw_if_index,
4501 self.vapi.nat44_interface_add_del_feature(
4502 sw_if_index=self.pg0.sw_if_index,
4503 flags=flags, is_add=1)
4504 self.vapi.nat44_interface_add_del_feature(
4505 sw_if_index=self.pg1.sw_if_index,
4507 self.vapi.nat44_interface_add_del_feature(
4508 sw_if_index=self.pg1.sw_if_index,
4509 flags=flags, is_add=1)
4511 self.server = self.pg1.remote_hosts[0]
4513 self.server_in_addr = self.server.ip4
4514 self.server_out_addr = '11.11.11.11'
4515 self.server_in_port = random.randint(1025, 65535)
4516 self.server_out_port = random.randint(1025, 65535)
4518 self.nat44_add_address(self.server_out_addr)
4520 # add static mappings for server
4521 self.nat44_add_static_mapping(self.server_in_addr,
4522 self.server_out_addr,
4523 self.server_in_port,
4524 self.server_out_port,
4525 proto=IP_PROTOS.tcp)
4526 self.nat44_add_static_mapping(self.server_in_addr,
4527 self.server_out_addr,
4528 self.server_in_port,
4529 self.server_out_port,
4530 proto=IP_PROTOS.udp)
4531 self.nat44_add_static_mapping(self.server_in_addr,
4532 self.server_out_addr,
4533 proto=IP_PROTOS.icmp)
4535 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4536 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4537 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4539 def test_reass_hairpinning(self):
4540 """ NAT44 fragments hairpinning """
4541 self.server = self.pg0.remote_hosts[1]
4542 self.host_in_port = random.randint(1025, 65535)
4543 self.server_in_port = random.randint(1025, 65535)
4544 self.server_out_port = random.randint(1025, 65535)
4546 self.nat44_add_address(self.nat_addr)
4547 flags = self.config_flags.NAT_IS_INSIDE
4548 self.vapi.nat44_interface_add_del_feature(
4549 sw_if_index=self.pg0.sw_if_index,
4550 flags=flags, is_add=1)
4551 self.vapi.nat44_interface_add_del_feature(
4552 sw_if_index=self.pg1.sw_if_index,
4554 # add static mapping for server
4555 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4556 self.server_in_port,
4557 self.server_out_port,
4558 proto=IP_PROTOS.tcp)
4559 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4560 self.server_in_port,
4561 self.server_out_port,
4562 proto=IP_PROTOS.udp)
4563 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
4565 self.reass_hairpinning(proto=IP_PROTOS.tcp)
4566 self.reass_hairpinning(proto=IP_PROTOS.udp)
4567 self.reass_hairpinning(proto=IP_PROTOS.icmp)
4569 def test_dynamic(self):
4570 """ NAT44 dynamic translation test """
4572 self.nat44_add_address(self.nat_addr)
4573 flags = self.config_flags.NAT_IS_INSIDE
4574 self.vapi.nat44_interface_add_del_feature(
4575 sw_if_index=self.pg0.sw_if_index,
4576 flags=flags, is_add=1)
4577 self.vapi.nat44_interface_add_del_feature(
4578 sw_if_index=self.pg1.sw_if_index,
4581 nat_config = self.vapi.nat_show_config()
4582 self.assertEqual(1, nat_config.endpoint_dependent)
4585 tcpn = self.statistics.get_err_counter(
4586 '/err/nat44-ed-in2out-slowpath/TCP packets')
4587 udpn = self.statistics.get_err_counter(
4588 '/err/nat44-ed-in2out-slowpath/UDP packets')
4589 icmpn = self.statistics.get_err_counter(
4590 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4591 totaln = self.statistics.get_err_counter(
4592 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4594 pkts = self.create_stream_in(self.pg0, self.pg1)
4595 self.pg0.add_stream(pkts)
4596 self.pg_enable_capture(self.pg_interfaces)
4598 capture = self.pg1.get_capture(len(pkts))
4599 self.verify_capture_out(capture)
4601 err = self.statistics.get_err_counter(
4602 '/err/nat44-ed-in2out-slowpath/TCP packets')
4603 self.assertEqual(err - tcpn, 2)
4604 err = self.statistics.get_err_counter(
4605 '/err/nat44-ed-in2out-slowpath/UDP packets')
4606 self.assertEqual(err - udpn, 1)
4607 err = self.statistics.get_err_counter(
4608 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4609 self.assertEqual(err - icmpn, 1)
4610 err = self.statistics.get_err_counter(
4611 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4612 self.assertEqual(err - totaln, 4)
4615 tcpn = self.statistics.get_err_counter(
4616 '/err/nat44-ed-out2in/TCP packets')
4617 udpn = self.statistics.get_err_counter(
4618 '/err/nat44-ed-out2in/UDP packets')
4619 icmpn = self.statistics.get_err_counter(
4620 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4621 totaln = self.statistics.get_err_counter(
4622 '/err/nat44-ed-out2in/good out2in packets processed')
4624 pkts = self.create_stream_out(self.pg1)
4625 self.pg1.add_stream(pkts)
4626 self.pg_enable_capture(self.pg_interfaces)
4628 capture = self.pg0.get_capture(len(pkts))
4629 self.verify_capture_in(capture, self.pg0)
4631 err = self.statistics.get_err_counter(
4632 '/err/nat44-ed-out2in/TCP packets')
4633 self.assertEqual(err - tcpn, 2)
4634 err = self.statistics.get_err_counter(
4635 '/err/nat44-ed-out2in/UDP packets')
4636 self.assertEqual(err - udpn, 1)
4637 err = self.statistics.get_err_counter(
4638 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4639 self.assertEqual(err - icmpn, 1)
4640 err = self.statistics.get_err_counter(
4641 '/err/nat44-ed-out2in/good out2in packets processed')
4642 self.assertEqual(err - totaln, 3)
4644 users = self.statistics.get_counter('/nat44/total-users')
4645 self.assertEqual(users[0][0], 1)
4646 sessions = self.statistics.get_counter('/nat44/total-sessions')
4647 self.assertEqual(sessions[0][0], 3)
4649 def test_dynamic_output_feature_vrf(self):
4650 """ NAT44 dynamic translation test: output-feature, VRF"""
4652 # other then default (0)
4655 self.nat44_add_address(self.nat_addr)
4656 flags = self.config_flags.NAT_IS_INSIDE
4657 self.vapi.nat44_interface_add_del_output_feature(
4658 sw_if_index=self.pg7.sw_if_index,
4659 flags=flags, is_add=1)
4660 self.vapi.nat44_interface_add_del_output_feature(
4661 sw_if_index=self.pg8.sw_if_index,
4665 self.vapi.ip_table_add_del(is_add=1,
4666 table={'table_id': new_vrf_id})
4668 self.pg7.unconfig_ip4()
4669 self.pg7.set_table_ip4(new_vrf_id)
4670 self.pg7.config_ip4()
4671 self.pg7.resolve_arp()
4673 self.pg8.unconfig_ip4()
4674 self.pg8.set_table_ip4(new_vrf_id)
4675 self.pg8.config_ip4()
4676 self.pg8.resolve_arp()
4678 nat_config = self.vapi.nat_show_config()
4679 self.assertEqual(1, nat_config.endpoint_dependent)
4682 tcpn = self.statistics.get_err_counter(
4683 '/err/nat44-ed-in2out-slowpath/TCP packets')
4684 udpn = self.statistics.get_err_counter(
4685 '/err/nat44-ed-in2out-slowpath/UDP packets')
4686 icmpn = self.statistics.get_err_counter(
4687 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4688 totaln = self.statistics.get_err_counter(
4689 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4691 pkts = self.create_stream_in(self.pg7, self.pg8)
4692 self.pg7.add_stream(pkts)
4693 self.pg_enable_capture(self.pg_interfaces)
4695 capture = self.pg8.get_capture(len(pkts))
4696 self.verify_capture_out(capture)
4698 err = self.statistics.get_err_counter(
4699 '/err/nat44-ed-in2out-slowpath/TCP packets')
4700 self.assertEqual(err - tcpn, 2)
4701 err = self.statistics.get_err_counter(
4702 '/err/nat44-ed-in2out-slowpath/UDP packets')
4703 self.assertEqual(err - udpn, 1)
4704 err = self.statistics.get_err_counter(
4705 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4706 self.assertEqual(err - icmpn, 1)
4707 err = self.statistics.get_err_counter(
4708 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4709 self.assertEqual(err - totaln, 4)
4712 tcpn = self.statistics.get_err_counter(
4713 '/err/nat44-ed-out2in/TCP packets')
4714 udpn = self.statistics.get_err_counter(
4715 '/err/nat44-ed-out2in/UDP packets')
4716 icmpn = self.statistics.get_err_counter(
4717 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4718 totaln = self.statistics.get_err_counter(
4719 '/err/nat44-ed-out2in/good out2in packets processed')
4721 pkts = self.create_stream_out(self.pg8)
4722 self.pg8.add_stream(pkts)
4723 self.pg_enable_capture(self.pg_interfaces)
4725 capture = self.pg7.get_capture(len(pkts))
4726 self.verify_capture_in(capture, self.pg7)
4728 err = self.statistics.get_err_counter(
4729 '/err/nat44-ed-out2in/TCP packets')
4730 self.assertEqual(err - tcpn, 2)
4731 err = self.statistics.get_err_counter(
4732 '/err/nat44-ed-out2in/UDP packets')
4733 self.assertEqual(err - udpn, 1)
4734 err = self.statistics.get_err_counter(
4735 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4736 self.assertEqual(err - icmpn, 1)
4737 err = self.statistics.get_err_counter(
4738 '/err/nat44-ed-out2in/good out2in packets processed')
4739 self.assertEqual(err - totaln, 3)
4741 users = self.statistics.get_counter('/nat44/total-users')
4742 self.assertEqual(users[0][0], 1)
4743 sessions = self.statistics.get_counter('/nat44/total-sessions')
4744 self.assertEqual(sessions[0][0], 3)
4747 self.pg7.unconfig_ip4()
4748 self.pg7.set_table_ip4(1)
4749 self.pg7.config_ip4()
4750 self.pg7.resolve_arp()
4752 self.pg8.unconfig_ip4()
4753 self.pg8.set_table_ip4(1)
4754 self.pg8.config_ip4()
4755 self.pg8.resolve_arp()
4757 self.vapi.ip_table_add_del(is_add=0,
4758 table={'table_id': new_vrf_id})
4760 def test_forwarding(self):
4761 """ NAT44 forwarding test """
4763 flags = self.config_flags.NAT_IS_INSIDE
4764 self.vapi.nat44_interface_add_del_feature(
4765 sw_if_index=self.pg0.sw_if_index,
4766 flags=flags, is_add=1)
4767 self.vapi.nat44_interface_add_del_feature(
4768 sw_if_index=self.pg1.sw_if_index,
4770 self.vapi.nat44_forwarding_enable_disable(enable=1)
4772 real_ip = self.pg0.remote_ip4
4773 alias_ip = self.nat_addr
4774 flags = self.config_flags.NAT_IS_ADDR_ONLY
4775 self.vapi.nat44_add_del_static_mapping(is_add=1,
4776 local_ip_address=real_ip,
4777 external_ip_address=alias_ip,
4778 external_sw_if_index=0xFFFFFFFF,
4782 # in2out - static mapping match
4784 pkts = self.create_stream_out(self.pg1)
4785 self.pg1.add_stream(pkts)
4786 self.pg_enable_capture(self.pg_interfaces)
4788 capture = self.pg0.get_capture(len(pkts))
4789 self.verify_capture_in(capture, self.pg0)
4791 pkts = self.create_stream_in(self.pg0, self.pg1)
4792 self.pg0.add_stream(pkts)
4793 self.pg_enable_capture(self.pg_interfaces)
4795 capture = self.pg1.get_capture(len(pkts))
4796 self.verify_capture_out(capture, same_port=True)
4798 # in2out - no static mapping match
4800 host0 = self.pg0.remote_hosts[0]
4801 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4803 pkts = self.create_stream_out(self.pg1,
4804 dst_ip=self.pg0.remote_ip4,
4805 use_inside_ports=True)
4806 self.pg1.add_stream(pkts)
4807 self.pg_enable_capture(self.pg_interfaces)
4809 capture = self.pg0.get_capture(len(pkts))
4810 self.verify_capture_in(capture, self.pg0)
4812 pkts = self.create_stream_in(self.pg0, self.pg1)
4813 self.pg0.add_stream(pkts)
4814 self.pg_enable_capture(self.pg_interfaces)
4816 capture = self.pg1.get_capture(len(pkts))
4817 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4820 self.pg0.remote_hosts[0] = host0
4822 user = self.pg0.remote_hosts[1]
4823 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4824 self.assertEqual(len(sessions), 3)
4825 self.assertTrue(sessions[0].flags &
4826 self.config_flags.NAT_IS_EXT_HOST_VALID)
4827 self.vapi.nat44_del_session(
4828 address=sessions[0].inside_ip_address,
4829 port=sessions[0].inside_port,
4830 protocol=sessions[0].protocol,
4831 flags=(self.config_flags.NAT_IS_INSIDE |
4832 self.config_flags.NAT_IS_EXT_HOST_VALID),
4833 ext_host_address=sessions[0].ext_host_address,
4834 ext_host_port=sessions[0].ext_host_port)
4835 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
4836 self.assertEqual(len(sessions), 2)
4839 self.vapi.nat44_forwarding_enable_disable(enable=0)
4840 flags = self.config_flags.NAT_IS_ADDR_ONLY
4841 self.vapi.nat44_add_del_static_mapping(
4843 local_ip_address=real_ip,
4844 external_ip_address=alias_ip,
4845 external_sw_if_index=0xFFFFFFFF,
4848 def test_static_lb(self):
4849 """ NAT44 local service load balancing """
4850 external_addr_n = self.nat_addr
4853 server1 = self.pg0.remote_hosts[0]
4854 server2 = self.pg0.remote_hosts[1]
4856 locals = [{'addr': server1.ip4,
4860 {'addr': server2.ip4,
4865 self.nat44_add_address(self.nat_addr)
4866 self.vapi.nat44_add_del_lb_static_mapping(
4868 external_addr=external_addr_n,
4869 external_port=external_port,
4870 protocol=IP_PROTOS.tcp,
4871 local_num=len(locals),
4873 flags = self.config_flags.NAT_IS_INSIDE
4874 self.vapi.nat44_interface_add_del_feature(
4875 sw_if_index=self.pg0.sw_if_index,
4876 flags=flags, is_add=1)
4877 self.vapi.nat44_interface_add_del_feature(
4878 sw_if_index=self.pg1.sw_if_index,
4881 # from client to service
4882 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4883 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4884 TCP(sport=12345, dport=external_port))
4885 self.pg1.add_stream(p)
4886 self.pg_enable_capture(self.pg_interfaces)
4888 capture = self.pg0.get_capture(1)
4894 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4895 if ip.dst == server1.ip4:
4899 self.assertEqual(tcp.dport, local_port)
4900 self.assert_packet_checksums_valid(p)
4902 self.logger.error(ppp("Unexpected or invalid packet:", p))
4905 # from service back to client
4906 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4907 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4908 TCP(sport=local_port, dport=12345))
4909 self.pg0.add_stream(p)
4910 self.pg_enable_capture(self.pg_interfaces)
4912 capture = self.pg1.get_capture(1)
4917 self.assertEqual(ip.src, self.nat_addr)
4918 self.assertEqual(tcp.sport, external_port)
4919 self.assert_packet_checksums_valid(p)
4921 self.logger.error(ppp("Unexpected or invalid packet:", p))
4924 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
4925 self.assertEqual(len(sessions), 1)
4926 self.assertTrue(sessions[0].flags &
4927 self.config_flags.NAT_IS_EXT_HOST_VALID)
4928 self.vapi.nat44_del_session(
4929 address=sessions[0].inside_ip_address,
4930 port=sessions[0].inside_port,
4931 protocol=sessions[0].protocol,
4932 flags=(self.config_flags.NAT_IS_INSIDE |
4933 self.config_flags.NAT_IS_EXT_HOST_VALID),
4934 ext_host_address=sessions[0].ext_host_address,
4935 ext_host_port=sessions[0].ext_host_port)
4936 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
4937 self.assertEqual(len(sessions), 0)
4939 @unittest.skipUnless(running_extended_tests, "part of extended tests")
4940 def test_static_lb_multi_clients(self):
4941 """ NAT44 local service load balancing - multiple clients"""
4943 external_addr = self.nat_addr
4946 server1 = self.pg0.remote_hosts[0]
4947 server2 = self.pg0.remote_hosts[1]
4948 server3 = self.pg0.remote_hosts[2]
4950 locals = [{'addr': server1.ip4,
4954 {'addr': server2.ip4,
4959 self.nat44_add_address(self.nat_addr)
4960 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
4961 external_addr=external_addr,
4962 external_port=external_port,
4963 protocol=IP_PROTOS.tcp,
4964 local_num=len(locals),
4966 flags = self.config_flags.NAT_IS_INSIDE
4967 self.vapi.nat44_interface_add_del_feature(
4968 sw_if_index=self.pg0.sw_if_index,
4969 flags=flags, is_add=1)
4970 self.vapi.nat44_interface_add_del_feature(
4971 sw_if_index=self.pg1.sw_if_index,
4976 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4978 for client in clients:
4979 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4980 IP(src=client, dst=self.nat_addr) /
4981 TCP(sport=12345, dport=external_port))
4983 self.pg1.add_stream(pkts)
4984 self.pg_enable_capture(self.pg_interfaces)
4986 capture = self.pg0.get_capture(len(pkts))
4988 if p[IP].dst == server1.ip4:
4992 self.assertGreater(server1_n, server2_n)
4995 'addr': server3.ip4,
5002 self.vapi.nat44_lb_static_mapping_add_del_local(
5004 external_addr=external_addr,
5005 external_port=external_port,
5007 protocol=IP_PROTOS.tcp)
5011 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
5013 for client in clients:
5014 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5015 IP(src=client, dst=self.nat_addr) /
5016 TCP(sport=12346, dport=external_port))
5018 self.assertGreater(len(pkts), 0)
5019 self.pg1.add_stream(pkts)
5020 self.pg_enable_capture(self.pg_interfaces)
5022 capture = self.pg0.get_capture(len(pkts))
5024 if p[IP].dst == server1.ip4:
5026 elif p[IP].dst == server2.ip4:
5030 self.assertGreater(server1_n, 0)
5031 self.assertGreater(server2_n, 0)
5032 self.assertGreater(server3_n, 0)
5035 'addr': server2.ip4,
5041 # remove one back-end
5042 self.vapi.nat44_lb_static_mapping_add_del_local(
5044 external_addr=external_addr,
5045 external_port=external_port,
5047 protocol=IP_PROTOS.tcp)
5051 self.pg1.add_stream(pkts)
5052 self.pg_enable_capture(self.pg_interfaces)
5054 capture = self.pg0.get_capture(len(pkts))
5056 if p[IP].dst == server1.ip4:
5058 elif p[IP].dst == server2.ip4:
5062 self.assertGreater(server1_n, 0)
5063 self.assertEqual(server2_n, 0)
5064 self.assertGreater(server3_n, 0)
5066 def test_static_lb_2(self):
5067 """ NAT44 local service load balancing (asymmetrical rule) """
5068 external_addr = self.nat_addr
5071 server1 = self.pg0.remote_hosts[0]
5072 server2 = self.pg0.remote_hosts[1]
5074 locals = [{'addr': server1.ip4,
5078 {'addr': server2.ip4,
5083 self.vapi.nat44_forwarding_enable_disable(enable=1)
5084 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5085 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5086 external_addr=external_addr,
5087 external_port=external_port,
5088 protocol=IP_PROTOS.tcp,
5089 local_num=len(locals),
5091 flags = self.config_flags.NAT_IS_INSIDE
5092 self.vapi.nat44_interface_add_del_feature(
5093 sw_if_index=self.pg0.sw_if_index,
5094 flags=flags, is_add=1)
5095 self.vapi.nat44_interface_add_del_feature(
5096 sw_if_index=self.pg1.sw_if_index,
5099 # from client to service
5100 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5101 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5102 TCP(sport=12345, dport=external_port))
5103 self.pg1.add_stream(p)
5104 self.pg_enable_capture(self.pg_interfaces)
5106 capture = self.pg0.get_capture(1)
5112 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
5113 if ip.dst == server1.ip4:
5117 self.assertEqual(tcp.dport, local_port)
5118 self.assert_packet_checksums_valid(p)
5120 self.logger.error(ppp("Unexpected or invalid packet:", p))
5123 # from service back to client
5124 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
5125 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
5126 TCP(sport=local_port, dport=12345))
5127 self.pg0.add_stream(p)
5128 self.pg_enable_capture(self.pg_interfaces)
5130 capture = self.pg1.get_capture(1)
5135 self.assertEqual(ip.src, self.nat_addr)
5136 self.assertEqual(tcp.sport, external_port)
5137 self.assert_packet_checksums_valid(p)
5139 self.logger.error(ppp("Unexpected or invalid packet:", p))
5142 # from client to server (no translation)
5143 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5144 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
5145 TCP(sport=12346, dport=local_port))
5146 self.pg1.add_stream(p)
5147 self.pg_enable_capture(self.pg_interfaces)
5149 capture = self.pg0.get_capture(1)
5155 self.assertEqual(ip.dst, server1.ip4)
5156 self.assertEqual(tcp.dport, local_port)
5157 self.assert_packet_checksums_valid(p)
5159 self.logger.error(ppp("Unexpected or invalid packet:", p))
5162 # from service back to client (no translation)
5163 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
5164 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
5165 TCP(sport=local_port, dport=12346))
5166 self.pg0.add_stream(p)
5167 self.pg_enable_capture(self.pg_interfaces)
5169 capture = self.pg1.get_capture(1)
5174 self.assertEqual(ip.src, server1.ip4)
5175 self.assertEqual(tcp.sport, local_port)
5176 self.assert_packet_checksums_valid(p)
5178 self.logger.error(ppp("Unexpected or invalid packet:", p))
5181 def test_lb_affinity(self):
5182 """ NAT44 local service load balancing affinity """
5183 external_addr = self.nat_addr
5186 server1 = self.pg0.remote_hosts[0]
5187 server2 = self.pg0.remote_hosts[1]
5189 locals = [{'addr': server1.ip4,
5193 {'addr': server2.ip4,
5198 self.nat44_add_address(self.nat_addr)
5199 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
5200 external_addr=external_addr,
5201 external_port=external_port,
5202 protocol=IP_PROTOS.tcp,
5204 local_num=len(locals),
5206 flags = self.config_flags.NAT_IS_INSIDE
5207 self.vapi.nat44_interface_add_del_feature(
5208 sw_if_index=self.pg0.sw_if_index,
5209 flags=flags, is_add=1)
5210 self.vapi.nat44_interface_add_del_feature(
5211 sw_if_index=self.pg1.sw_if_index,
5214 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5215 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5216 TCP(sport=1025, dport=external_port))
5217 self.pg1.add_stream(p)
5218 self.pg_enable_capture(self.pg_interfaces)
5220 capture = self.pg0.get_capture(1)
5221 backend = capture[0][IP].dst
5223 sessions = self.vapi.nat44_user_session_dump(backend, 0)
5224 self.assertEqual(len(sessions), 1)
5225 self.assertTrue(sessions[0].flags &
5226 self.config_flags.NAT_IS_EXT_HOST_VALID)
5227 self.vapi.nat44_del_session(
5228 address=sessions[0].inside_ip_address,
5229 port=sessions[0].inside_port,
5230 protocol=sessions[0].protocol,
5231 flags=(self.config_flags.NAT_IS_INSIDE |
5232 self.config_flags.NAT_IS_EXT_HOST_VALID),
5233 ext_host_address=sessions[0].ext_host_address,
5234 ext_host_port=sessions[0].ext_host_port)
5237 for port in range(1030, 1100):
5238 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5239 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5240 TCP(sport=port, dport=external_port))
5242 self.pg1.add_stream(pkts)
5243 self.pg_enable_capture(self.pg_interfaces)
5245 capture = self.pg0.get_capture(len(pkts))
5247 self.assertEqual(p[IP].dst, backend)
5249 def test_unknown_proto(self):
5250 """ NAT44 translate packet with unknown protocol """
5251 self.nat44_add_address(self.nat_addr)
5252 flags = self.config_flags.NAT_IS_INSIDE
5253 self.vapi.nat44_interface_add_del_feature(
5254 sw_if_index=self.pg0.sw_if_index,
5255 flags=flags, is_add=1)
5256 self.vapi.nat44_interface_add_del_feature(
5257 sw_if_index=self.pg1.sw_if_index,
5261 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5262 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5263 TCP(sport=self.tcp_port_in, dport=20))
5264 self.pg0.add_stream(p)
5265 self.pg_enable_capture(self.pg_interfaces)
5267 p = self.pg1.get_capture(1)
5269 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5270 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5272 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5273 TCP(sport=1234, dport=1234))
5274 self.pg0.add_stream(p)
5275 self.pg_enable_capture(self.pg_interfaces)
5277 p = self.pg1.get_capture(1)
5280 self.assertEqual(packet[IP].src, self.nat_addr)
5281 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5282 self.assertEqual(packet.haslayer(GRE), 1)
5283 self.assert_packet_checksums_valid(packet)
5285 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5289 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5290 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5292 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5293 TCP(sport=1234, dport=1234))
5294 self.pg1.add_stream(p)
5295 self.pg_enable_capture(self.pg_interfaces)
5297 p = self.pg0.get_capture(1)
5300 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
5301 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
5302 self.assertEqual(packet.haslayer(GRE), 1)
5303 self.assert_packet_checksums_valid(packet)
5305 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5308 def test_hairpinning_unknown_proto(self):
5309 """ NAT44 translate packet with unknown protocol - hairpinning """
5310 host = self.pg0.remote_hosts[0]
5311 server = self.pg0.remote_hosts[1]
5313 server_out_port = 8765
5314 server_nat_ip = "10.0.0.11"
5316 self.nat44_add_address(self.nat_addr)
5317 flags = self.config_flags.NAT_IS_INSIDE
5318 self.vapi.nat44_interface_add_del_feature(
5319 sw_if_index=self.pg0.sw_if_index,
5320 flags=flags, is_add=1)
5321 self.vapi.nat44_interface_add_del_feature(
5322 sw_if_index=self.pg1.sw_if_index,
5325 # add static mapping for server
5326 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
5329 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
5330 IP(src=host.ip4, dst=server_nat_ip) /
5331 TCP(sport=host_in_port, dport=server_out_port))
5332 self.pg0.add_stream(p)
5333 self.pg_enable_capture(self.pg_interfaces)
5335 self.pg0.get_capture(1)
5337 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5338 IP(src=host.ip4, dst=server_nat_ip) /
5340 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5341 TCP(sport=1234, dport=1234))
5342 self.pg0.add_stream(p)
5343 self.pg_enable_capture(self.pg_interfaces)
5345 p = self.pg0.get_capture(1)
5348 self.assertEqual(packet[IP].src, self.nat_addr)
5349 self.assertEqual(packet[IP].dst, server.ip4)
5350 self.assertEqual(packet.haslayer(GRE), 1)
5351 self.assert_packet_checksums_valid(packet)
5353 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5357 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5358 IP(src=server.ip4, dst=self.nat_addr) /
5360 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5361 TCP(sport=1234, dport=1234))
5362 self.pg0.add_stream(p)
5363 self.pg_enable_capture(self.pg_interfaces)
5365 p = self.pg0.get_capture(1)
5368 self.assertEqual(packet[IP].src, server_nat_ip)
5369 self.assertEqual(packet[IP].dst, host.ip4)
5370 self.assertEqual(packet.haslayer(GRE), 1)
5371 self.assert_packet_checksums_valid(packet)
5373 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5376 def test_output_feature_and_service(self):
5377 """ NAT44 interface output feature and services """
5378 external_addr = '1.2.3.4'
5382 self.vapi.nat44_forwarding_enable_disable(enable=1)
5383 self.nat44_add_address(self.nat_addr)
5384 flags = self.config_flags.NAT_IS_ADDR_ONLY
5385 self.vapi.nat44_add_del_identity_mapping(
5386 ip_address=self.pg1.remote_ip4, sw_if_index=0xFFFFFFFF,
5387 flags=flags, is_add=1)
5388 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5389 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5390 local_port, external_port,
5391 proto=IP_PROTOS.tcp, flags=flags)
5392 flags = self.config_flags.NAT_IS_INSIDE
5393 self.vapi.nat44_interface_add_del_feature(
5394 sw_if_index=self.pg0.sw_if_index,
5396 self.vapi.nat44_interface_add_del_feature(
5397 sw_if_index=self.pg0.sw_if_index,
5398 flags=flags, is_add=1)
5399 self.vapi.nat44_interface_add_del_output_feature(
5401 sw_if_index=self.pg1.sw_if_index)
5403 # from client to service
5404 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5405 IP(src=self.pg1.remote_ip4, dst=external_addr) /
5406 TCP(sport=12345, dport=external_port))
5407 self.pg1.add_stream(p)
5408 self.pg_enable_capture(self.pg_interfaces)
5410 capture = self.pg0.get_capture(1)
5415 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5416 self.assertEqual(tcp.dport, local_port)
5417 self.assert_packet_checksums_valid(p)
5419 self.logger.error(ppp("Unexpected or invalid packet:", p))
5422 # from service back to client
5423 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5424 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5425 TCP(sport=local_port, dport=12345))
5426 self.pg0.add_stream(p)
5427 self.pg_enable_capture(self.pg_interfaces)
5429 capture = self.pg1.get_capture(1)
5434 self.assertEqual(ip.src, external_addr)
5435 self.assertEqual(tcp.sport, external_port)
5436 self.assert_packet_checksums_valid(p)
5438 self.logger.error(ppp("Unexpected or invalid packet:", p))
5441 # from local network host to external network
5442 pkts = self.create_stream_in(self.pg0, self.pg1)
5443 self.pg0.add_stream(pkts)
5444 self.pg_enable_capture(self.pg_interfaces)
5446 capture = self.pg1.get_capture(len(pkts))
5447 self.verify_capture_out(capture)
5448 pkts = self.create_stream_in(self.pg0, self.pg1)
5449 self.pg0.add_stream(pkts)
5450 self.pg_enable_capture(self.pg_interfaces)
5452 capture = self.pg1.get_capture(len(pkts))
5453 self.verify_capture_out(capture)
5455 # from external network back to local network host
5456 pkts = self.create_stream_out(self.pg1)
5457 self.pg1.add_stream(pkts)
5458 self.pg_enable_capture(self.pg_interfaces)
5460 capture = self.pg0.get_capture(len(pkts))
5461 self.verify_capture_in(capture, self.pg0)
5463 def test_output_feature_and_service2(self):
5464 """ NAT44 interface output feature and service host direct access """
5465 self.vapi.nat44_forwarding_enable_disable(enable=1)
5466 self.nat44_add_address(self.nat_addr)
5467 self.vapi.nat44_interface_add_del_output_feature(
5469 sw_if_index=self.pg1.sw_if_index)
5471 # session initiated from service host - translate
5472 pkts = self.create_stream_in(self.pg0, self.pg1)
5473 self.pg0.add_stream(pkts)
5474 self.pg_enable_capture(self.pg_interfaces)
5476 capture = self.pg1.get_capture(len(pkts))
5477 self.verify_capture_out(capture)
5479 pkts = self.create_stream_out(self.pg1)
5480 self.pg1.add_stream(pkts)
5481 self.pg_enable_capture(self.pg_interfaces)
5483 capture = self.pg0.get_capture(len(pkts))
5484 self.verify_capture_in(capture, self.pg0)
5486 # session initiated from remote host - do not translate
5487 self.tcp_port_in = 60303
5488 self.udp_port_in = 60304
5489 self.icmp_id_in = 60305
5490 pkts = self.create_stream_out(self.pg1,
5491 self.pg0.remote_ip4,
5492 use_inside_ports=True)
5493 self.pg1.add_stream(pkts)
5494 self.pg_enable_capture(self.pg_interfaces)
5496 capture = self.pg0.get_capture(len(pkts))
5497 self.verify_capture_in(capture, self.pg0)
5499 pkts = self.create_stream_in(self.pg0, self.pg1)
5500 self.pg0.add_stream(pkts)
5501 self.pg_enable_capture(self.pg_interfaces)
5503 capture = self.pg1.get_capture(len(pkts))
5504 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5507 def test_output_feature_and_service3(self):
5508 """ NAT44 interface output feature and DST NAT """
5509 external_addr = '1.2.3.4'
5513 self.vapi.nat44_forwarding_enable_disable(enable=1)
5514 self.nat44_add_address(self.nat_addr)
5515 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5516 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5517 local_port, external_port,
5518 proto=IP_PROTOS.tcp, flags=flags)
5519 flags = self.config_flags.NAT_IS_INSIDE
5520 self.vapi.nat44_interface_add_del_feature(
5521 sw_if_index=self.pg0.sw_if_index,
5523 self.vapi.nat44_interface_add_del_feature(
5524 sw_if_index=self.pg0.sw_if_index,
5525 flags=flags, is_add=1)
5526 self.vapi.nat44_interface_add_del_output_feature(
5528 sw_if_index=self.pg1.sw_if_index)
5530 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5531 IP(src=self.pg0.remote_ip4, dst=external_addr) /
5532 TCP(sport=12345, dport=external_port))
5533 self.pg0.add_stream(p)
5534 self.pg_enable_capture(self.pg_interfaces)
5536 capture = self.pg1.get_capture(1)
5541 self.assertEqual(ip.src, self.pg0.remote_ip4)
5542 self.assertEqual(tcp.sport, 12345)
5543 self.assertEqual(ip.dst, self.pg1.remote_ip4)
5544 self.assertEqual(tcp.dport, local_port)
5545 self.assert_packet_checksums_valid(p)
5547 self.logger.error(ppp("Unexpected or invalid packet:", p))
5550 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5551 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5552 TCP(sport=local_port, dport=12345))
5553 self.pg1.add_stream(p)
5554 self.pg_enable_capture(self.pg_interfaces)
5556 capture = self.pg0.get_capture(1)
5561 self.assertEqual(ip.src, external_addr)
5562 self.assertEqual(tcp.sport, external_port)
5563 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5564 self.assertEqual(tcp.dport, 12345)
5565 self.assert_packet_checksums_valid(p)
5567 self.logger.error(ppp("Unexpected or invalid packet:", p))
5570 def test_next_src_nat(self):
5571 """ On way back forward packet to nat44-in2out node. """
5572 twice_nat_addr = '10.0.1.3'
5575 post_twice_nat_port = 0
5577 self.vapi.nat44_forwarding_enable_disable(enable=1)
5578 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5579 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5580 self.config_flags.NAT_IS_SELF_TWICE_NAT)
5581 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5582 local_port, external_port,
5583 proto=IP_PROTOS.tcp, vrf_id=1,
5585 self.vapi.nat44_interface_add_del_feature(
5586 sw_if_index=self.pg6.sw_if_index,
5589 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5590 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5591 TCP(sport=12345, dport=external_port))
5592 self.pg6.add_stream(p)
5593 self.pg_enable_capture(self.pg_interfaces)
5595 capture = self.pg6.get_capture(1)
5600 self.assertEqual(ip.src, twice_nat_addr)
5601 self.assertNotEqual(tcp.sport, 12345)
5602 post_twice_nat_port = tcp.sport
5603 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5604 self.assertEqual(tcp.dport, local_port)
5605 self.assert_packet_checksums_valid(p)
5607 self.logger.error(ppp("Unexpected or invalid packet:", p))
5610 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5611 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5612 TCP(sport=local_port, dport=post_twice_nat_port))
5613 self.pg6.add_stream(p)
5614 self.pg_enable_capture(self.pg_interfaces)
5616 capture = self.pg6.get_capture(1)
5621 self.assertEqual(ip.src, self.pg1.remote_ip4)
5622 self.assertEqual(tcp.sport, external_port)
5623 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5624 self.assertEqual(tcp.dport, 12345)
5625 self.assert_packet_checksums_valid(p)
5627 self.logger.error(ppp("Unexpected or invalid packet:", p))
5630 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5632 twice_nat_addr = '10.0.1.3'
5640 port_in1 = port_in + 1
5641 port_in2 = port_in + 2
5646 server1 = self.pg0.remote_hosts[0]
5647 server2 = self.pg0.remote_hosts[1]
5659 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5662 self.nat44_add_address(self.nat_addr)
5663 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5667 flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
5669 flags |= self.config_flags.NAT_IS_TWICE_NAT
5672 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5674 proto=IP_PROTOS.tcp,
5677 locals = [{'addr': server1.ip4,
5681 {'addr': server2.ip4,
5685 out_addr = self.nat_addr
5687 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
5688 external_addr=out_addr,
5689 external_port=port_out,
5690 protocol=IP_PROTOS.tcp,
5691 local_num=len(locals),
5693 flags = self.config_flags.NAT_IS_INSIDE
5694 self.vapi.nat44_interface_add_del_feature(
5695 sw_if_index=pg0.sw_if_index,
5696 flags=flags, is_add=1)
5697 self.vapi.nat44_interface_add_del_feature(
5698 sw_if_index=pg1.sw_if_index,
5705 assert client_id is not None
5707 client = self.pg0.remote_hosts[0]
5708 elif client_id == 2:
5709 client = self.pg0.remote_hosts[1]
5711 client = pg1.remote_hosts[0]
5712 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5713 IP(src=client.ip4, dst=self.nat_addr) /
5714 TCP(sport=eh_port_out, dport=port_out))
5716 self.pg_enable_capture(self.pg_interfaces)
5718 capture = pg0.get_capture(1)
5724 if ip.dst == server1.ip4:
5730 self.assertEqual(ip.dst, server.ip4)
5732 self.assertIn(tcp.dport, [port_in1, port_in2])
5734 self.assertEqual(tcp.dport, port_in)
5736 self.assertEqual(ip.src, twice_nat_addr)
5737 self.assertNotEqual(tcp.sport, eh_port_out)
5739 self.assertEqual(ip.src, client.ip4)
5740 self.assertEqual(tcp.sport, eh_port_out)
5742 eh_port_in = tcp.sport
5743 saved_port_in = tcp.dport
5744 self.assert_packet_checksums_valid(p)
5746 self.logger.error(ppp("Unexpected or invalid packet:", p))
5749 p = (Ether(src=server.mac, dst=pg0.local_mac) /
5750 IP(src=server.ip4, dst=eh_addr_in) /
5751 TCP(sport=saved_port_in, dport=eh_port_in))
5753 self.pg_enable_capture(self.pg_interfaces)
5755 capture = pg1.get_capture(1)
5760 self.assertEqual(ip.dst, client.ip4)
5761 self.assertEqual(ip.src, self.nat_addr)
5762 self.assertEqual(tcp.dport, eh_port_out)
5763 self.assertEqual(tcp.sport, port_out)
5764 self.assert_packet_checksums_valid(p)
5766 self.logger.error(ppp("Unexpected or invalid packet:", p))
5770 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5771 self.assertEqual(len(sessions), 1)
5772 self.assertTrue(sessions[0].flags &
5773 self.config_flags.NAT_IS_EXT_HOST_VALID)
5774 self.assertTrue(sessions[0].flags &
5775 self.config_flags.NAT_IS_TWICE_NAT)
5776 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
5777 self.vapi.nat44_del_session(
5778 address=sessions[0].inside_ip_address,
5779 port=sessions[0].inside_port,
5780 protocol=sessions[0].protocol,
5781 flags=(self.config_flags.NAT_IS_INSIDE |
5782 self.config_flags.NAT_IS_EXT_HOST_VALID),
5783 ext_host_address=sessions[0].ext_host_nat_address,
5784 ext_host_port=sessions[0].ext_host_nat_port)
5785 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
5786 self.assertEqual(len(sessions), 0)
5788 def test_twice_nat(self):
5790 self.twice_nat_common()
5792 def test_self_twice_nat_positive(self):
5793 """ Self Twice NAT44 (positive test) """
5794 self.twice_nat_common(self_twice_nat=True, same_pg=True)
5796 def test_self_twice_nat_negative(self):
5797 """ Self Twice NAT44 (negative test) """
5798 self.twice_nat_common(self_twice_nat=True)
5800 def test_twice_nat_lb(self):
5801 """ Twice NAT44 local service load balancing """
5802 self.twice_nat_common(lb=True)
5804 def test_self_twice_nat_lb_positive(self):
5805 """ Self Twice NAT44 local service load balancing (positive test) """
5806 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5809 def test_self_twice_nat_lb_negative(self):
5810 """ Self Twice NAT44 local service load balancing (negative test) """
5811 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5814 def test_twice_nat_interface_addr(self):
5815 """ Acquire twice NAT44 addresses from interface """
5816 flags = self.config_flags.NAT_IS_TWICE_NAT
5817 self.vapi.nat44_add_del_interface_addr(
5819 sw_if_index=self.pg3.sw_if_index,
5822 # no address in NAT pool
5823 adresses = self.vapi.nat44_address_dump()
5824 self.assertEqual(0, len(adresses))
5826 # configure interface address and check NAT address pool
5827 self.pg3.config_ip4()
5828 adresses = self.vapi.nat44_address_dump()
5829 self.assertEqual(1, len(adresses))
5830 self.assertEqual(str(adresses[0].ip_address),
5832 self.assertEqual(adresses[0].flags, flags)
5834 # remove interface address and check NAT address pool
5835 self.pg3.unconfig_ip4()
5836 adresses = self.vapi.nat44_address_dump()
5837 self.assertEqual(0, len(adresses))
5839 def test_tcp_close(self):
5840 """ Close TCP session from inside network - output feature """
5841 self.vapi.nat44_forwarding_enable_disable(enable=1)
5842 self.nat44_add_address(self.pg1.local_ip4)
5843 twice_nat_addr = '10.0.1.3'
5844 service_ip = '192.168.16.150'
5845 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5846 flags = self.config_flags.NAT_IS_INSIDE
5847 self.vapi.nat44_interface_add_del_feature(
5848 sw_if_index=self.pg0.sw_if_index,
5850 self.vapi.nat44_interface_add_del_feature(
5851 sw_if_index=self.pg0.sw_if_index,
5852 flags=flags, is_add=1)
5853 self.vapi.nat44_interface_add_del_output_feature(
5855 sw_if_index=self.pg1.sw_if_index)
5856 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5857 self.config_flags.NAT_IS_TWICE_NAT)
5858 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5862 proto=IP_PROTOS.tcp,
5864 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5865 start_sessnum = len(sessions)
5867 # SYN packet out->in
5868 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5869 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5870 TCP(sport=33898, dport=80, flags="S"))
5871 self.pg1.add_stream(p)
5872 self.pg_enable_capture(self.pg_interfaces)
5874 capture = self.pg0.get_capture(1)
5876 tcp_port = p[TCP].sport
5878 # SYN + ACK packet in->out
5879 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5880 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5881 TCP(sport=80, dport=tcp_port, flags="SA"))
5882 self.pg0.add_stream(p)
5883 self.pg_enable_capture(self.pg_interfaces)
5885 self.pg1.get_capture(1)
5887 # ACK packet out->in
5888 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5889 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5890 TCP(sport=33898, dport=80, flags="A"))
5891 self.pg1.add_stream(p)
5892 self.pg_enable_capture(self.pg_interfaces)
5894 self.pg0.get_capture(1)
5896 # FIN packet in -> out
5897 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5898 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5899 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5900 self.pg0.add_stream(p)
5901 self.pg_enable_capture(self.pg_interfaces)
5903 self.pg1.get_capture(1)
5905 # FIN+ACK packet out -> in
5906 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5907 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5908 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5909 self.pg1.add_stream(p)
5910 self.pg_enable_capture(self.pg_interfaces)
5912 self.pg0.get_capture(1)
5914 # ACK packet in -> out
5915 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5916 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5917 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5918 self.pg0.add_stream(p)
5919 self.pg_enable_capture(self.pg_interfaces)
5921 self.pg1.get_capture(1)
5923 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4,
5925 self.assertEqual(len(sessions) - start_sessnum, 0)
5927 def test_tcp_session_close_in(self):
5928 """ Close TCP session from inside network """
5929 self.tcp_port_out = 10505
5930 self.nat44_add_address(self.nat_addr)
5931 flags = self.config_flags.NAT_IS_TWICE_NAT
5932 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5936 proto=IP_PROTOS.tcp,
5938 flags = self.config_flags.NAT_IS_INSIDE
5939 self.vapi.nat44_interface_add_del_feature(
5940 sw_if_index=self.pg0.sw_if_index,
5941 flags=flags, is_add=1)
5942 self.vapi.nat44_interface_add_del_feature(
5943 sw_if_index=self.pg1.sw_if_index,
5946 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5947 start_sessnum = len(sessions)
5949 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
5950 tcp_transitory=2, icmp=5)
5952 self.initiate_tcp_session(self.pg0, self.pg1)
5954 # FIN packet in -> out
5955 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5956 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5957 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5958 flags="FA", seq=100, ack=300))
5959 self.pg0.add_stream(p)
5960 self.pg_enable_capture(self.pg_interfaces)
5962 self.pg1.get_capture(1)
5966 # ACK packet out -> in
5967 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5968 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5969 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5970 flags="A", seq=300, ack=101))
5973 # FIN packet out -> in
5974 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5975 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5976 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5977 flags="FA", seq=300, ack=101))
5980 self.pg1.add_stream(pkts)
5981 self.pg_enable_capture(self.pg_interfaces)
5983 self.pg0.get_capture(2)
5985 # ACK packet in -> out
5986 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5987 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5988 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5989 flags="A", seq=101, ack=301))
5990 self.pg0.add_stream(p)
5991 self.pg_enable_capture(self.pg_interfaces)
5993 self.pg1.get_capture(1)
5995 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
5996 self.assertEqual(len(sessions) - start_sessnum, 1)
5998 stats = self.statistics.get_counter(
5999 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6000 out2in_drops = stats[0]
6001 stats = self.statistics.get_counter(
6002 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6003 in2out_drops = stats[0]
6005 # extra FIN packet out -> in - this should be dropped
6006 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6007 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6008 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6009 flags="FA", seq=300, ack=101))
6011 self.pg1.add_stream(p)
6012 self.pg_enable_capture(self.pg_interfaces)
6014 self.pg0.assert_nothing_captured()
6016 # extra ACK packet in -> out - this should be dropped
6017 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6018 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6019 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6020 flags="A", seq=101, ack=301))
6021 self.pg0.add_stream(p)
6022 self.pg_enable_capture(self.pg_interfaces)
6024 self.pg1.assert_nothing_captured()
6026 stats = self.statistics.get_counter(
6027 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6028 self.assertEqual(stats[0] - out2in_drops, 1)
6029 stats = self.statistics.get_counter(
6030 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6031 self.assertEqual(stats[0] - in2out_drops, 1)
6034 # extra ACK packet in -> out - this will cause session to be wiped
6035 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6036 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6037 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6038 flags="A", seq=101, ack=301))
6039 self.pg0.add_stream(p)
6040 self.pg_enable_capture(self.pg_interfaces)
6042 self.pg1.assert_nothing_captured()
6043 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6044 self.assertEqual(len(sessions) - start_sessnum, 0)
6046 def test_tcp_session_close_out(self):
6047 """ Close TCP session from outside network """
6048 self.tcp_port_out = 10505
6049 self.nat44_add_address(self.nat_addr)
6050 flags = self.config_flags.NAT_IS_TWICE_NAT
6051 self.nat44_add_static_mapping(self.pg0.remote_ip4,
6055 proto=IP_PROTOS.tcp,
6057 flags = self.config_flags.NAT_IS_INSIDE
6058 self.vapi.nat44_interface_add_del_feature(
6059 sw_if_index=self.pg0.sw_if_index,
6060 flags=flags, is_add=1)
6061 self.vapi.nat44_interface_add_del_feature(
6062 sw_if_index=self.pg1.sw_if_index,
6065 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6066 start_sessnum = len(sessions)
6068 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6069 tcp_transitory=2, icmp=5)
6071 self.initiate_tcp_session(self.pg0, self.pg1)
6073 # FIN packet out -> in
6074 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6075 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6076 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6077 flags="FA", seq=100, ack=300))
6078 self.pg1.add_stream(p)
6079 self.pg_enable_capture(self.pg_interfaces)
6081 self.pg0.get_capture(1)
6083 # FIN+ACK packet in -> out
6084 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6085 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6086 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6087 flags="FA", seq=300, ack=101))
6089 self.pg0.add_stream(p)
6090 self.pg_enable_capture(self.pg_interfaces)
6092 self.pg1.get_capture(1)
6094 # ACK packet out -> in
6095 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6096 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6097 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6098 flags="A", seq=101, ack=301))
6099 self.pg1.add_stream(p)
6100 self.pg_enable_capture(self.pg_interfaces)
6102 self.pg0.get_capture(1)
6104 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6105 self.assertEqual(len(sessions) - start_sessnum, 1)
6107 stats = self.statistics.get_counter(
6108 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6109 out2in_drops = stats[0]
6110 stats = self.statistics.get_counter(
6111 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6112 in2out_drops = stats[0]
6114 # extra FIN packet out -> in - this should be dropped
6115 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6116 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6117 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6118 flags="FA", seq=300, ack=101))
6120 self.pg1.add_stream(p)
6121 self.pg_enable_capture(self.pg_interfaces)
6123 self.pg0.assert_nothing_captured()
6125 # extra ACK packet in -> out - this should be dropped
6126 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6127 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6128 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6129 flags="A", seq=101, ack=301))
6130 self.pg0.add_stream(p)
6131 self.pg_enable_capture(self.pg_interfaces)
6133 self.pg1.assert_nothing_captured()
6135 stats = self.statistics.get_counter(
6136 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6137 self.assertEqual(stats[0] - out2in_drops, 1)
6138 stats = self.statistics.get_counter(
6139 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6140 self.assertEqual(stats[0] - in2out_drops, 1)
6143 # extra ACK packet in -> out - this will cause session to be wiped
6144 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6145 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6146 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6147 flags="A", seq=101, ack=301))
6148 self.pg0.add_stream(p)
6149 self.pg_enable_capture(self.pg_interfaces)
6151 self.pg1.assert_nothing_captured()
6152 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6153 self.assertEqual(len(sessions) - start_sessnum, 0)
6155 def test_tcp_session_close_simultaneous(self):
6156 """ Close TCP session from inside network """
6157 self.tcp_port_out = 10505
6158 self.nat44_add_address(self.nat_addr)
6159 flags = self.config_flags.NAT_IS_TWICE_NAT
6160 self.nat44_add_static_mapping(self.pg0.remote_ip4,
6164 proto=IP_PROTOS.tcp,
6166 flags = self.config_flags.NAT_IS_INSIDE
6167 self.vapi.nat44_interface_add_del_feature(
6168 sw_if_index=self.pg0.sw_if_index,
6169 flags=flags, is_add=1)
6170 self.vapi.nat44_interface_add_del_feature(
6171 sw_if_index=self.pg1.sw_if_index,
6174 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6175 start_sessnum = len(sessions)
6177 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6178 tcp_transitory=2, icmp=5)
6180 self.initiate_tcp_session(self.pg0, self.pg1)
6182 # FIN packet in -> out
6183 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6184 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6185 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6186 flags="FA", seq=100, ack=300))
6187 self.pg0.add_stream(p)
6188 self.pg_enable_capture(self.pg_interfaces)
6190 self.pg1.get_capture(1)
6192 # FIN packet out -> in
6193 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6194 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6195 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6196 flags="FA", seq=300, ack=100))
6197 self.pg1.add_stream(p)
6198 self.pg_enable_capture(self.pg_interfaces)
6200 self.pg0.get_capture(1)
6202 # ACK packet in -> out
6203 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6204 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6205 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6206 flags="A", seq=101, ack=301))
6207 self.pg0.add_stream(p)
6208 self.pg_enable_capture(self.pg_interfaces)
6210 self.pg1.get_capture(1)
6212 # ACK packet out -> in
6213 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6214 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6215 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6216 flags="A", seq=301, ack=101))
6217 self.pg1.add_stream(p)
6218 self.pg_enable_capture(self.pg_interfaces)
6220 self.pg0.get_capture(1)
6222 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6223 self.assertEqual(len(sessions) - start_sessnum, 1)
6225 stats = self.statistics.get_counter(
6226 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6227 out2in_drops = stats[0]
6228 stats = self.statistics.get_counter(
6229 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6230 in2out_drops = stats[0]
6232 # extra FIN packet out -> in - this should be dropped
6233 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6234 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6235 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6236 flags="FA", seq=300, ack=101))
6238 self.pg1.add_stream(p)
6239 self.pg_enable_capture(self.pg_interfaces)
6241 self.pg0.assert_nothing_captured()
6243 # extra ACK packet in -> out - this should be dropped
6244 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6245 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6246 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6247 flags="A", seq=101, ack=301))
6248 self.pg0.add_stream(p)
6249 self.pg_enable_capture(self.pg_interfaces)
6251 self.pg1.assert_nothing_captured()
6253 stats = self.statistics.get_counter(
6254 '/err/nat44-ed-out2in/drops due to TCP in transitory timeout')
6255 self.assertEqual(stats[0] - out2in_drops, 1)
6256 stats = self.statistics.get_counter(
6257 '/err/nat44-ed-in2out/drops due to TCP in transitory timeout')
6258 self.assertEqual(stats[0] - in2out_drops, 1)
6261 # extra ACK packet in -> out - this will cause session to be wiped
6262 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6263 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6264 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6265 flags="A", seq=101, ack=301))
6266 self.pg0.add_stream(p)
6267 self.pg_enable_capture(self.pg_interfaces)
6269 self.pg1.assert_nothing_captured()
6270 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
6271 self.assertEqual(len(sessions) - start_sessnum, 0)
6273 def test_one_armed_nat44_static(self):
6274 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
6275 remote_host = self.pg4.remote_hosts[0]
6276 local_host = self.pg4.remote_hosts[1]
6281 self.vapi.nat44_forwarding_enable_disable(enable=1)
6282 self.nat44_add_address(self.nat_addr, twice_nat=1)
6283 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
6284 self.config_flags.NAT_IS_TWICE_NAT)
6285 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
6286 local_port, external_port,
6287 proto=IP_PROTOS.tcp, flags=flags)
6288 flags = self.config_flags.NAT_IS_INSIDE
6289 self.vapi.nat44_interface_add_del_feature(
6290 sw_if_index=self.pg4.sw_if_index,
6292 self.vapi.nat44_interface_add_del_feature(
6293 sw_if_index=self.pg4.sw_if_index,
6294 flags=flags, is_add=1)
6296 # from client to service
6297 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6298 IP(src=remote_host.ip4, dst=self.nat_addr) /
6299 TCP(sport=12345, dport=external_port))
6300 self.pg4.add_stream(p)
6301 self.pg_enable_capture(self.pg_interfaces)
6303 capture = self.pg4.get_capture(1)
6308 self.assertEqual(ip.dst, local_host.ip4)
6309 self.assertEqual(ip.src, self.nat_addr)
6310 self.assertEqual(tcp.dport, local_port)
6311 self.assertNotEqual(tcp.sport, 12345)
6312 eh_port_in = tcp.sport
6313 self.assert_packet_checksums_valid(p)
6315 self.logger.error(ppp("Unexpected or invalid packet:", p))
6318 # from service back to client
6319 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
6320 IP(src=local_host.ip4, dst=self.nat_addr) /
6321 TCP(sport=local_port, dport=eh_port_in))
6322 self.pg4.add_stream(p)
6323 self.pg_enable_capture(self.pg_interfaces)
6325 capture = self.pg4.get_capture(1)
6330 self.assertEqual(ip.src, self.nat_addr)
6331 self.assertEqual(ip.dst, remote_host.ip4)
6332 self.assertEqual(tcp.sport, external_port)
6333 self.assertEqual(tcp.dport, 12345)
6334 self.assert_packet_checksums_valid(p)
6336 self.logger.error(ppp("Unexpected or invalid packet:", p))
6339 def test_static_with_port_out2(self):
6340 """ 1:1 NAPT asymmetrical rule """
6345 self.vapi.nat44_forwarding_enable_disable(enable=1)
6346 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6347 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
6348 local_port, external_port,
6349 proto=IP_PROTOS.tcp, flags=flags)
6350 flags = self.config_flags.NAT_IS_INSIDE
6351 self.vapi.nat44_interface_add_del_feature(
6352 sw_if_index=self.pg0.sw_if_index,
6353 flags=flags, is_add=1)
6354 self.vapi.nat44_interface_add_del_feature(
6355 sw_if_index=self.pg1.sw_if_index,
6358 # from client to service
6359 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6360 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6361 TCP(sport=12345, dport=external_port))
6362 self.pg1.add_stream(p)
6363 self.pg_enable_capture(self.pg_interfaces)
6365 capture = self.pg0.get_capture(1)
6370 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6371 self.assertEqual(tcp.dport, local_port)
6372 self.assert_packet_checksums_valid(p)
6374 self.logger.error(ppp("Unexpected or invalid packet:", p))
6378 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6379 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6380 ICMP(type=11) / capture[0][IP])
6381 self.pg0.add_stream(p)
6382 self.pg_enable_capture(self.pg_interfaces)
6384 capture = self.pg1.get_capture(1)
6387 self.assertEqual(p[IP].src, self.nat_addr)
6389 self.assertEqual(inner.dst, self.nat_addr)
6390 self.assertEqual(inner[TCPerror].dport, external_port)
6392 self.logger.error(ppp("Unexpected or invalid packet:", p))
6395 # from service back to client
6396 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6397 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6398 TCP(sport=local_port, dport=12345))
6399 self.pg0.add_stream(p)
6400 self.pg_enable_capture(self.pg_interfaces)
6402 capture = self.pg1.get_capture(1)
6407 self.assertEqual(ip.src, self.nat_addr)
6408 self.assertEqual(tcp.sport, external_port)
6409 self.assert_packet_checksums_valid(p)
6411 self.logger.error(ppp("Unexpected or invalid packet:", p))
6415 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
6416 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6417 ICMP(type=11) / capture[0][IP])
6418 self.pg1.add_stream(p)
6419 self.pg_enable_capture(self.pg_interfaces)
6421 capture = self.pg0.get_capture(1)
6424 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
6426 self.assertEqual(inner.src, self.pg0.remote_ip4)
6427 self.assertEqual(inner[TCPerror].sport, local_port)
6429 self.logger.error(ppp("Unexpected or invalid packet:", p))
6432 # from client to server (no translation)
6433 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6434 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
6435 TCP(sport=12346, dport=local_port))
6436 self.pg1.add_stream(p)
6437 self.pg_enable_capture(self.pg_interfaces)
6439 capture = self.pg0.get_capture(1)
6444 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6445 self.assertEqual(tcp.dport, local_port)
6446 self.assert_packet_checksums_valid(p)
6448 self.logger.error(ppp("Unexpected or invalid packet:", p))
6451 # from service back to client (no translation)
6452 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6453 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6454 TCP(sport=local_port, dport=12346))
6455 self.pg0.add_stream(p)
6456 self.pg_enable_capture(self.pg_interfaces)
6458 capture = self.pg1.get_capture(1)
6463 self.assertEqual(ip.src, self.pg0.remote_ip4)
6464 self.assertEqual(tcp.sport, local_port)
6465 self.assert_packet_checksums_valid(p)
6467 self.logger.error(ppp("Unexpected or invalid packet:", p))
6470 def test_output_feature(self):
6471 """ NAT44 interface output feature (in2out postrouting) """
6472 self.vapi.nat44_forwarding_enable_disable(enable=1)
6473 self.nat44_add_address(self.nat_addr)
6474 self.vapi.nat44_interface_add_del_feature(
6475 sw_if_index=self.pg0.sw_if_index,
6477 self.vapi.nat44_interface_add_del_output_feature(
6479 sw_if_index=self.pg1.sw_if_index)
6482 pkts = self.create_stream_in(self.pg0, self.pg1)
6483 self.pg0.add_stream(pkts)
6484 self.pg_enable_capture(self.pg_interfaces)
6486 capture = self.pg1.get_capture(len(pkts))
6487 self.verify_capture_out(capture)
6490 pkts = self.create_stream_out(self.pg1)
6491 self.pg1.add_stream(pkts)
6492 self.pg_enable_capture(self.pg_interfaces)
6494 capture = self.pg0.get_capture(len(pkts))
6495 self.verify_capture_in(capture, self.pg0)
6497 def test_output_feature_stateful_acl(self):
6498 """ NAT44 endpoint-dependent output feature works with stateful ACL """
6499 self.nat44_add_address(self.nat_addr)
6500 self.vapi.nat44_interface_add_del_output_feature(
6501 sw_if_index=self.pg0.sw_if_index,
6502 flags=self.config_flags.NAT_IS_INSIDE,
6504 self.vapi.nat44_interface_add_del_output_feature(
6505 sw_if_index=self.pg1.sw_if_index,
6506 flags=self.config_flags.NAT_IS_OUTSIDE,
6509 # First ensure that the NAT is working sans ACL
6511 # send packets out2in, no sessions yet so packets should drop
6512 pkts_out2in = self.create_stream_out(self.pg1)
6513 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
6515 # send packets into inside intf, ensure received via outside intf
6516 pkts_in2out = self.create_stream_in(self.pg0, self.pg1)
6517 capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
6519 self.verify_capture_out(capture)
6521 # send out2in again, with sessions created it should work now
6522 pkts_out2in = self.create_stream_out(self.pg1)
6523 capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
6525 self.verify_capture_in(capture, self.pg0)
6527 # Create an ACL blocking everything
6528 out2in_deny_rule = {
6531 'src_ip_addr': inet_pton(AF_INET, "0.0.0.0"),
6532 'src_ip_prefix_len': 0,
6533 'dst_ip_addr': inet_pton(AF_INET, "0.0.0.0"),
6534 'dst_ip_prefix_len': 0,
6535 'srcport_or_icmptype_first': 0,
6536 'srcport_or_icmptype_last': 65535,
6537 'dstport_or_icmpcode_first': 0,
6538 'dstport_or_icmpcode_last': 65535,
6541 out2in_rules = [out2in_deny_rule]
6542 res = self.vapi.acl_add_replace(0xffffffff, out2in_rules)
6543 self.assertEqual(res.retval, 0, "error adding out2in ACL")
6544 out2in_acl = res.acl_index
6546 # apply as input acl on interface and confirm it blocks everything
6547 self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg1.sw_if_index,
6550 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
6552 # create an ACL to permit/reflect everything
6553 in2out_reflect_rule = {
6556 'src_ip_addr': inet_pton(AF_INET, "0.0.0.0"),
6557 'src_ip_prefix_len': 0,
6558 'dst_ip_addr': inet_pton(AF_INET, "0.0.0.0"),
6559 'dst_ip_prefix_len': 0,
6560 'srcport_or_icmptype_first': 0,
6561 'srcport_or_icmptype_last': 65535,
6562 'dstport_or_icmpcode_first': 0,
6563 'dstport_or_icmpcode_last': 65535,
6566 in2out_rules = [in2out_reflect_rule]
6567 res = self.vapi.acl_add_replace(0xffffffff, in2out_rules)
6568 self.assertEqual(res.retval, 0, "error adding in2out ACL")
6569 in2out_acl = res.acl_index
6572 self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg1.sw_if_index,
6574 acls=[out2in_acl, in2out_acl])
6575 # send in2out to generate ACL state (NAT state was created earlier)
6576 capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
6578 self.verify_capture_out(capture)
6580 # send out2in again. ACL state exists so it should work now.
6581 # TCP packets with the syn flag set also need the ack flag
6582 for p in pkts_out2in:
6583 if p.haslayer(TCP) and p[TCP].flags & 0x02:
6584 p[TCP].flags |= 0x10
6585 capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
6587 self.verify_capture_in(capture, self.pg0)
6588 self.logger.info(self.vapi.cli("show trace"))
6591 # Remove ACLs from interface
6592 self.vapi.acl_interface_set_acl_list(sw_if_index=self.pg1.sw_if_index,
6596 self.vapi.acl_del(acl_index=out2in_acl, expected_retval=0)
6597 self.vapi.acl_del(acl_index=in2out_acl, expected_retval=0)
6599 def test_multiple_vrf(self):
6600 """ Multiple VRF setup """
6601 external_addr = '1.2.3.4'
6606 self.vapi.nat44_forwarding_enable_disable(enable=1)
6607 self.nat44_add_address(self.nat_addr)
6608 flags = self.config_flags.NAT_IS_INSIDE
6609 self.vapi.nat44_interface_add_del_feature(
6610 sw_if_index=self.pg0.sw_if_index,
6612 self.vapi.nat44_interface_add_del_feature(
6613 sw_if_index=self.pg0.sw_if_index,
6614 flags=flags, is_add=1)
6615 self.vapi.nat44_interface_add_del_output_feature(
6617 sw_if_index=self.pg1.sw_if_index)
6618 self.vapi.nat44_interface_add_del_feature(
6619 sw_if_index=self.pg5.sw_if_index,
6621 self.vapi.nat44_interface_add_del_feature(
6622 sw_if_index=self.pg5.sw_if_index,
6623 flags=flags, is_add=1)
6624 self.vapi.nat44_interface_add_del_feature(
6625 sw_if_index=self.pg6.sw_if_index,
6627 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6628 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
6629 local_port, external_port, vrf_id=1,
6630 proto=IP_PROTOS.tcp, flags=flags)
6631 self.nat44_add_static_mapping(
6632 self.pg0.remote_ip4,
6633 external_sw_if_index=self.pg0.sw_if_index,
6634 local_port=local_port,
6636 external_port=external_port,
6637 proto=IP_PROTOS.tcp,
6641 # from client to service (both VRF1)
6642 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6643 IP(src=self.pg6.remote_ip4, dst=external_addr) /
6644 TCP(sport=12345, dport=external_port))
6645 self.pg6.add_stream(p)
6646 self.pg_enable_capture(self.pg_interfaces)
6648 capture = self.pg5.get_capture(1)
6653 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6654 self.assertEqual(tcp.dport, local_port)
6655 self.assert_packet_checksums_valid(p)
6657 self.logger.error(ppp("Unexpected or invalid packet:", p))
6660 # from service back to client (both VRF1)
6661 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6662 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6663 TCP(sport=local_port, dport=12345))
6664 self.pg5.add_stream(p)
6665 self.pg_enable_capture(self.pg_interfaces)
6667 capture = self.pg6.get_capture(1)
6672 self.assertEqual(ip.src, external_addr)
6673 self.assertEqual(tcp.sport, external_port)
6674 self.assert_packet_checksums_valid(p)
6676 self.logger.error(ppp("Unexpected or invalid packet:", p))
6679 # dynamic NAT from VRF1 to VRF0 (output-feature)
6680 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6681 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6682 TCP(sport=2345, dport=22))
6683 self.pg5.add_stream(p)
6684 self.pg_enable_capture(self.pg_interfaces)
6686 capture = self.pg1.get_capture(1)
6691 self.assertEqual(ip.src, self.nat_addr)
6692 self.assertNotEqual(tcp.sport, 2345)
6693 self.assert_packet_checksums_valid(p)
6696 self.logger.error(ppp("Unexpected or invalid packet:", p))
6699 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6700 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6701 TCP(sport=22, dport=port))
6702 self.pg1.add_stream(p)
6703 self.pg_enable_capture(self.pg_interfaces)
6705 capture = self.pg5.get_capture(1)
6710 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6711 self.assertEqual(tcp.dport, 2345)
6712 self.assert_packet_checksums_valid(p)
6714 self.logger.error(ppp("Unexpected or invalid packet:", p))
6717 # from client VRF1 to service VRF0
6718 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6719 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6720 TCP(sport=12346, dport=external_port))
6721 self.pg6.add_stream(p)
6722 self.pg_enable_capture(self.pg_interfaces)
6724 capture = self.pg0.get_capture(1)
6729 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6730 self.assertEqual(tcp.dport, local_port)
6731 self.assert_packet_checksums_valid(p)
6733 self.logger.error(ppp("Unexpected or invalid packet:", p))
6736 # from service VRF0 back to client VRF1
6737 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6738 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6739 TCP(sport=local_port, dport=12346))
6740 self.pg0.add_stream(p)
6741 self.pg_enable_capture(self.pg_interfaces)
6743 capture = self.pg6.get_capture(1)
6748 self.assertEqual(ip.src, self.pg0.local_ip4)
6749 self.assertEqual(tcp.sport, external_port)
6750 self.assert_packet_checksums_valid(p)
6752 self.logger.error(ppp("Unexpected or invalid packet:", p))
6755 # from client VRF0 to service VRF1
6756 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6757 IP(src=self.pg0.remote_ip4, dst=external_addr) /
6758 TCP(sport=12347, dport=external_port))
6759 self.pg0.add_stream(p)
6760 self.pg_enable_capture(self.pg_interfaces)
6762 capture = self.pg5.get_capture(1)
6767 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6768 self.assertEqual(tcp.dport, local_port)
6769 self.assert_packet_checksums_valid(p)
6771 self.logger.error(ppp("Unexpected or invalid packet:", p))
6774 # from service VRF1 back to client VRF0
6775 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6776 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6777 TCP(sport=local_port, dport=12347))
6778 self.pg5.add_stream(p)
6779 self.pg_enable_capture(self.pg_interfaces)
6781 capture = self.pg0.get_capture(1)
6786 self.assertEqual(ip.src, external_addr)
6787 self.assertEqual(tcp.sport, external_port)
6788 self.assert_packet_checksums_valid(p)
6790 self.logger.error(ppp("Unexpected or invalid packet:", p))
6793 # from client to server (both VRF1, no translation)
6794 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6795 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6796 TCP(sport=12348, dport=local_port))
6797 self.pg6.add_stream(p)
6798 self.pg_enable_capture(self.pg_interfaces)
6800 capture = self.pg5.get_capture(1)
6805 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6806 self.assertEqual(tcp.dport, local_port)
6807 self.assert_packet_checksums_valid(p)
6809 self.logger.error(ppp("Unexpected or invalid packet:", p))
6812 # from server back to client (both VRF1, no translation)
6813 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6814 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6815 TCP(sport=local_port, dport=12348))
6816 self.pg5.add_stream(p)
6817 self.pg_enable_capture(self.pg_interfaces)
6819 capture = self.pg6.get_capture(1)
6824 self.assertEqual(ip.src, self.pg5.remote_ip4)
6825 self.assertEqual(tcp.sport, local_port)
6826 self.assert_packet_checksums_valid(p)
6828 self.logger.error(ppp("Unexpected or invalid packet:", p))
6831 # from client VRF1 to server VRF0 (no translation)
6832 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6833 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6834 TCP(sport=local_port, dport=12349))
6835 self.pg0.add_stream(p)
6836 self.pg_enable_capture(self.pg_interfaces)
6838 capture = self.pg6.get_capture(1)
6843 self.assertEqual(ip.src, self.pg0.remote_ip4)
6844 self.assertEqual(tcp.sport, local_port)
6845 self.assert_packet_checksums_valid(p)
6847 self.logger.error(ppp("Unexpected or invalid packet:", p))
6850 # from server VRF0 back to client VRF1 (no translation)
6851 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6852 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6853 TCP(sport=local_port, dport=12349))
6854 self.pg0.add_stream(p)
6855 self.pg_enable_capture(self.pg_interfaces)
6857 capture = self.pg6.get_capture(1)
6862 self.assertEqual(ip.src, self.pg0.remote_ip4)
6863 self.assertEqual(tcp.sport, local_port)
6864 self.assert_packet_checksums_valid(p)
6866 self.logger.error(ppp("Unexpected or invalid packet:", p))
6869 # from client VRF0 to server VRF1 (no translation)
6870 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6871 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6872 TCP(sport=12344, dport=local_port))
6873 self.pg0.add_stream(p)
6874 self.pg_enable_capture(self.pg_interfaces)
6876 capture = self.pg5.get_capture(1)
6881 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6882 self.assertEqual(tcp.dport, local_port)
6883 self.assert_packet_checksums_valid(p)
6885 self.logger.error(ppp("Unexpected or invalid packet:", p))
6888 # from server VRF1 back to client VRF0 (no translation)
6889 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6890 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6891 TCP(sport=local_port, dport=12344))
6892 self.pg5.add_stream(p)
6893 self.pg_enable_capture(self.pg_interfaces)
6895 capture = self.pg0.get_capture(1)
6900 self.assertEqual(ip.src, self.pg5.remote_ip4)
6901 self.assertEqual(tcp.sport, local_port)
6902 self.assert_packet_checksums_valid(p)
6904 self.logger.error(ppp("Unexpected or invalid packet:", p))
6907 @unittest.skipUnless(running_extended_tests, "part of extended tests")
6908 def test_session_timeout(self):
6909 """ NAT44 session timeouts """
6910 self.nat44_add_address(self.nat_addr)
6911 flags = self.config_flags.NAT_IS_INSIDE
6912 self.vapi.nat44_interface_add_del_feature(
6913 sw_if_index=self.pg0.sw_if_index,
6914 flags=flags, is_add=1)
6915 self.vapi.nat44_interface_add_del_feature(
6916 sw_if_index=self.pg1.sw_if_index,
6918 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6919 tcp_transitory=240, icmp=5)
6923 for i in range(0, max_sessions):
6924 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6925 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6926 IP(src=src, dst=self.pg1.remote_ip4) /
6927 ICMP(id=1025, type='echo-request'))
6929 self.pg0.add_stream(pkts)
6930 self.pg_enable_capture(self.pg_interfaces)
6932 self.pg1.get_capture(max_sessions)
6937 for i in range(0, max_sessions):
6938 src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6939 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6940 IP(src=src, dst=self.pg1.remote_ip4) /
6941 ICMP(id=1026, type='echo-request'))
6943 self.pg0.add_stream(pkts)
6944 self.pg_enable_capture(self.pg_interfaces)
6946 self.pg1.get_capture(max_sessions)
6949 users = self.vapi.nat44_user_dump()
6951 nsessions = nsessions + user.nsessions
6952 self.assertLess(nsessions, 2 * max_sessions)
6954 @unittest.skipUnless(running_extended_tests, "part of extended tests")
6955 def test_session_rst_timeout(self):
6956 """ NAT44 session RST timeouts """
6957 self.nat44_add_address(self.nat_addr)
6958 flags = self.config_flags.NAT_IS_INSIDE
6959 self.vapi.nat44_interface_add_del_feature(
6960 sw_if_index=self.pg0.sw_if_index,
6961 flags=flags, is_add=1)
6962 self.vapi.nat44_interface_add_del_feature(
6963 sw_if_index=self.pg1.sw_if_index,
6965 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
6966 tcp_transitory=5, icmp=60)
6968 self.initiate_tcp_session(self.pg0, self.pg1)
6969 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6970 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6971 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6973 self.pg0.add_stream(p)
6974 self.pg_enable_capture(self.pg_interfaces)
6976 self.pg1.get_capture(1)
6980 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6981 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6982 TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6984 self.pg0.add_stream(p)
6985 self.pg_enable_capture(self.pg_interfaces)
6987 self.pg1.get_capture(1)
6990 users = self.vapi.nat44_user_dump()
6991 self.assertEqual(len(users), 1)
6992 self.assertEqual(str(users[0].ip_address),
6993 self.pg0.remote_ip4)
6994 self.assertEqual(users[0].nsessions, 1)
6996 def test_syslog_sess(self):
6997 """ Test syslog session creation and deletion """
6998 self.vapi.syslog_set_filter(
6999 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
7000 self.vapi.syslog_set_sender(self.pg2.local_ip4, self.pg2.remote_ip4)
7001 self.nat44_add_address(self.nat_addr)
7002 flags = self.config_flags.NAT_IS_INSIDE
7003 self.vapi.nat44_interface_add_del_feature(
7004 sw_if_index=self.pg0.sw_if_index,
7005 flags=flags, is_add=1)
7006 self.vapi.nat44_interface_add_del_feature(
7007 sw_if_index=self.pg1.sw_if_index,
7010 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7011 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7012 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
7013 self.pg0.add_stream(p)
7014 self.pg_enable_capture(self.pg_interfaces)
7016 capture = self.pg1.get_capture(1)
7017 self.tcp_port_out = capture[0][TCP].sport
7018 capture = self.pg2.get_capture(1)
7019 self.verify_syslog_sess(capture[0][Raw].load)
7021 self.pg_enable_capture(self.pg_interfaces)
7023 self.nat44_add_address(self.nat_addr, is_add=0)
7024 capture = self.pg2.get_capture(1)
7025 self.verify_syslog_sess(capture[0][Raw].load, False)
7028 super(TestNAT44EndpointDependent, self).tearDown()
7029 if not self.vpp_dead:
7031 self.vapi.cli("clear logging")
7033 def show_commands_at_teardown(self):
7034 self.logger.info(self.vapi.cli("show nat44 addresses"))
7035 self.logger.info(self.vapi.cli("show nat44 interfaces"))
7036 self.logger.info(self.vapi.cli("show nat44 static mappings"))
7037 self.logger.info(self.vapi.cli("show nat44 interface address"))
7038 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
7039 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
7040 self.logger.info(self.vapi.cli("show nat timeouts"))
7043 class TestNAT44Out2InDPO(MethodHolder):
7044 """ NAT44 Test Cases using out2in DPO """
7047 def setUpConstants(cls):
7048 super(TestNAT44Out2InDPO, cls).setUpConstants()
7049 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
7052 def setUpClass(cls):
7053 super(TestNAT44Out2InDPO, cls).setUpClass()
7054 cls.vapi.cli("set log class nat level debug")
7056 cls.tcp_port_in = 6303
7057 cls.tcp_port_out = 6303
7058 cls.udp_port_in = 6304
7059 cls.udp_port_out = 6304
7060 cls.icmp_id_in = 6305
7061 cls.icmp_id_out = 6305
7062 cls.nat_addr = '10.0.0.3'
7063 cls.dst_ip4 = '192.168.70.1'
7065 cls.create_pg_interfaces(range(2))
7068 cls.pg0.config_ip4()
7069 cls.pg0.resolve_arp()
7072 cls.pg1.config_ip6()
7073 cls.pg1.resolve_ndp()
7075 r1 = VppIpRoute(cls, "::", 0,
7076 [VppRoutePath(cls.pg1.remote_ip6,
7077 cls.pg1.sw_if_index)],
7082 def tearDownClass(cls):
7083 super(TestNAT44Out2InDPO, cls).tearDownClass()
7085 def configure_xlat(self):
7086 self.dst_ip6_pfx = '1:2:3::'
7087 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
7089 self.dst_ip6_pfx_len = 96
7090 self.src_ip6_pfx = '4:5:6::'
7091 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
7093 self.src_ip6_pfx_len = 96
7094 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
7095 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
7096 '\x00\x00\x00\x00', 0)
7098 @unittest.skip('Temporary disabled')
7099 def test_464xlat_ce(self):
7100 """ Test 464XLAT CE with NAT44 """
7102 nat_config = self.vapi.nat_show_config()
7103 self.assertEqual(1, nat_config.out2in_dpo)
7105 self.configure_xlat()
7107 flags = self.config_flags.NAT_IS_INSIDE
7108 self.vapi.nat44_interface_add_del_feature(
7109 sw_if_index=self.pg0.sw_if_index,
7110 flags=flags, is_add=1)
7111 self.vapi.nat44_add_del_address_range(first_ip_address=self.nat_addr_n,
7112 last_ip_address=self.nat_addr_n,
7113 vrf_id=0xFFFFFFFF, is_add=1)
7115 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7116 self.dst_ip6_pfx_len)
7117 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
7118 self.src_ip6_pfx_len)
7121 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7122 self.pg0.add_stream(pkts)
7123 self.pg_enable_capture(self.pg_interfaces)
7125 capture = self.pg1.get_capture(len(pkts))
7126 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
7129 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
7131 self.pg1.add_stream(pkts)
7132 self.pg_enable_capture(self.pg_interfaces)
7134 capture = self.pg0.get_capture(len(pkts))
7135 self.verify_capture_in(capture, self.pg0)
7137 self.vapi.nat44_interface_add_del_feature(
7138 sw_if_index=self.pg0.sw_if_index,
7140 self.vapi.nat44_add_del_address_range(
7141 first_ip_address=self.nat_addr_n,
7142 last_ip_address=self.nat_addr_n,
7145 @unittest.skip('Temporary disabled')
7146 def test_464xlat_ce_no_nat(self):
7147 """ Test 464XLAT CE without NAT44 """
7149 self.configure_xlat()
7151 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
7152 self.dst_ip6_pfx_len)
7153 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
7154 self.src_ip6_pfx_len)
7156 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
7157 self.pg0.add_stream(pkts)
7158 self.pg_enable_capture(self.pg_interfaces)
7160 capture = self.pg1.get_capture(len(pkts))
7161 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
7162 nat_ip=out_dst_ip6, same_port=True)
7164 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
7165 self.pg1.add_stream(pkts)
7166 self.pg_enable_capture(self.pg_interfaces)
7168 capture = self.pg0.get_capture(len(pkts))
7169 self.verify_capture_in(capture, self.pg0)
7172 class TestDeterministicNAT(MethodHolder):
7173 """ Deterministic NAT Test Cases """
7176 def setUpConstants(cls):
7177 super(TestDeterministicNAT, cls).setUpConstants()
7178 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
7181 def setUpClass(cls):
7182 super(TestDeterministicNAT, cls).setUpClass()
7183 cls.vapi.cli("set log class nat level debug")
7185 cls.tcp_port_in = 6303
7186 cls.tcp_external_port = 6303
7187 cls.udp_port_in = 6304
7188 cls.udp_external_port = 6304
7189 cls.icmp_id_in = 6305
7190 cls.nat_addr = '10.0.0.3'
7192 cls.create_pg_interfaces(range(3))
7193 cls.interfaces = list(cls.pg_interfaces)
7195 for i in cls.interfaces:
7200 cls.pg0.generate_remote_hosts(2)
7201 cls.pg0.configure_ipv4_neighbors()
7204 def tearDownClass(cls):
7205 super(TestDeterministicNAT, cls).tearDownClass()
7207 def create_stream_in(self, in_if, out_if, ttl=64):
7209 Create packet stream for inside network
7211 :param in_if: Inside interface
7212 :param out_if: Outside interface
7213 :param ttl: TTL of generated packets
7217 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7218 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7219 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
7223 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7224 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7225 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
7229 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
7230 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
7231 ICMP(id=self.icmp_id_in, type='echo-request'))
7236 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
7238 Create packet stream for outside network
7240 :param out_if: Outside interface
7241 :param dst_ip: Destination IP address (Default use global NAT address)
7242 :param ttl: TTL of generated packets
7245 dst_ip = self.nat_addr
7248 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7249 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7250 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
7254 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7255 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7256 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
7260 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
7261 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
7262 ICMP(id=self.icmp_external_id, type='echo-reply'))
7267 def verify_capture_out(self, capture, nat_ip=None):
7269 Verify captured packets on outside network
7271 :param capture: Captured packets
7272 :param nat_ip: Translated IP address (Default use global NAT address)
7273 :param same_port: Source port number is not translated (Default False)
7276 nat_ip = self.nat_addr
7277 for packet in capture:
7279 self.assertEqual(packet[IP].src, nat_ip)
7280 if packet.haslayer(TCP):
7281 self.tcp_port_out = packet[TCP].sport
7282 elif packet.haslayer(UDP):
7283 self.udp_port_out = packet[UDP].sport
7285 self.icmp_external_id = packet[ICMP].id
7287 self.logger.error(ppp("Unexpected or invalid packet "
7288 "(outside network):", packet))
7291 def test_deterministic_mode(self):
7292 """ NAT plugin run deterministic mode """
7293 in_addr = '172.16.255.0'
7294 out_addr = '172.17.255.50'
7295 in_addr_t = '172.16.255.20'
7299 nat_config = self.vapi.nat_show_config()
7300 self.assertEqual(1, nat_config.deterministic)
7302 self.vapi.nat_det_add_del_map(is_add=1, in_addr=in_addr,
7303 in_plen=in_plen, out_addr=out_addr,
7306 rep1 = self.vapi.nat_det_forward(in_addr_t)
7307 self.assertEqual(str(rep1.out_addr), out_addr)
7308 rep2 = self.vapi.nat_det_reverse(rep1.out_port_hi, out_addr)
7310 self.assertEqual(str(rep2.in_addr), in_addr_t)
7312 deterministic_mappings = self.vapi.nat_det_map_dump()
7313 self.assertEqual(len(deterministic_mappings), 1)
7314 dsm = deterministic_mappings[0]
7315 self.assertEqual(in_addr, str(dsm.in_addr))
7316 self.assertEqual(in_plen, dsm.in_plen)
7317 self.assertEqual(out_addr, str(dsm.out_addr))
7318 self.assertEqual(out_plen, dsm.out_plen)
7320 self.clear_nat_det()
7321 deterministic_mappings = self.vapi.nat_det_map_dump()
7322 self.assertEqual(len(deterministic_mappings), 0)
7324 def test_set_timeouts(self):
7325 """ Set deterministic NAT timeouts """
7326 timeouts_before = self.vapi.nat_get_timeouts()
7328 self.vapi.nat_set_timeouts(
7329 udp=timeouts_before.udp + 10,
7330 tcp_established=timeouts_before.tcp_established + 10,
7331 tcp_transitory=timeouts_before.tcp_transitory + 10,
7332 icmp=timeouts_before.icmp + 10)
7334 timeouts_after = self.vapi.nat_get_timeouts()
7336 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
7337 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
7338 self.assertNotEqual(timeouts_before.tcp_established,
7339 timeouts_after.tcp_established)
7340 self.assertNotEqual(timeouts_before.tcp_transitory,
7341 timeouts_after.tcp_transitory)
7343 def test_det_in(self):
7344 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
7346 nat_ip = "10.0.0.10"
7348 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7350 out_addr=socket.inet_aton(nat_ip),
7353 flags = self.config_flags.NAT_IS_INSIDE
7354 self.vapi.nat44_interface_add_del_feature(
7355 sw_if_index=self.pg0.sw_if_index,
7356 flags=flags, is_add=1)
7357 self.vapi.nat44_interface_add_del_feature(
7358 sw_if_index=self.pg1.sw_if_index,
7362 pkts = self.create_stream_in(self.pg0, self.pg1)
7363 self.pg0.add_stream(pkts)
7364 self.pg_enable_capture(self.pg_interfaces)
7366 capture = self.pg1.get_capture(len(pkts))
7367 self.verify_capture_out(capture, nat_ip)
7370 pkts = self.create_stream_out(self.pg1, nat_ip)
7371 self.pg1.add_stream(pkts)
7372 self.pg_enable_capture(self.pg_interfaces)
7374 capture = self.pg0.get_capture(len(pkts))
7375 self.verify_capture_in(capture, self.pg0)
7378 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4)
7379 self.assertEqual(len(sessions), 3)
7383 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7384 self.assertEqual(s.in_port, self.tcp_port_in)
7385 self.assertEqual(s.out_port, self.tcp_port_out)
7386 self.assertEqual(s.ext_port, self.tcp_external_port)
7390 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7391 self.assertEqual(s.in_port, self.udp_port_in)
7392 self.assertEqual(s.out_port, self.udp_port_out)
7393 self.assertEqual(s.ext_port, self.udp_external_port)
7397 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
7398 self.assertEqual(s.in_port, self.icmp_id_in)
7399 self.assertEqual(s.out_port, self.icmp_external_id)
7401 def test_multiple_users(self):
7402 """ Deterministic NAT multiple users """
7404 nat_ip = "10.0.0.10"
7406 external_port = 6303
7408 host0 = self.pg0.remote_hosts[0]
7409 host1 = self.pg0.remote_hosts[1]
7411 self.vapi.nat_det_add_del_map(is_add=1, in_addr=host0.ip4, in_plen=24,
7412 out_addr=socket.inet_aton(nat_ip),
7414 flags = self.config_flags.NAT_IS_INSIDE
7415 self.vapi.nat44_interface_add_del_feature(
7416 sw_if_index=self.pg0.sw_if_index,
7417 flags=flags, is_add=1)
7418 self.vapi.nat44_interface_add_del_feature(
7419 sw_if_index=self.pg1.sw_if_index,
7423 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
7424 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
7425 TCP(sport=port_in, dport=external_port))
7426 self.pg0.add_stream(p)
7427 self.pg_enable_capture(self.pg_interfaces)
7429 capture = self.pg1.get_capture(1)
7434 self.assertEqual(ip.src, nat_ip)
7435 self.assertEqual(ip.dst, self.pg1.remote_ip4)
7436 self.assertEqual(tcp.dport, external_port)
7437 port_out0 = tcp.sport
7439 self.logger.error(ppp("Unexpected or invalid packet:", p))
7443 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
7444 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
7445 TCP(sport=port_in, dport=external_port))
7446 self.pg0.add_stream(p)
7447 self.pg_enable_capture(self.pg_interfaces)
7449 capture = self.pg1.get_capture(1)
7454 self.assertEqual(ip.src, nat_ip)
7455 self.assertEqual(ip.dst, self.pg1.remote_ip4)
7456 self.assertEqual(tcp.dport, external_port)
7457 port_out1 = tcp.sport
7459 self.logger.error(ppp("Unexpected or invalid packet:", p))
7462 dms = self.vapi.nat_det_map_dump()
7463 self.assertEqual(1, len(dms))
7464 self.assertEqual(2, dms[0].ses_num)
7467 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7468 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
7469 TCP(sport=external_port, dport=port_out0))
7470 self.pg1.add_stream(p)
7471 self.pg_enable_capture(self.pg_interfaces)
7473 capture = self.pg0.get_capture(1)
7478 self.assertEqual(ip.src, self.pg1.remote_ip4)
7479 self.assertEqual(ip.dst, host0.ip4)
7480 self.assertEqual(tcp.dport, port_in)
7481 self.assertEqual(tcp.sport, external_port)
7483 self.logger.error(ppp("Unexpected or invalid packet:", p))
7487 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7488 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
7489 TCP(sport=external_port, dport=port_out1))
7490 self.pg1.add_stream(p)
7491 self.pg_enable_capture(self.pg_interfaces)
7493 capture = self.pg0.get_capture(1)
7498 self.assertEqual(ip.src, self.pg1.remote_ip4)
7499 self.assertEqual(ip.dst, host1.ip4)
7500 self.assertEqual(tcp.dport, port_in)
7501 self.assertEqual(tcp.sport, external_port)
7503 self.logger.error(ppp("Unexpected or invalid packet", p))
7506 # session close api test
7507 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
7509 self.pg1.remote_ip4,
7511 dms = self.vapi.nat_det_map_dump()
7512 self.assertEqual(dms[0].ses_num, 1)
7514 self.vapi.nat_det_close_session_in(host0.ip4,
7516 self.pg1.remote_ip4,
7518 dms = self.vapi.nat_det_map_dump()
7519 self.assertEqual(dms[0].ses_num, 0)
7521 def test_tcp_session_close_detection_in(self):
7522 """ Deterministic NAT TCP session close from inside network """
7523 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7525 out_addr=socket.inet_aton(self.nat_addr),
7527 flags = self.config_flags.NAT_IS_INSIDE
7528 self.vapi.nat44_interface_add_del_feature(
7529 sw_if_index=self.pg0.sw_if_index,
7530 flags=flags, is_add=1)
7531 self.vapi.nat44_interface_add_del_feature(
7532 sw_if_index=self.pg1.sw_if_index,
7535 self.initiate_tcp_session(self.pg0, self.pg1)
7537 # close the session from inside
7539 # FIN packet in -> out
7540 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7541 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7542 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7544 self.pg0.add_stream(p)
7545 self.pg_enable_capture(self.pg_interfaces)
7547 self.pg1.get_capture(1)
7551 # ACK packet out -> in
7552 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7553 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7554 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7558 # FIN packet out -> in
7559 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7560 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7561 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7565 self.pg1.add_stream(pkts)
7566 self.pg_enable_capture(self.pg_interfaces)
7568 self.pg0.get_capture(2)
7570 # ACK packet in -> out
7571 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7572 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7573 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7575 self.pg0.add_stream(p)
7576 self.pg_enable_capture(self.pg_interfaces)
7578 self.pg1.get_capture(1)
7580 # Check if deterministic NAT44 closed the session
7581 dms = self.vapi.nat_det_map_dump()
7582 self.assertEqual(0, dms[0].ses_num)
7584 self.logger.error("TCP session termination failed")
7587 def test_tcp_session_close_detection_out(self):
7588 """ Deterministic NAT TCP session close from outside network """
7589 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7591 out_addr=socket.inet_aton(self.nat_addr),
7593 flags = self.config_flags.NAT_IS_INSIDE
7594 self.vapi.nat44_interface_add_del_feature(
7595 sw_if_index=self.pg0.sw_if_index,
7596 flags=flags, is_add=1)
7597 self.vapi.nat44_interface_add_del_feature(
7598 sw_if_index=self.pg1.sw_if_index,
7601 self.initiate_tcp_session(self.pg0, self.pg1)
7603 # close the session from outside
7605 # FIN packet out -> in
7606 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7607 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7608 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7610 self.pg1.add_stream(p)
7611 self.pg_enable_capture(self.pg_interfaces)
7613 self.pg0.get_capture(1)
7617 # ACK packet in -> out
7618 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7619 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7620 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7624 # ACK packet in -> out
7625 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7626 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7627 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7631 self.pg0.add_stream(pkts)
7632 self.pg_enable_capture(self.pg_interfaces)
7634 self.pg1.get_capture(2)
7636 # ACK packet out -> in
7637 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7638 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7639 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7641 self.pg1.add_stream(p)
7642 self.pg_enable_capture(self.pg_interfaces)
7644 self.pg0.get_capture(1)
7646 # Check if deterministic NAT44 closed the session
7647 dms = self.vapi.nat_det_map_dump()
7648 self.assertEqual(0, dms[0].ses_num)
7650 self.logger.error("TCP session termination failed")
7653 @unittest.skipUnless(running_extended_tests, "part of extended tests")
7654 def test_session_timeout(self):
7655 """ Deterministic NAT session timeouts """
7656 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7658 out_addr=socket.inet_aton(self.nat_addr),
7660 flags = self.config_flags.NAT_IS_INSIDE
7661 self.vapi.nat44_interface_add_del_feature(
7662 sw_if_index=self.pg0.sw_if_index,
7663 flags=flags, is_add=1)
7664 self.vapi.nat44_interface_add_del_feature(
7665 sw_if_index=self.pg1.sw_if_index,
7668 self.initiate_tcp_session(self.pg0, self.pg1)
7669 self.vapi.nat_set_timeouts(udp=5, tcp_established=5, tcp_transitory=5,
7671 pkts = self.create_stream_in(self.pg0, self.pg1)
7672 self.pg0.add_stream(pkts)
7673 self.pg_enable_capture(self.pg_interfaces)
7675 capture = self.pg1.get_capture(len(pkts))
7678 dms = self.vapi.nat_det_map_dump()
7679 self.assertEqual(0, dms[0].ses_num)
7681 @unittest.skipUnless(running_extended_tests, "part of extended tests")
7682 def test_session_limit_per_user(self):
7683 """ Deterministic NAT maximum sessions per user limit """
7684 self.vapi.nat_det_add_del_map(is_add=1, in_addr=self.pg0.remote_ip4,
7686 out_addr=socket.inet_aton(self.nat_addr),
7688 flags = self.config_flags.NAT_IS_INSIDE
7689 self.vapi.nat44_interface_add_del_feature(
7690 sw_if_index=self.pg0.sw_if_index,
7691 flags=flags, is_add=1)
7692 self.vapi.nat44_interface_add_del_feature(
7693 sw_if_index=self.pg1.sw_if_index,
7695 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4,
7696 src_address=self.pg2.local_ip4,
7698 template_interval=10)
7699 self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7703 for port in range(1025, 2025):
7704 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7705 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7706 UDP(sport=port, dport=port))
7709 self.pg0.add_stream(pkts)
7710 self.pg_enable_capture(self.pg_interfaces)
7712 capture = self.pg1.get_capture(len(pkts))
7714 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7715 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7716 UDP(sport=3001, dport=3002))
7717 self.pg0.add_stream(p)
7718 self.pg_enable_capture(self.pg_interfaces)
7720 capture = self.pg1.assert_nothing_captured()
7722 # verify ICMP error packet
7723 capture = self.pg0.get_capture(1)
7725 self.assertTrue(p.haslayer(ICMP))
7727 self.assertEqual(icmp.type, 3)
7728 self.assertEqual(icmp.code, 1)
7729 self.assertTrue(icmp.haslayer(IPerror))
7730 inner_ip = icmp[IPerror]
7731 self.assertEqual(inner_ip[UDPerror].sport, 3001)
7732 self.assertEqual(inner_ip[UDPerror].dport, 3002)
7734 dms = self.vapi.nat_det_map_dump()
7736 self.assertEqual(1000, dms[0].ses_num)
7738 # verify IPFIX logging
7739 self.vapi.ipfix_flush()
7741 capture = self.pg2.get_capture(2)
7742 ipfix = IPFIXDecoder()
7743 # first load template
7745 self.assertTrue(p.haslayer(IPFIX))
7746 if p.haslayer(Template):
7747 ipfix.add_template(p.getlayer(Template))
7748 # verify events in data set
7750 if p.haslayer(Data):
7751 data = ipfix.decode_data_set(p.getlayer(Set))
7752 self.verify_ipfix_max_entries_per_user(data,
7754 self.pg0.remote_ip4)
7756 def clear_nat_det(self):
7758 Clear deterministic NAT configuration.
7760 self.vapi.nat_ipfix_enable_disable(domain_id=1, src_port=4739,
7762 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
7763 tcp_transitory=240, icmp=60)
7764 deterministic_mappings = self.vapi.nat_det_map_dump()
7765 for dsm in deterministic_mappings:
7766 self.vapi.nat_det_add_del_map(is_add=0, in_addr=dsm.in_addr,
7767 in_plen=dsm.in_plen,
7768 out_addr=dsm.out_addr,
7769 out_plen=dsm.out_plen)
7771 interfaces = self.vapi.nat44_interface_dump()
7772 for intf in interfaces:
7773 self.vapi.nat44_interface_add_del_feature(
7774 sw_if_index=intf.sw_if_index,
7778 super(TestDeterministicNAT, self).tearDown()
7779 if not self.vpp_dead:
7780 self.clear_nat_det()
7782 def show_commands_at_teardown(self):
7783 self.logger.info(self.vapi.cli("show nat44 interfaces"))
7784 self.logger.info(self.vapi.cli("show nat timeouts"))
7786 self.vapi.cli("show nat44 deterministic mappings"))
7788 self.vapi.cli("show nat44 deterministic sessions"))
7791 class TestNAT64(MethodHolder):
7792 """ NAT64 Test Cases """
7795 def setUpConstants(cls):
7796 super(TestNAT64, cls).setUpConstants()
7797 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
7798 "nat64 st hash buckets 256", "}"])
7801 def setUpClass(cls):
7802 super(TestNAT64, cls).setUpClass()
7804 cls.tcp_port_in = 6303
7805 cls.tcp_port_out = 6303
7806 cls.udp_port_in = 6304
7807 cls.udp_port_out = 6304
7808 cls.icmp_id_in = 6305
7809 cls.icmp_id_out = 6305
7810 cls.tcp_external_port = 80
7811 cls.nat_addr = '10.0.0.3'
7812 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
7814 cls.vrf1_nat_addr = '10.0.10.3'
7815 cls.ipfix_src_port = 4739
7816 cls.ipfix_domain_id = 1
7818 cls.create_pg_interfaces(range(6))
7819 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
7820 cls.ip6_interfaces.append(cls.pg_interfaces[2])
7821 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
7823 cls.vapi.ip_table_add_del(is_add=1,
7824 table={'table_id': cls.vrf1_id,
7827 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
7829 cls.pg0.generate_remote_hosts(2)
7831 for i in cls.ip6_interfaces:
7834 i.configure_ipv6_neighbors()
7836 for i in cls.ip4_interfaces:
7842 cls.pg3.config_ip4()
7843 cls.pg3.resolve_arp()
7844 cls.pg3.config_ip6()
7845 cls.pg3.configure_ipv6_neighbors()
7848 cls.pg5.config_ip6()
7851 def tearDownClass(cls):
7852 super(TestNAT64, cls).tearDownClass()
7854 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
7855 """ NAT64 inside interface handles Neighbor Advertisement """
7857 flags = self.config_flags.NAT_IS_INSIDE
7858 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7859 sw_if_index=self.pg5.sw_if_index)
7862 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7863 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7864 ICMPv6EchoRequest())
7866 self.pg5.add_stream(pkts)
7867 self.pg_enable_capture(self.pg_interfaces)
7870 # Wait for Neighbor Solicitation
7871 capture = self.pg5.get_capture(len(pkts))
7874 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7875 self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
7876 tgt = packet[ICMPv6ND_NS].tgt
7878 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7881 # Send Neighbor Advertisement
7882 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7883 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7884 ICMPv6ND_NA(tgt=tgt) /
7885 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
7887 self.pg5.add_stream(pkts)
7888 self.pg_enable_capture(self.pg_interfaces)
7891 # Try to send ping again
7893 self.pg5.add_stream(pkts)
7894 self.pg_enable_capture(self.pg_interfaces)
7897 # Wait for ping reply
7898 capture = self.pg5.get_capture(len(pkts))
7901 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7902 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
7903 self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
7905 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7908 def test_pool(self):
7909 """ Add/delete address to NAT64 pool """
7910 nat_addr = '1.2.3.4'
7912 self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7914 vrf_id=0xFFFFFFFF, is_add=1)
7916 addresses = self.vapi.nat64_pool_addr_dump()
7917 self.assertEqual(len(addresses), 1)
7918 self.assertEqual(str(addresses[0].address), nat_addr)
7920 self.vapi.nat64_add_del_pool_addr_range(start_addr=nat_addr,
7922 vrf_id=0xFFFFFFFF, is_add=0)
7924 addresses = self.vapi.nat64_pool_addr_dump()
7925 self.assertEqual(len(addresses), 0)
7927 def test_interface(self):
7928 """ Enable/disable NAT64 feature on the interface """
7929 flags = self.config_flags.NAT_IS_INSIDE
7930 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
7931 sw_if_index=self.pg0.sw_if_index)
7932 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
7933 sw_if_index=self.pg1.sw_if_index)
7935 interfaces = self.vapi.nat64_interface_dump()
7936 self.assertEqual(len(interfaces), 2)
7939 for intf in interfaces:
7940 if intf.sw_if_index == self.pg0.sw_if_index:
7941 self.assertEqual(intf.flags, self.config_flags.NAT_IS_INSIDE)
7943 elif intf.sw_if_index == self.pg1.sw_if_index:
7944 self.assertEqual(intf.flags, self.config_flags.NAT_IS_OUTSIDE)
7946 self.assertTrue(pg0_found)
7947 self.assertTrue(pg1_found)
7949 features = self.vapi.cli("show interface features pg0")
7950 self.assertIn('nat64-in2out', features)
7951 features = self.vapi.cli("show interface features pg1")
7952 self.assertIn('nat64-out2in', features)
7954 self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7955 sw_if_index=self.pg0.sw_if_index)
7956 self.vapi.nat64_add_del_interface(is_add=0, flags=flags,
7957 sw_if_index=self.pg1.sw_if_index)
7959 interfaces = self.vapi.nat64_interface_dump()
7960 self.assertEqual(len(interfaces), 0)
7962 def test_static_bib(self):
7963 """ Add/delete static BIB entry """
7964 in_addr = '2001:db8:85a3::8a2e:370:7334'
7965 out_addr = '10.1.1.3'
7968 proto = IP_PROTOS.tcp
7970 self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7971 i_port=in_port, o_port=out_port,
7972 proto=proto, vrf_id=0, is_add=1)
7973 bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
7976 if bibe.flags & self.config_flags.NAT_IS_STATIC:
7978 self.assertEqual(str(bibe.i_addr), in_addr)
7979 self.assertEqual(str(bibe.o_addr), out_addr)
7980 self.assertEqual(bibe.i_port, in_port)
7981 self.assertEqual(bibe.o_port, out_port)
7982 self.assertEqual(static_bib_num, 1)
7983 bibs = self.statistics.get_counter('/nat64/total-bibs')
7984 self.assertEqual(bibs[0][0], 1)
7986 self.vapi.nat64_add_del_static_bib(i_addr=in_addr, o_addr=out_addr,
7987 i_port=in_port, o_port=out_port,
7988 proto=proto, vrf_id=0, is_add=0)
7989 bib = self.vapi.nat64_bib_dump(proto=IP_PROTOS.tcp)
7992 if bibe.flags & self.config_flags.NAT_IS_STATIC:
7994 self.assertEqual(static_bib_num, 0)
7995 bibs = self.statistics.get_counter('/nat64/total-bibs')
7996 self.assertEqual(bibs[0][0], 0)
7998 def test_set_timeouts(self):
7999 """ Set NAT64 timeouts """
8000 # verify default values
8001 timeouts = self.vapi.nat_get_timeouts()
8002 self.assertEqual(timeouts.udp, 300)
8003 self.assertEqual(timeouts.icmp, 60)
8004 self.assertEqual(timeouts.tcp_transitory, 240)
8005 self.assertEqual(timeouts.tcp_established, 7440)
8007 # set and verify custom values
8008 self.vapi.nat_set_timeouts(udp=200, tcp_established=7450,
8009 tcp_transitory=250, icmp=30)
8010 timeouts = self.vapi.nat_get_timeouts()
8011 self.assertEqual(timeouts.udp, 200)
8012 self.assertEqual(timeouts.icmp, 30)
8013 self.assertEqual(timeouts.tcp_transitory, 250)
8014 self.assertEqual(timeouts.tcp_established, 7450)
8016 def test_dynamic(self):
8017 """ NAT64 dynamic translation test """
8018 self.tcp_port_in = 6303
8019 self.udp_port_in = 6304
8020 self.icmp_id_in = 6305
8022 ses_num_start = self.nat64_get_ses_num()
8024 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8025 end_addr=self.nat_addr,
8028 flags = self.config_flags.NAT_IS_INSIDE
8029 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8030 sw_if_index=self.pg0.sw_if_index)
8031 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8032 sw_if_index=self.pg1.sw_if_index)
8035 tcpn = self.statistics.get_err_counter('/err/nat64-in2out/TCP packets')
8036 udpn = self.statistics.get_err_counter('/err/nat64-in2out/UDP packets')
8037 icmpn = self.statistics.get_err_counter(
8038 '/err/nat64-in2out/ICMP packets')
8039 totaln = self.statistics.get_err_counter(
8040 '/err/nat64-in2out/good in2out packets processed')
8042 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8043 self.pg0.add_stream(pkts)
8044 self.pg_enable_capture(self.pg_interfaces)
8046 capture = self.pg1.get_capture(len(pkts))
8047 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8048 dst_ip=self.pg1.remote_ip4)
8050 err = self.statistics.get_err_counter('/err/nat64-in2out/TCP packets')
8051 self.assertEqual(err - tcpn, 1)
8052 err = self.statistics.get_err_counter('/err/nat64-in2out/UDP packets')
8053 self.assertEqual(err - udpn, 1)
8054 err = self.statistics.get_err_counter('/err/nat64-in2out/ICMP packets')
8055 self.assertEqual(err - icmpn, 1)
8056 err = self.statistics.get_err_counter(
8057 '/err/nat64-in2out/good in2out packets processed')
8058 self.assertEqual(err - totaln, 3)
8061 tcpn = self.statistics.get_err_counter('/err/nat64-out2in/TCP packets')
8062 udpn = self.statistics.get_err_counter('/err/nat64-out2in/UDP packets')
8063 icmpn = self.statistics.get_err_counter(
8064 '/err/nat64-out2in/ICMP packets')
8065 totaln = self.statistics.get_err_counter(
8066 '/err/nat64-out2in/good out2in packets processed')
8068 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8069 self.pg1.add_stream(pkts)
8070 self.pg_enable_capture(self.pg_interfaces)
8072 capture = self.pg0.get_capture(len(pkts))
8073 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8074 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8076 err = self.statistics.get_err_counter('/err/nat64-out2in/TCP packets')
8077 self.assertEqual(err - tcpn, 2)
8078 err = self.statistics.get_err_counter('/err/nat64-out2in/UDP packets')
8079 self.assertEqual(err - udpn, 1)
8080 err = self.statistics.get_err_counter('/err/nat64-out2in/ICMP packets')
8081 self.assertEqual(err - icmpn, 1)
8082 err = self.statistics.get_err_counter(
8083 '/err/nat64-out2in/good out2in packets processed')
8084 self.assertEqual(err - totaln, 4)
8086 bibs = self.statistics.get_counter('/nat64/total-bibs')
8087 self.assertEqual(bibs[0][0], 3)
8088 sessions = self.statistics.get_counter('/nat64/total-sessions')
8089 self.assertEqual(sessions[0][0], 3)
8092 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8093 self.pg0.add_stream(pkts)
8094 self.pg_enable_capture(self.pg_interfaces)
8096 capture = self.pg1.get_capture(len(pkts))
8097 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8098 dst_ip=self.pg1.remote_ip4)
8101 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8102 self.pg1.add_stream(pkts)
8103 self.pg_enable_capture(self.pg_interfaces)
8105 capture = self.pg0.get_capture(len(pkts))
8106 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8108 ses_num_end = self.nat64_get_ses_num()
8110 self.assertEqual(ses_num_end - ses_num_start, 3)
8112 # tenant with specific VRF
8113 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
8114 end_addr=self.vrf1_nat_addr,
8115 vrf_id=self.vrf1_id, is_add=1)
8116 flags = self.config_flags.NAT_IS_INSIDE
8117 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8118 sw_if_index=self.pg2.sw_if_index)
8120 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
8121 self.pg2.add_stream(pkts)
8122 self.pg_enable_capture(self.pg_interfaces)
8124 capture = self.pg1.get_capture(len(pkts))
8125 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
8126 dst_ip=self.pg1.remote_ip4)
8128 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
8129 self.pg1.add_stream(pkts)
8130 self.pg_enable_capture(self.pg_interfaces)
8132 capture = self.pg2.get_capture(len(pkts))
8133 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
8135 def test_static(self):
8136 """ NAT64 static translation test """
8137 self.tcp_port_in = 60303
8138 self.udp_port_in = 60304
8139 self.icmp_id_in = 60305
8140 self.tcp_port_out = 60303
8141 self.udp_port_out = 60304
8142 self.icmp_id_out = 60305
8144 ses_num_start = self.nat64_get_ses_num()
8146 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8147 end_addr=self.nat_addr,
8150 flags = self.config_flags.NAT_IS_INSIDE
8151 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8152 sw_if_index=self.pg0.sw_if_index)
8153 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8154 sw_if_index=self.pg1.sw_if_index)
8156 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8157 o_addr=self.nat_addr,
8158 i_port=self.tcp_port_in,
8159 o_port=self.tcp_port_out,
8160 proto=IP_PROTOS.tcp, vrf_id=0,
8162 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8163 o_addr=self.nat_addr,
8164 i_port=self.udp_port_in,
8165 o_port=self.udp_port_out,
8166 proto=IP_PROTOS.udp, vrf_id=0,
8168 self.vapi.nat64_add_del_static_bib(i_addr=self.pg0.remote_ip6n,
8169 o_addr=self.nat_addr,
8170 i_port=self.icmp_id_in,
8171 o_port=self.icmp_id_out,
8172 proto=IP_PROTOS.icmp, vrf_id=0,
8176 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8177 self.pg0.add_stream(pkts)
8178 self.pg_enable_capture(self.pg_interfaces)
8180 capture = self.pg1.get_capture(len(pkts))
8181 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8182 dst_ip=self.pg1.remote_ip4, same_port=True)
8185 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8186 self.pg1.add_stream(pkts)
8187 self.pg_enable_capture(self.pg_interfaces)
8189 capture = self.pg0.get_capture(len(pkts))
8190 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8191 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
8193 ses_num_end = self.nat64_get_ses_num()
8195 self.assertEqual(ses_num_end - ses_num_start, 3)
8197 @unittest.skipUnless(running_extended_tests, "part of extended tests")
8198 def test_session_timeout(self):
8199 """ NAT64 session timeout """
8200 self.icmp_id_in = 1234
8201 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8202 end_addr=self.nat_addr,
8205 flags = self.config_flags.NAT_IS_INSIDE
8206 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8207 sw_if_index=self.pg0.sw_if_index)
8208 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8209 sw_if_index=self.pg1.sw_if_index)
8210 self.vapi.nat_set_timeouts(udp=300, tcp_established=5,
8214 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8215 self.pg0.add_stream(pkts)
8216 self.pg_enable_capture(self.pg_interfaces)
8218 capture = self.pg1.get_capture(len(pkts))
8220 ses_num_before_timeout = self.nat64_get_ses_num()
8224 # ICMP and TCP session after timeout
8225 ses_num_after_timeout = self.nat64_get_ses_num()
8226 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
8228 def test_icmp_error(self):
8229 """ NAT64 ICMP Error message translation """
8230 self.tcp_port_in = 6303
8231 self.udp_port_in = 6304
8232 self.icmp_id_in = 6305
8234 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8235 end_addr=self.nat_addr,
8238 flags = self.config_flags.NAT_IS_INSIDE
8239 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8240 sw_if_index=self.pg0.sw_if_index)
8241 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8242 sw_if_index=self.pg1.sw_if_index)
8244 # send some packets to create sessions
8245 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
8246 self.pg0.add_stream(pkts)
8247 self.pg_enable_capture(self.pg_interfaces)
8249 capture_ip4 = self.pg1.get_capture(len(pkts))
8250 self.verify_capture_out(capture_ip4,
8251 nat_ip=self.nat_addr,
8252 dst_ip=self.pg1.remote_ip4)
8254 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8255 self.pg1.add_stream(pkts)
8256 self.pg_enable_capture(self.pg_interfaces)
8258 capture_ip6 = self.pg0.get_capture(len(pkts))
8259 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
8260 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
8261 self.pg0.remote_ip6)
8264 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8265 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
8266 ICMPv6DestUnreach(code=1) /
8267 packet[IPv6] for packet in capture_ip6]
8268 self.pg0.add_stream(pkts)
8269 self.pg_enable_capture(self.pg_interfaces)
8271 capture = self.pg1.get_capture(len(pkts))
8272 for packet in capture:
8274 self.assertEqual(packet[IP].src, self.nat_addr)
8275 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
8276 self.assertEqual(packet[ICMP].type, 3)
8277 self.assertEqual(packet[ICMP].code, 13)
8278 inner = packet[IPerror]
8279 self.assertEqual(inner.src, self.pg1.remote_ip4)
8280 self.assertEqual(inner.dst, self.nat_addr)
8281 self.assert_packet_checksums_valid(packet)
8282 if inner.haslayer(TCPerror):
8283 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
8284 elif inner.haslayer(UDPerror):
8285 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
8287 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
8289 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8293 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8294 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8295 ICMP(type=3, code=13) /
8296 packet[IP] for packet in capture_ip4]
8297 self.pg1.add_stream(pkts)
8298 self.pg_enable_capture(self.pg_interfaces)
8300 capture = self.pg0.get_capture(len(pkts))
8301 for packet in capture:
8303 self.assertEqual(packet[IPv6].src, ip.src)
8304 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8305 icmp = packet[ICMPv6DestUnreach]
8306 self.assertEqual(icmp.code, 1)
8307 inner = icmp[IPerror6]
8308 self.assertEqual(inner.src, self.pg0.remote_ip6)
8309 self.assertEqual(inner.dst, ip.src)
8310 self.assert_icmpv6_checksum_valid(packet)
8311 if inner.haslayer(TCPerror):
8312 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
8313 elif inner.haslayer(UDPerror):
8314 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
8316 self.assertEqual(inner[ICMPv6EchoRequest].id,
8319 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8322 def test_hairpinning(self):
8323 """ NAT64 hairpinning """
8325 client = self.pg0.remote_hosts[0]
8326 server = self.pg0.remote_hosts[1]
8327 server_tcp_in_port = 22
8328 server_tcp_out_port = 4022
8329 server_udp_in_port = 23
8330 server_udp_out_port = 4023
8331 client_tcp_in_port = 1234
8332 client_udp_in_port = 1235
8333 client_tcp_out_port = 0
8334 client_udp_out_port = 0
8335 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8336 nat_addr_ip6 = ip.src
8338 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8339 end_addr=self.nat_addr,
8342 flags = self.config_flags.NAT_IS_INSIDE
8343 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8344 sw_if_index=self.pg0.sw_if_index)
8345 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8346 sw_if_index=self.pg1.sw_if_index)
8348 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8349 o_addr=self.nat_addr,
8350 i_port=server_tcp_in_port,
8351 o_port=server_tcp_out_port,
8352 proto=IP_PROTOS.tcp, vrf_id=0,
8354 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8355 o_addr=self.nat_addr,
8356 i_port=server_udp_in_port,
8357 o_port=server_udp_out_port,
8358 proto=IP_PROTOS.udp, vrf_id=0,
8363 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8364 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8365 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8367 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8368 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8369 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
8371 self.pg0.add_stream(pkts)
8372 self.pg_enable_capture(self.pg_interfaces)
8374 capture = self.pg0.get_capture(len(pkts))
8375 for packet in capture:
8377 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8378 self.assertEqual(packet[IPv6].dst, server.ip6)
8379 self.assert_packet_checksums_valid(packet)
8380 if packet.haslayer(TCP):
8381 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
8382 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
8383 client_tcp_out_port = packet[TCP].sport
8385 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
8386 self.assertEqual(packet[UDP].dport, server_udp_in_port)
8387 client_udp_out_port = packet[UDP].sport
8389 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8394 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8395 IPv6(src=server.ip6, dst=nat_addr_ip6) /
8396 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
8398 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8399 IPv6(src=server.ip6, dst=nat_addr_ip6) /
8400 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
8402 self.pg0.add_stream(pkts)
8403 self.pg_enable_capture(self.pg_interfaces)
8405 capture = self.pg0.get_capture(len(pkts))
8406 for packet in capture:
8408 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8409 self.assertEqual(packet[IPv6].dst, client.ip6)
8410 self.assert_packet_checksums_valid(packet)
8411 if packet.haslayer(TCP):
8412 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
8413 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
8415 self.assertEqual(packet[UDP].sport, server_udp_out_port)
8416 self.assertEqual(packet[UDP].dport, client_udp_in_port)
8418 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8423 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8424 IPv6(src=client.ip6, dst=nat_addr_ip6) /
8425 ICMPv6DestUnreach(code=1) /
8426 packet[IPv6] for packet in capture]
8427 self.pg0.add_stream(pkts)
8428 self.pg_enable_capture(self.pg_interfaces)
8430 capture = self.pg0.get_capture(len(pkts))
8431 for packet in capture:
8433 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
8434 self.assertEqual(packet[IPv6].dst, server.ip6)
8435 icmp = packet[ICMPv6DestUnreach]
8436 self.assertEqual(icmp.code, 1)
8437 inner = icmp[IPerror6]
8438 self.assertEqual(inner.src, server.ip6)
8439 self.assertEqual(inner.dst, nat_addr_ip6)
8440 self.assert_packet_checksums_valid(packet)
8441 if inner.haslayer(TCPerror):
8442 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
8443 self.assertEqual(inner[TCPerror].dport,
8444 client_tcp_out_port)
8446 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
8447 self.assertEqual(inner[UDPerror].dport,
8448 client_udp_out_port)
8450 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8453 def test_prefix(self):
8454 """ NAT64 Network-Specific Prefix """
8456 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8457 end_addr=self.nat_addr,
8460 flags = self.config_flags.NAT_IS_INSIDE
8461 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8462 sw_if_index=self.pg0.sw_if_index)
8463 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8464 sw_if_index=self.pg1.sw_if_index)
8465 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.vrf1_nat_addr,
8466 end_addr=self.vrf1_nat_addr,
8467 vrf_id=self.vrf1_id, is_add=1)
8468 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8469 sw_if_index=self.pg2.sw_if_index)
8472 global_pref64 = "2001:db8::"
8473 global_pref64_len = 32
8474 global_pref64_str = "{}/{}".format(global_pref64, global_pref64_len)
8475 self.vapi.nat64_add_del_prefix(prefix=global_pref64_str, vrf_id=0,
8478 prefix = self.vapi.nat64_prefix_dump()
8479 self.assertEqual(len(prefix), 1)
8480 self.assertEqual(str(prefix[0].prefix), global_pref64_str)
8481 self.assertEqual(prefix[0].vrf_id, 0)
8483 # Add tenant specific prefix
8484 vrf1_pref64 = "2001:db8:122:300::"
8485 vrf1_pref64_len = 56
8486 vrf1_pref64_str = "{}/{}".format(vrf1_pref64, vrf1_pref64_len)
8487 self.vapi.nat64_add_del_prefix(prefix=vrf1_pref64_str,
8488 vrf_id=self.vrf1_id, is_add=1)
8490 prefix = self.vapi.nat64_prefix_dump()
8491 self.assertEqual(len(prefix), 2)
8494 pkts = self.create_stream_in_ip6(self.pg0,
8497 plen=global_pref64_len)
8498 self.pg0.add_stream(pkts)
8499 self.pg_enable_capture(self.pg_interfaces)
8501 capture = self.pg1.get_capture(len(pkts))
8502 self.verify_capture_out(capture, nat_ip=self.nat_addr,
8503 dst_ip=self.pg1.remote_ip4)
8505 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
8506 self.pg1.add_stream(pkts)
8507 self.pg_enable_capture(self.pg_interfaces)
8509 capture = self.pg0.get_capture(len(pkts))
8510 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8513 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
8515 # Tenant specific prefix
8516 pkts = self.create_stream_in_ip6(self.pg2,
8519 plen=vrf1_pref64_len)
8520 self.pg2.add_stream(pkts)
8521 self.pg_enable_capture(self.pg_interfaces)
8523 capture = self.pg1.get_capture(len(pkts))
8524 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
8525 dst_ip=self.pg1.remote_ip4)
8527 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
8528 self.pg1.add_stream(pkts)
8529 self.pg_enable_capture(self.pg_interfaces)
8531 capture = self.pg2.get_capture(len(pkts))
8532 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
8535 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
8537 def test_unknown_proto(self):
8538 """ NAT64 translate packet with unknown protocol """
8540 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8541 end_addr=self.nat_addr,
8544 flags = self.config_flags.NAT_IS_INSIDE
8545 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8546 sw_if_index=self.pg0.sw_if_index)
8547 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8548 sw_if_index=self.pg1.sw_if_index)
8549 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8552 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8553 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
8554 TCP(sport=self.tcp_port_in, dport=20))
8555 self.pg0.add_stream(p)
8556 self.pg_enable_capture(self.pg_interfaces)
8558 p = self.pg1.get_capture(1)
8560 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8561 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
8563 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8564 TCP(sport=1234, dport=1234))
8565 self.pg0.add_stream(p)
8566 self.pg_enable_capture(self.pg_interfaces)
8568 p = self.pg1.get_capture(1)
8571 self.assertEqual(packet[IP].src, self.nat_addr)
8572 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
8573 self.assertEqual(packet.haslayer(GRE), 1)
8574 self.assert_packet_checksums_valid(packet)
8576 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8580 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8581 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8583 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8584 TCP(sport=1234, dport=1234))
8585 self.pg1.add_stream(p)
8586 self.pg_enable_capture(self.pg_interfaces)
8588 p = self.pg0.get_capture(1)
8591 self.assertEqual(packet[IPv6].src, remote_ip6)
8592 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8593 self.assertEqual(packet[IPv6].nh, 47)
8595 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8598 def test_hairpinning_unknown_proto(self):
8599 """ NAT64 translate packet with unknown protocol - hairpinning """
8601 client = self.pg0.remote_hosts[0]
8602 server = self.pg0.remote_hosts[1]
8603 server_tcp_in_port = 22
8604 server_tcp_out_port = 4022
8605 client_tcp_in_port = 1234
8606 client_tcp_out_port = 1235
8607 server_nat_ip = "10.0.0.100"
8608 client_nat_ip = "10.0.0.110"
8609 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
8610 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
8612 self.vapi.nat64_add_del_pool_addr_range(start_addr=server_nat_ip,
8613 end_addr=client_nat_ip,
8616 flags = self.config_flags.NAT_IS_INSIDE
8617 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8618 sw_if_index=self.pg0.sw_if_index)
8619 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8620 sw_if_index=self.pg1.sw_if_index)
8622 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8623 o_addr=server_nat_ip,
8624 i_port=server_tcp_in_port,
8625 o_port=server_tcp_out_port,
8626 proto=IP_PROTOS.tcp, vrf_id=0,
8629 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8630 o_addr=server_nat_ip, i_port=0,
8632 proto=IP_PROTOS.gre, vrf_id=0,
8635 self.vapi.nat64_add_del_static_bib(i_addr=client.ip6n,
8636 o_addr=client_nat_ip,
8637 i_port=client_tcp_in_port,
8638 o_port=client_tcp_out_port,
8639 proto=IP_PROTOS.tcp, vrf_id=0,
8643 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8644 IPv6(src=client.ip6, dst=server_nat_ip6) /
8645 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8646 self.pg0.add_stream(p)
8647 self.pg_enable_capture(self.pg_interfaces)
8649 p = self.pg0.get_capture(1)
8651 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8652 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
8654 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8655 TCP(sport=1234, dport=1234))
8656 self.pg0.add_stream(p)
8657 self.pg_enable_capture(self.pg_interfaces)
8659 p = self.pg0.get_capture(1)
8662 self.assertEqual(packet[IPv6].src, client_nat_ip6)
8663 self.assertEqual(packet[IPv6].dst, server.ip6)
8664 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
8666 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8670 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8671 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
8673 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8674 TCP(sport=1234, dport=1234))
8675 self.pg0.add_stream(p)
8676 self.pg_enable_capture(self.pg_interfaces)
8678 p = self.pg0.get_capture(1)
8681 self.assertEqual(packet[IPv6].src, server_nat_ip6)
8682 self.assertEqual(packet[IPv6].dst, client.ip6)
8683 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
8685 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8688 def test_one_armed_nat64(self):
8689 """ One armed NAT64 """
8691 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
8695 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8696 end_addr=self.nat_addr,
8699 flags = self.config_flags.NAT_IS_INSIDE
8700 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8701 sw_if_index=self.pg3.sw_if_index)
8702 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8703 sw_if_index=self.pg3.sw_if_index)
8706 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8707 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
8708 TCP(sport=12345, dport=80))
8709 self.pg3.add_stream(p)
8710 self.pg_enable_capture(self.pg_interfaces)
8712 capture = self.pg3.get_capture(1)
8717 self.assertEqual(ip.src, self.nat_addr)
8718 self.assertEqual(ip.dst, self.pg3.remote_ip4)
8719 self.assertNotEqual(tcp.sport, 12345)
8720 external_port = tcp.sport
8721 self.assertEqual(tcp.dport, 80)
8722 self.assert_packet_checksums_valid(p)
8724 self.logger.error(ppp("Unexpected or invalid packet:", p))
8728 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8729 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
8730 TCP(sport=80, dport=external_port))
8731 self.pg3.add_stream(p)
8732 self.pg_enable_capture(self.pg_interfaces)
8734 capture = self.pg3.get_capture(1)
8739 self.assertEqual(ip.src, remote_host_ip6)
8740 self.assertEqual(ip.dst, self.pg3.remote_ip6)
8741 self.assertEqual(tcp.sport, 80)
8742 self.assertEqual(tcp.dport, 12345)
8743 self.assert_packet_checksums_valid(p)
8745 self.logger.error(ppp("Unexpected or invalid packet:", p))
8748 def test_frag_in_order(self):
8749 """ NAT64 translate fragments arriving in 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)
8766 self.pg0.add_stream(pkts)
8767 self.pg_enable_capture(self.pg_interfaces)
8769 frags = self.pg1.get_capture(len(pkts))
8770 p = self.reass_frags_and_verify(frags,
8772 self.pg1.remote_ip4)
8773 self.assertEqual(p[TCP].dport, 20)
8774 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8775 self.tcp_port_out = p[TCP].sport
8776 self.assertEqual(data, p[Raw].load)
8779 data = b"A" * 4 + b"b" * 16 + b"C" * 3
8780 pkts = self.create_stream_frag(self.pg1,
8785 self.pg1.add_stream(pkts)
8786 self.pg_enable_capture(self.pg_interfaces)
8788 frags = self.pg0.get_capture(len(pkts))
8789 self.logger.debug(ppc("Captured:", frags))
8790 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8791 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8792 self.assertEqual(p[TCP].sport, 20)
8793 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8794 self.assertEqual(data, p[Raw].load)
8796 def test_reass_hairpinning(self):
8797 """ NAT64 fragments hairpinning """
8799 server = self.pg0.remote_hosts[1]
8800 server_in_port = random.randint(1025, 65535)
8801 server_out_port = random.randint(1025, 65535)
8802 client_in_port = random.randint(1025, 65535)
8803 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8804 nat_addr_ip6 = ip.src
8806 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8807 end_addr=self.nat_addr,
8810 flags = self.config_flags.NAT_IS_INSIDE
8811 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8812 sw_if_index=self.pg0.sw_if_index)
8813 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8814 sw_if_index=self.pg1.sw_if_index)
8816 # add static BIB entry for server
8817 self.vapi.nat64_add_del_static_bib(i_addr=server.ip6n,
8818 o_addr=self.nat_addr,
8819 i_port=server_in_port,
8820 o_port=server_out_port,
8821 proto=IP_PROTOS.tcp, vrf_id=0,
8824 # send packet from host to server
8825 pkts = self.create_stream_frag_ip6(self.pg0,
8830 self.pg0.add_stream(pkts)
8831 self.pg_enable_capture(self.pg_interfaces)
8833 frags = self.pg0.get_capture(len(pkts))
8834 self.logger.debug(ppc("Captured:", frags))
8835 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
8836 self.assertNotEqual(p[TCP].sport, client_in_port)
8837 self.assertEqual(p[TCP].dport, server_in_port)
8838 self.assertEqual(data, p[Raw].load)
8840 def test_frag_out_of_order(self):
8841 """ NAT64 translate fragments arriving out of order """
8842 self.tcp_port_in = random.randint(1025, 65535)
8844 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8845 end_addr=self.nat_addr,
8848 flags = self.config_flags.NAT_IS_INSIDE
8849 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8850 sw_if_index=self.pg0.sw_if_index)
8851 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8852 sw_if_index=self.pg1.sw_if_index)
8856 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8857 self.tcp_port_in, 20, data)
8859 self.pg0.add_stream(pkts)
8860 self.pg_enable_capture(self.pg_interfaces)
8862 frags = self.pg1.get_capture(len(pkts))
8863 p = self.reass_frags_and_verify(frags,
8865 self.pg1.remote_ip4)
8866 self.assertEqual(p[TCP].dport, 20)
8867 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8868 self.tcp_port_out = p[TCP].sport
8869 self.assertEqual(data, p[Raw].load)
8872 data = b"A" * 4 + b"B" * 16 + b"C" * 3
8873 pkts = self.create_stream_frag(self.pg1,
8879 self.pg1.add_stream(pkts)
8880 self.pg_enable_capture(self.pg_interfaces)
8882 frags = self.pg0.get_capture(len(pkts))
8883 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8884 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8885 self.assertEqual(p[TCP].sport, 20)
8886 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8887 self.assertEqual(data, p[Raw].load)
8889 def test_interface_addr(self):
8890 """ Acquire NAT64 pool addresses from interface """
8891 self.vapi.nat64_add_del_interface_addr(
8893 sw_if_index=self.pg4.sw_if_index)
8895 # no address in NAT64 pool
8896 addresses = self.vapi.nat44_address_dump()
8897 self.assertEqual(0, len(addresses))
8899 # configure interface address and check NAT64 address pool
8900 self.pg4.config_ip4()
8901 addresses = self.vapi.nat64_pool_addr_dump()
8902 self.assertEqual(len(addresses), 1)
8904 self.assertEqual(str(addresses[0].address),
8907 # remove interface address and check NAT64 address pool
8908 self.pg4.unconfig_ip4()
8909 addresses = self.vapi.nat64_pool_addr_dump()
8910 self.assertEqual(0, len(addresses))
8912 @unittest.skipUnless(running_extended_tests, "part of extended tests")
8913 def test_ipfix_max_bibs_sessions(self):
8914 """ IPFIX logging maximum session and BIB entries exceeded """
8917 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8921 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
8922 end_addr=self.nat_addr,
8925 flags = self.config_flags.NAT_IS_INSIDE
8926 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
8927 sw_if_index=self.pg0.sw_if_index)
8928 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
8929 sw_if_index=self.pg1.sw_if_index)
8933 for i in range(0, max_bibs):
8934 src = "fd01:aa::%x" % (i)
8935 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8936 IPv6(src=src, dst=remote_host_ip6) /
8937 TCP(sport=12345, dport=80))
8939 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8940 IPv6(src=src, dst=remote_host_ip6) /
8941 TCP(sport=12345, dport=22))
8943 self.pg0.add_stream(pkts)
8944 self.pg_enable_capture(self.pg_interfaces)
8946 self.pg1.get_capture(max_sessions)
8948 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
8949 src_address=self.pg3.local_ip4,
8951 template_interval=10)
8952 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8953 src_port=self.ipfix_src_port,
8956 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8957 IPv6(src=src, dst=remote_host_ip6) /
8958 TCP(sport=12345, dport=25))
8959 self.pg0.add_stream(p)
8960 self.pg_enable_capture(self.pg_interfaces)
8962 self.pg1.assert_nothing_captured()
8964 self.vapi.ipfix_flush()
8965 capture = self.pg3.get_capture(9)
8966 ipfix = IPFIXDecoder()
8967 # first load template
8969 self.assertTrue(p.haslayer(IPFIX))
8970 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8971 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8972 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8973 self.assertEqual(p[UDP].dport, 4739)
8974 self.assertEqual(p[IPFIX].observationDomainID,
8975 self.ipfix_domain_id)
8976 if p.haslayer(Template):
8977 ipfix.add_template(p.getlayer(Template))
8978 # verify events in data set
8980 if p.haslayer(Data):
8981 data = ipfix.decode_data_set(p.getlayer(Set))
8982 self.verify_ipfix_max_sessions(data, max_sessions)
8984 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8985 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8986 TCP(sport=12345, dport=80))
8987 self.pg0.add_stream(p)
8988 self.pg_enable_capture(self.pg_interfaces)
8990 self.pg1.assert_nothing_captured()
8992 self.vapi.ipfix_flush()
8993 capture = self.pg3.get_capture(1)
8994 # verify events in data set
8996 self.assertTrue(p.haslayer(IPFIX))
8997 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8998 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8999 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
9000 self.assertEqual(p[UDP].dport, 4739)
9001 self.assertEqual(p[IPFIX].observationDomainID,
9002 self.ipfix_domain_id)
9003 if p.haslayer(Data):
9004 data = ipfix.decode_data_set(p.getlayer(Set))
9005 self.verify_ipfix_max_bibs(data, max_bibs)
9007 def test_ipfix_bib_ses(self):
9008 """ IPFIX logging NAT64 BIB/session create and delete events """
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.set_ipfix_exporter(collector_address=self.pg3.remote_ip4,
9024 src_address=self.pg3.local_ip4,
9026 template_interval=10)
9027 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
9028 src_port=self.ipfix_src_port,
9032 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
9033 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
9034 TCP(sport=self.tcp_port_in, dport=25))
9035 self.pg0.add_stream(p)
9036 self.pg_enable_capture(self.pg_interfaces)
9038 p = self.pg1.get_capture(1)
9039 self.tcp_port_out = p[0][TCP].sport
9040 self.vapi.ipfix_flush()
9041 capture = self.pg3.get_capture(10)
9042 ipfix = IPFIXDecoder()
9043 # first load template
9045 self.assertTrue(p.haslayer(IPFIX))
9046 self.assertEqual(p[IP].src, self.pg3.local_ip4)
9047 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
9048 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
9049 self.assertEqual(p[UDP].dport, 4739)
9050 self.assertEqual(p[IPFIX].observationDomainID,
9051 self.ipfix_domain_id)
9052 if p.haslayer(Template):
9053 ipfix.add_template(p.getlayer(Template))
9054 # verify events in data set
9056 if p.haslayer(Data):
9057 data = ipfix.decode_data_set(p.getlayer(Set))
9058 if scapy.compat.orb(data[0][230]) == 10:
9059 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
9060 elif scapy.compat.orb(data[0][230]) == 6:
9061 self.verify_ipfix_nat64_ses(data,
9063 self.pg0.remote_ip6n,
9064 self.pg1.remote_ip4,
9067 self.logger.error(ppp("Unexpected or invalid packet: ", p))
9070 self.pg_enable_capture(self.pg_interfaces)
9071 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9072 end_addr=self.nat_addr,
9075 self.vapi.ipfix_flush()
9076 capture = self.pg3.get_capture(2)
9077 # verify events in data set
9079 self.assertTrue(p.haslayer(IPFIX))
9080 self.assertEqual(p[IP].src, self.pg3.local_ip4)
9081 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
9082 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
9083 self.assertEqual(p[UDP].dport, 4739)
9084 self.assertEqual(p[IPFIX].observationDomainID,
9085 self.ipfix_domain_id)
9086 if p.haslayer(Data):
9087 data = ipfix.decode_data_set(p.getlayer(Set))
9088 if scapy.compat.orb(data[0][230]) == 11:
9089 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
9090 elif scapy.compat.orb(data[0][230]) == 7:
9091 self.verify_ipfix_nat64_ses(data,
9093 self.pg0.remote_ip6n,
9094 self.pg1.remote_ip4,
9097 self.logger.error(ppp("Unexpected or invalid packet: ", p))
9099 def test_syslog_sess(self):
9100 """ Test syslog session creation and deletion """
9101 self.tcp_port_in = random.randint(1025, 65535)
9102 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
9106 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9107 end_addr=self.nat_addr,
9110 flags = self.config_flags.NAT_IS_INSIDE
9111 self.vapi.nat64_add_del_interface(is_add=1, flags=flags,
9112 sw_if_index=self.pg0.sw_if_index)
9113 self.vapi.nat64_add_del_interface(is_add=1, flags=0,
9114 sw_if_index=self.pg1.sw_if_index)
9115 self.vapi.syslog_set_filter(
9116 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_INFO)
9117 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
9119 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
9120 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
9121 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
9122 self.pg0.add_stream(p)
9123 self.pg_enable_capture(self.pg_interfaces)
9125 p = self.pg1.get_capture(1)
9126 self.tcp_port_out = p[0][TCP].sport
9127 capture = self.pg3.get_capture(1)
9128 self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
9130 self.pg_enable_capture(self.pg_interfaces)
9132 self.vapi.nat64_add_del_pool_addr_range(start_addr=self.nat_addr,
9133 end_addr=self.nat_addr,
9136 capture = self.pg3.get_capture(1)
9137 self.verify_syslog_sess(capture[0][Raw].load, False, True)
9139 def nat64_get_ses_num(self):
9141 Return number of active NAT64 sessions.
9143 st = self.vapi.nat64_st_dump(proto=255)
9146 def clear_nat64(self):
9148 Clear NAT64 configuration.
9150 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
9151 src_port=self.ipfix_src_port,
9153 self.ipfix_src_port = 4739
9154 self.ipfix_domain_id = 1
9156 self.vapi.syslog_set_filter(
9157 self.SYSLOG_SEVERITY.SYSLOG_API_SEVERITY_EMERG)
9159 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
9160 tcp_transitory=240, icmp=60)
9162 interfaces = self.vapi.nat64_interface_dump()
9163 for intf in interfaces:
9164 self.vapi.nat64_add_del_interface(is_add=0, flags=intf.flags,
9165 sw_if_index=intf.sw_if_index)
9167 bib = self.vapi.nat64_bib_dump(proto=255)
9169 if bibe.flags & self.config_flags.NAT_IS_STATIC:
9170 self.vapi.nat64_add_del_static_bib(i_addr=bibe.i_addr,
9178 adresses = self.vapi.nat64_pool_addr_dump()
9179 for addr in adresses:
9180 self.vapi.nat64_add_del_pool_addr_range(start_addr=addr.address,
9181 end_addr=addr.address,
9185 prefixes = self.vapi.nat64_prefix_dump()
9186 for prefix in prefixes:
9187 self.vapi.nat64_add_del_prefix(prefix=str(prefix.prefix),
9188 vrf_id=prefix.vrf_id, is_add=0)
9190 bibs = self.statistics.get_counter('/nat64/total-bibs')
9191 self.assertEqual(bibs[0][0], 0)
9192 sessions = self.statistics.get_counter('/nat64/total-sessions')
9193 self.assertEqual(sessions[0][0], 0)
9196 super(TestNAT64, self).tearDown()
9197 if not self.vpp_dead:
9200 def show_commands_at_teardown(self):
9201 self.logger.info(self.vapi.cli("show nat64 pool"))
9202 self.logger.info(self.vapi.cli("show nat64 interfaces"))
9203 self.logger.info(self.vapi.cli("show nat64 prefix"))
9204 self.logger.info(self.vapi.cli("show nat64 bib all"))
9205 self.logger.info(self.vapi.cli("show nat64 session table all"))
9208 class TestNAT66(MethodHolder):
9209 """ NAT66 Test Cases """
9212 def setUpClass(cls):
9213 super(TestNAT66, cls).setUpClass()
9215 cls.nat_addr = 'fd01:ff::2'
9217 cls.create_pg_interfaces(range(2))
9218 cls.interfaces = list(cls.pg_interfaces)
9220 for i in cls.interfaces:
9223 i.configure_ipv6_neighbors()
9226 def tearDownClass(cls):
9227 super(TestNAT66, cls).tearDownClass()
9229 def test_static(self):
9230 """ 1:1 NAT66 test """
9231 flags = self.config_flags.NAT_IS_INSIDE
9232 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9233 sw_if_index=self.pg0.sw_if_index)
9234 self.vapi.nat66_add_del_interface(is_add=1,
9235 sw_if_index=self.pg1.sw_if_index)
9236 self.vapi.nat66_add_del_static_mapping(
9237 local_ip_address=self.pg0.remote_ip6n,
9238 external_ip_address=self.nat_addr,
9243 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9244 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9247 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9248 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9251 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9252 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9253 ICMPv6EchoRequest())
9255 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9256 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9257 GRE() / IP() / TCP())
9259 self.pg0.add_stream(pkts)
9260 self.pg_enable_capture(self.pg_interfaces)
9262 capture = self.pg1.get_capture(len(pkts))
9264 for packet in capture:
9266 self.assertEqual(packet[IPv6].src, self.nat_addr)
9267 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9268 self.assert_packet_checksums_valid(packet)
9270 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9275 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9276 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9279 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9280 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9283 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9284 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9287 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9288 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9289 GRE() / IP() / TCP())
9291 self.pg1.add_stream(pkts)
9292 self.pg_enable_capture(self.pg_interfaces)
9294 capture = self.pg0.get_capture(len(pkts))
9295 for packet in capture:
9297 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
9298 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
9299 self.assert_packet_checksums_valid(packet)
9301 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9304 sm = self.vapi.nat66_static_mapping_dump()
9305 self.assertEqual(len(sm), 1)
9306 self.assertEqual(sm[0].total_pkts, 8)
9308 def test_check_no_translate(self):
9309 """ NAT66 translate only when egress interface is outside interface """
9310 flags = self.config_flags.NAT_IS_INSIDE
9311 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9312 sw_if_index=self.pg0.sw_if_index)
9313 self.vapi.nat66_add_del_interface(is_add=1, flags=flags,
9314 sw_if_index=self.pg1.sw_if_index)
9315 self.vapi.nat66_add_del_static_mapping(
9316 local_ip_address=self.pg0.remote_ip6n,
9317 external_ip_address=self.nat_addr,
9321 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9322 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9324 self.pg0.add_stream([p])
9325 self.pg_enable_capture(self.pg_interfaces)
9327 capture = self.pg1.get_capture(1)
9330 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
9331 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9333 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9336 def clear_nat66(self):
9338 Clear NAT66 configuration.
9340 interfaces = self.vapi.nat66_interface_dump()
9341 for intf in interfaces:
9342 self.vapi.nat66_add_del_interface(is_add=0, flags=intf.flags,
9343 sw_if_index=intf.sw_if_index)
9345 static_mappings = self.vapi.nat66_static_mapping_dump()
9346 for sm in static_mappings:
9347 self.vapi.nat66_add_del_static_mapping(
9348 local_ip_address=sm.local_ip_address,
9349 external_ip_address=sm.external_ip_address, vrf_id=sm.vrf_id,
9353 super(TestNAT66, self).tearDown()
9356 def show_commands_at_teardown(self):
9357 self.logger.info(self.vapi.cli("show nat66 interfaces"))
9358 self.logger.info(self.vapi.cli("show nat66 static mappings"))
9361 if __name__ == '__main__':
9362 unittest.main(testRunner=VppTestRunner)