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 vpp_papi_provider import SYSLOG_SEVERITY
27 from io import BytesIO
28 from vpp_papi import VppEnum
29 from scapy.all import bind_layers, Packet, ByteEnumField, ShortField, \
30 IPField, IntField, LongField, XByteField, FlagsField, FieldLenField, \
32 from ipaddress import IPv6Network
35 # NAT HA protocol event data
38 fields_desc = [ByteEnumField("event_type", None,
39 {1: "add", 2: "del", 3: "refresh"}),
40 ByteEnumField("protocol", None,
41 {0: "udp", 1: "tcp", 2: "icmp"}),
42 ShortField("flags", 0),
43 IPField("in_addr", None),
44 IPField("out_addr", None),
45 ShortField("in_port", None),
46 ShortField("out_port", None),
47 IPField("eh_addr", None),
48 IPField("ehn_addr", None),
49 ShortField("eh_port", None),
50 ShortField("ehn_port", None),
51 IntField("fib_index", None),
52 IntField("total_pkts", 0),
53 LongField("total_bytes", 0)]
55 def extract_padding(self, s):
59 # NAT HA protocol header
60 class HANATStateSync(Packet):
61 name = "HA NAT state sync"
62 fields_desc = [XByteField("version", 1),
63 FlagsField("flags", 0, 8, ['ACK']),
64 FieldLenField("count", None, count_of="events"),
65 IntField("sequence_number", 1),
66 IntField("thread_index", 0),
67 PacketListField("events", [], Event,
68 count_from=lambda pkt: pkt.count)]
71 class MethodHolder(VppTestCase):
72 """ NAT create capture and verify method holder """
75 def config_flags(self):
76 return VppEnum.vl_api_nat_config_flags_t
78 def clear_nat44(self):
80 Clear NAT44 configuration.
82 if hasattr(self, 'pg7') and hasattr(self, 'pg8'):
83 # I found no elegant way to do this
84 self.vapi.ip_add_del_route(
85 dst_address=self.pg7.remote_ip4n,
86 dst_address_length=32,
87 next_hop_address=self.pg7.remote_ip4n,
88 next_hop_sw_if_index=self.pg7.sw_if_index,
90 self.vapi.ip_add_del_route(
91 dst_address=self.pg8.remote_ip4n,
92 dst_address_length=32,
93 next_hop_address=self.pg8.remote_ip4n,
94 next_hop_sw_if_index=self.pg8.sw_if_index,
97 for intf in [self.pg7, self.pg8]:
98 self.vapi.ip_neighbor_add_del(
102 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
103 IP_API_NEIGHBOR_FLAG_STATIC),
106 if self.pg7.has_ip4_config:
107 self.pg7.unconfig_ip4()
109 self.vapi.nat44_forwarding_enable_disable(0)
111 interfaces = self.vapi.nat44_interface_addr_dump()
112 for intf in interfaces:
113 self.vapi.nat44_add_del_interface_addr(intf.sw_if_index,
117 self.vapi.nat_ipfix_enable_disable(enable=0,
118 src_port=self.ipfix_src_port,
119 domain_id=self.ipfix_domain_id)
120 self.ipfix_src_port = 4739
121 self.ipfix_domain_id = 1
123 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
125 self.vapi.nat_ha_set_listener('0.0.0.0', 0)
126 self.vapi.nat_ha_set_failover('0.0.0.0', 0)
128 interfaces = self.vapi.nat44_interface_dump()
129 for intf in interfaces:
130 if intf.flags & self.config_flags.NAT_IS_INSIDE and \
131 intf.flags & self.config_flags.NAT_IS_OUTSIDE:
132 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
134 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
138 interfaces = self.vapi.nat44_interface_output_feature_dump()
139 for intf in interfaces:
140 self.vapi.nat44_interface_add_del_output_feature(intf.sw_if_index,
143 static_mappings = self.vapi.nat44_static_mapping_dump()
144 for sm in static_mappings:
145 self.vapi.nat44_add_del_static_mapping(
147 sm.external_ip_address,
148 sm.external_sw_if_index,
157 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
158 for lb_sm in lb_static_mappings:
159 self.vapi.nat44_add_del_lb_static_mapping(
169 identity_mappings = self.vapi.nat44_identity_mapping_dump()
170 for id_m in identity_mappings:
171 self.vapi.nat44_add_del_identity_mapping(
175 sw_if_index=id_m.sw_if_index,
177 protocol=id_m.protocol,
180 addresses = self.vapi.nat44_address_dump()
181 for addr in addresses:
182 self.vapi.nat44_add_del_address_range(addr.ip_address,
187 self.vapi.nat_set_reass()
188 self.vapi.nat_set_reass(is_ip6=1)
189 self.verify_no_nat44_user()
190 self.vapi.nat_set_timeouts()
191 self.vapi.nat_set_addr_and_port_alloc_alg()
192 self.vapi.nat_set_mss_clamping()
194 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
195 local_port=0, external_port=0, vrf_id=0,
196 is_add=1, external_sw_if_index=0xFFFFFFFF,
197 proto=0, tag="", flags=0):
199 Add/delete NAT44 static mapping
201 :param local_ip: Local IP address
202 :param external_ip: External IP address
203 :param local_port: Local port number (Optional)
204 :param external_port: External port number (Optional)
205 :param vrf_id: VRF ID (Default 0)
206 :param is_add: 1 if add, 0 if delete (Default add)
207 :param external_sw_if_index: External interface instead of IP address
208 :param proto: IP protocol (Mandatory if port specified)
209 :param tag: Opaque string tag
210 :param flags: NAT configuration flags
213 if not (local_port and external_port):
214 flags |= self.config_flags.NAT_IS_ADDR_ONLY
216 self.vapi.nat44_add_del_static_mapping(
219 external_sw_if_index,
228 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
230 Add/delete NAT44 address
232 :param ip: IP address
233 :param is_add: 1 if add, 0 if delete (Default add)
234 :param twice_nat: twice NAT address for external hosts
236 flags = self.config_flags.NAT_IS_TWICE_NAT if twice_nat else 0
237 self.vapi.nat44_add_del_address_range(ip, ip, is_add,
241 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
243 Create packet stream for inside network
245 :param in_if: Inside interface
246 :param out_if: Outside interface
247 :param dst_ip: Destination address
248 :param ttl: TTL of generated packets
251 dst_ip = out_if.remote_ip4
255 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
256 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
257 TCP(sport=self.tcp_port_in, dport=20))
261 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
262 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
263 UDP(sport=self.udp_port_in, dport=20))
267 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
268 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
269 ICMP(id=self.icmp_id_in, type='echo-request'))
274 def compose_ip6(self, ip4, pref, plen):
276 Compose IPv4-embedded IPv6 addresses
278 :param ip4: IPv4 address
279 :param pref: IPv6 prefix
280 :param plen: IPv6 prefix length
281 :returns: IPv4-embedded IPv6 addresses
283 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
284 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
299 pref_n[10] = ip4_n[3]
303 pref_n[10] = ip4_n[2]
304 pref_n[11] = ip4_n[3]
307 pref_n[10] = ip4_n[1]
308 pref_n[11] = ip4_n[2]
309 pref_n[12] = ip4_n[3]
311 pref_n[12] = ip4_n[0]
312 pref_n[13] = ip4_n[1]
313 pref_n[14] = ip4_n[2]
314 pref_n[15] = ip4_n[3]
315 packed_pref_n = b''.join([scapy.compat.chb(x) for x in pref_n])
316 return socket.inet_ntop(socket.AF_INET6, packed_pref_n)
318 def extract_ip4(self, ip6, plen):
320 Extract IPv4 address embedded in IPv6 addresses
322 :param ip6: IPv6 address
323 :param plen: IPv6 prefix length
324 :returns: extracted IPv4 address
326 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
358 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
360 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
362 Create IPv6 packet stream for inside network
364 :param in_if: Inside interface
365 :param out_if: Outside interface
366 :param ttl: Hop Limit of generated packets
367 :param pref: NAT64 prefix
368 :param plen: NAT64 prefix length
372 dst = ''.join(['64:ff9b::', out_if.remote_ip4])
374 dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
377 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
378 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
379 TCP(sport=self.tcp_port_in, dport=20))
383 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
384 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
385 UDP(sport=self.udp_port_in, dport=20))
389 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
390 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
391 ICMPv6EchoRequest(id=self.icmp_id_in))
396 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
397 use_inside_ports=False):
399 Create packet stream for outside network
401 :param out_if: Outside interface
402 :param dst_ip: Destination IP address (Default use global NAT address)
403 :param ttl: TTL of generated packets
404 :param use_inside_ports: Use inside NAT ports as destination ports
405 instead of outside ports
408 dst_ip = self.nat_addr
409 if not use_inside_ports:
410 tcp_port = self.tcp_port_out
411 udp_port = self.udp_port_out
412 icmp_id = self.icmp_id_out
414 tcp_port = self.tcp_port_in
415 udp_port = self.udp_port_in
416 icmp_id = self.icmp_id_in
419 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
420 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
421 TCP(dport=tcp_port, sport=20))
425 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
426 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
427 UDP(dport=udp_port, sport=20))
431 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
432 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
433 ICMP(id=icmp_id, type='echo-reply'))
438 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
440 Create packet stream for outside network
442 :param out_if: Outside interface
443 :param dst_ip: Destination IP address (Default use global NAT address)
444 :param hl: HL of generated packets
448 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
449 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
450 TCP(dport=self.tcp_port_out, sport=20))
454 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
455 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
456 UDP(dport=self.udp_port_out, sport=20))
460 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
461 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
462 ICMPv6EchoReply(id=self.icmp_id_out))
467 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
468 dst_ip=None, is_ip6=False):
470 Verify captured packets on outside network
472 :param capture: Captured packets
473 :param nat_ip: Translated IP address (Default use global NAT address)
474 :param same_port: Source port number is not translated (Default False)
475 :param dst_ip: Destination IP address (Default do not verify)
476 :param is_ip6: If L3 protocol is IPv6 (Default False)
480 ICMP46 = ICMPv6EchoRequest
485 nat_ip = self.nat_addr
486 for packet in capture:
489 self.assert_packet_checksums_valid(packet)
490 self.assertEqual(packet[IP46].src, nat_ip)
491 if dst_ip is not None:
492 self.assertEqual(packet[IP46].dst, dst_ip)
493 if packet.haslayer(TCP):
495 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
498 packet[TCP].sport, self.tcp_port_in)
499 self.tcp_port_out = packet[TCP].sport
500 self.assert_packet_checksums_valid(packet)
501 elif packet.haslayer(UDP):
503 self.assertEqual(packet[UDP].sport, self.udp_port_in)
506 packet[UDP].sport, self.udp_port_in)
507 self.udp_port_out = packet[UDP].sport
510 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
512 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
513 self.icmp_id_out = packet[ICMP46].id
514 self.assert_packet_checksums_valid(packet)
516 self.logger.error(ppp("Unexpected or invalid packet "
517 "(outside network):", packet))
520 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
523 Verify captured packets on outside network
525 :param capture: Captured packets
526 :param nat_ip: Translated IP address
527 :param same_port: Source port number is not translated (Default False)
528 :param dst_ip: Destination IP address (Default do not verify)
530 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
533 def verify_capture_in(self, capture, in_if):
535 Verify captured packets on inside network
537 :param capture: Captured packets
538 :param in_if: Inside interface
540 for packet in capture:
542 self.assert_packet_checksums_valid(packet)
543 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
544 if packet.haslayer(TCP):
545 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
546 elif packet.haslayer(UDP):
547 self.assertEqual(packet[UDP].dport, self.udp_port_in)
549 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
551 self.logger.error(ppp("Unexpected or invalid packet "
552 "(inside network):", packet))
555 def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
557 Verify captured IPv6 packets on inside network
559 :param capture: Captured packets
560 :param src_ip: Source IP
561 :param dst_ip: Destination IP address
563 for packet in capture:
565 self.assertEqual(packet[IPv6].src, src_ip)
566 self.assertEqual(packet[IPv6].dst, dst_ip)
567 self.assert_packet_checksums_valid(packet)
568 if packet.haslayer(TCP):
569 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
570 elif packet.haslayer(UDP):
571 self.assertEqual(packet[UDP].dport, self.udp_port_in)
573 self.assertEqual(packet[ICMPv6EchoReply].id,
576 self.logger.error(ppp("Unexpected or invalid packet "
577 "(inside network):", packet))
580 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
582 Verify captured packet that don't have to be translated
584 :param capture: Captured packets
585 :param ingress_if: Ingress interface
586 :param egress_if: Egress interface
588 for packet in capture:
590 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
591 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
592 if packet.haslayer(TCP):
593 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
594 elif packet.haslayer(UDP):
595 self.assertEqual(packet[UDP].sport, self.udp_port_in)
597 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
599 self.logger.error(ppp("Unexpected or invalid packet "
600 "(inside network):", packet))
603 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
606 Verify captured packets with ICMP errors on outside network
608 :param capture: Captured packets
609 :param src_ip: Translated IP address or IP address of VPP
610 (Default use global NAT address)
611 :param icmp_type: Type of error ICMP packet
612 we are expecting (Default 11)
615 src_ip = self.nat_addr
616 for packet in capture:
618 self.assertEqual(packet[IP].src, src_ip)
619 self.assertEqual(packet.haslayer(ICMP), 1)
621 self.assertEqual(icmp.type, icmp_type)
622 self.assertTrue(icmp.haslayer(IPerror))
623 inner_ip = icmp[IPerror]
624 if inner_ip.haslayer(TCPerror):
625 self.assertEqual(inner_ip[TCPerror].dport,
627 elif inner_ip.haslayer(UDPerror):
628 self.assertEqual(inner_ip[UDPerror].dport,
631 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
633 self.logger.error(ppp("Unexpected or invalid packet "
634 "(outside network):", packet))
637 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
639 Verify captured packets with ICMP errors on inside network
641 :param capture: Captured packets
642 :param in_if: Inside interface
643 :param icmp_type: Type of error ICMP packet
644 we are expecting (Default 11)
646 for packet in capture:
648 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
649 self.assertEqual(packet.haslayer(ICMP), 1)
651 self.assertEqual(icmp.type, icmp_type)
652 self.assertTrue(icmp.haslayer(IPerror))
653 inner_ip = icmp[IPerror]
654 if inner_ip.haslayer(TCPerror):
655 self.assertEqual(inner_ip[TCPerror].sport,
657 elif inner_ip.haslayer(UDPerror):
658 self.assertEqual(inner_ip[UDPerror].sport,
661 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
663 self.logger.error(ppp("Unexpected or invalid packet "
664 "(inside network):", packet))
667 def create_stream_frag(self, src_if, dst, sport, dport, data,
668 proto=IP_PROTOS.tcp, echo_reply=False):
670 Create fragmented packet stream
672 :param src_if: Source interface
673 :param dst: Destination IPv4 address
674 :param sport: Source port
675 :param dport: Destination port
676 :param data: Payload data
677 :param proto: protocol (TCP, UDP, ICMP)
678 :param echo_reply: use echo_reply if protocol is ICMP
681 if proto == IP_PROTOS.tcp:
682 p = (IP(src=src_if.remote_ip4, dst=dst) /
683 TCP(sport=sport, dport=dport) /
685 p = p.__class__(scapy.compat.raw(p))
686 chksum = p[TCP].chksum
687 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
688 elif proto == IP_PROTOS.udp:
689 proto_header = UDP(sport=sport, dport=dport)
690 elif proto == IP_PROTOS.icmp:
692 proto_header = ICMP(id=sport, type='echo-request')
694 proto_header = ICMP(id=sport, type='echo-reply')
696 raise Exception("Unsupported protocol")
697 id = random.randint(0, 65535)
699 if proto == IP_PROTOS.tcp:
702 raw = Raw(data[0:16])
703 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
704 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
708 if proto == IP_PROTOS.tcp:
709 raw = Raw(data[4:20])
711 raw = Raw(data[16:32])
712 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
713 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
717 if proto == IP_PROTOS.tcp:
721 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
722 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
728 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
729 pref=None, plen=0, frag_size=128):
731 Create fragmented packet stream
733 :param src_if: Source interface
734 :param dst: Destination IPv4 address
735 :param sport: Source TCP port
736 :param dport: Destination TCP port
737 :param data: Payload data
738 :param pref: NAT64 prefix
739 :param plen: NAT64 prefix length
740 :param fragsize: size of fragments
744 dst_ip6 = ''.join(['64:ff9b::', dst])
746 dst_ip6 = self.compose_ip6(dst, pref, plen)
748 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
749 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
750 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
751 TCP(sport=sport, dport=dport) /
754 return fragment6(p, frag_size)
756 def reass_frags_and_verify(self, frags, src, dst):
758 Reassemble and verify fragmented packet
760 :param frags: Captured fragments
761 :param src: Source IPv4 address to verify
762 :param dst: Destination IPv4 address to verify
764 :returns: Reassembled IPv4 packet
768 self.assertEqual(p[IP].src, src)
769 self.assertEqual(p[IP].dst, dst)
770 self.assert_ip_checksum_valid(p)
771 buffer.seek(p[IP].frag * 8)
772 buffer.write(bytes(p[IP].payload))
773 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
774 proto=frags[0][IP].proto)
775 if ip.proto == IP_PROTOS.tcp:
776 p = (ip / TCP(buffer.getvalue()))
777 self.assert_tcp_checksum_valid(p)
778 elif ip.proto == IP_PROTOS.udp:
779 p = (ip / UDP(buffer.getvalue()[:8]) /
780 Raw(buffer.getvalue()[8:]))
781 elif ip.proto == IP_PROTOS.icmp:
782 p = (ip / ICMP(buffer.getvalue()))
785 def reass_frags_and_verify_ip6(self, frags, src, dst):
787 Reassemble and verify fragmented packet
789 :param frags: Captured fragments
790 :param src: Source IPv6 address to verify
791 :param dst: Destination IPv6 address to verify
793 :returns: Reassembled IPv6 packet
797 self.assertEqual(p[IPv6].src, src)
798 self.assertEqual(p[IPv6].dst, dst)
799 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
800 buffer.write(bytes(p[IPv6ExtHdrFragment].payload))
801 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
802 nh=frags[0][IPv6ExtHdrFragment].nh)
803 if ip.nh == IP_PROTOS.tcp:
804 p = (ip / TCP(buffer.getvalue()))
805 elif ip.nh == IP_PROTOS.udp:
806 p = (ip / UDP(buffer.getvalue()))
807 self.assert_packet_checksums_valid(p)
810 def initiate_tcp_session(self, in_if, out_if):
812 Initiates TCP session
814 :param in_if: Inside interface
815 :param out_if: Outside interface
819 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
820 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
821 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
824 self.pg_enable_capture(self.pg_interfaces)
826 capture = out_if.get_capture(1)
828 self.tcp_port_out = p[TCP].sport
830 # SYN + ACK packet out->in
831 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
832 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
833 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
836 self.pg_enable_capture(self.pg_interfaces)
841 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
842 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
843 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
846 self.pg_enable_capture(self.pg_interfaces)
848 out_if.get_capture(1)
851 self.logger.error("TCP 3 way handshake failed")
854 def verify_ipfix_nat44_ses(self, data):
856 Verify IPFIX NAT44 session create/delete event
858 :param data: Decoded IPFIX data records
860 nat44_ses_create_num = 0
861 nat44_ses_delete_num = 0
862 self.assertEqual(6, len(data))
865 self.assertIn(scapy.compat.orb(record[230]), [4, 5])
866 if scapy.compat.orb(record[230]) == 4:
867 nat44_ses_create_num += 1
869 nat44_ses_delete_num += 1
871 self.assertEqual(self.pg0.remote_ip4n, record[8])
872 # postNATSourceIPv4Address
873 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
876 self.assertEqual(struct.pack("!I", 0), record[234])
877 # protocolIdentifier/sourceTransportPort/postNAPTSourceTransportPort
878 if IP_PROTOS.icmp == scapy.compat.orb(record[4]):
879 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
880 self.assertEqual(struct.pack("!H", self.icmp_id_out),
882 elif IP_PROTOS.tcp == scapy.compat.orb(record[4]):
883 self.assertEqual(struct.pack("!H", self.tcp_port_in),
885 self.assertEqual(struct.pack("!H", self.tcp_port_out),
887 elif IP_PROTOS.udp == scapy.compat.orb(record[4]):
888 self.assertEqual(struct.pack("!H", self.udp_port_in),
890 self.assertEqual(struct.pack("!H", self.udp_port_out),
893 self.fail("Invalid protocol")
894 self.assertEqual(3, nat44_ses_create_num)
895 self.assertEqual(3, nat44_ses_delete_num)
897 def verify_ipfix_addr_exhausted(self, data):
899 Verify IPFIX NAT addresses event
901 :param data: Decoded IPFIX data records
903 self.assertEqual(1, len(data))
906 self.assertEqual(scapy.compat.orb(record[230]), 3)
908 self.assertEqual(struct.pack("!I", 0), record[283])
910 def verify_ipfix_max_sessions(self, data, limit):
912 Verify IPFIX maximum session entries exceeded event
914 :param data: Decoded IPFIX data records
915 :param limit: Number of maximum session entries that can be created.
917 self.assertEqual(1, len(data))
920 self.assertEqual(scapy.compat.orb(record[230]), 13)
921 # natQuotaExceededEvent
922 self.assertEqual(struct.pack("I", 1), record[466])
924 self.assertEqual(struct.pack("I", limit), record[471])
926 def verify_ipfix_max_bibs(self, data, limit):
928 Verify IPFIX maximum BIB entries exceeded event
930 :param data: Decoded IPFIX data records
931 :param limit: Number of maximum BIB entries that can be created.
933 self.assertEqual(1, len(data))
936 self.assertEqual(scapy.compat.orb(record[230]), 13)
937 # natQuotaExceededEvent
938 self.assertEqual(struct.pack("I", 2), record[466])
940 self.assertEqual(struct.pack("I", limit), record[472])
942 def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
944 Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
946 :param data: Decoded IPFIX data records
947 :param limit: Number of maximum fragments pending reassembly
948 :param src_addr: IPv6 source address
950 self.assertEqual(1, len(data))
953 self.assertEqual(scapy.compat.orb(record[230]), 13)
954 # natQuotaExceededEvent
955 self.assertEqual(struct.pack("I", 5), record[466])
956 # maxFragmentsPendingReassembly
957 self.assertEqual(struct.pack("I", limit), record[475])
959 self.assertEqual(src_addr, record[27])
961 def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
963 Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
965 :param data: Decoded IPFIX data records
966 :param limit: Number of maximum fragments pending reassembly
967 :param src_addr: IPv4 source address
969 self.assertEqual(1, len(data))
972 self.assertEqual(scapy.compat.orb(record[230]), 13)
973 # natQuotaExceededEvent
974 self.assertEqual(struct.pack("I", 5), record[466])
975 # maxFragmentsPendingReassembly
976 self.assertEqual(struct.pack("I", limit), record[475])
978 self.assertEqual(src_addr, record[8])
980 def verify_ipfix_bib(self, data, is_create, src_addr):
982 Verify IPFIX NAT64 BIB create and delete events
984 :param data: Decoded IPFIX data records
985 :param is_create: Create event if nonzero value otherwise delete event
986 :param src_addr: IPv6 source address
988 self.assertEqual(1, len(data))
992 self.assertEqual(scapy.compat.orb(record[230]), 10)
994 self.assertEqual(scapy.compat.orb(record[230]), 11)
996 self.assertEqual(src_addr, record[27])
997 # postNATSourceIPv4Address
998 self.assertEqual(self.nat_addr_n, record[225])
1000 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
1002 self.assertEqual(struct.pack("!I", 0), record[234])
1003 # sourceTransportPort
1004 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1005 # postNAPTSourceTransportPort
1006 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1008 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
1011 Verify IPFIX NAT64 session create and delete events
1013 :param data: Decoded IPFIX data records
1014 :param is_create: Create event if nonzero value otherwise delete event
1015 :param src_addr: IPv6 source address
1016 :param dst_addr: IPv4 destination address
1017 :param dst_port: destination TCP port
1019 self.assertEqual(1, len(data))
1023 self.assertEqual(scapy.compat.orb(record[230]), 6)
1025 self.assertEqual(scapy.compat.orb(record[230]), 7)
1027 self.assertEqual(src_addr, record[27])
1028 # destinationIPv6Address
1029 self.assertEqual(socket.inet_pton(socket.AF_INET6,
1030 self.compose_ip6(dst_addr,
1034 # postNATSourceIPv4Address
1035 self.assertEqual(self.nat_addr_n, record[225])
1036 # postNATDestinationIPv4Address
1037 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
1039 # protocolIdentifier
1040 self.assertEqual(IP_PROTOS.tcp, scapy.compat.orb(record[4]))
1042 self.assertEqual(struct.pack("!I", 0), record[234])
1043 # sourceTransportPort
1044 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1045 # postNAPTSourceTransportPort
1046 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1047 # destinationTransportPort
1048 self.assertEqual(struct.pack("!H", dst_port), record[11])
1049 # postNAPTDestinationTransportPort
1050 self.assertEqual(struct.pack("!H", dst_port), record[228])
1052 def verify_no_nat44_user(self):
1053 """ Verify that there is no NAT44 user """
1054 users = self.vapi.nat44_user_dump()
1055 self.assertEqual(len(users), 0)
1056 users = self.statistics.get_counter('/nat44/total-users')
1057 self.assertEqual(users[0][0], 0)
1058 sessions = self.statistics.get_counter('/nat44/total-sessions')
1059 self.assertEqual(sessions[0][0], 0)
1061 def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
1063 Verify IPFIX maximum entries per user exceeded event
1065 :param data: Decoded IPFIX data records
1066 :param limit: Number of maximum entries per user
1067 :param src_addr: IPv4 source address
1069 self.assertEqual(1, len(data))
1072 self.assertEqual(scapy.compat.orb(record[230]), 13)
1073 # natQuotaExceededEvent
1074 self.assertEqual(struct.pack("I", 3), record[466])
1076 self.assertEqual(struct.pack("I", limit), record[473])
1078 self.assertEqual(src_addr, record[8])
1080 def verify_syslog_apmap(self, data, is_add=True):
1081 message = data.decode('utf-8')
1083 message = SyslogMessage.parse(message)
1084 except ParseError as e:
1085 self.logger.error(e)
1088 self.assertEqual(message.severity, SyslogSeverity.info)
1089 self.assertEqual(message.appname, 'NAT')
1090 self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
1091 sd_params = message.sd.get('napmap')
1092 self.assertTrue(sd_params is not None)
1093 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1094 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1095 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1096 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1097 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1098 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1099 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1100 self.assertTrue(sd_params.get('SSUBIX') is not None)
1101 self.assertEqual(sd_params.get('SVLAN'), '0')
1103 def verify_syslog_sess(self, data, is_add=True, is_ip6=False):
1104 message = data.decode('utf-8')
1106 message = SyslogMessage.parse(message)
1107 except ParseError as e:
1108 self.logger.error(e)
1111 self.assertEqual(message.severity, SyslogSeverity.info)
1112 self.assertEqual(message.appname, 'NAT')
1113 self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL')
1114 sd_params = message.sd.get('nsess')
1115 self.assertTrue(sd_params is not None)
1117 self.assertEqual(sd_params.get('IATYP'), 'IPv6')
1118 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
1120 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1121 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1122 self.assertTrue(sd_params.get('SSUBIX') is not None)
1123 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1124 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1125 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1126 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1127 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1128 self.assertEqual(sd_params.get('SVLAN'), '0')
1129 self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
1130 self.assertEqual(sd_params.get('XDPORT'),
1131 "%d" % self.tcp_external_port)
1133 def verify_mss_value(self, pkt, mss):
1135 Verify TCP MSS value
1140 if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
1141 raise TypeError("Not a TCP/IP packet")
1143 for option in pkt[TCP].options:
1144 if option[0] == 'MSS':
1145 self.assertEqual(option[1], mss)
1146 self.assert_tcp_checksum_valid(pkt)
1149 def proto2layer(proto):
1150 if proto == IP_PROTOS.tcp:
1152 elif proto == IP_PROTOS.udp:
1154 elif proto == IP_PROTOS.icmp:
1157 raise Exception("Unsupported protocol")
1159 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1160 layer = self.proto2layer(proto)
1162 if proto == IP_PROTOS.tcp:
1163 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1165 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1166 self.port_in = random.randint(1025, 65535)
1168 reass = self.vapi.nat_reass_dump()
1169 reass_n_start = len(reass)
1172 pkts = self.create_stream_frag(self.pg0,
1173 self.pg1.remote_ip4,
1178 self.pg0.add_stream(pkts)
1179 self.pg_enable_capture(self.pg_interfaces)
1181 frags = self.pg1.get_capture(len(pkts))
1182 if not dont_translate:
1183 p = self.reass_frags_and_verify(frags,
1185 self.pg1.remote_ip4)
1187 p = self.reass_frags_and_verify(frags,
1188 self.pg0.remote_ip4,
1189 self.pg1.remote_ip4)
1190 if proto != IP_PROTOS.icmp:
1191 if not dont_translate:
1192 self.assertEqual(p[layer].dport, 20)
1193 self.assertNotEqual(p[layer].sport, self.port_in)
1195 self.assertEqual(p[layer].sport, self.port_in)
1197 if not dont_translate:
1198 self.assertNotEqual(p[layer].id, self.port_in)
1200 self.assertEqual(p[layer].id, self.port_in)
1201 self.assertEqual(data, p[Raw].load)
1204 if not dont_translate:
1205 dst_addr = self.nat_addr
1207 dst_addr = self.pg0.remote_ip4
1208 if proto != IP_PROTOS.icmp:
1210 dport = p[layer].sport
1214 pkts = self.create_stream_frag(self.pg1,
1221 self.pg1.add_stream(pkts)
1222 self.pg_enable_capture(self.pg_interfaces)
1224 frags = self.pg0.get_capture(len(pkts))
1225 p = self.reass_frags_and_verify(frags,
1226 self.pg1.remote_ip4,
1227 self.pg0.remote_ip4)
1228 if proto != IP_PROTOS.icmp:
1229 self.assertEqual(p[layer].sport, 20)
1230 self.assertEqual(p[layer].dport, self.port_in)
1232 self.assertEqual(p[layer].id, self.port_in)
1233 self.assertEqual(data, p[Raw].load)
1235 reass = self.vapi.nat_reass_dump()
1236 reass_n_end = len(reass)
1238 self.assertEqual(reass_n_end - reass_n_start, 2)
1240 def frag_in_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1241 layer = self.proto2layer(proto)
1243 if proto == IP_PROTOS.tcp:
1244 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1246 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1247 self.port_in = random.randint(1025, 65535)
1250 reass = self.vapi.nat_reass_dump()
1251 reass_n_start = len(reass)
1254 pkts = self.create_stream_frag(self.pg0,
1255 self.server_out_addr,
1257 self.server_out_port,
1260 self.pg0.add_stream(pkts)
1261 self.pg_enable_capture(self.pg_interfaces)
1263 frags = self.pg1.get_capture(len(pkts))
1264 p = self.reass_frags_and_verify(frags,
1265 self.pg0.remote_ip4,
1266 self.server_in_addr)
1267 if proto != IP_PROTOS.icmp:
1268 self.assertEqual(p[layer].sport, self.port_in)
1269 self.assertEqual(p[layer].dport, self.server_in_port)
1271 self.assertEqual(p[layer].id, self.port_in)
1272 self.assertEqual(data, p[Raw].load)
1275 if proto != IP_PROTOS.icmp:
1276 pkts = self.create_stream_frag(self.pg1,
1277 self.pg0.remote_ip4,
1278 self.server_in_port,
1283 pkts = self.create_stream_frag(self.pg1,
1284 self.pg0.remote_ip4,
1290 self.pg1.add_stream(pkts)
1291 self.pg_enable_capture(self.pg_interfaces)
1293 frags = self.pg0.get_capture(len(pkts))
1294 p = self.reass_frags_and_verify(frags,
1295 self.server_out_addr,
1296 self.pg0.remote_ip4)
1297 if proto != IP_PROTOS.icmp:
1298 self.assertEqual(p[layer].sport, self.server_out_port)
1299 self.assertEqual(p[layer].dport, self.port_in)
1301 self.assertEqual(p[layer].id, self.port_in)
1302 self.assertEqual(data, p[Raw].load)
1304 reass = self.vapi.nat_reass_dump()
1305 reass_n_end = len(reass)
1307 self.assertEqual(reass_n_end - reass_n_start, 2)
1309 def reass_hairpinning(self, proto=IP_PROTOS.tcp):
1310 layer = self.proto2layer(proto)
1312 if proto == IP_PROTOS.tcp:
1313 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1315 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1317 # send packet from host to server
1318 pkts = self.create_stream_frag(self.pg0,
1321 self.server_out_port,
1324 self.pg0.add_stream(pkts)
1325 self.pg_enable_capture(self.pg_interfaces)
1327 frags = self.pg0.get_capture(len(pkts))
1328 p = self.reass_frags_and_verify(frags,
1331 if proto != IP_PROTOS.icmp:
1332 self.assertNotEqual(p[layer].sport, self.host_in_port)
1333 self.assertEqual(p[layer].dport, self.server_in_port)
1335 self.assertNotEqual(p[layer].id, self.host_in_port)
1336 self.assertEqual(data, p[Raw].load)
1338 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1339 layer = self.proto2layer(proto)
1341 if proto == IP_PROTOS.tcp:
1342 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1344 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1345 self.port_in = random.randint(1025, 65535)
1349 pkts = self.create_stream_frag(self.pg0,
1350 self.pg1.remote_ip4,
1356 self.pg0.add_stream(pkts)
1357 self.pg_enable_capture(self.pg_interfaces)
1359 frags = self.pg1.get_capture(len(pkts))
1360 if not dont_translate:
1361 p = self.reass_frags_and_verify(frags,
1363 self.pg1.remote_ip4)
1365 p = self.reass_frags_and_verify(frags,
1366 self.pg0.remote_ip4,
1367 self.pg1.remote_ip4)
1368 if proto != IP_PROTOS.icmp:
1369 if not dont_translate:
1370 self.assertEqual(p[layer].dport, 20)
1371 self.assertNotEqual(p[layer].sport, self.port_in)
1373 self.assertEqual(p[layer].sport, self.port_in)
1375 if not dont_translate:
1376 self.assertNotEqual(p[layer].id, self.port_in)
1378 self.assertEqual(p[layer].id, self.port_in)
1379 self.assertEqual(data, p[Raw].load)
1382 if not dont_translate:
1383 dst_addr = self.nat_addr
1385 dst_addr = self.pg0.remote_ip4
1386 if proto != IP_PROTOS.icmp:
1388 dport = p[layer].sport
1392 pkts = self.create_stream_frag(self.pg1,
1400 self.pg1.add_stream(pkts)
1401 self.pg_enable_capture(self.pg_interfaces)
1403 frags = self.pg0.get_capture(len(pkts))
1404 p = self.reass_frags_and_verify(frags,
1405 self.pg1.remote_ip4,
1406 self.pg0.remote_ip4)
1407 if proto != IP_PROTOS.icmp:
1408 self.assertEqual(p[layer].sport, 20)
1409 self.assertEqual(p[layer].dport, self.port_in)
1411 self.assertEqual(p[layer].id, self.port_in)
1412 self.assertEqual(data, p[Raw].load)
1414 def frag_out_of_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1415 layer = self.proto2layer(proto)
1417 if proto == IP_PROTOS.tcp:
1418 data = b"A" * 4 + b"B" * 16 + b"C" * 3
1420 data = b"A" * 16 + b"B" * 16 + b"C" * 3
1421 self.port_in = random.randint(1025, 65535)
1425 pkts = self.create_stream_frag(self.pg0,
1426 self.server_out_addr,
1428 self.server_out_port,
1432 self.pg0.add_stream(pkts)
1433 self.pg_enable_capture(self.pg_interfaces)
1435 frags = self.pg1.get_capture(len(pkts))
1436 p = self.reass_frags_and_verify(frags,
1437 self.pg0.remote_ip4,
1438 self.server_in_addr)
1439 if proto != IP_PROTOS.icmp:
1440 self.assertEqual(p[layer].dport, self.server_in_port)
1441 self.assertEqual(p[layer].sport, self.port_in)
1442 self.assertEqual(p[layer].dport, self.server_in_port)
1444 self.assertEqual(p[layer].id, self.port_in)
1445 self.assertEqual(data, p[Raw].load)
1448 if proto != IP_PROTOS.icmp:
1449 pkts = self.create_stream_frag(self.pg1,
1450 self.pg0.remote_ip4,
1451 self.server_in_port,
1456 pkts = self.create_stream_frag(self.pg1,
1457 self.pg0.remote_ip4,
1464 self.pg1.add_stream(pkts)
1465 self.pg_enable_capture(self.pg_interfaces)
1467 frags = self.pg0.get_capture(len(pkts))
1468 p = self.reass_frags_and_verify(frags,
1469 self.server_out_addr,
1470 self.pg0.remote_ip4)
1471 if proto != IP_PROTOS.icmp:
1472 self.assertEqual(p[layer].sport, self.server_out_port)
1473 self.assertEqual(p[layer].dport, self.port_in)
1475 self.assertEqual(p[layer].id, self.port_in)
1476 self.assertEqual(data, p[Raw].load)
1479 class TestNAT44(MethodHolder):
1480 """ NAT44 Test Cases """
1483 def setUpClass(cls):
1484 super(TestNAT44, cls).setUpClass()
1485 cls.vapi.cli("set log class nat level debug")
1488 cls.tcp_port_in = 6303
1489 cls.tcp_port_out = 6303
1490 cls.udp_port_in = 6304
1491 cls.udp_port_out = 6304
1492 cls.icmp_id_in = 6305
1493 cls.icmp_id_out = 6305
1494 cls.nat_addr = '10.0.0.3'
1495 cls.ipfix_src_port = 4739
1496 cls.ipfix_domain_id = 1
1497 cls.tcp_external_port = 80
1498 cls.udp_external_port = 69
1500 cls.create_pg_interfaces(range(10))
1501 cls.interfaces = list(cls.pg_interfaces[0:4])
1503 for i in cls.interfaces:
1508 cls.pg0.generate_remote_hosts(3)
1509 cls.pg0.configure_ipv4_neighbors()
1511 cls.pg1.generate_remote_hosts(1)
1512 cls.pg1.configure_ipv4_neighbors()
1514 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
1515 cls.vapi.ip_table_add_del(is_add=1, table_id=10)
1516 cls.vapi.ip_table_add_del(is_add=1, table_id=20)
1518 cls.pg4._local_ip4 = "172.16.255.1"
1519 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1520 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1521 cls.pg4.set_table_ip4(10)
1522 cls.pg5._local_ip4 = "172.17.255.3"
1523 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1524 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
1525 cls.pg5.set_table_ip4(10)
1526 cls.pg6._local_ip4 = "172.16.255.1"
1527 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1528 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1529 cls.pg6.set_table_ip4(20)
1530 for i in cls.overlapping_interfaces:
1538 cls.pg9.generate_remote_hosts(2)
1539 cls.pg9.config_ip4()
1540 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
1541 cls.vapi.sw_interface_add_del_address(
1542 sw_if_index=cls.pg9.sw_if_index, address=ip_addr_n,
1545 cls.pg9.resolve_arp()
1546 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1547 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1548 cls.pg9.resolve_arp()
1551 super(TestNAT44, cls).tearDownClass()
1555 def tearDownClass(cls):
1556 super(TestNAT44, cls).tearDownClass()
1558 def test_dynamic(self):
1559 """ NAT44 dynamic translation test """
1560 self.nat44_add_address(self.nat_addr)
1561 flags = self.config_flags.NAT_IS_INSIDE
1562 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1564 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1567 tcpn = self.statistics.get_counter(
1568 '/err/nat44-in2out-slowpath/TCP packets')
1569 udpn = self.statistics.get_counter(
1570 '/err/nat44-in2out-slowpath/UDP packets')
1571 icmpn = self.statistics.get_counter(
1572 '/err/nat44-in2out-slowpath/ICMP packets')
1573 totaln = self.statistics.get_counter(
1574 '/err/nat44-in2out-slowpath/good in2out packets processed')
1576 pkts = self.create_stream_in(self.pg0, self.pg1)
1577 self.pg0.add_stream(pkts)
1578 self.pg_enable_capture(self.pg_interfaces)
1580 capture = self.pg1.get_capture(len(pkts))
1581 self.verify_capture_out(capture)
1583 err = self.statistics.get_counter(
1584 '/err/nat44-in2out-slowpath/TCP packets')
1585 self.assertEqual(err - tcpn, 1)
1586 err = self.statistics.get_counter(
1587 '/err/nat44-in2out-slowpath/UDP packets')
1588 self.assertEqual(err - udpn, 1)
1589 err = self.statistics.get_counter(
1590 '/err/nat44-in2out-slowpath/ICMP packets')
1591 self.assertEqual(err - icmpn, 1)
1592 err = self.statistics.get_counter(
1593 '/err/nat44-in2out-slowpath/good in2out packets processed')
1594 self.assertEqual(err - totaln, 3)
1597 tcpn = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
1598 udpn = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
1599 icmpn = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
1600 totaln = self.statistics.get_counter(
1601 '/err/nat44-out2in/good out2in packets processed')
1603 pkts = self.create_stream_out(self.pg1)
1604 self.pg1.add_stream(pkts)
1605 self.pg_enable_capture(self.pg_interfaces)
1607 capture = self.pg0.get_capture(len(pkts))
1608 self.verify_capture_in(capture, self.pg0)
1610 err = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
1611 self.assertEqual(err - tcpn, 1)
1612 err = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
1613 self.assertEqual(err - udpn, 1)
1614 err = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
1615 self.assertEqual(err - icmpn, 1)
1616 err = self.statistics.get_counter(
1617 '/err/nat44-out2in/good out2in packets processed')
1618 self.assertEqual(err - totaln, 3)
1620 users = self.statistics.get_counter('/nat44/total-users')
1621 self.assertEqual(users[0][0], 1)
1622 sessions = self.statistics.get_counter('/nat44/total-sessions')
1623 self.assertEqual(sessions[0][0], 3)
1625 def test_dynamic_icmp_errors_in2out_ttl_1(self):
1626 """ NAT44 handling of client packets with TTL=1 """
1628 self.nat44_add_address(self.nat_addr)
1629 flags = self.config_flags.NAT_IS_INSIDE
1630 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1632 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1634 # Client side - generate traffic
1635 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1636 self.pg0.add_stream(pkts)
1637 self.pg_enable_capture(self.pg_interfaces)
1640 # Client side - verify ICMP type 11 packets
1641 capture = self.pg0.get_capture(len(pkts))
1642 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1644 def test_dynamic_icmp_errors_out2in_ttl_1(self):
1645 """ NAT44 handling of server packets with TTL=1 """
1647 self.nat44_add_address(self.nat_addr)
1648 flags = self.config_flags.NAT_IS_INSIDE
1649 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1651 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1653 # Client side - create sessions
1654 pkts = self.create_stream_in(self.pg0, self.pg1)
1655 self.pg0.add_stream(pkts)
1656 self.pg_enable_capture(self.pg_interfaces)
1659 # Server side - generate traffic
1660 capture = self.pg1.get_capture(len(pkts))
1661 self.verify_capture_out(capture)
1662 pkts = self.create_stream_out(self.pg1, ttl=1)
1663 self.pg1.add_stream(pkts)
1664 self.pg_enable_capture(self.pg_interfaces)
1667 # Server side - verify ICMP type 11 packets
1668 capture = self.pg1.get_capture(len(pkts))
1669 self.verify_capture_out_with_icmp_errors(capture,
1670 src_ip=self.pg1.local_ip4)
1672 def test_dynamic_icmp_errors_in2out_ttl_2(self):
1673 """ NAT44 handling of error responses to client packets with TTL=2 """
1675 self.nat44_add_address(self.nat_addr)
1676 flags = self.config_flags.NAT_IS_INSIDE
1677 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1679 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1681 # Client side - generate traffic
1682 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1683 self.pg0.add_stream(pkts)
1684 self.pg_enable_capture(self.pg_interfaces)
1687 # Server side - simulate ICMP type 11 response
1688 capture = self.pg1.get_capture(len(pkts))
1689 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1690 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1691 ICMP(type=11) / packet[IP] for packet in capture]
1692 self.pg1.add_stream(pkts)
1693 self.pg_enable_capture(self.pg_interfaces)
1696 # Client side - verify ICMP type 11 packets
1697 capture = self.pg0.get_capture(len(pkts))
1698 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1700 def test_dynamic_icmp_errors_out2in_ttl_2(self):
1701 """ NAT44 handling of error responses to server packets with TTL=2 """
1703 self.nat44_add_address(self.nat_addr)
1704 flags = self.config_flags.NAT_IS_INSIDE
1705 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1707 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1709 # Client side - create sessions
1710 pkts = self.create_stream_in(self.pg0, self.pg1)
1711 self.pg0.add_stream(pkts)
1712 self.pg_enable_capture(self.pg_interfaces)
1715 # Server side - generate traffic
1716 capture = self.pg1.get_capture(len(pkts))
1717 self.verify_capture_out(capture)
1718 pkts = self.create_stream_out(self.pg1, ttl=2)
1719 self.pg1.add_stream(pkts)
1720 self.pg_enable_capture(self.pg_interfaces)
1723 # Client side - simulate ICMP type 11 response
1724 capture = self.pg0.get_capture(len(pkts))
1725 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1726 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1727 ICMP(type=11) / packet[IP] for packet in capture]
1728 self.pg0.add_stream(pkts)
1729 self.pg_enable_capture(self.pg_interfaces)
1732 # Server side - verify ICMP type 11 packets
1733 capture = self.pg1.get_capture(len(pkts))
1734 self.verify_capture_out_with_icmp_errors(capture)
1736 def test_ping_out_interface_from_outside(self):
1737 """ Ping NAT44 out interface from outside network """
1739 self.nat44_add_address(self.nat_addr)
1740 flags = self.config_flags.NAT_IS_INSIDE
1741 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1743 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1745 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1746 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1747 ICMP(id=self.icmp_id_out, type='echo-request'))
1749 self.pg1.add_stream(pkts)
1750 self.pg_enable_capture(self.pg_interfaces)
1752 capture = self.pg1.get_capture(len(pkts))
1755 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1756 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1757 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1758 self.assertEqual(packet[ICMP].type, 0) # echo reply
1760 self.logger.error(ppp("Unexpected or invalid packet "
1761 "(outside network):", packet))
1764 def test_ping_internal_host_from_outside(self):
1765 """ Ping internal host from outside network """
1767 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1768 flags = self.config_flags.NAT_IS_INSIDE
1769 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1771 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1774 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1775 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
1776 ICMP(id=self.icmp_id_out, type='echo-request'))
1777 self.pg1.add_stream(pkt)
1778 self.pg_enable_capture(self.pg_interfaces)
1780 capture = self.pg0.get_capture(1)
1781 self.verify_capture_in(capture, self.pg0)
1782 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1785 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1786 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1787 ICMP(id=self.icmp_id_in, type='echo-reply'))
1788 self.pg0.add_stream(pkt)
1789 self.pg_enable_capture(self.pg_interfaces)
1791 capture = self.pg1.get_capture(1)
1792 self.verify_capture_out(capture, same_port=True)
1793 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1795 def test_forwarding(self):
1796 """ NAT44 forwarding test """
1798 flags = self.config_flags.NAT_IS_INSIDE
1799 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1801 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1802 self.vapi.nat44_forwarding_enable_disable(1)
1804 real_ip = self.pg0.remote_ip4n
1805 alias_ip = self.nat_addr
1806 flags = self.config_flags.NAT_IS_ADDR_ONLY
1807 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1808 external_ip=alias_ip,
1812 # static mapping match
1814 pkts = self.create_stream_out(self.pg1)
1815 self.pg1.add_stream(pkts)
1816 self.pg_enable_capture(self.pg_interfaces)
1818 capture = self.pg0.get_capture(len(pkts))
1819 self.verify_capture_in(capture, self.pg0)
1821 pkts = self.create_stream_in(self.pg0, self.pg1)
1822 self.pg0.add_stream(pkts)
1823 self.pg_enable_capture(self.pg_interfaces)
1825 capture = self.pg1.get_capture(len(pkts))
1826 self.verify_capture_out(capture, same_port=True)
1828 # no static mapping match
1830 host0 = self.pg0.remote_hosts[0]
1831 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1833 pkts = self.create_stream_out(self.pg1,
1834 dst_ip=self.pg0.remote_ip4,
1835 use_inside_ports=True)
1836 self.pg1.add_stream(pkts)
1837 self.pg_enable_capture(self.pg_interfaces)
1839 capture = self.pg0.get_capture(len(pkts))
1840 self.verify_capture_in(capture, self.pg0)
1842 pkts = self.create_stream_in(self.pg0, self.pg1)
1843 self.pg0.add_stream(pkts)
1844 self.pg_enable_capture(self.pg_interfaces)
1846 capture = self.pg1.get_capture(len(pkts))
1847 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1850 self.pg0.remote_hosts[0] = host0
1853 self.vapi.nat44_forwarding_enable_disable(0)
1854 flags = self.config_flags.NAT_IS_ADDR_ONLY
1855 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1856 external_ip=alias_ip,
1857 is_add=0, flags=flags)
1859 def test_static_in(self):
1860 """ 1:1 NAT initialized from inside network """
1862 nat_ip = "10.0.0.10"
1863 self.tcp_port_out = 6303
1864 self.udp_port_out = 6304
1865 self.icmp_id_out = 6305
1867 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1868 flags = self.config_flags.NAT_IS_INSIDE
1869 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1871 self.vapi.nat44_interface_add_del_feature(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).split(b'\0', 1)[0], b'')
1875 self.assertEqual(sm[0].protocol, 0)
1876 self.assertEqual(sm[0].local_port, 0)
1877 self.assertEqual(sm[0].external_port, 0)
1880 pkts = self.create_stream_in(self.pg0, self.pg1)
1881 self.pg0.add_stream(pkts)
1882 self.pg_enable_capture(self.pg_interfaces)
1884 capture = self.pg1.get_capture(len(pkts))
1885 self.verify_capture_out(capture, nat_ip, True)
1888 pkts = self.create_stream_out(self.pg1, nat_ip)
1889 self.pg1.add_stream(pkts)
1890 self.pg_enable_capture(self.pg_interfaces)
1892 capture = self.pg0.get_capture(len(pkts))
1893 self.verify_capture_in(capture, self.pg0)
1895 def test_static_out(self):
1896 """ 1:1 NAT initialized from outside network """
1898 nat_ip = "10.0.0.20"
1899 self.tcp_port_out = 6303
1900 self.udp_port_out = 6304
1901 self.icmp_id_out = 6305
1904 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
1905 flags = self.config_flags.NAT_IS_INSIDE
1906 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1908 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1909 sm = self.vapi.nat44_static_mapping_dump()
1910 self.assertEqual(len(sm), 1)
1911 self.assertEqual((sm[0].tag).split(b'\0', 1)[0], tag)
1914 pkts = self.create_stream_out(self.pg1, nat_ip)
1915 self.pg1.add_stream(pkts)
1916 self.pg_enable_capture(self.pg_interfaces)
1918 capture = self.pg0.get_capture(len(pkts))
1919 self.verify_capture_in(capture, self.pg0)
1922 pkts = self.create_stream_in(self.pg0, self.pg1)
1923 self.pg0.add_stream(pkts)
1924 self.pg_enable_capture(self.pg_interfaces)
1926 capture = self.pg1.get_capture(len(pkts))
1927 self.verify_capture_out(capture, nat_ip, True)
1929 def test_static_with_port_in(self):
1930 """ 1:1 NAPT initialized from inside network """
1932 self.tcp_port_out = 3606
1933 self.udp_port_out = 3607
1934 self.icmp_id_out = 3608
1936 self.nat44_add_address(self.nat_addr)
1937 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1938 self.tcp_port_in, self.tcp_port_out,
1939 proto=IP_PROTOS.tcp)
1940 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1941 self.udp_port_in, self.udp_port_out,
1942 proto=IP_PROTOS.udp)
1943 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1944 self.icmp_id_in, self.icmp_id_out,
1945 proto=IP_PROTOS.icmp)
1946 flags = self.config_flags.NAT_IS_INSIDE
1947 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1949 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1952 pkts = self.create_stream_in(self.pg0, self.pg1)
1953 self.pg0.add_stream(pkts)
1954 self.pg_enable_capture(self.pg_interfaces)
1956 capture = self.pg1.get_capture(len(pkts))
1957 self.verify_capture_out(capture)
1960 pkts = self.create_stream_out(self.pg1)
1961 self.pg1.add_stream(pkts)
1962 self.pg_enable_capture(self.pg_interfaces)
1964 capture = self.pg0.get_capture(len(pkts))
1965 self.verify_capture_in(capture, self.pg0)
1967 def test_static_with_port_out(self):
1968 """ 1:1 NAPT initialized from outside network """
1970 self.tcp_port_out = 30606
1971 self.udp_port_out = 30607
1972 self.icmp_id_out = 30608
1974 self.nat44_add_address(self.nat_addr)
1975 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1976 self.tcp_port_in, self.tcp_port_out,
1977 proto=IP_PROTOS.tcp)
1978 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1979 self.udp_port_in, self.udp_port_out,
1980 proto=IP_PROTOS.udp)
1981 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1982 self.icmp_id_in, self.icmp_id_out,
1983 proto=IP_PROTOS.icmp)
1984 flags = self.config_flags.NAT_IS_INSIDE
1985 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
1987 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
1990 pkts = self.create_stream_out(self.pg1)
1991 self.pg1.add_stream(pkts)
1992 self.pg_enable_capture(self.pg_interfaces)
1994 capture = self.pg0.get_capture(len(pkts))
1995 self.verify_capture_in(capture, self.pg0)
1998 pkts = self.create_stream_in(self.pg0, self.pg1)
1999 self.pg0.add_stream(pkts)
2000 self.pg_enable_capture(self.pg_interfaces)
2002 capture = self.pg1.get_capture(len(pkts))
2003 self.verify_capture_out(capture)
2005 def test_static_vrf_aware(self):
2006 """ 1:1 NAT VRF awareness """
2008 nat_ip1 = "10.0.0.30"
2009 nat_ip2 = "10.0.0.40"
2010 self.tcp_port_out = 6303
2011 self.udp_port_out = 6304
2012 self.icmp_id_out = 6305
2014 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
2016 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
2018 flags = self.config_flags.NAT_IS_INSIDE
2019 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index)
2020 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2022 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
2025 # inside interface VRF match NAT44 static mapping VRF
2026 pkts = self.create_stream_in(self.pg4, self.pg3)
2027 self.pg4.add_stream(pkts)
2028 self.pg_enable_capture(self.pg_interfaces)
2030 capture = self.pg3.get_capture(len(pkts))
2031 self.verify_capture_out(capture, nat_ip1, True)
2033 # inside interface VRF don't match NAT44 static mapping VRF (packets
2035 pkts = self.create_stream_in(self.pg0, self.pg3)
2036 self.pg0.add_stream(pkts)
2037 self.pg_enable_capture(self.pg_interfaces)
2039 self.pg3.assert_nothing_captured()
2041 def test_dynamic_to_static(self):
2042 """ Switch from dynamic translation to 1:1NAT """
2043 nat_ip = "10.0.0.10"
2044 self.tcp_port_out = 6303
2045 self.udp_port_out = 6304
2046 self.icmp_id_out = 6305
2048 self.nat44_add_address(self.nat_addr)
2049 flags = self.config_flags.NAT_IS_INSIDE
2050 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2052 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2055 pkts = self.create_stream_in(self.pg0, self.pg1)
2056 self.pg0.add_stream(pkts)
2057 self.pg_enable_capture(self.pg_interfaces)
2059 capture = self.pg1.get_capture(len(pkts))
2060 self.verify_capture_out(capture)
2063 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2064 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2065 self.assertEqual(len(sessions), 0)
2066 pkts = self.create_stream_in(self.pg0, self.pg1)
2067 self.pg0.add_stream(pkts)
2068 self.pg_enable_capture(self.pg_interfaces)
2070 capture = self.pg1.get_capture(len(pkts))
2071 self.verify_capture_out(capture, nat_ip, True)
2073 def test_identity_nat(self):
2074 """ Identity NAT """
2075 flags = self.config_flags.NAT_IS_ADDR_ONLY
2076 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n,
2078 flags = self.config_flags.NAT_IS_INSIDE
2079 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2081 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2083 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2084 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2085 TCP(sport=12345, dport=56789))
2086 self.pg1.add_stream(p)
2087 self.pg_enable_capture(self.pg_interfaces)
2089 capture = self.pg0.get_capture(1)
2094 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2095 self.assertEqual(ip.src, self.pg1.remote_ip4)
2096 self.assertEqual(tcp.dport, 56789)
2097 self.assertEqual(tcp.sport, 12345)
2098 self.assert_packet_checksums_valid(p)
2100 self.logger.error(ppp("Unexpected or invalid packet:", p))
2103 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2104 self.assertEqual(len(sessions), 0)
2105 flags = self.config_flags.NAT_IS_ADDR_ONLY
2106 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n,
2107 flags=flags, vrf_id=1)
2108 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2109 self.assertEqual(len(identity_mappings), 2)
2111 def test_multiple_inside_interfaces(self):
2112 """ NAT44 multiple non-overlapping address space inside interfaces """
2114 self.nat44_add_address(self.nat_addr)
2115 flags = self.config_flags.NAT_IS_INSIDE
2116 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2118 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2120 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index)
2122 # between two NAT44 inside interfaces (no translation)
2123 pkts = self.create_stream_in(self.pg0, self.pg1)
2124 self.pg0.add_stream(pkts)
2125 self.pg_enable_capture(self.pg_interfaces)
2127 capture = self.pg1.get_capture(len(pkts))
2128 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
2130 # from NAT44 inside to interface without NAT44 feature (no translation)
2131 pkts = self.create_stream_in(self.pg0, self.pg2)
2132 self.pg0.add_stream(pkts)
2133 self.pg_enable_capture(self.pg_interfaces)
2135 capture = self.pg2.get_capture(len(pkts))
2136 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2138 # in2out 1st interface
2139 pkts = self.create_stream_in(self.pg0, self.pg3)
2140 self.pg0.add_stream(pkts)
2141 self.pg_enable_capture(self.pg_interfaces)
2143 capture = self.pg3.get_capture(len(pkts))
2144 self.verify_capture_out(capture)
2146 # out2in 1st interface
2147 pkts = self.create_stream_out(self.pg3)
2148 self.pg3.add_stream(pkts)
2149 self.pg_enable_capture(self.pg_interfaces)
2151 capture = self.pg0.get_capture(len(pkts))
2152 self.verify_capture_in(capture, self.pg0)
2154 # in2out 2nd interface
2155 pkts = self.create_stream_in(self.pg1, self.pg3)
2156 self.pg1.add_stream(pkts)
2157 self.pg_enable_capture(self.pg_interfaces)
2159 capture = self.pg3.get_capture(len(pkts))
2160 self.verify_capture_out(capture)
2162 # out2in 2nd interface
2163 pkts = self.create_stream_out(self.pg3)
2164 self.pg3.add_stream(pkts)
2165 self.pg_enable_capture(self.pg_interfaces)
2167 capture = self.pg1.get_capture(len(pkts))
2168 self.verify_capture_in(capture, self.pg1)
2170 def test_inside_overlapping_interfaces(self):
2171 """ NAT44 multiple inside interfaces with overlapping address space """
2173 static_nat_ip = "10.0.0.10"
2174 self.nat44_add_address(self.nat_addr)
2175 flags = self.config_flags.NAT_IS_INSIDE
2176 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index)
2177 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
2179 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index,
2181 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
2183 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2186 # between NAT44 inside interfaces with same VRF (no translation)
2187 pkts = self.create_stream_in(self.pg4, self.pg5)
2188 self.pg4.add_stream(pkts)
2189 self.pg_enable_capture(self.pg_interfaces)
2191 capture = self.pg5.get_capture(len(pkts))
2192 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2194 # between NAT44 inside interfaces with different VRF (hairpinning)
2195 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2196 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2197 TCP(sport=1234, dport=5678))
2198 self.pg4.add_stream(p)
2199 self.pg_enable_capture(self.pg_interfaces)
2201 capture = self.pg6.get_capture(1)
2206 self.assertEqual(ip.src, self.nat_addr)
2207 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2208 self.assertNotEqual(tcp.sport, 1234)
2209 self.assertEqual(tcp.dport, 5678)
2211 self.logger.error(ppp("Unexpected or invalid packet:", p))
2214 # in2out 1st interface
2215 pkts = self.create_stream_in(self.pg4, self.pg3)
2216 self.pg4.add_stream(pkts)
2217 self.pg_enable_capture(self.pg_interfaces)
2219 capture = self.pg3.get_capture(len(pkts))
2220 self.verify_capture_out(capture)
2222 # out2in 1st interface
2223 pkts = self.create_stream_out(self.pg3)
2224 self.pg3.add_stream(pkts)
2225 self.pg_enable_capture(self.pg_interfaces)
2227 capture = self.pg4.get_capture(len(pkts))
2228 self.verify_capture_in(capture, self.pg4)
2230 # in2out 2nd interface
2231 pkts = self.create_stream_in(self.pg5, self.pg3)
2232 self.pg5.add_stream(pkts)
2233 self.pg_enable_capture(self.pg_interfaces)
2235 capture = self.pg3.get_capture(len(pkts))
2236 self.verify_capture_out(capture)
2238 # out2in 2nd interface
2239 pkts = self.create_stream_out(self.pg3)
2240 self.pg3.add_stream(pkts)
2241 self.pg_enable_capture(self.pg_interfaces)
2243 capture = self.pg5.get_capture(len(pkts))
2244 self.verify_capture_in(capture, self.pg5)
2247 addresses = self.vapi.nat44_address_dump()
2248 self.assertEqual(len(addresses), 1)
2249 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
2250 self.assertEqual(len(sessions), 3)
2251 for session in sessions:
2252 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2253 self.assertEqual(str(session.inside_ip_address),
2254 self.pg5.remote_ip4)
2255 self.assertEqual(session.outside_ip_address,
2256 addresses[0].ip_address)
2257 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2258 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2259 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2260 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2261 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2262 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2263 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2264 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2265 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2267 # in2out 3rd interface
2268 pkts = self.create_stream_in(self.pg6, self.pg3)
2269 self.pg6.add_stream(pkts)
2270 self.pg_enable_capture(self.pg_interfaces)
2272 capture = self.pg3.get_capture(len(pkts))
2273 self.verify_capture_out(capture, static_nat_ip, True)
2275 # out2in 3rd interface
2276 pkts = self.create_stream_out(self.pg3, static_nat_ip)
2277 self.pg3.add_stream(pkts)
2278 self.pg_enable_capture(self.pg_interfaces)
2280 capture = self.pg6.get_capture(len(pkts))
2281 self.verify_capture_in(capture, self.pg6)
2283 # general user and session dump verifications
2284 users = self.vapi.nat44_user_dump()
2285 self.assertGreaterEqual(len(users), 3)
2286 addresses = self.vapi.nat44_address_dump()
2287 self.assertEqual(len(addresses), 1)
2289 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2291 for session in sessions:
2292 self.assertEqual(user.ip_address, session.inside_ip_address)
2293 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2294 self.assertTrue(session.protocol in
2295 [IP_PROTOS.tcp, IP_PROTOS.udp,
2297 self.assertFalse(session.flags &
2298 self.config_flags.NAT_IS_EXT_HOST_VALID)
2301 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
2302 self.assertGreaterEqual(len(sessions), 4)
2303 for session in sessions:
2304 self.assertFalse(session.flags & self.config_flags.NAT_IS_STATIC)
2305 self.assertEqual(str(session.inside_ip_address),
2306 self.pg4.remote_ip4)
2307 self.assertEqual(session.outside_ip_address,
2308 addresses[0].ip_address)
2311 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
2312 self.assertGreaterEqual(len(sessions), 3)
2313 for session in sessions:
2314 self.assertTrue(session.flags & self.config_flags.NAT_IS_STATIC)
2315 self.assertEqual(str(session.inside_ip_address),
2316 self.pg6.remote_ip4)
2317 self.assertEqual(str(session.outside_ip_address),
2319 self.assertTrue(session.inside_port in
2320 [self.tcp_port_in, self.udp_port_in,
2323 def test_hairpinning(self):
2324 """ NAT44 hairpinning - 1:1 NAPT """
2326 host = self.pg0.remote_hosts[0]
2327 server = self.pg0.remote_hosts[1]
2330 server_in_port = 5678
2331 server_out_port = 8765
2333 self.nat44_add_address(self.nat_addr)
2334 flags = self.config_flags.NAT_IS_INSIDE
2335 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2337 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2339 # add static mapping for server
2340 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2341 server_in_port, server_out_port,
2342 proto=IP_PROTOS.tcp)
2344 # send packet from host to server
2345 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2346 IP(src=host.ip4, dst=self.nat_addr) /
2347 TCP(sport=host_in_port, dport=server_out_port))
2348 self.pg0.add_stream(p)
2349 self.pg_enable_capture(self.pg_interfaces)
2351 capture = self.pg0.get_capture(1)
2356 self.assertEqual(ip.src, self.nat_addr)
2357 self.assertEqual(ip.dst, server.ip4)
2358 self.assertNotEqual(tcp.sport, host_in_port)
2359 self.assertEqual(tcp.dport, server_in_port)
2360 self.assert_packet_checksums_valid(p)
2361 host_out_port = tcp.sport
2363 self.logger.error(ppp("Unexpected or invalid packet:", p))
2366 # send reply from server to host
2367 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2368 IP(src=server.ip4, dst=self.nat_addr) /
2369 TCP(sport=server_in_port, dport=host_out_port))
2370 self.pg0.add_stream(p)
2371 self.pg_enable_capture(self.pg_interfaces)
2373 capture = self.pg0.get_capture(1)
2378 self.assertEqual(ip.src, self.nat_addr)
2379 self.assertEqual(ip.dst, host.ip4)
2380 self.assertEqual(tcp.sport, server_out_port)
2381 self.assertEqual(tcp.dport, host_in_port)
2382 self.assert_packet_checksums_valid(p)
2384 self.logger.error(ppp("Unexpected or invalid packet:", p))
2387 def test_hairpinning2(self):
2388 """ NAT44 hairpinning - 1:1 NAT"""
2390 server1_nat_ip = "10.0.0.10"
2391 server2_nat_ip = "10.0.0.11"
2392 host = self.pg0.remote_hosts[0]
2393 server1 = self.pg0.remote_hosts[1]
2394 server2 = self.pg0.remote_hosts[2]
2395 server_tcp_port = 22
2396 server_udp_port = 20
2398 self.nat44_add_address(self.nat_addr)
2399 flags = self.config_flags.NAT_IS_INSIDE
2400 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2402 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2404 # add static mapping for servers
2405 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2406 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
2410 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2411 IP(src=host.ip4, dst=server1_nat_ip) /
2412 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2414 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2415 IP(src=host.ip4, dst=server1_nat_ip) /
2416 UDP(sport=self.udp_port_in, dport=server_udp_port))
2418 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2419 IP(src=host.ip4, dst=server1_nat_ip) /
2420 ICMP(id=self.icmp_id_in, type='echo-request'))
2422 self.pg0.add_stream(pkts)
2423 self.pg_enable_capture(self.pg_interfaces)
2425 capture = self.pg0.get_capture(len(pkts))
2426 for packet in capture:
2428 self.assertEqual(packet[IP].src, self.nat_addr)
2429 self.assertEqual(packet[IP].dst, server1.ip4)
2430 if packet.haslayer(TCP):
2431 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2432 self.assertEqual(packet[TCP].dport, server_tcp_port)
2433 self.tcp_port_out = packet[TCP].sport
2434 self.assert_packet_checksums_valid(packet)
2435 elif packet.haslayer(UDP):
2436 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2437 self.assertEqual(packet[UDP].dport, server_udp_port)
2438 self.udp_port_out = packet[UDP].sport
2440 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2441 self.icmp_id_out = packet[ICMP].id
2443 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2448 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2449 IP(src=server1.ip4, dst=self.nat_addr) /
2450 TCP(sport=server_tcp_port, dport=self.tcp_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 UDP(sport=server_udp_port, dport=self.udp_port_out))
2456 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2457 IP(src=server1.ip4, dst=self.nat_addr) /
2458 ICMP(id=self.icmp_id_out, type='echo-reply'))
2460 self.pg0.add_stream(pkts)
2461 self.pg_enable_capture(self.pg_interfaces)
2463 capture = self.pg0.get_capture(len(pkts))
2464 for packet in capture:
2466 self.assertEqual(packet[IP].src, server1_nat_ip)
2467 self.assertEqual(packet[IP].dst, host.ip4)
2468 if packet.haslayer(TCP):
2469 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2470 self.assertEqual(packet[TCP].sport, server_tcp_port)
2471 self.assert_packet_checksums_valid(packet)
2472 elif packet.haslayer(UDP):
2473 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2474 self.assertEqual(packet[UDP].sport, server_udp_port)
2476 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2478 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2481 # server2 to server1
2483 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2484 IP(src=server2.ip4, dst=server1_nat_ip) /
2485 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2487 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2488 IP(src=server2.ip4, dst=server1_nat_ip) /
2489 UDP(sport=self.udp_port_in, dport=server_udp_port))
2491 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2492 IP(src=server2.ip4, dst=server1_nat_ip) /
2493 ICMP(id=self.icmp_id_in, type='echo-request'))
2495 self.pg0.add_stream(pkts)
2496 self.pg_enable_capture(self.pg_interfaces)
2498 capture = self.pg0.get_capture(len(pkts))
2499 for packet in capture:
2501 self.assertEqual(packet[IP].src, server2_nat_ip)
2502 self.assertEqual(packet[IP].dst, server1.ip4)
2503 if packet.haslayer(TCP):
2504 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2505 self.assertEqual(packet[TCP].dport, server_tcp_port)
2506 self.tcp_port_out = packet[TCP].sport
2507 self.assert_packet_checksums_valid(packet)
2508 elif packet.haslayer(UDP):
2509 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2510 self.assertEqual(packet[UDP].dport, server_udp_port)
2511 self.udp_port_out = packet[UDP].sport
2513 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2514 self.icmp_id_out = packet[ICMP].id
2516 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2519 # server1 to server2
2521 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2522 IP(src=server1.ip4, dst=server2_nat_ip) /
2523 TCP(sport=server_tcp_port, dport=self.tcp_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 UDP(sport=server_udp_port, dport=self.udp_port_out))
2529 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2530 IP(src=server1.ip4, dst=server2_nat_ip) /
2531 ICMP(id=self.icmp_id_out, type='echo-reply'))
2533 self.pg0.add_stream(pkts)
2534 self.pg_enable_capture(self.pg_interfaces)
2536 capture = self.pg0.get_capture(len(pkts))
2537 for packet in capture:
2539 self.assertEqual(packet[IP].src, server1_nat_ip)
2540 self.assertEqual(packet[IP].dst, server2.ip4)
2541 if packet.haslayer(TCP):
2542 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2543 self.assertEqual(packet[TCP].sport, server_tcp_port)
2544 self.assert_packet_checksums_valid(packet)
2545 elif packet.haslayer(UDP):
2546 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2547 self.assertEqual(packet[UDP].sport, server_udp_port)
2549 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2551 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2554 def test_max_translations_per_user(self):
2555 """ MAX translations per user - recycle the least recently used """
2557 self.nat44_add_address(self.nat_addr)
2558 flags = self.config_flags.NAT_IS_INSIDE
2559 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2561 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2563 # get maximum number of translations per user
2564 nat44_config = self.vapi.nat_show_config()
2566 # send more than maximum number of translations per user packets
2567 pkts_num = nat44_config.max_translations_per_user + 5
2569 for port in range(0, pkts_num):
2570 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2571 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2572 TCP(sport=1025 + port))
2574 self.pg0.add_stream(pkts)
2575 self.pg_enable_capture(self.pg_interfaces)
2578 # verify number of translated packet
2579 self.pg1.get_capture(pkts_num)
2581 users = self.vapi.nat44_user_dump()
2583 if user.ip_address == self.pg0.remote_ip4n:
2584 self.assertEqual(user.nsessions,
2585 nat44_config.max_translations_per_user)
2586 self.assertEqual(user.nstaticsessions, 0)
2589 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2591 proto=IP_PROTOS.tcp)
2592 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2593 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2594 TCP(sport=tcp_port))
2595 self.pg0.add_stream(p)
2596 self.pg_enable_capture(self.pg_interfaces)
2598 self.pg1.get_capture(1)
2599 users = self.vapi.nat44_user_dump()
2601 if user.ip_address == self.pg0.remote_ip4n:
2602 self.assertEqual(user.nsessions,
2603 nat44_config.max_translations_per_user - 1)
2604 self.assertEqual(user.nstaticsessions, 1)
2606 def test_interface_addr(self):
2607 """ Acquire NAT44 addresses from interface """
2608 self.vapi.nat44_add_del_interface_addr(self.pg7.sw_if_index)
2610 # no address in NAT pool
2611 addresses = self.vapi.nat44_address_dump()
2612 self.assertEqual(0, len(addresses))
2614 # configure interface address and check NAT address pool
2615 self.pg7.config_ip4()
2616 addresses = self.vapi.nat44_address_dump()
2617 self.assertEqual(1, len(addresses))
2618 self.assertEqual(str(addresses[0].ip_address), self.pg7.local_ip4)
2620 # remove interface address and check NAT address pool
2621 self.pg7.unconfig_ip4()
2622 addresses = self.vapi.nat44_address_dump()
2623 self.assertEqual(0, len(addresses))
2625 def test_interface_addr_static_mapping(self):
2626 """ Static mapping with addresses from interface """
2629 self.vapi.nat44_add_del_interface_addr(self.pg7.sw_if_index)
2630 self.nat44_add_static_mapping(
2632 external_sw_if_index=self.pg7.sw_if_index,
2635 # static mappings with external interface
2636 static_mappings = self.vapi.nat44_static_mapping_dump()
2637 self.assertEqual(1, len(static_mappings))
2638 self.assertEqual(self.pg7.sw_if_index,
2639 static_mappings[0].external_sw_if_index)
2640 self.assertEqual((static_mappings[0].tag).split(b'\0', 1)[0], tag)
2642 # configure interface address and check static mappings
2643 self.pg7.config_ip4()
2644 static_mappings = self.vapi.nat44_static_mapping_dump()
2645 self.assertEqual(2, len(static_mappings))
2647 for sm in static_mappings:
2648 if sm.external_sw_if_index == 0xFFFFFFFF:
2649 self.assertEqual(str(sm.external_ip_address),
2651 self.assertEqual((sm.tag).split(b'\0', 1)[0], tag)
2653 self.assertTrue(resolved)
2655 # remove interface address and check static mappings
2656 self.pg7.unconfig_ip4()
2657 static_mappings = self.vapi.nat44_static_mapping_dump()
2658 self.assertEqual(1, len(static_mappings))
2659 self.assertEqual(self.pg7.sw_if_index,
2660 static_mappings[0].external_sw_if_index)
2661 self.assertEqual((static_mappings[0].tag).split(b'\0', 1)[0], tag)
2663 # configure interface address again and check static mappings
2664 self.pg7.config_ip4()
2665 static_mappings = self.vapi.nat44_static_mapping_dump()
2666 self.assertEqual(2, len(static_mappings))
2668 for sm in static_mappings:
2669 if sm.external_sw_if_index == 0xFFFFFFFF:
2670 self.assertEqual(str(sm.external_ip_address),
2672 self.assertEqual((sm.tag).split(b'\0', 1)[0], tag)
2674 self.assertTrue(resolved)
2676 # remove static mapping
2677 self.nat44_add_static_mapping(
2679 external_sw_if_index=self.pg7.sw_if_index,
2682 static_mappings = self.vapi.nat44_static_mapping_dump()
2683 self.assertEqual(0, len(static_mappings))
2685 def test_interface_addr_identity_nat(self):
2686 """ Identity NAT with addresses from interface """
2689 self.vapi.nat44_add_del_interface_addr(self.pg7.sw_if_index)
2690 self.vapi.nat44_add_del_identity_mapping(
2691 sw_if_index=self.pg7.sw_if_index,
2693 protocol=IP_PROTOS.tcp)
2695 # identity mappings with external interface
2696 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2697 self.assertEqual(1, len(identity_mappings))
2698 self.assertEqual(self.pg7.sw_if_index,
2699 identity_mappings[0].sw_if_index)
2701 # configure interface address and check identity mappings
2702 self.pg7.config_ip4()
2703 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2705 self.assertEqual(2, len(identity_mappings))
2706 for sm in identity_mappings:
2707 if sm.sw_if_index == 0xFFFFFFFF:
2708 self.assertEqual(str(identity_mappings[0].ip_address),
2710 self.assertEqual(port, identity_mappings[0].port)
2711 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2713 self.assertTrue(resolved)
2715 # remove interface address and check identity mappings
2716 self.pg7.unconfig_ip4()
2717 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2718 self.assertEqual(1, len(identity_mappings))
2719 self.assertEqual(self.pg7.sw_if_index,
2720 identity_mappings[0].sw_if_index)
2722 def test_ipfix_nat44_sess(self):
2723 """ IPFIX logging NAT44 session created/deleted """
2724 self.ipfix_domain_id = 10
2725 self.ipfix_src_port = 20202
2726 collector_port = 30303
2727 bind_layers(UDP, IPFIX, dport=30303)
2728 self.nat44_add_address(self.nat_addr)
2729 flags = self.config_flags.NAT_IS_INSIDE
2730 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2732 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2733 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2734 src_address=self.pg3.local_ip4n,
2736 template_interval=10,
2737 collector_port=collector_port)
2738 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2739 src_port=self.ipfix_src_port)
2741 pkts = self.create_stream_in(self.pg0, self.pg1)
2742 self.pg0.add_stream(pkts)
2743 self.pg_enable_capture(self.pg_interfaces)
2745 capture = self.pg1.get_capture(len(pkts))
2746 self.verify_capture_out(capture)
2747 self.nat44_add_address(self.nat_addr, is_add=0)
2748 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2749 capture = self.pg3.get_capture(9)
2750 ipfix = IPFIXDecoder()
2751 # first load template
2753 self.assertTrue(p.haslayer(IPFIX))
2754 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2755 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2756 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2757 self.assertEqual(p[UDP].dport, collector_port)
2758 self.assertEqual(p[IPFIX].observationDomainID,
2759 self.ipfix_domain_id)
2760 if p.haslayer(Template):
2761 ipfix.add_template(p.getlayer(Template))
2762 # verify events in data set
2764 if p.haslayer(Data):
2765 data = ipfix.decode_data_set(p.getlayer(Set))
2766 self.verify_ipfix_nat44_ses(data)
2768 def test_ipfix_addr_exhausted(self):
2769 """ IPFIX logging NAT addresses exhausted """
2770 flags = self.config_flags.NAT_IS_INSIDE
2771 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2773 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2774 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2775 src_address=self.pg3.local_ip4n,
2777 template_interval=10)
2778 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2779 src_port=self.ipfix_src_port)
2781 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2782 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2784 self.pg0.add_stream(p)
2785 self.pg_enable_capture(self.pg_interfaces)
2787 self.pg1.assert_nothing_captured()
2789 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2790 capture = self.pg3.get_capture(9)
2791 ipfix = IPFIXDecoder()
2792 # first load template
2794 self.assertTrue(p.haslayer(IPFIX))
2795 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2796 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2797 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2798 self.assertEqual(p[UDP].dport, 4739)
2799 self.assertEqual(p[IPFIX].observationDomainID,
2800 self.ipfix_domain_id)
2801 if p.haslayer(Template):
2802 ipfix.add_template(p.getlayer(Template))
2803 # verify events in data set
2805 if p.haslayer(Data):
2806 data = ipfix.decode_data_set(p.getlayer(Set))
2807 self.verify_ipfix_addr_exhausted(data)
2809 @unittest.skipUnless(running_extended_tests, "part of extended tests")
2810 def test_ipfix_max_sessions(self):
2811 """ IPFIX logging maximum session entries exceeded """
2812 self.nat44_add_address(self.nat_addr)
2813 flags = self.config_flags.NAT_IS_INSIDE
2814 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2816 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2818 nat44_config = self.vapi.nat_show_config()
2819 max_sessions = 10 * nat44_config.translation_buckets
2822 for i in range(0, max_sessions):
2823 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2824 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2825 IP(src=src, dst=self.pg1.remote_ip4) /
2828 self.pg0.add_stream(pkts)
2829 self.pg_enable_capture(self.pg_interfaces)
2832 self.pg1.get_capture(max_sessions)
2833 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2834 src_address=self.pg3.local_ip4n,
2836 template_interval=10)
2837 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
2838 src_port=self.ipfix_src_port)
2840 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2841 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2843 self.pg0.add_stream(p)
2844 self.pg_enable_capture(self.pg_interfaces)
2846 self.pg1.assert_nothing_captured()
2848 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2849 capture = self.pg3.get_capture(9)
2850 ipfix = IPFIXDecoder()
2851 # first load template
2853 self.assertTrue(p.haslayer(IPFIX))
2854 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2855 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2856 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2857 self.assertEqual(p[UDP].dport, 4739)
2858 self.assertEqual(p[IPFIX].observationDomainID,
2859 self.ipfix_domain_id)
2860 if p.haslayer(Template):
2861 ipfix.add_template(p.getlayer(Template))
2862 # verify events in data set
2864 if p.haslayer(Data):
2865 data = ipfix.decode_data_set(p.getlayer(Set))
2866 self.verify_ipfix_max_sessions(data, max_sessions)
2868 def test_syslog_apmap(self):
2869 """ Test syslog address and port mapping creation and deletion """
2870 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
2871 self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
2872 self.nat44_add_address(self.nat_addr)
2873 flags = self.config_flags.NAT_IS_INSIDE
2874 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2876 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2878 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2879 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2880 TCP(sport=self.tcp_port_in, dport=20))
2881 self.pg0.add_stream(p)
2882 self.pg_enable_capture(self.pg_interfaces)
2884 capture = self.pg1.get_capture(1)
2885 self.tcp_port_out = capture[0][TCP].sport
2886 capture = self.pg3.get_capture(1)
2887 self.verify_syslog_apmap(capture[0][Raw].load)
2889 self.pg_enable_capture(self.pg_interfaces)
2891 self.nat44_add_address(self.nat_addr, is_add=0)
2892 capture = self.pg3.get_capture(1)
2893 self.verify_syslog_apmap(capture[0][Raw].load, False)
2895 def test_pool_addr_fib(self):
2896 """ NAT44 add pool addresses to FIB """
2897 static_addr = '10.0.0.10'
2898 self.nat44_add_address(self.nat_addr)
2899 flags = self.config_flags.NAT_IS_INSIDE
2900 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2902 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2903 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
2906 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2907 ARP(op=ARP.who_has, pdst=self.nat_addr,
2908 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2909 self.pg1.add_stream(p)
2910 self.pg_enable_capture(self.pg_interfaces)
2912 capture = self.pg1.get_capture(1)
2913 self.assertTrue(capture[0].haslayer(ARP))
2914 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2917 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2918 ARP(op=ARP.who_has, pdst=static_addr,
2919 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2920 self.pg1.add_stream(p)
2921 self.pg_enable_capture(self.pg_interfaces)
2923 capture = self.pg1.get_capture(1)
2924 self.assertTrue(capture[0].haslayer(ARP))
2925 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2927 # send ARP to non-NAT44 interface
2928 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2929 ARP(op=ARP.who_has, pdst=self.nat_addr,
2930 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2931 self.pg2.add_stream(p)
2932 self.pg_enable_capture(self.pg_interfaces)
2934 self.pg1.assert_nothing_captured()
2936 # remove addresses and verify
2937 self.nat44_add_address(self.nat_addr, is_add=0)
2938 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2941 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2942 ARP(op=ARP.who_has, pdst=self.nat_addr,
2943 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2944 self.pg1.add_stream(p)
2945 self.pg_enable_capture(self.pg_interfaces)
2947 self.pg1.assert_nothing_captured()
2949 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2950 ARP(op=ARP.who_has, pdst=static_addr,
2951 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2952 self.pg1.add_stream(p)
2953 self.pg_enable_capture(self.pg_interfaces)
2955 self.pg1.assert_nothing_captured()
2957 def test_vrf_mode(self):
2958 """ NAT44 tenant VRF aware address pool mode """
2962 nat_ip1 = "10.0.0.10"
2963 nat_ip2 = "10.0.0.11"
2965 self.pg0.unconfig_ip4()
2966 self.pg1.unconfig_ip4()
2967 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
2968 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
2969 self.pg0.set_table_ip4(vrf_id1)
2970 self.pg1.set_table_ip4(vrf_id2)
2971 self.pg0.config_ip4()
2972 self.pg1.config_ip4()
2973 self.pg0.resolve_arp()
2974 self.pg1.resolve_arp()
2976 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2977 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2978 flags = self.config_flags.NAT_IS_INSIDE
2979 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
2981 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2983 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index)
2987 pkts = self.create_stream_in(self.pg0, self.pg2)
2988 self.pg0.add_stream(pkts)
2989 self.pg_enable_capture(self.pg_interfaces)
2991 capture = self.pg2.get_capture(len(pkts))
2992 self.verify_capture_out(capture, nat_ip1)
2995 pkts = self.create_stream_in(self.pg1, self.pg2)
2996 self.pg1.add_stream(pkts)
2997 self.pg_enable_capture(self.pg_interfaces)
2999 capture = self.pg2.get_capture(len(pkts))
3000 self.verify_capture_out(capture, nat_ip2)
3003 self.pg0.unconfig_ip4()
3004 self.pg1.unconfig_ip4()
3005 self.pg0.set_table_ip4(0)
3006 self.pg1.set_table_ip4(0)
3007 self.pg0.config_ip4()
3008 self.pg1.config_ip4()
3009 self.pg0.resolve_arp()
3010 self.pg1.resolve_arp()
3011 self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id1)
3012 self.vapi.ip_table_add_del(is_add=0, table_id=vrf_id2)
3014 def test_vrf_feature_independent(self):
3015 """ NAT44 tenant VRF independent address pool mode """
3017 nat_ip1 = "10.0.0.10"
3018 nat_ip2 = "10.0.0.11"
3020 self.nat44_add_address(nat_ip1)
3021 self.nat44_add_address(nat_ip2, vrf_id=99)
3022 flags = self.config_flags.NAT_IS_INSIDE
3023 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3025 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3027 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index)
3030 pkts = self.create_stream_in(self.pg0, self.pg2)
3031 self.pg0.add_stream(pkts)
3032 self.pg_enable_capture(self.pg_interfaces)
3034 capture = self.pg2.get_capture(len(pkts))
3035 self.verify_capture_out(capture, nat_ip1)
3038 pkts = self.create_stream_in(self.pg1, self.pg2)
3039 self.pg1.add_stream(pkts)
3040 self.pg_enable_capture(self.pg_interfaces)
3042 capture = self.pg2.get_capture(len(pkts))
3043 self.verify_capture_out(capture, nat_ip1)
3045 def test_dynamic_ipless_interfaces(self):
3046 """ NAT44 interfaces without configured IP address """
3048 self.vapi.ip_neighbor_add_del(
3049 self.pg7.sw_if_index,
3050 self.pg7.remote_mac,
3051 self.pg7.remote_ip4,
3052 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3053 IP_API_NEIGHBOR_FLAG_STATIC))
3054 self.vapi.ip_neighbor_add_del(
3055 self.pg8.sw_if_index,
3056 self.pg8.remote_mac,
3057 self.pg8.remote_ip4,
3058 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3059 IP_API_NEIGHBOR_FLAG_STATIC))
3061 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3062 dst_address_length=32,
3063 next_hop_address=self.pg7.remote_ip4n,
3064 next_hop_sw_if_index=self.pg7.sw_if_index)
3065 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3066 dst_address_length=32,
3067 next_hop_address=self.pg8.remote_ip4n,
3068 next_hop_sw_if_index=self.pg8.sw_if_index)
3070 self.nat44_add_address(self.nat_addr)
3071 flags = self.config_flags.NAT_IS_INSIDE
3072 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index,
3074 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index)
3077 pkts = self.create_stream_in(self.pg7, self.pg8)
3078 self.pg7.add_stream(pkts)
3079 self.pg_enable_capture(self.pg_interfaces)
3081 capture = self.pg8.get_capture(len(pkts))
3082 self.verify_capture_out(capture)
3085 pkts = self.create_stream_out(self.pg8, self.nat_addr)
3086 self.pg8.add_stream(pkts)
3087 self.pg_enable_capture(self.pg_interfaces)
3089 capture = self.pg7.get_capture(len(pkts))
3090 self.verify_capture_in(capture, self.pg7)
3092 def test_static_ipless_interfaces(self):
3093 """ NAT44 interfaces without configured IP address - 1:1 NAT """
3095 self.vapi.ip_neighbor_add_del(
3096 self.pg7.sw_if_index,
3097 self.pg7.remote_mac,
3098 self.pg7.remote_ip4,
3099 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3100 IP_API_NEIGHBOR_FLAG_STATIC))
3101 self.vapi.ip_neighbor_add_del(
3102 self.pg8.sw_if_index,
3103 self.pg8.remote_mac,
3104 self.pg8.remote_ip4,
3105 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3106 IP_API_NEIGHBOR_FLAG_STATIC))
3108 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3109 dst_address_length=32,
3110 next_hop_address=self.pg7.remote_ip4n,
3111 next_hop_sw_if_index=self.pg7.sw_if_index)
3112 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3113 dst_address_length=32,
3114 next_hop_address=self.pg8.remote_ip4n,
3115 next_hop_sw_if_index=self.pg8.sw_if_index)
3117 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
3118 flags = self.config_flags.NAT_IS_INSIDE
3119 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index,
3121 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index)
3124 pkts = self.create_stream_out(self.pg8)
3125 self.pg8.add_stream(pkts)
3126 self.pg_enable_capture(self.pg_interfaces)
3128 capture = self.pg7.get_capture(len(pkts))
3129 self.verify_capture_in(capture, self.pg7)
3132 pkts = self.create_stream_in(self.pg7, self.pg8)
3133 self.pg7.add_stream(pkts)
3134 self.pg_enable_capture(self.pg_interfaces)
3136 capture = self.pg8.get_capture(len(pkts))
3137 self.verify_capture_out(capture, self.nat_addr, True)
3139 def test_static_with_port_ipless_interfaces(self):
3140 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
3142 self.tcp_port_out = 30606
3143 self.udp_port_out = 30607
3144 self.icmp_id_out = 30608
3146 self.vapi.ip_neighbor_add_del(
3147 self.pg7.sw_if_index,
3148 self.pg7.remote_mac,
3149 self.pg7.remote_ip4,
3150 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3151 IP_API_NEIGHBOR_FLAG_STATIC))
3152 self.vapi.ip_neighbor_add_del(
3153 self.pg8.sw_if_index,
3154 self.pg8.remote_mac,
3155 self.pg8.remote_ip4,
3156 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3157 IP_API_NEIGHBOR_FLAG_STATIC))
3159 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3160 dst_address_length=32,
3161 next_hop_address=self.pg7.remote_ip4n,
3162 next_hop_sw_if_index=self.pg7.sw_if_index)
3163 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3164 dst_address_length=32,
3165 next_hop_address=self.pg8.remote_ip4n,
3166 next_hop_sw_if_index=self.pg8.sw_if_index)
3168 self.nat44_add_address(self.nat_addr)
3169 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3170 self.tcp_port_in, self.tcp_port_out,
3171 proto=IP_PROTOS.tcp)
3172 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3173 self.udp_port_in, self.udp_port_out,
3174 proto=IP_PROTOS.udp)
3175 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3176 self.icmp_id_in, self.icmp_id_out,
3177 proto=IP_PROTOS.icmp)
3178 flags = self.config_flags.NAT_IS_INSIDE
3179 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index,
3181 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index)
3184 pkts = self.create_stream_out(self.pg8)
3185 self.pg8.add_stream(pkts)
3186 self.pg_enable_capture(self.pg_interfaces)
3188 capture = self.pg7.get_capture(len(pkts))
3189 self.verify_capture_in(capture, self.pg7)
3192 pkts = self.create_stream_in(self.pg7, self.pg8)
3193 self.pg7.add_stream(pkts)
3194 self.pg_enable_capture(self.pg_interfaces)
3196 capture = self.pg8.get_capture(len(pkts))
3197 self.verify_capture_out(capture)
3199 def test_static_unknown_proto(self):
3200 """ 1:1 NAT translate packet with unknown protocol """
3201 nat_ip = "10.0.0.10"
3202 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
3203 flags = self.config_flags.NAT_IS_INSIDE
3204 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3206 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3209 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3210 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3212 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3213 TCP(sport=1234, dport=1234))
3214 self.pg0.add_stream(p)
3215 self.pg_enable_capture(self.pg_interfaces)
3217 p = self.pg1.get_capture(1)
3220 self.assertEqual(packet[IP].src, nat_ip)
3221 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3222 self.assertEqual(packet.haslayer(GRE), 1)
3223 self.assert_packet_checksums_valid(packet)
3225 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3229 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3230 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3232 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3233 TCP(sport=1234, dport=1234))
3234 self.pg1.add_stream(p)
3235 self.pg_enable_capture(self.pg_interfaces)
3237 p = self.pg0.get_capture(1)
3240 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3241 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3242 self.assertEqual(packet.haslayer(GRE), 1)
3243 self.assert_packet_checksums_valid(packet)
3245 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3248 def test_hairpinning_static_unknown_proto(self):
3249 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3251 host = self.pg0.remote_hosts[0]
3252 server = self.pg0.remote_hosts[1]
3254 host_nat_ip = "10.0.0.10"
3255 server_nat_ip = "10.0.0.11"
3257 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3258 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3259 flags = self.config_flags.NAT_IS_INSIDE
3260 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3262 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3265 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3266 IP(src=host.ip4, dst=server_nat_ip) /
3268 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3269 TCP(sport=1234, dport=1234))
3270 self.pg0.add_stream(p)
3271 self.pg_enable_capture(self.pg_interfaces)
3273 p = self.pg0.get_capture(1)
3276 self.assertEqual(packet[IP].src, host_nat_ip)
3277 self.assertEqual(packet[IP].dst, server.ip4)
3278 self.assertEqual(packet.haslayer(GRE), 1)
3279 self.assert_packet_checksums_valid(packet)
3281 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3285 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3286 IP(src=server.ip4, dst=host_nat_ip) /
3288 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3289 TCP(sport=1234, dport=1234))
3290 self.pg0.add_stream(p)
3291 self.pg_enable_capture(self.pg_interfaces)
3293 p = self.pg0.get_capture(1)
3296 self.assertEqual(packet[IP].src, server_nat_ip)
3297 self.assertEqual(packet[IP].dst, host.ip4)
3298 self.assertEqual(packet.haslayer(GRE), 1)
3299 self.assert_packet_checksums_valid(packet)
3301 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3304 def test_output_feature(self):
3305 """ NAT44 interface output feature (in2out postrouting) """
3306 self.nat44_add_address(self.nat_addr)
3307 flags = self.config_flags.NAT_IS_INSIDE
3308 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index,
3310 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3312 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index)
3315 pkts = self.create_stream_in(self.pg0, self.pg3)
3316 self.pg0.add_stream(pkts)
3317 self.pg_enable_capture(self.pg_interfaces)
3319 capture = self.pg3.get_capture(len(pkts))
3320 self.verify_capture_out(capture)
3323 pkts = self.create_stream_out(self.pg3)
3324 self.pg3.add_stream(pkts)
3325 self.pg_enable_capture(self.pg_interfaces)
3327 capture = self.pg0.get_capture(len(pkts))
3328 self.verify_capture_in(capture, self.pg0)
3330 # from non-NAT interface to NAT inside interface
3331 pkts = self.create_stream_in(self.pg2, self.pg0)
3332 self.pg2.add_stream(pkts)
3333 self.pg_enable_capture(self.pg_interfaces)
3335 capture = self.pg0.get_capture(len(pkts))
3336 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3338 def test_output_feature_vrf_aware(self):
3339 """ NAT44 interface output feature VRF aware (in2out postrouting) """
3340 nat_ip_vrf10 = "10.0.0.10"
3341 nat_ip_vrf20 = "10.0.0.20"
3343 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3344 dst_address_length=32,
3345 next_hop_address=self.pg3.remote_ip4n,
3346 next_hop_sw_if_index=self.pg3.sw_if_index,
3348 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3349 dst_address_length=32,
3350 next_hop_address=self.pg3.remote_ip4n,
3351 next_hop_sw_if_index=self.pg3.sw_if_index,
3354 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3355 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3356 flags = self.config_flags.NAT_IS_INSIDE
3357 self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index,
3359 self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index,
3361 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index)
3364 pkts = self.create_stream_in(self.pg4, self.pg3)
3365 self.pg4.add_stream(pkts)
3366 self.pg_enable_capture(self.pg_interfaces)
3368 capture = self.pg3.get_capture(len(pkts))
3369 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3372 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3373 self.pg3.add_stream(pkts)
3374 self.pg_enable_capture(self.pg_interfaces)
3376 capture = self.pg4.get_capture(len(pkts))
3377 self.verify_capture_in(capture, self.pg4)
3380 pkts = self.create_stream_in(self.pg6, self.pg3)
3381 self.pg6.add_stream(pkts)
3382 self.pg_enable_capture(self.pg_interfaces)
3384 capture = self.pg3.get_capture(len(pkts))
3385 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3388 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3389 self.pg3.add_stream(pkts)
3390 self.pg_enable_capture(self.pg_interfaces)
3392 capture = self.pg6.get_capture(len(pkts))
3393 self.verify_capture_in(capture, self.pg6)
3395 def test_output_feature_hairpinning(self):
3396 """ NAT44 interface output feature hairpinning (in2out postrouting) """
3397 host = self.pg0.remote_hosts[0]
3398 server = self.pg0.remote_hosts[1]
3401 server_in_port = 5678
3402 server_out_port = 8765
3404 self.nat44_add_address(self.nat_addr)
3405 flags = self.config_flags.NAT_IS_INSIDE
3406 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index,
3408 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
3410 # add static mapping for server
3411 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3412 server_in_port, server_out_port,
3413 proto=IP_PROTOS.tcp)
3415 # send packet from host to server
3416 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3417 IP(src=host.ip4, dst=self.nat_addr) /
3418 TCP(sport=host_in_port, dport=server_out_port))
3419 self.pg0.add_stream(p)
3420 self.pg_enable_capture(self.pg_interfaces)
3422 capture = self.pg0.get_capture(1)
3427 self.assertEqual(ip.src, self.nat_addr)
3428 self.assertEqual(ip.dst, server.ip4)
3429 self.assertNotEqual(tcp.sport, host_in_port)
3430 self.assertEqual(tcp.dport, server_in_port)
3431 self.assert_packet_checksums_valid(p)
3432 host_out_port = tcp.sport
3434 self.logger.error(ppp("Unexpected or invalid packet:", p))
3437 # send reply from server to host
3438 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3439 IP(src=server.ip4, dst=self.nat_addr) /
3440 TCP(sport=server_in_port, dport=host_out_port))
3441 self.pg0.add_stream(p)
3442 self.pg_enable_capture(self.pg_interfaces)
3444 capture = self.pg0.get_capture(1)
3449 self.assertEqual(ip.src, self.nat_addr)
3450 self.assertEqual(ip.dst, host.ip4)
3451 self.assertEqual(tcp.sport, server_out_port)
3452 self.assertEqual(tcp.dport, host_in_port)
3453 self.assert_packet_checksums_valid(p)
3455 self.logger.error(ppp("Unexpected or invalid packet:", p))
3458 def test_one_armed_nat44(self):
3459 """ One armed NAT44 """
3460 remote_host = self.pg9.remote_hosts[0]
3461 local_host = self.pg9.remote_hosts[1]
3464 self.nat44_add_address(self.nat_addr)
3465 flags = self.config_flags.NAT_IS_INSIDE
3466 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3467 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3471 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3472 IP(src=local_host.ip4, dst=remote_host.ip4) /
3473 TCP(sport=12345, dport=80))
3474 self.pg9.add_stream(p)
3475 self.pg_enable_capture(self.pg_interfaces)
3477 capture = self.pg9.get_capture(1)
3482 self.assertEqual(ip.src, self.nat_addr)
3483 self.assertEqual(ip.dst, remote_host.ip4)
3484 self.assertNotEqual(tcp.sport, 12345)
3485 external_port = tcp.sport
3486 self.assertEqual(tcp.dport, 80)
3487 self.assert_packet_checksums_valid(p)
3489 self.logger.error(ppp("Unexpected or invalid packet:", p))
3493 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3494 IP(src=remote_host.ip4, dst=self.nat_addr) /
3495 TCP(sport=80, dport=external_port))
3496 self.pg9.add_stream(p)
3497 self.pg_enable_capture(self.pg_interfaces)
3499 capture = self.pg9.get_capture(1)
3504 self.assertEqual(ip.src, remote_host.ip4)
3505 self.assertEqual(ip.dst, local_host.ip4)
3506 self.assertEqual(tcp.sport, 80)
3507 self.assertEqual(tcp.dport, 12345)
3508 self.assert_packet_checksums_valid(p)
3510 self.logger.error(ppp("Unexpected or invalid packet:", p))
3513 err = self.statistics.get_counter('/err/nat44-classify/next in2out')
3514 self.assertEqual(err, 1)
3515 err = self.statistics.get_counter('/err/nat44-classify/next out2in')
3516 self.assertEqual(err, 1)
3518 def test_del_session(self):
3519 """ Delete NAT44 session """
3520 self.nat44_add_address(self.nat_addr)
3521 flags = self.config_flags.NAT_IS_INSIDE
3522 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3524 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3526 pkts = self.create_stream_in(self.pg0, self.pg1)
3527 self.pg0.add_stream(pkts)
3528 self.pg_enable_capture(self.pg_interfaces)
3530 self.pg1.get_capture(len(pkts))
3532 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3533 nsessions = len(sessions)
3535 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3536 sessions[0].inside_port,
3537 sessions[0].protocol,
3538 flags=self.config_flags.NAT_IS_INSIDE)
3539 self.vapi.nat44_del_session(sessions[1].outside_ip_address,
3540 sessions[1].outside_port,
3541 sessions[1].protocol)
3543 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3544 self.assertEqual(nsessions - len(sessions), 2)
3546 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3547 sessions[0].inside_port,
3548 sessions[0].protocol,
3549 flags=self.config_flags.NAT_IS_INSIDE)
3551 self.verify_no_nat44_user()
3553 def test_set_get_reass(self):
3554 """ NAT44 set/get virtual fragmentation reassembly """
3555 reas_cfg1 = self.vapi.nat_get_reass()
3557 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3558 max_reass=reas_cfg1.ip4_max_reass * 2,
3559 max_frag=reas_cfg1.ip4_max_frag * 2)
3561 reas_cfg2 = self.vapi.nat_get_reass()
3563 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3564 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3565 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3567 self.vapi.nat_set_reass(drop_frag=1)
3568 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3570 def test_frag_in_order(self):
3571 """ NAT44 translate fragments arriving in order """
3573 self.nat44_add_address(self.nat_addr)
3574 flags = self.config_flags.NAT_IS_INSIDE
3575 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3577 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3579 self.frag_in_order(proto=IP_PROTOS.tcp)
3580 self.frag_in_order(proto=IP_PROTOS.udp)
3581 self.frag_in_order(proto=IP_PROTOS.icmp)
3583 def test_frag_forwarding(self):
3584 """ NAT44 forwarding fragment test """
3585 self.vapi.nat44_add_del_interface_addr(self.pg1.sw_if_index)
3586 flags = self.config_flags.NAT_IS_INSIDE
3587 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3589 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3590 self.vapi.nat44_forwarding_enable_disable(1)
3592 data = b"A" * 16 + b"B" * 16 + b"C" * 3
3593 pkts = self.create_stream_frag(self.pg1,
3594 self.pg0.remote_ip4,
3598 proto=IP_PROTOS.udp)
3599 self.pg1.add_stream(pkts)
3600 self.pg_enable_capture(self.pg_interfaces)
3602 frags = self.pg0.get_capture(len(pkts))
3603 p = self.reass_frags_and_verify(frags,
3604 self.pg1.remote_ip4,
3605 self.pg0.remote_ip4)
3606 self.assertEqual(p[UDP].sport, 4789)
3607 self.assertEqual(p[UDP].dport, 4789)
3608 self.assertEqual(data, p[Raw].load)
3610 def test_reass_hairpinning(self):
3611 """ NAT44 fragments hairpinning """
3613 self.server = self.pg0.remote_hosts[1]
3614 self.host_in_port = random.randint(1025, 65535)
3615 self.server_in_port = random.randint(1025, 65535)
3616 self.server_out_port = random.randint(1025, 65535)
3618 self.nat44_add_address(self.nat_addr)
3619 flags = self.config_flags.NAT_IS_INSIDE
3620 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3622 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3623 # add static mapping for server
3624 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3625 self.server_in_port,
3626 self.server_out_port,
3627 proto=IP_PROTOS.tcp)
3628 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3629 self.server_in_port,
3630 self.server_out_port,
3631 proto=IP_PROTOS.udp)
3632 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
3634 self.reass_hairpinning(proto=IP_PROTOS.tcp)
3635 self.reass_hairpinning(proto=IP_PROTOS.udp)
3636 self.reass_hairpinning(proto=IP_PROTOS.icmp)
3638 def test_frag_out_of_order(self):
3639 """ NAT44 translate fragments arriving out of order """
3641 self.nat44_add_address(self.nat_addr)
3642 flags = self.config_flags.NAT_IS_INSIDE
3643 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3645 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3647 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3648 self.frag_out_of_order(proto=IP_PROTOS.udp)
3649 self.frag_out_of_order(proto=IP_PROTOS.icmp)
3651 def test_port_restricted(self):
3652 """ Port restricted NAT44 (MAP-E CE) """
3653 self.nat44_add_address(self.nat_addr)
3654 flags = self.config_flags.NAT_IS_INSIDE
3655 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3657 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3658 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3663 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3664 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3665 TCP(sport=4567, dport=22))
3666 self.pg0.add_stream(p)
3667 self.pg_enable_capture(self.pg_interfaces)
3669 capture = self.pg1.get_capture(1)
3674 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3675 self.assertEqual(ip.src, self.nat_addr)
3676 self.assertEqual(tcp.dport, 22)
3677 self.assertNotEqual(tcp.sport, 4567)
3678 self.assertEqual((tcp.sport >> 6) & 63, 10)
3679 self.assert_packet_checksums_valid(p)
3681 self.logger.error(ppp("Unexpected or invalid packet:", p))
3684 def test_port_range(self):
3685 """ External address port range """
3686 self.nat44_add_address(self.nat_addr)
3687 flags = self.config_flags.NAT_IS_INSIDE
3688 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3690 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3691 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3696 for port in range(0, 5):
3697 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3698 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3699 TCP(sport=1125 + port))
3701 self.pg0.add_stream(pkts)
3702 self.pg_enable_capture(self.pg_interfaces)
3704 capture = self.pg1.get_capture(3)
3707 self.assertGreaterEqual(tcp.sport, 1025)
3708 self.assertLessEqual(tcp.sport, 1027)
3710 def test_ipfix_max_frags(self):
3711 """ IPFIX logging maximum fragments pending reassembly exceeded """
3712 self.nat44_add_address(self.nat_addr)
3713 flags = self.config_flags.NAT_IS_INSIDE
3714 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3716 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3717 self.vapi.nat_set_reass(max_frag=1)
3718 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
3719 src_address=self.pg3.local_ip4n,
3721 template_interval=10)
3722 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
3723 src_port=self.ipfix_src_port)
3725 data = b"A" * 4 + b"B" * 16 + b"C" * 3
3726 self.tcp_port_in = random.randint(1025, 65535)
3727 pkts = self.create_stream_frag(self.pg0,
3728 self.pg1.remote_ip4,
3733 self.pg0.add_stream(pkts)
3734 self.pg_enable_capture(self.pg_interfaces)
3736 self.pg1.assert_nothing_captured()
3738 self.vapi.cli("ipfix flush") # FIXME this should be an API call
3739 capture = self.pg3.get_capture(9)
3740 ipfix = IPFIXDecoder()
3741 # first load template
3743 self.assertTrue(p.haslayer(IPFIX))
3744 self.assertEqual(p[IP].src, self.pg3.local_ip4)
3745 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
3746 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
3747 self.assertEqual(p[UDP].dport, 4739)
3748 self.assertEqual(p[IPFIX].observationDomainID,
3749 self.ipfix_domain_id)
3750 if p.haslayer(Template):
3751 ipfix.add_template(p.getlayer(Template))
3752 # verify events in data set
3754 if p.haslayer(Data):
3755 data = ipfix.decode_data_set(p.getlayer(Set))
3756 self.verify_ipfix_max_fragments_ip4(data, 1,
3757 self.pg0.remote_ip4n)
3759 def test_multiple_outside_vrf(self):
3760 """ Multiple outside VRF """
3764 self.pg1.unconfig_ip4()
3765 self.pg2.unconfig_ip4()
3766 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id1)
3767 self.vapi.ip_table_add_del(is_add=1, table_id=vrf_id2)
3768 self.pg1.set_table_ip4(vrf_id1)
3769 self.pg2.set_table_ip4(vrf_id2)
3770 self.pg1.config_ip4()
3771 self.pg2.config_ip4()
3772 self.pg1.resolve_arp()
3773 self.pg2.resolve_arp()
3775 self.nat44_add_address(self.nat_addr)
3776 flags = self.config_flags.NAT_IS_INSIDE
3777 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3779 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3780 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index)
3784 pkts = self.create_stream_in(self.pg0, self.pg1)
3785 self.pg0.add_stream(pkts)
3786 self.pg_enable_capture(self.pg_interfaces)
3788 capture = self.pg1.get_capture(len(pkts))
3789 self.verify_capture_out(capture, self.nat_addr)
3791 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3792 self.pg1.add_stream(pkts)
3793 self.pg_enable_capture(self.pg_interfaces)
3795 capture = self.pg0.get_capture(len(pkts))
3796 self.verify_capture_in(capture, self.pg0)
3798 self.tcp_port_in = 60303
3799 self.udp_port_in = 60304
3800 self.icmp_id_in = 60305
3803 pkts = self.create_stream_in(self.pg0, self.pg2)
3804 self.pg0.add_stream(pkts)
3805 self.pg_enable_capture(self.pg_interfaces)
3807 capture = self.pg2.get_capture(len(pkts))
3808 self.verify_capture_out(capture, self.nat_addr)
3810 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3811 self.pg2.add_stream(pkts)
3812 self.pg_enable_capture(self.pg_interfaces)
3814 capture = self.pg0.get_capture(len(pkts))
3815 self.verify_capture_in(capture, self.pg0)
3818 self.pg1.unconfig_ip4()
3819 self.pg2.unconfig_ip4()
3820 self.pg1.set_table_ip4(0)
3821 self.pg2.set_table_ip4(0)
3822 self.pg1.config_ip4()
3823 self.pg2.config_ip4()
3824 self.pg1.resolve_arp()
3825 self.pg2.resolve_arp()
3827 @unittest.skipUnless(running_extended_tests, "part of extended tests")
3828 def test_session_timeout(self):
3829 """ NAT44 session timeouts """
3830 self.nat44_add_address(self.nat_addr)
3831 flags = self.config_flags.NAT_IS_INSIDE
3832 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3834 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3835 self.vapi.nat_set_timeouts(udp=5)
3839 for i in range(0, max_sessions):
3840 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3841 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3842 IP(src=src, dst=self.pg1.remote_ip4) /
3843 UDP(sport=1025, dport=53))
3845 self.pg0.add_stream(pkts)
3846 self.pg_enable_capture(self.pg_interfaces)
3848 self.pg1.get_capture(max_sessions)
3853 for i in range(0, max_sessions):
3854 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3855 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3856 IP(src=src, dst=self.pg1.remote_ip4) /
3857 UDP(sport=1026, dport=53))
3859 self.pg0.add_stream(pkts)
3860 self.pg_enable_capture(self.pg_interfaces)
3862 self.pg1.get_capture(max_sessions)
3865 users = self.vapi.nat44_user_dump()
3867 nsessions = nsessions + user.nsessions
3868 self.assertLess(nsessions, 2 * max_sessions)
3870 def test_mss_clamping(self):
3871 """ TCP MSS clamping """
3872 self.nat44_add_address(self.nat_addr)
3873 flags = self.config_flags.NAT_IS_INSIDE
3874 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3876 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3878 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3879 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3880 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3881 flags="S", options=[('MSS', 1400)]))
3883 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3884 self.pg0.add_stream(p)
3885 self.pg_enable_capture(self.pg_interfaces)
3887 capture = self.pg1.get_capture(1)
3888 # Negotiated MSS value greater than configured - changed
3889 self.verify_mss_value(capture[0], 1000)
3891 self.vapi.nat_set_mss_clamping(enable=0)
3892 self.pg0.add_stream(p)
3893 self.pg_enable_capture(self.pg_interfaces)
3895 capture = self.pg1.get_capture(1)
3896 # MSS clamping disabled - negotiated MSS unchanged
3897 self.verify_mss_value(capture[0], 1400)
3899 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3900 self.pg0.add_stream(p)
3901 self.pg_enable_capture(self.pg_interfaces)
3903 capture = self.pg1.get_capture(1)
3904 # Negotiated MSS value smaller than configured - unchanged
3905 self.verify_mss_value(capture[0], 1400)
3907 @unittest.skipUnless(running_extended_tests, "part of extended tests")
3908 def test_ha_send(self):
3909 """ Send HA session synchronization events (active) """
3910 self.nat44_add_address(self.nat_addr)
3911 flags = self.config_flags.NAT_IS_INSIDE
3912 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3914 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3915 self.vapi.nat_ha_set_listener(self.pg3.local_ip4, port=12345)
3916 self.vapi.nat_ha_set_failover(self.pg3.remote_ip4, port=12346)
3917 bind_layers(UDP, HANATStateSync, sport=12345)
3920 pkts = self.create_stream_in(self.pg0, self.pg1)
3921 self.pg0.add_stream(pkts)
3922 self.pg_enable_capture(self.pg_interfaces)
3924 capture = self.pg1.get_capture(len(pkts))
3925 self.verify_capture_out(capture)
3926 # active send HA events
3927 self.vapi.nat_ha_flush()
3928 stats = self.statistics.get_counter('/nat44/ha/add-event-send')
3929 self.assertEqual(stats[0][0], 3)
3930 capture = self.pg3.get_capture(1)
3932 self.assert_packet_checksums_valid(p)
3936 hanat = p[HANATStateSync]
3938 self.logger.error(ppp("Invalid packet:", p))
3941 self.assertEqual(ip.src, self.pg3.local_ip4)
3942 self.assertEqual(ip.dst, self.pg3.remote_ip4)
3943 self.assertEqual(udp.sport, 12345)
3944 self.assertEqual(udp.dport, 12346)
3945 self.assertEqual(hanat.version, 1)
3946 self.assertEqual(hanat.thread_index, 0)
3947 self.assertEqual(hanat.count, 3)
3948 seq = hanat.sequence_number
3949 for event in hanat.events:
3950 self.assertEqual(event.event_type, 1)
3951 self.assertEqual(event.in_addr, self.pg0.remote_ip4)
3952 self.assertEqual(event.out_addr, self.nat_addr)
3953 self.assertEqual(event.fib_index, 0)
3955 # ACK received events
3956 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
3957 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
3958 UDP(sport=12346, dport=12345) /
3959 HANATStateSync(sequence_number=seq, flags='ACK'))
3960 self.pg3.add_stream(ack)
3962 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
3963 self.assertEqual(stats[0][0], 1)
3965 # delete one session
3966 self.pg_enable_capture(self.pg_interfaces)
3967 self.vapi.nat44_del_session(self.pg0.remote_ip4n,
3970 flags=self.config_flags.NAT_IS_INSIDE)
3971 self.vapi.nat_ha_flush()
3972 stats = self.statistics.get_counter('/nat44/ha/del-event-send')
3973 self.assertEqual(stats[0][0], 1)
3974 capture = self.pg3.get_capture(1)
3977 hanat = p[HANATStateSync]
3979 self.logger.error(ppp("Invalid packet:", p))
3982 self.assertGreater(hanat.sequence_number, seq)
3984 # do not send ACK, active retry send HA event again
3985 self.pg_enable_capture(self.pg_interfaces)
3987 stats = self.statistics.get_counter('/nat44/ha/retry-count')
3988 self.assertEqual(stats[0][0], 3)
3989 stats = self.statistics.get_counter('/nat44/ha/missed-count')
3990 self.assertEqual(stats[0][0], 1)
3991 capture = self.pg3.get_capture(3)
3992 for packet in capture:
3993 self.assertEqual(packet, p)
3995 # session counters refresh
3996 pkts = self.create_stream_out(self.pg1)
3997 self.pg1.add_stream(pkts)
3998 self.pg_enable_capture(self.pg_interfaces)
4000 self.pg0.get_capture(2)
4001 self.vapi.nat_ha_flush()
4002 stats = self.statistics.get_counter('/nat44/ha/refresh-event-send')
4003 self.assertEqual(stats[0][0], 2)
4004 capture = self.pg3.get_capture(1)
4006 self.assert_packet_checksums_valid(p)
4010 hanat = p[HANATStateSync]
4012 self.logger.error(ppp("Invalid packet:", p))
4015 self.assertEqual(ip.src, self.pg3.local_ip4)
4016 self.assertEqual(ip.dst, self.pg3.remote_ip4)
4017 self.assertEqual(udp.sport, 12345)
4018 self.assertEqual(udp.dport, 12346)
4019 self.assertEqual(hanat.version, 1)
4020 self.assertEqual(hanat.count, 2)
4021 seq = hanat.sequence_number
4022 for event in hanat.events:
4023 self.assertEqual(event.event_type, 3)
4024 self.assertEqual(event.out_addr, self.nat_addr)
4025 self.assertEqual(event.fib_index, 0)
4026 self.assertEqual(event.total_pkts, 2)
4027 self.assertGreater(event.total_bytes, 0)
4029 ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4030 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4031 UDP(sport=12346, dport=12345) /
4032 HANATStateSync(sequence_number=seq, flags='ACK'))
4033 self.pg3.add_stream(ack)
4035 stats = self.statistics.get_counter('/nat44/ha/ack-recv')
4036 self.assertEqual(stats[0][0], 2)
4038 def test_ha_recv(self):
4039 """ Receive HA session synchronization events (passive) """
4040 self.nat44_add_address(self.nat_addr)
4041 flags = self.config_flags.NAT_IS_INSIDE
4042 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4044 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4045 self.vapi.nat_ha_set_listener(self.pg3.local_ip4, port=12345)
4046 bind_layers(UDP, HANATStateSync, sport=12345)
4048 self.tcp_port_out = random.randint(1025, 65535)
4049 self.udp_port_out = random.randint(1025, 65535)
4051 # send HA session add events to failover/passive
4052 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4053 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4054 UDP(sport=12346, dport=12345) /
4055 HANATStateSync(sequence_number=1, events=[
4056 Event(event_type='add', protocol='tcp',
4057 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4058 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4059 eh_addr=self.pg1.remote_ip4,
4060 ehn_addr=self.pg1.remote_ip4,
4061 eh_port=self.tcp_external_port,
4062 ehn_port=self.tcp_external_port, fib_index=0),
4063 Event(event_type='add', protocol='udp',
4064 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4065 in_port=self.udp_port_in, out_port=self.udp_port_out,
4066 eh_addr=self.pg1.remote_ip4,
4067 ehn_addr=self.pg1.remote_ip4,
4068 eh_port=self.udp_external_port,
4069 ehn_port=self.udp_external_port, fib_index=0)]))
4071 self.pg3.add_stream(p)
4072 self.pg_enable_capture(self.pg_interfaces)
4075 capture = self.pg3.get_capture(1)
4078 hanat = p[HANATStateSync]
4080 self.logger.error(ppp("Invalid packet:", p))
4083 self.assertEqual(hanat.sequence_number, 1)
4084 self.assertEqual(hanat.flags, 'ACK')
4085 self.assertEqual(hanat.version, 1)
4086 self.assertEqual(hanat.thread_index, 0)
4087 stats = self.statistics.get_counter('/nat44/ha/ack-send')
4088 self.assertEqual(stats[0][0], 1)
4089 stats = self.statistics.get_counter('/nat44/ha/add-event-recv')
4090 self.assertEqual(stats[0][0], 2)
4091 users = self.statistics.get_counter('/nat44/total-users')
4092 self.assertEqual(users[0][0], 1)
4093 sessions = self.statistics.get_counter('/nat44/total-sessions')
4094 self.assertEqual(sessions[0][0], 2)
4095 users = self.vapi.nat44_user_dump()
4096 self.assertEqual(len(users), 1)
4097 self.assertEqual(str(users[0].ip_address),
4098 self.pg0.remote_ip4)
4099 # there should be 2 sessions created by HA
4100 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4102 self.assertEqual(len(sessions), 2)
4103 for session in sessions:
4104 self.assertEqual(str(session.inside_ip_address),
4105 self.pg0.remote_ip4)
4106 self.assertEqual(str(session.outside_ip_address),
4108 self.assertIn(session.inside_port,
4109 [self.tcp_port_in, self.udp_port_in])
4110 self.assertIn(session.outside_port,
4111 [self.tcp_port_out, self.udp_port_out])
4112 self.assertIn(session.protocol, [IP_PROTOS.tcp, IP_PROTOS.udp])
4114 # send HA session delete event to failover/passive
4115 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4116 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4117 UDP(sport=12346, dport=12345) /
4118 HANATStateSync(sequence_number=2, events=[
4119 Event(event_type='del', protocol='udp',
4120 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4121 in_port=self.udp_port_in, out_port=self.udp_port_out,
4122 eh_addr=self.pg1.remote_ip4,
4123 ehn_addr=self.pg1.remote_ip4,
4124 eh_port=self.udp_external_port,
4125 ehn_port=self.udp_external_port, fib_index=0)]))
4127 self.pg3.add_stream(p)
4128 self.pg_enable_capture(self.pg_interfaces)
4131 capture = self.pg3.get_capture(1)
4134 hanat = p[HANATStateSync]
4136 self.logger.error(ppp("Invalid packet:", p))
4139 self.assertEqual(hanat.sequence_number, 2)
4140 self.assertEqual(hanat.flags, 'ACK')
4141 self.assertEqual(hanat.version, 1)
4142 users = self.vapi.nat44_user_dump()
4143 self.assertEqual(len(users), 1)
4144 self.assertEqual(str(users[0].ip_address),
4145 self.pg0.remote_ip4)
4146 # now we should have only 1 session, 1 deleted by HA
4147 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4149 self.assertEqual(len(sessions), 1)
4150 stats = self.statistics.get_counter('/nat44/ha/del-event-recv')
4151 self.assertEqual(stats[0][0], 1)
4153 stats = self.statistics.get_counter('/err/nat-ha/pkts-processed')
4154 self.assertEqual(stats, 2)
4156 # send HA session refresh event to failover/passive
4157 p = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
4158 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
4159 UDP(sport=12346, dport=12345) /
4160 HANATStateSync(sequence_number=3, events=[
4161 Event(event_type='refresh', protocol='tcp',
4162 in_addr=self.pg0.remote_ip4, out_addr=self.nat_addr,
4163 in_port=self.tcp_port_in, out_port=self.tcp_port_out,
4164 eh_addr=self.pg1.remote_ip4,
4165 ehn_addr=self.pg1.remote_ip4,
4166 eh_port=self.tcp_external_port,
4167 ehn_port=self.tcp_external_port, fib_index=0,
4168 total_bytes=1024, total_pkts=2)]))
4169 self.pg3.add_stream(p)
4170 self.pg_enable_capture(self.pg_interfaces)
4173 capture = self.pg3.get_capture(1)
4176 hanat = p[HANATStateSync]
4178 self.logger.error(ppp("Invalid packet:", p))
4181 self.assertEqual(hanat.sequence_number, 3)
4182 self.assertEqual(hanat.flags, 'ACK')
4183 self.assertEqual(hanat.version, 1)
4184 users = self.vapi.nat44_user_dump()
4185 self.assertEqual(len(users), 1)
4186 self.assertEqual(str(users[0].ip_address),
4187 self.pg0.remote_ip4)
4188 sessions = self.vapi.nat44_user_session_dump(users[0].ip_address,
4190 self.assertEqual(len(sessions), 1)
4191 session = sessions[0]
4192 self.assertEqual(session.total_bytes, 1024)
4193 self.assertEqual(session.total_pkts, 2)
4194 stats = self.statistics.get_counter('/nat44/ha/refresh-event-recv')
4195 self.assertEqual(stats[0][0], 1)
4197 stats = self.statistics.get_counter('/err/nat-ha/pkts-processed')
4198 self.assertEqual(stats, 3)
4200 # send packet to test session created by HA
4201 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4202 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4203 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
4204 self.pg1.add_stream(p)
4205 self.pg_enable_capture(self.pg_interfaces)
4207 capture = self.pg0.get_capture(1)
4213 self.logger.error(ppp("Invalid packet:", p))
4216 self.assertEqual(ip.src, self.pg1.remote_ip4)
4217 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4218 self.assertEqual(tcp.sport, self.tcp_external_port)
4219 self.assertEqual(tcp.dport, self.tcp_port_in)
4222 super(TestNAT44, self).tearDown()
4224 self.vapi.cli("clear logging")
4226 def show_commands_at_teardown(self):
4227 self.logger.info(self.vapi.cli("show nat44 addresses"))
4228 self.logger.info(self.vapi.cli("show nat44 interfaces"))
4229 self.logger.info(self.vapi.cli("show nat44 static mappings"))
4230 self.logger.info(self.vapi.cli("show nat44 interface address"))
4231 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
4232 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
4233 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
4234 self.logger.info(self.vapi.cli("show nat timeouts"))
4236 self.vapi.cli("show nat addr-port-assignment-alg"))
4237 self.logger.info(self.vapi.cli("show nat ha"))
4240 class TestNAT44EndpointDependent(MethodHolder):
4241 """ Endpoint-Dependent mapping and filtering test cases """
4244 def setUpConstants(cls):
4245 super(TestNAT44EndpointDependent, cls).setUpConstants()
4246 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
4249 def setUpClass(cls):
4250 super(TestNAT44EndpointDependent, cls).setUpClass()
4251 cls.vapi.cli("set log class nat level debug")
4253 cls.tcp_port_in = 6303
4254 cls.tcp_port_out = 6303
4255 cls.udp_port_in = 6304
4256 cls.udp_port_out = 6304
4257 cls.icmp_id_in = 6305
4258 cls.icmp_id_out = 6305
4259 cls.nat_addr = '10.0.0.3'
4260 cls.ipfix_src_port = 4739
4261 cls.ipfix_domain_id = 1
4262 cls.tcp_external_port = 80
4264 cls.create_pg_interfaces(range(7))
4265 cls.interfaces = list(cls.pg_interfaces[0:3])
4267 for i in cls.interfaces:
4272 cls.pg0.generate_remote_hosts(3)
4273 cls.pg0.configure_ipv4_neighbors()
4277 cls.pg4.generate_remote_hosts(2)
4278 cls.pg4.config_ip4()
4279 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
4280 cls.vapi.sw_interface_add_del_address(
4281 sw_if_index=cls.pg4.sw_if_index, address=ip_addr_n,
4284 cls.pg4.resolve_arp()
4285 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
4286 cls.pg4.resolve_arp()
4288 zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
4289 cls.vapi.ip_table_add_del(is_add=1, table_id=1)
4291 cls.pg5._local_ip4 = "10.1.1.1"
4292 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
4294 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
4295 cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
4296 socket.AF_INET, cls.pg5.remote_ip4)
4297 cls.pg5.set_table_ip4(1)
4298 cls.pg5.config_ip4()
4300 cls.vapi.ip_add_del_route(dst_address=cls.pg5.remote_ip4n,
4301 dst_address_length=32,
4302 next_hop_address=zero_ip4n,
4303 next_hop_sw_if_index=cls.pg5.sw_if_index,
4306 cls.pg6._local_ip4 = "10.1.2.1"
4307 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
4309 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
4310 cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
4311 socket.AF_INET, cls.pg6.remote_ip4)
4312 cls.pg6.set_table_ip4(1)
4313 cls.pg6.config_ip4()
4315 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4316 dst_address_length=32,
4317 next_hop_address=zero_ip4n,
4318 next_hop_sw_if_index=cls.pg6.sw_if_index,
4321 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
4322 dst_address_length=16,
4323 next_hop_address=zero_ip4n, table_id=0,
4324 next_hop_table_id=1)
4325 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
4326 dst_address_length=0,
4327 next_hop_address=zero_ip4n, table_id=1,
4328 next_hop_table_id=0)
4329 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
4330 dst_address_length=0,
4331 next_hop_address=cls.pg1.local_ip4n,
4332 next_hop_sw_if_index=cls.pg1.sw_if_index,
4335 cls.pg5.resolve_arp()
4336 cls.pg6.resolve_arp()
4339 super(TestNAT44EndpointDependent, cls).tearDownClass()
4343 def tearDownClass(cls):
4344 super(TestNAT44EndpointDependent, cls).tearDownClass()
4346 def test_frag_in_order(self):
4347 """ NAT44 translate fragments arriving in order """
4348 self.nat44_add_address(self.nat_addr)
4349 flags = self.config_flags.NAT_IS_INSIDE
4350 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4352 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4353 self.frag_in_order(proto=IP_PROTOS.tcp)
4354 self.frag_in_order(proto=IP_PROTOS.udp)
4355 self.frag_in_order(proto=IP_PROTOS.icmp)
4357 def test_frag_in_order_dont_translate(self):
4358 """ NAT44 don't translate fragments arriving in order """
4359 flags = self.config_flags.NAT_IS_INSIDE
4360 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4362 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4363 self.vapi.nat44_forwarding_enable_disable(enable=True)
4364 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
4366 def test_frag_out_of_order(self):
4367 """ NAT44 translate fragments arriving out of order """
4368 self.nat44_add_address(self.nat_addr)
4369 flags = self.config_flags.NAT_IS_INSIDE
4370 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4372 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4373 self.frag_out_of_order(proto=IP_PROTOS.tcp)
4374 self.frag_out_of_order(proto=IP_PROTOS.udp)
4375 self.frag_out_of_order(proto=IP_PROTOS.icmp)
4377 def test_frag_out_of_order_dont_translate(self):
4378 """ NAT44 don't translate fragments arriving out of order """
4379 flags = self.config_flags.NAT_IS_INSIDE
4380 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4382 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4383 self.vapi.nat44_forwarding_enable_disable(enable=True)
4384 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
4386 def test_frag_in_order_in_plus_out(self):
4387 """ in+out interface fragments in order """
4388 flags = self.config_flags.NAT_IS_INSIDE
4389 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4390 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4392 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4393 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4396 self.server = self.pg1.remote_hosts[0]
4398 self.server_in_addr = self.server.ip4
4399 self.server_out_addr = '11.11.11.11'
4400 self.server_in_port = random.randint(1025, 65535)
4401 self.server_out_port = random.randint(1025, 65535)
4403 self.nat44_add_address(self.server_out_addr)
4405 # add static mappings for server
4406 self.nat44_add_static_mapping(self.server_in_addr,
4407 self.server_out_addr,
4408 self.server_in_port,
4409 self.server_out_port,
4410 proto=IP_PROTOS.tcp)
4411 self.nat44_add_static_mapping(self.server_in_addr,
4412 self.server_out_addr,
4413 self.server_in_port,
4414 self.server_out_port,
4415 proto=IP_PROTOS.udp)
4416 self.nat44_add_static_mapping(self.server_in_addr,
4417 self.server_out_addr,
4418 proto=IP_PROTOS.icmp)
4420 self.vapi.nat_set_reass(timeout=10)
4422 self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4423 self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4424 self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4426 def test_frag_out_of_order_in_plus_out(self):
4427 """ in+out interface fragments out of order """
4428 flags = self.config_flags.NAT_IS_INSIDE
4429 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4430 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4432 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4433 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4436 self.server = self.pg1.remote_hosts[0]
4438 self.server_in_addr = self.server.ip4
4439 self.server_out_addr = '11.11.11.11'
4440 self.server_in_port = random.randint(1025, 65535)
4441 self.server_out_port = random.randint(1025, 65535)
4443 self.nat44_add_address(self.server_out_addr)
4445 # add static mappings for server
4446 self.nat44_add_static_mapping(self.server_in_addr,
4447 self.server_out_addr,
4448 self.server_in_port,
4449 self.server_out_port,
4450 proto=IP_PROTOS.tcp)
4451 self.nat44_add_static_mapping(self.server_in_addr,
4452 self.server_out_addr,
4453 self.server_in_port,
4454 self.server_out_port,
4455 proto=IP_PROTOS.udp)
4456 self.nat44_add_static_mapping(self.server_in_addr,
4457 self.server_out_addr,
4458 proto=IP_PROTOS.icmp)
4460 self.vapi.nat_set_reass(timeout=10)
4462 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4463 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4464 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4466 def test_reass_hairpinning(self):
4467 """ NAT44 fragments hairpinning """
4468 self.server = self.pg0.remote_hosts[1]
4469 self.host_in_port = random.randint(1025, 65535)
4470 self.server_in_port = random.randint(1025, 65535)
4471 self.server_out_port = random.randint(1025, 65535)
4473 self.nat44_add_address(self.nat_addr)
4474 flags = self.config_flags.NAT_IS_INSIDE
4475 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4477 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4478 # add static mapping for server
4479 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4480 self.server_in_port,
4481 self.server_out_port,
4482 proto=IP_PROTOS.tcp)
4483 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4484 self.server_in_port,
4485 self.server_out_port,
4486 proto=IP_PROTOS.udp)
4487 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
4489 self.reass_hairpinning(proto=IP_PROTOS.tcp)
4490 self.reass_hairpinning(proto=IP_PROTOS.udp)
4491 self.reass_hairpinning(proto=IP_PROTOS.icmp)
4493 def test_dynamic(self):
4494 """ NAT44 dynamic translation test """
4496 self.nat44_add_address(self.nat_addr)
4497 flags = self.config_flags.NAT_IS_INSIDE
4498 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4500 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4502 nat_config = self.vapi.nat_show_config()
4503 self.assertEqual(1, nat_config.endpoint_dependent)
4506 tcpn = self.statistics.get_counter(
4507 '/err/nat44-ed-in2out-slowpath/TCP packets')
4508 udpn = self.statistics.get_counter(
4509 '/err/nat44-ed-in2out-slowpath/UDP packets')
4510 icmpn = self.statistics.get_counter(
4511 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4512 totaln = self.statistics.get_counter(
4513 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4515 pkts = self.create_stream_in(self.pg0, self.pg1)
4516 self.pg0.add_stream(pkts)
4517 self.pg_enable_capture(self.pg_interfaces)
4519 capture = self.pg1.get_capture(len(pkts))
4520 self.verify_capture_out(capture)
4522 err = self.statistics.get_counter(
4523 '/err/nat44-ed-in2out-slowpath/TCP packets')
4524 self.assertEqual(err - tcpn, 1)
4525 err = self.statistics.get_counter(
4526 '/err/nat44-ed-in2out-slowpath/UDP packets')
4527 self.assertEqual(err - udpn, 1)
4528 err = self.statistics.get_counter(
4529 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4530 self.assertEqual(err - icmpn, 1)
4531 err = self.statistics.get_counter(
4532 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4533 self.assertEqual(err - totaln, 3)
4536 tcpn = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4537 udpn = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4538 icmpn = self.statistics.get_counter(
4539 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4540 totaln = self.statistics.get_counter(
4541 '/err/nat44-ed-out2in/good out2in packets processed')
4543 pkts = self.create_stream_out(self.pg1)
4544 self.pg1.add_stream(pkts)
4545 self.pg_enable_capture(self.pg_interfaces)
4547 capture = self.pg0.get_capture(len(pkts))
4548 self.verify_capture_in(capture, self.pg0)
4550 err = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4551 self.assertEqual(err - tcpn, 1)
4552 err = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4553 self.assertEqual(err - udpn, 1)
4554 err = self.statistics.get_counter(
4555 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4556 self.assertEqual(err - icmpn, 1)
4557 err = self.statistics.get_counter(
4558 '/err/nat44-ed-out2in/good out2in packets processed')
4559 self.assertEqual(err - totaln, 2)
4561 users = self.statistics.get_counter('/nat44/total-users')
4562 self.assertEqual(users[0][0], 1)
4563 sessions = self.statistics.get_counter('/nat44/total-sessions')
4564 self.assertEqual(sessions[0][0], 3)
4566 def test_forwarding(self):
4567 """ NAT44 forwarding test """
4569 flags = self.config_flags.NAT_IS_INSIDE
4570 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4572 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4573 self.vapi.nat44_forwarding_enable_disable(1)
4575 real_ip = self.pg0.remote_ip4
4576 alias_ip = self.nat_addr
4577 flags = self.config_flags.NAT_IS_ADDR_ONLY
4578 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4579 external_ip=alias_ip,
4583 # in2out - static mapping match
4585 pkts = self.create_stream_out(self.pg1)
4586 self.pg1.add_stream(pkts)
4587 self.pg_enable_capture(self.pg_interfaces)
4589 capture = self.pg0.get_capture(len(pkts))
4590 self.verify_capture_in(capture, self.pg0)
4592 pkts = self.create_stream_in(self.pg0, self.pg1)
4593 self.pg0.add_stream(pkts)
4594 self.pg_enable_capture(self.pg_interfaces)
4596 capture = self.pg1.get_capture(len(pkts))
4597 self.verify_capture_out(capture, same_port=True)
4599 # in2out - no static mapping match
4601 host0 = self.pg0.remote_hosts[0]
4602 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4604 pkts = self.create_stream_out(self.pg1,
4605 dst_ip=self.pg0.remote_ip4,
4606 use_inside_ports=True)
4607 self.pg1.add_stream(pkts)
4608 self.pg_enable_capture(self.pg_interfaces)
4610 capture = self.pg0.get_capture(len(pkts))
4611 self.verify_capture_in(capture, self.pg0)
4613 pkts = self.create_stream_in(self.pg0, self.pg1)
4614 self.pg0.add_stream(pkts)
4615 self.pg_enable_capture(self.pg_interfaces)
4617 capture = self.pg1.get_capture(len(pkts))
4618 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4621 self.pg0.remote_hosts[0] = host0
4623 user = self.pg0.remote_hosts[1]
4624 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4625 self.assertEqual(len(sessions), 3)
4626 self.assertTrue(sessions[0].flags &
4627 self.config_flags.NAT_IS_EXT_HOST_VALID)
4628 self.vapi.nat44_del_session(
4629 sessions[0].inside_ip_address,
4630 sessions[0].inside_port,
4631 sessions[0].protocol,
4632 flags=(self.config_flags.NAT_IS_INSIDE |
4633 self.config_flags.NAT_IS_EXT_HOST_VALID),
4634 ext_host_address=sessions[0].ext_host_address,
4635 ext_host_port=sessions[0].ext_host_port)
4636 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4637 self.assertEqual(len(sessions), 2)
4640 self.vapi.nat44_forwarding_enable_disable(0)
4641 flags = self.config_flags.NAT_IS_ADDR_ONLY
4642 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4643 external_ip=alias_ip,
4644 is_add=0, flags=flags)
4646 def test_static_lb(self):
4647 """ NAT44 local service load balancing """
4648 external_addr_n = self.nat_addr
4651 server1 = self.pg0.remote_hosts[0]
4652 server2 = self.pg0.remote_hosts[1]
4654 locals = [{'addr': server1.ip4n,
4658 {'addr': server2.ip4n,
4663 self.nat44_add_address(self.nat_addr)
4664 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4667 local_num=len(locals),
4669 flags = self.config_flags.NAT_IS_INSIDE
4670 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4672 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4674 # from client to service
4675 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4676 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4677 TCP(sport=12345, dport=external_port))
4678 self.pg1.add_stream(p)
4679 self.pg_enable_capture(self.pg_interfaces)
4681 capture = self.pg0.get_capture(1)
4687 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4688 if ip.dst == server1.ip4:
4692 self.assertEqual(tcp.dport, local_port)
4693 self.assert_packet_checksums_valid(p)
4695 self.logger.error(ppp("Unexpected or invalid packet:", p))
4698 # from service back to client
4699 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4700 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4701 TCP(sport=local_port, dport=12345))
4702 self.pg0.add_stream(p)
4703 self.pg_enable_capture(self.pg_interfaces)
4705 capture = self.pg1.get_capture(1)
4710 self.assertEqual(ip.src, self.nat_addr)
4711 self.assertEqual(tcp.sport, external_port)
4712 self.assert_packet_checksums_valid(p)
4714 self.logger.error(ppp("Unexpected or invalid packet:", p))
4717 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4718 self.assertEqual(len(sessions), 1)
4719 self.assertTrue(sessions[0].flags &
4720 self.config_flags.NAT_IS_EXT_HOST_VALID)
4721 self.vapi.nat44_del_session(
4722 sessions[0].inside_ip_address,
4723 sessions[0].inside_port,
4724 sessions[0].protocol,
4725 flags=(self.config_flags.NAT_IS_INSIDE |
4726 self.config_flags.NAT_IS_EXT_HOST_VALID),
4727 ext_host_address=sessions[0].ext_host_address,
4728 ext_host_port=sessions[0].ext_host_port)
4729 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4730 self.assertEqual(len(sessions), 0)
4732 @unittest.skipUnless(running_extended_tests, "part of extended tests")
4733 def test_static_lb_multi_clients(self):
4734 """ NAT44 local service load balancing - multiple clients"""
4736 external_addr = self.nat_addr
4739 server1 = self.pg0.remote_hosts[0]
4740 server2 = self.pg0.remote_hosts[1]
4741 server3 = self.pg0.remote_hosts[2]
4743 locals = [{'addr': server1.ip4n,
4747 {'addr': server2.ip4n,
4752 self.nat44_add_address(self.nat_addr)
4753 self.vapi.nat44_add_del_lb_static_mapping(external_addr,
4756 local_num=len(locals),
4758 flags = self.config_flags.NAT_IS_INSIDE
4759 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4761 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4765 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4767 for client in clients:
4768 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4769 IP(src=client, dst=self.nat_addr) /
4770 TCP(sport=12345, dport=external_port))
4772 self.pg1.add_stream(pkts)
4773 self.pg_enable_capture(self.pg_interfaces)
4775 capture = self.pg0.get_capture(len(pkts))
4777 if p[IP].dst == server1.ip4:
4781 self.assertGreater(server1_n, server2_n)
4784 self.vapi.nat44_lb_static_mapping_add_del_local(external_addr,
4793 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
4795 for client in clients:
4796 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4797 IP(src=client, dst=self.nat_addr) /
4798 TCP(sport=12346, dport=external_port))
4800 self.assertGreater(len(pkts), 0)
4801 self.pg1.add_stream(pkts)
4802 self.pg_enable_capture(self.pg_interfaces)
4804 capture = self.pg0.get_capture(len(pkts))
4806 if p[IP].dst == server1.ip4:
4808 elif p[IP].dst == server2.ip4:
4812 self.assertGreater(server1_n, 0)
4813 self.assertGreater(server2_n, 0)
4814 self.assertGreater(server3_n, 0)
4816 # remove one back-end
4817 self.vapi.nat44_lb_static_mapping_add_del_local(external_addr,
4827 self.pg1.add_stream(pkts)
4828 self.pg_enable_capture(self.pg_interfaces)
4830 capture = self.pg0.get_capture(len(pkts))
4832 if p[IP].dst == server1.ip4:
4834 elif p[IP].dst == server2.ip4:
4838 self.assertGreater(server1_n, 0)
4839 self.assertEqual(server2_n, 0)
4840 self.assertGreater(server3_n, 0)
4842 def test_static_lb_2(self):
4843 """ NAT44 local service load balancing (asymmetrical rule) """
4844 external_addr = self.nat_addr
4847 server1 = self.pg0.remote_hosts[0]
4848 server2 = self.pg0.remote_hosts[1]
4850 locals = [{'addr': server1.ip4n,
4854 {'addr': server2.ip4n,
4859 self.vapi.nat44_forwarding_enable_disable(1)
4860 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
4861 self.vapi.nat44_add_del_lb_static_mapping(external_addr,
4864 local_num=len(locals),
4867 flags = self.config_flags.NAT_IS_INSIDE
4868 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4870 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4872 # from client to service
4873 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4874 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4875 TCP(sport=12345, dport=external_port))
4876 self.pg1.add_stream(p)
4877 self.pg_enable_capture(self.pg_interfaces)
4879 capture = self.pg0.get_capture(1)
4885 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4886 if ip.dst == server1.ip4:
4890 self.assertEqual(tcp.dport, local_port)
4891 self.assert_packet_checksums_valid(p)
4893 self.logger.error(ppp("Unexpected or invalid packet:", p))
4896 # from service back to client
4897 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4898 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4899 TCP(sport=local_port, dport=12345))
4900 self.pg0.add_stream(p)
4901 self.pg_enable_capture(self.pg_interfaces)
4903 capture = self.pg1.get_capture(1)
4908 self.assertEqual(ip.src, self.nat_addr)
4909 self.assertEqual(tcp.sport, external_port)
4910 self.assert_packet_checksums_valid(p)
4912 self.logger.error(ppp("Unexpected or invalid packet:", p))
4915 # from client to server (no translation)
4916 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4917 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
4918 TCP(sport=12346, dport=local_port))
4919 self.pg1.add_stream(p)
4920 self.pg_enable_capture(self.pg_interfaces)
4922 capture = self.pg0.get_capture(1)
4928 self.assertEqual(ip.dst, server1.ip4)
4929 self.assertEqual(tcp.dport, local_port)
4930 self.assert_packet_checksums_valid(p)
4932 self.logger.error(ppp("Unexpected or invalid packet:", p))
4935 # from service back to client (no translation)
4936 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
4937 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
4938 TCP(sport=local_port, dport=12346))
4939 self.pg0.add_stream(p)
4940 self.pg_enable_capture(self.pg_interfaces)
4942 capture = self.pg1.get_capture(1)
4947 self.assertEqual(ip.src, server1.ip4)
4948 self.assertEqual(tcp.sport, local_port)
4949 self.assert_packet_checksums_valid(p)
4951 self.logger.error(ppp("Unexpected or invalid packet:", p))
4954 def test_lb_affinity(self):
4955 """ NAT44 local service load balancing affinity """
4956 external_addr = self.nat_addr
4959 server1 = self.pg0.remote_hosts[0]
4960 server2 = self.pg0.remote_hosts[1]
4962 locals = [{'addr': server1.ip4n,
4966 {'addr': server2.ip4n,
4971 self.nat44_add_address(self.nat_addr)
4972 self.vapi.nat44_add_del_lb_static_mapping(external_addr,
4976 local_num=len(locals),
4978 flags = self.config_flags.NAT_IS_INSIDE
4979 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4981 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4983 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4984 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4985 TCP(sport=1025, dport=external_port))
4986 self.pg1.add_stream(p)
4987 self.pg_enable_capture(self.pg_interfaces)
4989 capture = self.pg0.get_capture(1)
4990 backend = capture[0][IP].dst
4992 sessions = self.vapi.nat44_user_session_dump(backend, 0)
4993 self.assertEqual(len(sessions), 1)
4994 self.assertTrue(sessions[0].flags &
4995 self.config_flags.NAT_IS_EXT_HOST_VALID)
4996 self.vapi.nat44_del_session(
4997 sessions[0].inside_ip_address,
4998 sessions[0].inside_port,
4999 sessions[0].protocol,
5000 flags=(self.config_flags.NAT_IS_INSIDE |
5001 self.config_flags.NAT_IS_EXT_HOST_VALID),
5002 ext_host_address=sessions[0].ext_host_address,
5003 ext_host_port=sessions[0].ext_host_port)
5006 for port in range(1030, 1100):
5007 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5008 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5009 TCP(sport=port, dport=external_port))
5011 self.pg1.add_stream(pkts)
5012 self.pg_enable_capture(self.pg_interfaces)
5014 capture = self.pg0.get_capture(len(pkts))
5016 self.assertEqual(p[IP].dst, backend)
5018 def test_unknown_proto(self):
5019 """ NAT44 translate packet with unknown protocol """
5020 self.nat44_add_address(self.nat_addr)
5021 flags = self.config_flags.NAT_IS_INSIDE
5022 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5024 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
5027 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5028 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5029 TCP(sport=self.tcp_port_in, dport=20))
5030 self.pg0.add_stream(p)
5031 self.pg_enable_capture(self.pg_interfaces)
5033 p = self.pg1.get_capture(1)
5035 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5036 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5038 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5039 TCP(sport=1234, dport=1234))
5040 self.pg0.add_stream(p)
5041 self.pg_enable_capture(self.pg_interfaces)
5043 p = self.pg1.get_capture(1)
5046 self.assertEqual(packet[IP].src, self.nat_addr)
5047 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
5048 self.assertEqual(packet.haslayer(GRE), 1)
5049 self.assert_packet_checksums_valid(packet)
5051 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5055 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5056 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5058 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5059 TCP(sport=1234, dport=1234))
5060 self.pg1.add_stream(p)
5061 self.pg_enable_capture(self.pg_interfaces)
5063 p = self.pg0.get_capture(1)
5066 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
5067 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
5068 self.assertEqual(packet.haslayer(GRE), 1)
5069 self.assert_packet_checksums_valid(packet)
5071 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5074 def test_hairpinning_unknown_proto(self):
5075 """ NAT44 translate packet with unknown protocol - hairpinning """
5076 host = self.pg0.remote_hosts[0]
5077 server = self.pg0.remote_hosts[1]
5079 server_out_port = 8765
5080 server_nat_ip = "10.0.0.11"
5082 self.nat44_add_address(self.nat_addr)
5083 flags = self.config_flags.NAT_IS_INSIDE
5084 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5086 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
5088 # add static mapping for server
5089 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
5092 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
5093 IP(src=host.ip4, dst=server_nat_ip) /
5094 TCP(sport=host_in_port, dport=server_out_port))
5095 self.pg0.add_stream(p)
5096 self.pg_enable_capture(self.pg_interfaces)
5098 self.pg0.get_capture(1)
5100 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
5101 IP(src=host.ip4, dst=server_nat_ip) /
5103 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5104 TCP(sport=1234, dport=1234))
5105 self.pg0.add_stream(p)
5106 self.pg_enable_capture(self.pg_interfaces)
5108 p = self.pg0.get_capture(1)
5111 self.assertEqual(packet[IP].src, self.nat_addr)
5112 self.assertEqual(packet[IP].dst, server.ip4)
5113 self.assertEqual(packet.haslayer(GRE), 1)
5114 self.assert_packet_checksums_valid(packet)
5116 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5120 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
5121 IP(src=server.ip4, dst=self.nat_addr) /
5123 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
5124 TCP(sport=1234, dport=1234))
5125 self.pg0.add_stream(p)
5126 self.pg_enable_capture(self.pg_interfaces)
5128 p = self.pg0.get_capture(1)
5131 self.assertEqual(packet[IP].src, server_nat_ip)
5132 self.assertEqual(packet[IP].dst, host.ip4)
5133 self.assertEqual(packet.haslayer(GRE), 1)
5134 self.assert_packet_checksums_valid(packet)
5136 self.logger.error(ppp("Unexpected or invalid packet:", packet))
5139 def test_output_feature_and_service(self):
5140 """ NAT44 interface output feature and services """
5141 external_addr = '1.2.3.4'
5145 self.vapi.nat44_forwarding_enable_disable(1)
5146 self.nat44_add_address(self.nat_addr)
5147 flags = self.config_flags.NAT_IS_ADDR_ONLY
5148 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n,
5150 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5151 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
5152 local_port, external_port,
5153 proto=IP_PROTOS.tcp, flags=flags)
5154 flags = self.config_flags.NAT_IS_INSIDE
5155 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5156 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5158 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
5160 # from client to service
5161 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5162 IP(src=self.pg1.remote_ip4, dst=external_addr) /
5163 TCP(sport=12345, dport=external_port))
5164 self.pg1.add_stream(p)
5165 self.pg_enable_capture(self.pg_interfaces)
5167 capture = self.pg0.get_capture(1)
5172 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5173 self.assertEqual(tcp.dport, local_port)
5174 self.assert_packet_checksums_valid(p)
5176 self.logger.error(ppp("Unexpected or invalid packet:", p))
5179 # from service back to client
5180 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5181 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5182 TCP(sport=local_port, dport=12345))
5183 self.pg0.add_stream(p)
5184 self.pg_enable_capture(self.pg_interfaces)
5186 capture = self.pg1.get_capture(1)
5191 self.assertEqual(ip.src, external_addr)
5192 self.assertEqual(tcp.sport, external_port)
5193 self.assert_packet_checksums_valid(p)
5195 self.logger.error(ppp("Unexpected or invalid packet:", p))
5198 # from local network host to external network
5199 pkts = self.create_stream_in(self.pg0, self.pg1)
5200 self.pg0.add_stream(pkts)
5201 self.pg_enable_capture(self.pg_interfaces)
5203 capture = self.pg1.get_capture(len(pkts))
5204 self.verify_capture_out(capture)
5205 pkts = self.create_stream_in(self.pg0, self.pg1)
5206 self.pg0.add_stream(pkts)
5207 self.pg_enable_capture(self.pg_interfaces)
5209 capture = self.pg1.get_capture(len(pkts))
5210 self.verify_capture_out(capture)
5212 # from external network back to local network host
5213 pkts = self.create_stream_out(self.pg1)
5214 self.pg1.add_stream(pkts)
5215 self.pg_enable_capture(self.pg_interfaces)
5217 capture = self.pg0.get_capture(len(pkts))
5218 self.verify_capture_in(capture, self.pg0)
5220 def test_output_feature_and_service2(self):
5221 """ NAT44 interface output feature and service host direct access """
5222 self.vapi.nat44_forwarding_enable_disable(1)
5223 self.nat44_add_address(self.nat_addr)
5224 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
5226 # session initiated from service host - translate
5227 pkts = self.create_stream_in(self.pg0, self.pg1)
5228 self.pg0.add_stream(pkts)
5229 self.pg_enable_capture(self.pg_interfaces)
5231 capture = self.pg1.get_capture(len(pkts))
5232 self.verify_capture_out(capture)
5234 pkts = self.create_stream_out(self.pg1)
5235 self.pg1.add_stream(pkts)
5236 self.pg_enable_capture(self.pg_interfaces)
5238 capture = self.pg0.get_capture(len(pkts))
5239 self.verify_capture_in(capture, self.pg0)
5241 # session initiated from remote host - do not translate
5242 self.tcp_port_in = 60303
5243 self.udp_port_in = 60304
5244 self.icmp_id_in = 60305
5245 pkts = self.create_stream_out(self.pg1,
5246 self.pg0.remote_ip4,
5247 use_inside_ports=True)
5248 self.pg1.add_stream(pkts)
5249 self.pg_enable_capture(self.pg_interfaces)
5251 capture = self.pg0.get_capture(len(pkts))
5252 self.verify_capture_in(capture, self.pg0)
5254 pkts = self.create_stream_in(self.pg0, self.pg1)
5255 self.pg0.add_stream(pkts)
5256 self.pg_enable_capture(self.pg_interfaces)
5258 capture = self.pg1.get_capture(len(pkts))
5259 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
5262 def test_output_feature_and_service3(self):
5263 """ NAT44 interface output feature and DST NAT """
5264 external_addr = '1.2.3.4'
5268 self.vapi.nat44_forwarding_enable_disable(1)
5269 self.nat44_add_address(self.nat_addr)
5270 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5271 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
5272 local_port, external_port,
5273 proto=IP_PROTOS.tcp, flags=flags)
5274 flags = self.config_flags.NAT_IS_INSIDE
5275 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5276 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5278 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
5280 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5281 IP(src=self.pg0.remote_ip4, dst=external_addr) /
5282 TCP(sport=12345, dport=external_port))
5283 self.pg0.add_stream(p)
5284 self.pg_enable_capture(self.pg_interfaces)
5286 capture = self.pg1.get_capture(1)
5291 self.assertEqual(ip.src, self.pg0.remote_ip4)
5292 self.assertEqual(tcp.sport, 12345)
5293 self.assertEqual(ip.dst, self.pg1.remote_ip4)
5294 self.assertEqual(tcp.dport, local_port)
5295 self.assert_packet_checksums_valid(p)
5297 self.logger.error(ppp("Unexpected or invalid packet:", p))
5300 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5301 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5302 TCP(sport=local_port, dport=12345))
5303 self.pg1.add_stream(p)
5304 self.pg_enable_capture(self.pg_interfaces)
5306 capture = self.pg0.get_capture(1)
5311 self.assertEqual(ip.src, external_addr)
5312 self.assertEqual(tcp.sport, external_port)
5313 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5314 self.assertEqual(tcp.dport, 12345)
5315 self.assert_packet_checksums_valid(p)
5317 self.logger.error(ppp("Unexpected or invalid packet:", p))
5320 def test_next_src_nat(self):
5321 """ On way back forward packet to nat44-in2out node. """
5322 twice_nat_addr = '10.0.1.3'
5325 post_twice_nat_port = 0
5327 self.vapi.nat44_forwarding_enable_disable(1)
5328 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5329 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5330 self.config_flags.NAT_IS_SELF_TWICE_NAT)
5331 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
5332 local_port, external_port,
5333 proto=IP_PROTOS.tcp, vrf_id=1,
5335 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
5337 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5338 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
5339 TCP(sport=12345, dport=external_port))
5340 self.pg6.add_stream(p)
5341 self.pg_enable_capture(self.pg_interfaces)
5343 capture = self.pg6.get_capture(1)
5348 self.assertEqual(ip.src, twice_nat_addr)
5349 self.assertNotEqual(tcp.sport, 12345)
5350 post_twice_nat_port = tcp.sport
5351 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5352 self.assertEqual(tcp.dport, local_port)
5353 self.assert_packet_checksums_valid(p)
5355 self.logger.error(ppp("Unexpected or invalid packet:", p))
5358 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5359 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
5360 TCP(sport=local_port, dport=post_twice_nat_port))
5361 self.pg6.add_stream(p)
5362 self.pg_enable_capture(self.pg_interfaces)
5364 capture = self.pg6.get_capture(1)
5369 self.assertEqual(ip.src, self.pg1.remote_ip4)
5370 self.assertEqual(tcp.sport, external_port)
5371 self.assertEqual(ip.dst, self.pg6.remote_ip4)
5372 self.assertEqual(tcp.dport, 12345)
5373 self.assert_packet_checksums_valid(p)
5375 self.logger.error(ppp("Unexpected or invalid packet:", p))
5378 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
5380 twice_nat_addr = '10.0.1.3'
5388 port_in1 = port_in + 1
5389 port_in2 = port_in + 2
5394 server1 = self.pg0.remote_hosts[0]
5395 server2 = self.pg0.remote_hosts[1]
5407 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
5410 self.nat44_add_address(self.nat_addr)
5411 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5415 flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
5417 flags |= self.config_flags.NAT_IS_TWICE_NAT
5420 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
5422 proto=IP_PROTOS.tcp,
5425 locals = [{'addr': server1.ip4n,
5429 {'addr': server2.ip4n,
5433 out_addr = self.nat_addr
5435 self.vapi.nat44_add_del_lb_static_mapping(out_addr,
5438 local_num=len(locals),
5441 flags = self.config_flags.NAT_IS_INSIDE
5442 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index,
5444 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index)
5450 assert client_id is not None
5452 client = self.pg0.remote_hosts[0]
5453 elif client_id == 2:
5454 client = self.pg0.remote_hosts[1]
5456 client = pg1.remote_hosts[0]
5457 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5458 IP(src=client.ip4, dst=self.nat_addr) /
5459 TCP(sport=eh_port_out, dport=port_out))
5461 self.pg_enable_capture(self.pg_interfaces)
5463 capture = pg0.get_capture(1)
5469 if ip.dst == server1.ip4:
5475 self.assertEqual(ip.dst, server.ip4)
5477 self.assertIn(tcp.dport, [port_in1, port_in2])
5479 self.assertEqual(tcp.dport, port_in)
5481 self.assertEqual(ip.src, twice_nat_addr)
5482 self.assertNotEqual(tcp.sport, eh_port_out)
5484 self.assertEqual(ip.src, client.ip4)
5485 self.assertEqual(tcp.sport, eh_port_out)
5487 eh_port_in = tcp.sport
5488 saved_port_in = tcp.dport
5489 self.assert_packet_checksums_valid(p)
5491 self.logger.error(ppp("Unexpected or invalid packet:", p))
5494 p = (Ether(src=server.mac, dst=pg0.local_mac) /
5495 IP(src=server.ip4, dst=eh_addr_in) /
5496 TCP(sport=saved_port_in, dport=eh_port_in))
5498 self.pg_enable_capture(self.pg_interfaces)
5500 capture = pg1.get_capture(1)
5505 self.assertEqual(ip.dst, client.ip4)
5506 self.assertEqual(ip.src, self.nat_addr)
5507 self.assertEqual(tcp.dport, eh_port_out)
5508 self.assertEqual(tcp.sport, port_out)
5509 self.assert_packet_checksums_valid(p)
5511 self.logger.error(ppp("Unexpected or invalid packet:", p))
5515 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5516 self.assertEqual(len(sessions), 1)
5517 self.assertTrue(sessions[0].flags &
5518 self.config_flags.NAT_IS_EXT_HOST_VALID)
5519 self.assertTrue(sessions[0].flags &
5520 self.config_flags.NAT_IS_TWICE_NAT)
5521 self.logger.error(self.vapi.cli("show nat44 sessions detail"))
5522 self.vapi.nat44_del_session(
5523 sessions[0].inside_ip_address,
5524 sessions[0].inside_port,
5525 sessions[0].protocol,
5526 flags=(self.config_flags.NAT_IS_INSIDE |
5527 self.config_flags.NAT_IS_EXT_HOST_VALID),
5528 ext_host_address=sessions[0].ext_host_nat_address,
5529 ext_host_port=sessions[0].ext_host_nat_port)
5530 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5531 self.assertEqual(len(sessions), 0)
5533 def test_twice_nat(self):
5535 self.twice_nat_common()
5537 def test_self_twice_nat_positive(self):
5538 """ Self Twice NAT44 (positive test) """
5539 self.twice_nat_common(self_twice_nat=True, same_pg=True)
5541 def test_self_twice_nat_negative(self):
5542 """ Self Twice NAT44 (negative test) """
5543 self.twice_nat_common(self_twice_nat=True)
5545 def test_twice_nat_lb(self):
5546 """ Twice NAT44 local service load balancing """
5547 self.twice_nat_common(lb=True)
5549 def test_self_twice_nat_lb_positive(self):
5550 """ Self Twice NAT44 local service load balancing (positive test) """
5551 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5554 def test_self_twice_nat_lb_negative(self):
5555 """ Self Twice NAT44 local service load balancing (negative test) """
5556 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5559 def test_twice_nat_interface_addr(self):
5560 """ Acquire twice NAT44 addresses from interface """
5561 flags = self.config_flags.NAT_IS_TWICE_NAT
5562 self.vapi.nat44_add_del_interface_addr(self.pg3.sw_if_index,
5565 # no address in NAT pool
5566 adresses = self.vapi.nat44_address_dump()
5567 self.assertEqual(0, len(adresses))
5569 # configure interface address and check NAT address pool
5570 self.pg3.config_ip4()
5571 adresses = self.vapi.nat44_address_dump()
5572 self.assertEqual(1, len(adresses))
5573 self.assertEqual(str(adresses[0].ip_address),
5575 self.assertEqual(adresses[0].flags, flags)
5577 # remove interface address and check NAT address pool
5578 self.pg3.unconfig_ip4()
5579 adresses = self.vapi.nat44_address_dump()
5580 self.assertEqual(0, len(adresses))
5582 def test_tcp_close(self):
5583 """ Close TCP session from inside network - output feature """
5584 self.vapi.nat44_forwarding_enable_disable(1)
5585 self.nat44_add_address(self.pg1.local_ip4)
5586 twice_nat_addr = '10.0.1.3'
5587 service_ip = '192.168.16.150'
5588 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5589 flags = self.config_flags.NAT_IS_INSIDE
5590 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5591 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5593 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
5594 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5595 self.config_flags.NAT_IS_TWICE_NAT)
5596 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5600 proto=IP_PROTOS.tcp,
5602 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5603 start_sessnum = len(sessions)
5605 # SYN packet out->in
5606 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5607 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5608 TCP(sport=33898, dport=80, flags="S"))
5609 self.pg1.add_stream(p)
5610 self.pg_enable_capture(self.pg_interfaces)
5612 capture = self.pg0.get_capture(1)
5614 tcp_port = p[TCP].sport
5616 # SYN + ACK packet in->out
5617 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5618 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5619 TCP(sport=80, dport=tcp_port, flags="SA"))
5620 self.pg0.add_stream(p)
5621 self.pg_enable_capture(self.pg_interfaces)
5623 self.pg1.get_capture(1)
5625 # ACK packet out->in
5626 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5627 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5628 TCP(sport=33898, dport=80, flags="A"))
5629 self.pg1.add_stream(p)
5630 self.pg_enable_capture(self.pg_interfaces)
5632 self.pg0.get_capture(1)
5634 # FIN packet in -> out
5635 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5636 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5637 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5638 self.pg0.add_stream(p)
5639 self.pg_enable_capture(self.pg_interfaces)
5641 self.pg1.get_capture(1)
5643 # FIN+ACK packet out -> in
5644 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5645 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5646 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5647 self.pg1.add_stream(p)
5648 self.pg_enable_capture(self.pg_interfaces)
5650 self.pg0.get_capture(1)
5652 # ACK packet in -> out
5653 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5654 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5655 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5656 self.pg0.add_stream(p)
5657 self.pg_enable_capture(self.pg_interfaces)
5659 self.pg1.get_capture(1)
5661 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5663 self.assertEqual(len(sessions) - start_sessnum, 0)
5665 def test_tcp_session_close_in(self):
5666 """ Close TCP session from inside network """
5667 self.tcp_port_out = 10505
5668 self.nat44_add_address(self.nat_addr)
5669 flags = self.config_flags.NAT_IS_TWICE_NAT
5670 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5674 proto=IP_PROTOS.tcp,
5676 flags = self.config_flags.NAT_IS_INSIDE
5677 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5679 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
5681 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5682 start_sessnum = len(sessions)
5684 self.initiate_tcp_session(self.pg0, self.pg1)
5686 # FIN packet in -> out
5687 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5688 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5689 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5690 flags="FA", seq=100, ack=300))
5691 self.pg0.add_stream(p)
5692 self.pg_enable_capture(self.pg_interfaces)
5694 self.pg1.get_capture(1)
5698 # ACK packet out -> in
5699 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5700 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5701 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5702 flags="A", seq=300, ack=101))
5705 # FIN packet out -> in
5706 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5707 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5708 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5709 flags="FA", seq=300, ack=101))
5712 self.pg1.add_stream(pkts)
5713 self.pg_enable_capture(self.pg_interfaces)
5715 self.pg0.get_capture(2)
5717 # ACK packet in -> out
5718 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5719 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5720 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5721 flags="A", seq=101, ack=301))
5722 self.pg0.add_stream(p)
5723 self.pg_enable_capture(self.pg_interfaces)
5725 self.pg1.get_capture(1)
5727 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5729 self.assertEqual(len(sessions) - start_sessnum, 0)
5731 def test_tcp_session_close_out(self):
5732 """ Close TCP session from outside network """
5733 self.tcp_port_out = 10505
5734 self.nat44_add_address(self.nat_addr)
5735 flags = self.config_flags.NAT_IS_TWICE_NAT
5736 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5740 proto=IP_PROTOS.tcp,
5742 flags = self.config_flags.NAT_IS_INSIDE
5743 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5745 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
5747 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5748 start_sessnum = len(sessions)
5750 self.initiate_tcp_session(self.pg0, self.pg1)
5752 # FIN packet out -> in
5753 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5754 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5755 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5756 flags="FA", seq=100, ack=300))
5757 self.pg1.add_stream(p)
5758 self.pg_enable_capture(self.pg_interfaces)
5760 self.pg0.get_capture(1)
5762 # FIN+ACK packet in -> out
5763 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5764 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5765 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5766 flags="FA", seq=300, ack=101))
5768 self.pg0.add_stream(p)
5769 self.pg_enable_capture(self.pg_interfaces)
5771 self.pg1.get_capture(1)
5773 # ACK packet out -> in
5774 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5775 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5776 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5777 flags="A", seq=101, ack=301))
5778 self.pg1.add_stream(p)
5779 self.pg_enable_capture(self.pg_interfaces)
5781 self.pg0.get_capture(1)
5783 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5785 self.assertEqual(len(sessions) - start_sessnum, 0)
5787 def test_tcp_session_close_simultaneous(self):
5788 """ Close TCP session from inside network """
5789 self.tcp_port_out = 10505
5790 self.nat44_add_address(self.nat_addr)
5791 flags = self.config_flags.NAT_IS_TWICE_NAT
5792 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5796 proto=IP_PROTOS.tcp,
5798 flags = self.config_flags.NAT_IS_INSIDE
5799 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5801 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
5803 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5804 start_sessnum = len(sessions)
5806 self.initiate_tcp_session(self.pg0, self.pg1)
5808 # FIN packet in -> out
5809 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5810 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5811 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5812 flags="FA", seq=100, ack=300))
5813 self.pg0.add_stream(p)
5814 self.pg_enable_capture(self.pg_interfaces)
5816 self.pg1.get_capture(1)
5818 # FIN packet out -> in
5819 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5820 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5821 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5822 flags="FA", seq=300, ack=100))
5823 self.pg1.add_stream(p)
5824 self.pg_enable_capture(self.pg_interfaces)
5826 self.pg0.get_capture(1)
5828 # ACK packet in -> out
5829 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5830 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5831 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5832 flags="A", seq=101, ack=301))
5833 self.pg0.add_stream(p)
5834 self.pg_enable_capture(self.pg_interfaces)
5836 self.pg1.get_capture(1)
5838 # ACK packet out -> in
5839 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5840 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5841 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5842 flags="A", seq=301, ack=101))
5843 self.pg1.add_stream(p)
5844 self.pg_enable_capture(self.pg_interfaces)
5846 self.pg0.get_capture(1)
5848 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5850 self.assertEqual(len(sessions) - start_sessnum, 0)
5852 def test_one_armed_nat44_static(self):
5853 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
5854 remote_host = self.pg4.remote_hosts[0]
5855 local_host = self.pg4.remote_hosts[1]
5860 self.vapi.nat44_forwarding_enable_disable(1)
5861 self.nat44_add_address(self.nat_addr, twice_nat=1)
5862 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
5863 self.config_flags.NAT_IS_TWICE_NAT)
5864 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
5865 local_port, external_port,
5866 proto=IP_PROTOS.tcp, flags=flags)
5867 flags = self.config_flags.NAT_IS_INSIDE
5868 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
5869 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
5872 # from client to service
5873 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5874 IP(src=remote_host.ip4, dst=self.nat_addr) /
5875 TCP(sport=12345, dport=external_port))
5876 self.pg4.add_stream(p)
5877 self.pg_enable_capture(self.pg_interfaces)
5879 capture = self.pg4.get_capture(1)
5884 self.assertEqual(ip.dst, local_host.ip4)
5885 self.assertEqual(ip.src, self.nat_addr)
5886 self.assertEqual(tcp.dport, local_port)
5887 self.assertNotEqual(tcp.sport, 12345)
5888 eh_port_in = tcp.sport
5889 self.assert_packet_checksums_valid(p)
5891 self.logger.error(ppp("Unexpected or invalid packet:", p))
5894 # from service back to client
5895 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5896 IP(src=local_host.ip4, dst=self.nat_addr) /
5897 TCP(sport=local_port, dport=eh_port_in))
5898 self.pg4.add_stream(p)
5899 self.pg_enable_capture(self.pg_interfaces)
5901 capture = self.pg4.get_capture(1)
5906 self.assertEqual(ip.src, self.nat_addr)
5907 self.assertEqual(ip.dst, remote_host.ip4)
5908 self.assertEqual(tcp.sport, external_port)
5909 self.assertEqual(tcp.dport, 12345)
5910 self.assert_packet_checksums_valid(p)
5912 self.logger.error(ppp("Unexpected or invalid packet:", p))
5915 def test_static_with_port_out2(self):
5916 """ 1:1 NAPT asymmetrical rule """
5921 self.vapi.nat44_forwarding_enable_disable(1)
5922 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
5923 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
5924 local_port, external_port,
5925 proto=IP_PROTOS.tcp, flags=flags)
5926 flags = self.config_flags.NAT_IS_INSIDE
5927 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5929 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
5931 # from client to service
5932 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5933 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5934 TCP(sport=12345, dport=external_port))
5935 self.pg1.add_stream(p)
5936 self.pg_enable_capture(self.pg_interfaces)
5938 capture = self.pg0.get_capture(1)
5943 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5944 self.assertEqual(tcp.dport, local_port)
5945 self.assert_packet_checksums_valid(p)
5947 self.logger.error(ppp("Unexpected or invalid packet:", p))
5951 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5952 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5953 ICMP(type=11) / capture[0][IP])
5954 self.pg0.add_stream(p)
5955 self.pg_enable_capture(self.pg_interfaces)
5957 capture = self.pg1.get_capture(1)
5960 self.assertEqual(p[IP].src, self.nat_addr)
5962 self.assertEqual(inner.dst, self.nat_addr)
5963 self.assertEqual(inner[TCPerror].dport, external_port)
5965 self.logger.error(ppp("Unexpected or invalid packet:", p))
5968 # from service back to client
5969 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5970 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5971 TCP(sport=local_port, dport=12345))
5972 self.pg0.add_stream(p)
5973 self.pg_enable_capture(self.pg_interfaces)
5975 capture = self.pg1.get_capture(1)
5980 self.assertEqual(ip.src, self.nat_addr)
5981 self.assertEqual(tcp.sport, external_port)
5982 self.assert_packet_checksums_valid(p)
5984 self.logger.error(ppp("Unexpected or invalid packet:", p))
5988 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5989 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5990 ICMP(type=11) / capture[0][IP])
5991 self.pg1.add_stream(p)
5992 self.pg_enable_capture(self.pg_interfaces)
5994 capture = self.pg0.get_capture(1)
5997 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
5999 self.assertEqual(inner.src, self.pg0.remote_ip4)
6000 self.assertEqual(inner[TCPerror].sport, local_port)
6002 self.logger.error(ppp("Unexpected or invalid packet:", p))
6005 # from client to server (no translation)
6006 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6007 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
6008 TCP(sport=12346, dport=local_port))
6009 self.pg1.add_stream(p)
6010 self.pg_enable_capture(self.pg_interfaces)
6012 capture = self.pg0.get_capture(1)
6017 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6018 self.assertEqual(tcp.dport, local_port)
6019 self.assert_packet_checksums_valid(p)
6021 self.logger.error(ppp("Unexpected or invalid packet:", p))
6024 # from service back to client (no translation)
6025 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6026 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6027 TCP(sport=local_port, dport=12346))
6028 self.pg0.add_stream(p)
6029 self.pg_enable_capture(self.pg_interfaces)
6031 capture = self.pg1.get_capture(1)
6036 self.assertEqual(ip.src, self.pg0.remote_ip4)
6037 self.assertEqual(tcp.sport, local_port)
6038 self.assert_packet_checksums_valid(p)
6040 self.logger.error(ppp("Unexpected or invalid packet:", p))
6043 def test_output_feature(self):
6044 """ NAT44 interface output feature (in2out postrouting) """
6045 self.vapi.nat44_forwarding_enable_disable(1)
6046 self.nat44_add_address(self.nat_addr)
6047 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6048 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
6051 pkts = self.create_stream_in(self.pg0, self.pg1)
6052 self.pg0.add_stream(pkts)
6053 self.pg_enable_capture(self.pg_interfaces)
6055 capture = self.pg1.get_capture(len(pkts))
6056 self.verify_capture_out(capture)
6059 pkts = self.create_stream_out(self.pg1)
6060 self.pg1.add_stream(pkts)
6061 self.pg_enable_capture(self.pg_interfaces)
6063 capture = self.pg0.get_capture(len(pkts))
6064 self.verify_capture_in(capture, self.pg0)
6066 def test_multiple_vrf(self):
6067 """ Multiple VRF setup """
6068 external_addr = '1.2.3.4'
6073 self.vapi.nat44_forwarding_enable_disable(1)
6074 self.nat44_add_address(self.nat_addr)
6075 flags = self.config_flags.NAT_IS_INSIDE
6076 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6077 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6079 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
6080 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
6081 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index,
6083 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
6084 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
6085 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
6086 local_port, external_port, vrf_id=1,
6087 proto=IP_PROTOS.tcp, flags=flags)
6088 self.nat44_add_static_mapping(
6089 self.pg0.remote_ip4,
6090 external_sw_if_index=self.pg0.sw_if_index,
6091 local_port=local_port,
6093 external_port=external_port,
6094 proto=IP_PROTOS.tcp,
6098 # from client to service (both VRF1)
6099 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6100 IP(src=self.pg6.remote_ip4, dst=external_addr) /
6101 TCP(sport=12345, dport=external_port))
6102 self.pg6.add_stream(p)
6103 self.pg_enable_capture(self.pg_interfaces)
6105 capture = self.pg5.get_capture(1)
6110 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6111 self.assertEqual(tcp.dport, local_port)
6112 self.assert_packet_checksums_valid(p)
6114 self.logger.error(ppp("Unexpected or invalid packet:", p))
6117 # from service back to client (both VRF1)
6118 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6119 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6120 TCP(sport=local_port, dport=12345))
6121 self.pg5.add_stream(p)
6122 self.pg_enable_capture(self.pg_interfaces)
6124 capture = self.pg6.get_capture(1)
6129 self.assertEqual(ip.src, external_addr)
6130 self.assertEqual(tcp.sport, external_port)
6131 self.assert_packet_checksums_valid(p)
6133 self.logger.error(ppp("Unexpected or invalid packet:", p))
6136 # dynamic NAT from VRF1 to VRF0 (output-feature)
6137 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6138 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
6139 TCP(sport=2345, dport=22))
6140 self.pg5.add_stream(p)
6141 self.pg_enable_capture(self.pg_interfaces)
6143 capture = self.pg1.get_capture(1)
6148 self.assertEqual(ip.src, self.nat_addr)
6149 self.assertNotEqual(tcp.sport, 2345)
6150 self.assert_packet_checksums_valid(p)
6153 self.logger.error(ppp("Unexpected or invalid packet:", p))
6156 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6157 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6158 TCP(sport=22, dport=port))
6159 self.pg1.add_stream(p)
6160 self.pg_enable_capture(self.pg_interfaces)
6162 capture = self.pg5.get_capture(1)
6167 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6168 self.assertEqual(tcp.dport, 2345)
6169 self.assert_packet_checksums_valid(p)
6171 self.logger.error(ppp("Unexpected or invalid packet:", p))
6174 # from client VRF1 to service VRF0
6175 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6176 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
6177 TCP(sport=12346, dport=external_port))
6178 self.pg6.add_stream(p)
6179 self.pg_enable_capture(self.pg_interfaces)
6181 capture = self.pg0.get_capture(1)
6186 self.assertEqual(ip.dst, self.pg0.remote_ip4)
6187 self.assertEqual(tcp.dport, local_port)
6188 self.assert_packet_checksums_valid(p)
6190 self.logger.error(ppp("Unexpected or invalid packet:", p))
6193 # from service VRF0 back to client VRF1
6194 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6195 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6196 TCP(sport=local_port, dport=12346))
6197 self.pg0.add_stream(p)
6198 self.pg_enable_capture(self.pg_interfaces)
6200 capture = self.pg6.get_capture(1)
6205 self.assertEqual(ip.src, self.pg0.local_ip4)
6206 self.assertEqual(tcp.sport, external_port)
6207 self.assert_packet_checksums_valid(p)
6209 self.logger.error(ppp("Unexpected or invalid packet:", p))
6212 # from client VRF0 to service VRF1
6213 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6214 IP(src=self.pg0.remote_ip4, dst=external_addr) /
6215 TCP(sport=12347, dport=external_port))
6216 self.pg0.add_stream(p)
6217 self.pg_enable_capture(self.pg_interfaces)
6219 capture = self.pg5.get_capture(1)
6224 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6225 self.assertEqual(tcp.dport, local_port)
6226 self.assert_packet_checksums_valid(p)
6228 self.logger.error(ppp("Unexpected or invalid packet:", p))
6231 # from service VRF1 back to client VRF0
6232 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6233 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6234 TCP(sport=local_port, dport=12347))
6235 self.pg5.add_stream(p)
6236 self.pg_enable_capture(self.pg_interfaces)
6238 capture = self.pg0.get_capture(1)
6243 self.assertEqual(ip.src, external_addr)
6244 self.assertEqual(tcp.sport, external_port)
6245 self.assert_packet_checksums_valid(p)
6247 self.logger.error(ppp("Unexpected or invalid packet:", p))
6250 # from client to server (both VRF1, no translation)
6251 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
6252 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
6253 TCP(sport=12348, dport=local_port))
6254 self.pg6.add_stream(p)
6255 self.pg_enable_capture(self.pg_interfaces)
6257 capture = self.pg5.get_capture(1)
6262 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6263 self.assertEqual(tcp.dport, local_port)
6264 self.assert_packet_checksums_valid(p)
6266 self.logger.error(ppp("Unexpected or invalid packet:", p))
6269 # from server back to client (both VRF1, no translation)
6270 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6271 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
6272 TCP(sport=local_port, dport=12348))
6273 self.pg5.add_stream(p)
6274 self.pg_enable_capture(self.pg_interfaces)
6276 capture = self.pg6.get_capture(1)
6281 self.assertEqual(ip.src, self.pg5.remote_ip4)
6282 self.assertEqual(tcp.sport, local_port)
6283 self.assert_packet_checksums_valid(p)
6285 self.logger.error(ppp("Unexpected or invalid packet:", p))
6288 # from client VRF1 to server VRF0 (no translation)
6289 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6290 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6291 TCP(sport=local_port, dport=12349))
6292 self.pg0.add_stream(p)
6293 self.pg_enable_capture(self.pg_interfaces)
6295 capture = self.pg6.get_capture(1)
6300 self.assertEqual(ip.src, self.pg0.remote_ip4)
6301 self.assertEqual(tcp.sport, local_port)
6302 self.assert_packet_checksums_valid(p)
6304 self.logger.error(ppp("Unexpected or invalid packet:", p))
6307 # from server VRF0 back to client VRF1 (no translation)
6308 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6309 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
6310 TCP(sport=local_port, dport=12349))
6311 self.pg0.add_stream(p)
6312 self.pg_enable_capture(self.pg_interfaces)
6314 capture = self.pg6.get_capture(1)
6319 self.assertEqual(ip.src, self.pg0.remote_ip4)
6320 self.assertEqual(tcp.sport, local_port)
6321 self.assert_packet_checksums_valid(p)
6323 self.logger.error(ppp("Unexpected or invalid packet:", p))
6326 # from client VRF0 to server VRF1 (no translation)
6327 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6328 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
6329 TCP(sport=12344, dport=local_port))
6330 self.pg0.add_stream(p)
6331 self.pg_enable_capture(self.pg_interfaces)
6333 capture = self.pg5.get_capture(1)
6338 self.assertEqual(ip.dst, self.pg5.remote_ip4)
6339 self.assertEqual(tcp.dport, local_port)
6340 self.assert_packet_checksums_valid(p)
6342 self.logger.error(ppp("Unexpected or invalid packet:", p))
6345 # from server VRF1 back to client VRF0 (no translation)
6346 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
6347 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
6348 TCP(sport=local_port, dport=12344))
6349 self.pg5.add_stream(p)
6350 self.pg_enable_capture(self.pg_interfaces)
6352 capture = self.pg0.get_capture(1)
6357 self.assertEqual(ip.src, self.pg5.remote_ip4)
6358 self.assertEqual(tcp.sport, local_port)
6359 self.assert_packet_checksums_valid(p)
6361 self.logger.error(ppp("Unexpected or invalid packet:", p))
6364 @unittest.skipUnless(running_extended_tests, "part of extended tests")
6365 def test_session_timeout(self):
6366 """ NAT44 session timeouts """
6367 self.nat44_add_address(self.nat_addr)
6368 flags = self.config_flags.NAT_IS_INSIDE
6369 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6371 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
6372 self.vapi.nat_set_timeouts(icmp=5)
6376 for i in range(0, max_sessions):
6377 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6378 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6379 IP(src=src, dst=self.pg1.remote_ip4) /
6380 ICMP(id=1025, type='echo-request'))
6382 self.pg0.add_stream(pkts)
6383 self.pg_enable_capture(self.pg_interfaces)
6385 self.pg1.get_capture(max_sessions)
6390 for i in range(0, max_sessions):
6391 src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
6392 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6393 IP(src=src, dst=self.pg1.remote_ip4) /
6394 ICMP(id=1026, type='echo-request'))
6396 self.pg0.add_stream(pkts)
6397 self.pg_enable_capture(self.pg_interfaces)
6399 self.pg1.get_capture(max_sessions)
6402 users = self.vapi.nat44_user_dump()
6404 nsessions = nsessions + user.nsessions
6405 self.assertLess(nsessions, 2 * max_sessions)
6407 @unittest.skipUnless(running_extended_tests, "part of extended tests")
6408 def test_session_rst_timeout(self):
6409 """ NAT44 session RST timeouts """
6410 self.nat44_add_address(self.nat_addr)
6411 flags = self.config_flags.NAT_IS_INSIDE
6412 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6414 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
6415 self.vapi.nat_set_timeouts(tcp_transitory=5)
6417 self.initiate_tcp_session(self.pg0, self.pg1)
6418 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6419 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6420 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6422 self.pg0.add_stream(p)
6423 self.pg_enable_capture(self.pg_interfaces)
6425 self.pg1.get_capture(1)
6429 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6430 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6431 TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
6433 self.pg0.add_stream(p)
6434 self.pg_enable_capture(self.pg_interfaces)
6436 self.pg1.get_capture(1)
6439 users = self.vapi.nat44_user_dump()
6440 self.assertEqual(len(users), 1)
6441 self.assertEqual(str(users[0].ip_address),
6442 self.pg0.remote_ip4)
6443 self.assertEqual(users[0].nsessions, 1)
6445 @unittest.skipUnless(running_extended_tests, "part of extended tests")
6446 def test_session_limit_per_user(self):
6447 """ Maximum sessions per user limit """
6448 self.nat44_add_address(self.nat_addr)
6449 flags = self.config_flags.NAT_IS_INSIDE
6450 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6452 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
6453 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
6454 src_address=self.pg2.local_ip4n,
6456 template_interval=10)
6457 self.vapi.nat_set_timeouts(udp=5)
6459 # get maximum number of translations per user
6460 nat44_config = self.vapi.nat_show_config()
6463 for port in range(0, nat44_config.max_translations_per_user):
6464 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6465 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6466 UDP(sport=1025 + port, dport=1025 + port))
6469 self.pg0.add_stream(pkts)
6470 self.pg_enable_capture(self.pg_interfaces)
6472 capture = self.pg1.get_capture(len(pkts))
6474 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
6475 src_port=self.ipfix_src_port)
6477 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6478 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6479 UDP(sport=3001, dport=3002))
6480 self.pg0.add_stream(p)
6481 self.pg_enable_capture(self.pg_interfaces)
6483 capture = self.pg1.assert_nothing_captured()
6485 # verify IPFIX logging
6486 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6488 capture = self.pg2.get_capture(10)
6489 ipfix = IPFIXDecoder()
6490 # first load template
6492 self.assertTrue(p.haslayer(IPFIX))
6493 if p.haslayer(Template):
6494 ipfix.add_template(p.getlayer(Template))
6495 # verify events in data set
6497 if p.haslayer(Data):
6498 data = ipfix.decode_data_set(p.getlayer(Set))
6499 self.verify_ipfix_max_entries_per_user(
6501 nat44_config.max_translations_per_user,
6502 self.pg0.remote_ip4n)
6505 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6506 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6507 UDP(sport=3001, dport=3002))
6508 self.pg0.add_stream(p)
6509 self.pg_enable_capture(self.pg_interfaces)
6511 self.pg1.get_capture(1)
6513 def test_syslog_sess(self):
6514 """ Test syslog session creation and deletion """
6515 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
6516 self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
6517 self.nat44_add_address(self.nat_addr)
6518 flags = self.config_flags.NAT_IS_INSIDE
6519 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6521 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
6523 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6524 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6525 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6526 self.pg0.add_stream(p)
6527 self.pg_enable_capture(self.pg_interfaces)
6529 capture = self.pg1.get_capture(1)
6530 self.tcp_port_out = capture[0][TCP].sport
6531 capture = self.pg2.get_capture(1)
6532 self.verify_syslog_sess(capture[0][Raw].load)
6534 self.pg_enable_capture(self.pg_interfaces)
6536 self.nat44_add_address(self.nat_addr, is_add=0)
6537 capture = self.pg2.get_capture(1)
6538 self.verify_syslog_sess(capture[0][Raw].load, False)
6541 super(TestNAT44EndpointDependent, self).tearDown()
6542 if not self.vpp_dead:
6544 self.vapi.cli("clear logging")
6546 def show_commands_at_teardown(self):
6547 self.logger.info(self.vapi.cli("show nat44 addresses"))
6548 self.logger.info(self.vapi.cli("show nat44 interfaces"))
6549 self.logger.info(self.vapi.cli("show nat44 static mappings"))
6550 self.logger.info(self.vapi.cli("show nat44 interface address"))
6551 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
6552 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
6553 self.logger.info(self.vapi.cli("show nat timeouts"))
6556 class TestNAT44Out2InDPO(MethodHolder):
6557 """ NAT44 Test Cases using out2in DPO """
6560 def setUpConstants(cls):
6561 super(TestNAT44Out2InDPO, cls).setUpConstants()
6562 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
6565 def setUpClass(cls):
6566 super(TestNAT44Out2InDPO, cls).setUpClass()
6567 cls.vapi.cli("set log class nat level debug")
6570 cls.tcp_port_in = 6303
6571 cls.tcp_port_out = 6303
6572 cls.udp_port_in = 6304
6573 cls.udp_port_out = 6304
6574 cls.icmp_id_in = 6305
6575 cls.icmp_id_out = 6305
6576 cls.nat_addr = '10.0.0.3'
6577 cls.dst_ip4 = '192.168.70.1'
6579 cls.create_pg_interfaces(range(2))
6582 cls.pg0.config_ip4()
6583 cls.pg0.resolve_arp()
6586 cls.pg1.config_ip6()
6587 cls.pg1.resolve_ndp()
6589 cls.vapi.ip_add_del_route(dst_address=b'\x00' * 16,
6590 dst_address_length=0,
6591 next_hop_address=cls.pg1.remote_ip6n,
6592 next_hop_sw_if_index=cls.pg1.sw_if_index,
6596 super(TestNAT44Out2InDPO, cls).tearDownClass()
6600 def tearDownClass(cls):
6601 super(TestNAT44Out2InDPO, cls).tearDownClass()
6603 def configure_xlat(self):
6604 self.dst_ip6_pfx = '1:2:3::'
6605 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6607 self.dst_ip6_pfx_len = 96
6608 self.src_ip6_pfx = '4:5:6::'
6609 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6611 self.src_ip6_pfx_len = 96
6612 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
6613 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
6614 '\x00\x00\x00\x00', 0)
6616 @unittest.skip('Temporary disabled')
6617 def test_464xlat_ce(self):
6618 """ Test 464XLAT CE with NAT44 """
6620 nat_config = self.vapi.nat_show_config()
6621 self.assertEqual(1, nat_config.out2in_dpo)
6623 self.configure_xlat()
6625 flags = self.config_flags.NAT_IS_INSIDE
6626 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6628 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
6630 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6631 self.dst_ip6_pfx_len)
6632 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
6633 self.src_ip6_pfx_len)
6636 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6637 self.pg0.add_stream(pkts)
6638 self.pg_enable_capture(self.pg_interfaces)
6640 capture = self.pg1.get_capture(len(pkts))
6641 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
6644 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
6646 self.pg1.add_stream(pkts)
6647 self.pg_enable_capture(self.pg_interfaces)
6649 capture = self.pg0.get_capture(len(pkts))
6650 self.verify_capture_in(capture, self.pg0)
6652 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6653 is_add=0, flags=flags)
6654 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
6655 self.nat_addr_n, is_add=0)
6657 @unittest.skip('Temporary disabled')
6658 def test_464xlat_ce_no_nat(self):
6659 """ Test 464XLAT CE without NAT44 """
6661 self.configure_xlat()
6663 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6664 self.dst_ip6_pfx_len)
6665 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
6666 self.src_ip6_pfx_len)
6668 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6669 self.pg0.add_stream(pkts)
6670 self.pg_enable_capture(self.pg_interfaces)
6672 capture = self.pg1.get_capture(len(pkts))
6673 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
6674 nat_ip=out_dst_ip6, same_port=True)
6676 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
6677 self.pg1.add_stream(pkts)
6678 self.pg_enable_capture(self.pg_interfaces)
6680 capture = self.pg0.get_capture(len(pkts))
6681 self.verify_capture_in(capture, self.pg0)
6684 class TestDeterministicNAT(MethodHolder):
6685 """ Deterministic NAT Test Cases """
6688 def setUpConstants(cls):
6689 super(TestDeterministicNAT, cls).setUpConstants()
6690 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
6693 def setUpClass(cls):
6694 super(TestDeterministicNAT, cls).setUpClass()
6695 cls.vapi.cli("set log class nat level debug")
6698 cls.tcp_port_in = 6303
6699 cls.tcp_external_port = 6303
6700 cls.udp_port_in = 6304
6701 cls.udp_external_port = 6304
6702 cls.icmp_id_in = 6305
6703 cls.nat_addr = '10.0.0.3'
6705 cls.create_pg_interfaces(range(3))
6706 cls.interfaces = list(cls.pg_interfaces)
6708 for i in cls.interfaces:
6713 cls.pg0.generate_remote_hosts(2)
6714 cls.pg0.configure_ipv4_neighbors()
6717 super(TestDeterministicNAT, cls).tearDownClass()
6721 def tearDownClass(cls):
6722 super(TestDeterministicNAT, cls).tearDownClass()
6724 def create_stream_in(self, in_if, out_if, ttl=64):
6726 Create packet stream for inside network
6728 :param in_if: Inside interface
6729 :param out_if: Outside interface
6730 :param ttl: TTL of generated packets
6734 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6735 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
6736 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6740 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6741 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
6742 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
6746 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6747 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
6748 ICMP(id=self.icmp_id_in, type='echo-request'))
6753 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
6755 Create packet stream for outside network
6757 :param out_if: Outside interface
6758 :param dst_ip: Destination IP address (Default use global NAT address)
6759 :param ttl: TTL of generated packets
6762 dst_ip = self.nat_addr
6765 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6766 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
6767 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
6771 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6772 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
6773 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
6777 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6778 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
6779 ICMP(id=self.icmp_external_id, type='echo-reply'))
6784 def verify_capture_out(self, capture, nat_ip=None):
6786 Verify captured packets on outside network
6788 :param capture: Captured packets
6789 :param nat_ip: Translated IP address (Default use global NAT address)
6790 :param same_port: Source port number is not translated (Default False)
6793 nat_ip = self.nat_addr
6794 for packet in capture:
6796 self.assertEqual(packet[IP].src, nat_ip)
6797 if packet.haslayer(TCP):
6798 self.tcp_port_out = packet[TCP].sport
6799 elif packet.haslayer(UDP):
6800 self.udp_port_out = packet[UDP].sport
6802 self.icmp_external_id = packet[ICMP].id
6804 self.logger.error(ppp("Unexpected or invalid packet "
6805 "(outside network):", packet))
6808 def test_deterministic_mode(self):
6809 """ NAT plugin run deterministic mode """
6810 in_addr = '172.16.255.0'
6811 out_addr = '172.17.255.50'
6812 in_addr_t = '172.16.255.20'
6816 nat_config = self.vapi.nat_show_config()
6817 self.assertEqual(1, nat_config.deterministic)
6819 self.vapi.nat_det_add_del_map(1, in_addr, in_plen, out_addr, out_plen)
6821 rep1 = self.vapi.nat_det_forward(in_addr_t)
6822 self.assertEqual(str(rep1.out_addr), out_addr)
6823 rep2 = self.vapi.nat_det_reverse(rep1.out_port_hi, out_addr)
6825 self.assertEqual(str(rep2.in_addr), in_addr_t)
6827 deterministic_mappings = self.vapi.nat_det_map_dump()
6828 self.assertEqual(len(deterministic_mappings), 1)
6829 dsm = deterministic_mappings[0]
6830 self.assertEqual(in_addr, str(dsm.in_addr))
6831 self.assertEqual(in_plen, dsm.in_plen)
6832 self.assertEqual(out_addr, str(dsm.out_addr))
6833 self.assertEqual(out_plen, dsm.out_plen)
6835 self.clear_nat_det()
6836 deterministic_mappings = self.vapi.nat_det_map_dump()
6837 self.assertEqual(len(deterministic_mappings), 0)
6839 def test_set_timeouts(self):
6840 """ Set deterministic NAT timeouts """
6841 timeouts_before = self.vapi.nat_get_timeouts()
6843 self.vapi.nat_set_timeouts(timeouts_before.udp + 10,
6844 timeouts_before.tcp_established + 10,
6845 timeouts_before.tcp_transitory + 10,
6846 timeouts_before.icmp + 10)
6848 timeouts_after = self.vapi.nat_get_timeouts()
6850 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
6851 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
6852 self.assertNotEqual(timeouts_before.tcp_established,
6853 timeouts_after.tcp_established)
6854 self.assertNotEqual(timeouts_before.tcp_transitory,
6855 timeouts_after.tcp_transitory)
6857 def test_det_in(self):
6858 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
6860 nat_ip = "10.0.0.10"
6862 self.vapi.nat_det_add_del_map(1,
6863 self.pg0.remote_ip4n,
6865 socket.inet_aton(nat_ip),
6868 flags = self.config_flags.NAT_IS_INSIDE
6869 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6871 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
6874 pkts = self.create_stream_in(self.pg0, self.pg1)
6875 self.pg0.add_stream(pkts)
6876 self.pg_enable_capture(self.pg_interfaces)
6878 capture = self.pg1.get_capture(len(pkts))
6879 self.verify_capture_out(capture, nat_ip)
6882 pkts = self.create_stream_out(self.pg1, nat_ip)
6883 self.pg1.add_stream(pkts)
6884 self.pg_enable_capture(self.pg_interfaces)
6886 capture = self.pg0.get_capture(len(pkts))
6887 self.verify_capture_in(capture, self.pg0)
6890 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
6891 self.assertEqual(len(sessions), 3)
6895 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
6896 self.assertEqual(s.in_port, self.tcp_port_in)
6897 self.assertEqual(s.out_port, self.tcp_port_out)
6898 self.assertEqual(s.ext_port, self.tcp_external_port)
6902 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
6903 self.assertEqual(s.in_port, self.udp_port_in)
6904 self.assertEqual(s.out_port, self.udp_port_out)
6905 self.assertEqual(s.ext_port, self.udp_external_port)
6909 self.assertEqual(str(s.ext_addr), self.pg1.remote_ip4)
6910 self.assertEqual(s.in_port, self.icmp_id_in)
6911 self.assertEqual(s.out_port, self.icmp_external_id)
6913 def test_multiple_users(self):
6914 """ Deterministic NAT multiple users """
6916 nat_ip = "10.0.0.10"
6918 external_port = 6303
6920 host0 = self.pg0.remote_hosts[0]
6921 host1 = self.pg0.remote_hosts[1]
6923 self.vapi.nat_det_add_del_map(1,
6926 socket.inet_aton(nat_ip),
6928 flags = self.config_flags.NAT_IS_INSIDE
6929 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6931 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
6934 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
6935 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
6936 TCP(sport=port_in, dport=external_port))
6937 self.pg0.add_stream(p)
6938 self.pg_enable_capture(self.pg_interfaces)
6940 capture = self.pg1.get_capture(1)
6945 self.assertEqual(ip.src, nat_ip)
6946 self.assertEqual(ip.dst, self.pg1.remote_ip4)
6947 self.assertEqual(tcp.dport, external_port)
6948 port_out0 = tcp.sport
6950 self.logger.error(ppp("Unexpected or invalid packet:", p))
6954 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
6955 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
6956 TCP(sport=port_in, dport=external_port))
6957 self.pg0.add_stream(p)
6958 self.pg_enable_capture(self.pg_interfaces)
6960 capture = self.pg1.get_capture(1)
6965 self.assertEqual(ip.src, nat_ip)
6966 self.assertEqual(ip.dst, self.pg1.remote_ip4)
6967 self.assertEqual(tcp.dport, external_port)
6968 port_out1 = tcp.sport
6970 self.logger.error(ppp("Unexpected or invalid packet:", p))
6973 dms = self.vapi.nat_det_map_dump()
6974 self.assertEqual(1, len(dms))
6975 self.assertEqual(2, dms[0].ses_num)
6978 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6979 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
6980 TCP(sport=external_port, dport=port_out0))
6981 self.pg1.add_stream(p)
6982 self.pg_enable_capture(self.pg_interfaces)
6984 capture = self.pg0.get_capture(1)
6989 self.assertEqual(ip.src, self.pg1.remote_ip4)
6990 self.assertEqual(ip.dst, host0.ip4)
6991 self.assertEqual(tcp.dport, port_in)
6992 self.assertEqual(tcp.sport, external_port)
6994 self.logger.error(ppp("Unexpected or invalid packet:", p))
6998 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6999 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
7000 TCP(sport=external_port, dport=port_out1))
7001 self.pg1.add_stream(p)
7002 self.pg_enable_capture(self.pg_interfaces)
7004 capture = self.pg0.get_capture(1)
7009 self.assertEqual(ip.src, self.pg1.remote_ip4)
7010 self.assertEqual(ip.dst, host1.ip4)
7011 self.assertEqual(tcp.dport, port_in)
7012 self.assertEqual(tcp.sport, external_port)
7014 self.logger.error(ppp("Unexpected or invalid packet", p))
7017 # session close api test
7018 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
7020 self.pg1.remote_ip4n,
7022 dms = self.vapi.nat_det_map_dump()
7023 self.assertEqual(dms[0].ses_num, 1)
7025 self.vapi.nat_det_close_session_in(host0.ip4n,
7027 self.pg1.remote_ip4n,
7029 dms = self.vapi.nat_det_map_dump()
7030 self.assertEqual(dms[0].ses_num, 0)
7032 def test_tcp_session_close_detection_in(self):
7033 """ Deterministic NAT TCP session close from inside network """
7034 self.vapi.nat_det_add_del_map(1,
7035 self.pg0.remote_ip4n,
7037 socket.inet_aton(self.nat_addr),
7039 flags = self.config_flags.NAT_IS_INSIDE
7040 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
7042 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
7044 self.initiate_tcp_session(self.pg0, self.pg1)
7046 # close the session from inside
7048 # FIN packet in -> out
7049 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7050 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7051 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7053 self.pg0.add_stream(p)
7054 self.pg_enable_capture(self.pg_interfaces)
7056 self.pg1.get_capture(1)
7060 # ACK packet out -> in
7061 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7062 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7063 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7067 # FIN packet out -> in
7068 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7069 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7070 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7074 self.pg1.add_stream(pkts)
7075 self.pg_enable_capture(self.pg_interfaces)
7077 self.pg0.get_capture(2)
7079 # ACK packet in -> out
7080 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7081 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7082 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7084 self.pg0.add_stream(p)
7085 self.pg_enable_capture(self.pg_interfaces)
7087 self.pg1.get_capture(1)
7089 # Check if deterministic NAT44 closed the session
7090 dms = self.vapi.nat_det_map_dump()
7091 self.assertEqual(0, dms[0].ses_num)
7093 self.logger.error("TCP session termination failed")
7096 def test_tcp_session_close_detection_out(self):
7097 """ Deterministic NAT TCP session close from outside network """
7098 self.vapi.nat_det_add_del_map(1,
7099 self.pg0.remote_ip4n,
7101 socket.inet_aton(self.nat_addr),
7103 flags = self.config_flags.NAT_IS_INSIDE
7104 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
7106 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
7108 self.initiate_tcp_session(self.pg0, self.pg1)
7110 # close the session from outside
7112 # FIN packet out -> in
7113 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7114 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7115 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7117 self.pg1.add_stream(p)
7118 self.pg_enable_capture(self.pg_interfaces)
7120 self.pg0.get_capture(1)
7124 # ACK packet in -> out
7125 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7126 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7127 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7131 # ACK packet in -> out
7132 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7133 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7134 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
7138 self.pg0.add_stream(pkts)
7139 self.pg_enable_capture(self.pg_interfaces)
7141 self.pg1.get_capture(2)
7143 # ACK packet out -> in
7144 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
7145 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7146 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
7148 self.pg1.add_stream(p)
7149 self.pg_enable_capture(self.pg_interfaces)
7151 self.pg0.get_capture(1)
7153 # Check if deterministic NAT44 closed the session
7154 dms = self.vapi.nat_det_map_dump()
7155 self.assertEqual(0, dms[0].ses_num)
7157 self.logger.error("TCP session termination failed")
7160 @unittest.skipUnless(running_extended_tests, "part of extended tests")
7161 def test_session_timeout(self):
7162 """ Deterministic NAT session timeouts """
7163 self.vapi.nat_det_add_del_map(1,
7164 self.pg0.remote_ip4n,
7166 socket.inet_aton(self.nat_addr),
7168 flags = self.config_flags.NAT_IS_INSIDE
7169 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
7171 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
7173 self.initiate_tcp_session(self.pg0, self.pg1)
7174 self.vapi.nat_set_timeouts(5, 5, 5, 5)
7175 pkts = self.create_stream_in(self.pg0, self.pg1)
7176 self.pg0.add_stream(pkts)
7177 self.pg_enable_capture(self.pg_interfaces)
7179 capture = self.pg1.get_capture(len(pkts))
7182 dms = self.vapi.nat_det_map_dump()
7183 self.assertEqual(0, dms[0].ses_num)
7185 @unittest.skipUnless(running_extended_tests, "part of extended tests")
7186 def test_session_limit_per_user(self):
7187 """ Deterministic NAT maximum sessions per user limit """
7188 self.vapi.nat_det_add_del_map(1,
7189 self.pg0.remote_ip4n,
7191 socket.inet_aton(self.nat_addr),
7193 flags = self.config_flags.NAT_IS_INSIDE
7194 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
7196 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
7197 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
7198 src_address=self.pg2.local_ip4n,
7200 template_interval=10)
7201 self.vapi.nat_ipfix_enable_disable()
7204 for port in range(1025, 2025):
7205 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7206 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7207 UDP(sport=port, dport=port))
7210 self.pg0.add_stream(pkts)
7211 self.pg_enable_capture(self.pg_interfaces)
7213 capture = self.pg1.get_capture(len(pkts))
7215 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7216 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
7217 UDP(sport=3001, dport=3002))
7218 self.pg0.add_stream(p)
7219 self.pg_enable_capture(self.pg_interfaces)
7221 capture = self.pg1.assert_nothing_captured()
7223 # verify ICMP error packet
7224 capture = self.pg0.get_capture(1)
7226 self.assertTrue(p.haslayer(ICMP))
7228 self.assertEqual(icmp.type, 3)
7229 self.assertEqual(icmp.code, 1)
7230 self.assertTrue(icmp.haslayer(IPerror))
7231 inner_ip = icmp[IPerror]
7232 self.assertEqual(inner_ip[UDPerror].sport, 3001)
7233 self.assertEqual(inner_ip[UDPerror].dport, 3002)
7235 dms = self.vapi.nat_det_map_dump()
7237 self.assertEqual(1000, dms[0].ses_num)
7239 # verify IPFIX logging
7240 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7242 capture = self.pg2.get_capture(2)
7243 ipfix = IPFIXDecoder()
7244 # first load template
7246 self.assertTrue(p.haslayer(IPFIX))
7247 if p.haslayer(Template):
7248 ipfix.add_template(p.getlayer(Template))
7249 # verify events in data set
7251 if p.haslayer(Data):
7252 data = ipfix.decode_data_set(p.getlayer(Set))
7253 self.verify_ipfix_max_entries_per_user(data,
7255 self.pg0.remote_ip4n)
7257 def clear_nat_det(self):
7259 Clear deterministic NAT configuration.
7261 self.vapi.nat_ipfix_enable_disable(enable=0)
7262 self.vapi.nat_set_timeouts()
7263 deterministic_mappings = self.vapi.nat_det_map_dump()
7264 for dsm in deterministic_mappings:
7265 self.vapi.nat_det_add_del_map(0,
7271 interfaces = self.vapi.nat44_interface_dump()
7272 for intf in interfaces:
7273 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
7278 super(TestDeterministicNAT, self).tearDown()
7279 if not self.vpp_dead:
7280 self.clear_nat_det()
7282 def show_commands_at_teardown(self):
7283 self.logger.info(self.vapi.cli("show nat44 interfaces"))
7284 self.logger.info(self.vapi.cli("show nat timeouts"))
7286 self.vapi.cli("show nat44 deterministic mappings"))
7288 self.vapi.cli("show nat44 deterministic sessions"))
7291 class TestNAT64(MethodHolder):
7292 """ NAT64 Test Cases """
7295 def setUpConstants(cls):
7296 super(TestNAT64, cls).setUpConstants()
7297 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
7298 "nat64 st hash buckets 256", "}"])
7301 def setUpClass(cls):
7302 super(TestNAT64, cls).setUpClass()
7305 cls.tcp_port_in = 6303
7306 cls.tcp_port_out = 6303
7307 cls.udp_port_in = 6304
7308 cls.udp_port_out = 6304
7309 cls.icmp_id_in = 6305
7310 cls.icmp_id_out = 6305
7311 cls.tcp_external_port = 80
7312 cls.nat_addr = '10.0.0.3'
7313 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
7315 cls.vrf1_nat_addr = '10.0.10.3'
7316 cls.ipfix_src_port = 4739
7317 cls.ipfix_domain_id = 1
7319 cls.create_pg_interfaces(range(6))
7320 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
7321 cls.ip6_interfaces.append(cls.pg_interfaces[2])
7322 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
7324 cls.vapi.ip_table_add_del(is_ipv6=1, is_add=1,
7325 table_id=cls.vrf1_id)
7327 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
7329 cls.pg0.generate_remote_hosts(2)
7331 for i in cls.ip6_interfaces:
7334 i.configure_ipv6_neighbors()
7336 for i in cls.ip4_interfaces:
7342 cls.pg3.config_ip4()
7343 cls.pg3.resolve_arp()
7344 cls.pg3.config_ip6()
7345 cls.pg3.configure_ipv6_neighbors()
7348 cls.pg5.config_ip6()
7351 super(TestNAT64, cls).tearDownClass()
7355 def tearDownClass(cls):
7356 super(TestNAT64, cls).tearDownClass()
7358 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
7359 """ NAT64 inside interface handles Neighbor Advertisement """
7361 flags = self.config_flags.NAT_IS_INSIDE
7362 self.vapi.nat64_add_del_interface(1, flags, self.pg5.sw_if_index)
7365 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7366 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7367 ICMPv6EchoRequest())
7369 self.pg5.add_stream(pkts)
7370 self.pg_enable_capture(self.pg_interfaces)
7373 # Wait for Neighbor Solicitation
7374 capture = self.pg5.get_capture(len(pkts))
7377 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7378 self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
7379 tgt = packet[ICMPv6ND_NS].tgt
7381 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7384 # Send Neighbor Advertisement
7385 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
7386 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
7387 ICMPv6ND_NA(tgt=tgt) /
7388 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
7390 self.pg5.add_stream(pkts)
7391 self.pg_enable_capture(self.pg_interfaces)
7394 # Try to send ping again
7396 self.pg5.add_stream(pkts)
7397 self.pg_enable_capture(self.pg_interfaces)
7400 # Wait for ping reply
7401 capture = self.pg5.get_capture(len(pkts))
7404 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
7405 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
7406 self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
7408 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7411 def test_pool(self):
7412 """ Add/delete address to NAT64 pool """
7413 nat_addr = '1.2.3.4'
7415 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
7417 addresses = self.vapi.nat64_pool_addr_dump()
7418 self.assertEqual(len(addresses), 1)
7419 self.assertEqual(str(addresses[0].address), nat_addr)
7421 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
7423 addresses = self.vapi.nat64_pool_addr_dump()
7424 self.assertEqual(len(addresses), 0)
7426 def test_interface(self):
7427 """ Enable/disable NAT64 feature on the interface """
7428 flags = self.config_flags.NAT_IS_INSIDE
7429 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
7430 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
7432 interfaces = self.vapi.nat64_interface_dump()
7433 self.assertEqual(len(interfaces), 2)
7436 for intf in interfaces:
7437 if intf.sw_if_index == self.pg0.sw_if_index:
7438 self.assertEqual(intf.flags, self.config_flags.NAT_IS_INSIDE)
7440 elif intf.sw_if_index == self.pg1.sw_if_index:
7441 self.assertEqual(intf.flags, self.config_flags.NAT_IS_OUTSIDE)
7443 self.assertTrue(pg0_found)
7444 self.assertTrue(pg1_found)
7446 features = self.vapi.cli("show interface features pg0")
7447 self.assertIn('nat64-in2out', features)
7448 features = self.vapi.cli("show interface features pg1")
7449 self.assertIn('nat64-out2in', features)
7451 self.vapi.nat64_add_del_interface(0, flags, self.pg0.sw_if_index)
7452 self.vapi.nat64_add_del_interface(0, flags, self.pg1.sw_if_index)
7454 interfaces = self.vapi.nat64_interface_dump()
7455 self.assertEqual(len(interfaces), 0)
7457 def test_static_bib(self):
7458 """ Add/delete static BIB entry """
7459 in_addr = '2001:db8:85a3::8a2e:370:7334'
7460 out_addr = '10.1.1.3'
7463 proto = IP_PROTOS.tcp
7465 self.vapi.nat64_add_del_static_bib(in_addr,
7470 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
7473 if bibe.flags & self.config_flags.NAT_IS_STATIC:
7475 self.assertEqual(str(bibe.i_addr), in_addr)
7476 self.assertEqual(str(bibe.o_addr), out_addr)
7477 self.assertEqual(bibe.i_port, in_port)
7478 self.assertEqual(bibe.o_port, out_port)
7479 self.assertEqual(static_bib_num, 1)
7480 bibs = self.statistics.get_counter('/nat64/total-bibs')
7481 self.assertEqual(bibs[0][0], 1)
7483 self.vapi.nat64_add_del_static_bib(in_addr,
7489 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
7492 if bibe.flags & self.config_flags.NAT_IS_STATIC:
7494 self.assertEqual(static_bib_num, 0)
7495 bibs = self.statistics.get_counter('/nat64/total-bibs')
7496 self.assertEqual(bibs[0][0], 0)
7498 def test_set_timeouts(self):
7499 """ Set NAT64 timeouts """
7500 # verify default values
7501 timeouts = self.vapi.nat_get_timeouts()
7502 self.assertEqual(timeouts.udp, 300)
7503 self.assertEqual(timeouts.icmp, 60)
7504 self.assertEqual(timeouts.tcp_transitory, 240)
7505 self.assertEqual(timeouts.tcp_established, 7440)
7507 # set and verify custom values
7508 self.vapi.nat_set_timeouts(udp=200, icmp=30, tcp_transitory=250,
7509 tcp_established=7450)
7510 timeouts = self.vapi.nat_get_timeouts()
7511 self.assertEqual(timeouts.udp, 200)
7512 self.assertEqual(timeouts.icmp, 30)
7513 self.assertEqual(timeouts.tcp_transitory, 250)
7514 self.assertEqual(timeouts.tcp_established, 7450)
7516 def test_dynamic(self):
7517 """ NAT64 dynamic translation test """
7518 self.tcp_port_in = 6303
7519 self.udp_port_in = 6304
7520 self.icmp_id_in = 6305
7522 ses_num_start = self.nat64_get_ses_num()
7524 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
7526 flags = self.config_flags.NAT_IS_INSIDE
7527 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
7528 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
7531 tcpn = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7532 udpn = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7533 icmpn = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7534 totaln = self.statistics.get_counter(
7535 '/err/nat64-in2out/good in2out packets processed')
7537 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7538 self.pg0.add_stream(pkts)
7539 self.pg_enable_capture(self.pg_interfaces)
7541 capture = self.pg1.get_capture(len(pkts))
7542 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7543 dst_ip=self.pg1.remote_ip4)
7545 err = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7546 self.assertEqual(err - tcpn, 1)
7547 err = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7548 self.assertEqual(err - udpn, 1)
7549 err = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7550 self.assertEqual(err - icmpn, 1)
7551 err = self.statistics.get_counter(
7552 '/err/nat64-in2out/good in2out packets processed')
7553 self.assertEqual(err - totaln, 3)
7556 tcpn = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7557 udpn = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7558 icmpn = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7559 totaln = self.statistics.get_counter(
7560 '/err/nat64-out2in/good out2in packets processed')
7562 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7563 self.pg1.add_stream(pkts)
7564 self.pg_enable_capture(self.pg_interfaces)
7566 capture = self.pg0.get_capture(len(pkts))
7567 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7568 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7570 err = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7571 self.assertEqual(err - tcpn, 1)
7572 err = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7573 self.assertEqual(err - udpn, 1)
7574 err = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7575 self.assertEqual(err - icmpn, 1)
7576 err = self.statistics.get_counter(
7577 '/err/nat64-out2in/good out2in packets processed')
7578 self.assertEqual(err - totaln, 3)
7580 bibs = self.statistics.get_counter('/nat64/total-bibs')
7581 self.assertEqual(bibs[0][0], 3)
7582 sessions = self.statistics.get_counter('/nat64/total-sessions')
7583 self.assertEqual(sessions[0][0], 3)
7586 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7587 self.pg0.add_stream(pkts)
7588 self.pg_enable_capture(self.pg_interfaces)
7590 capture = self.pg1.get_capture(len(pkts))
7591 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7592 dst_ip=self.pg1.remote_ip4)
7595 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7596 self.pg1.add_stream(pkts)
7597 self.pg_enable_capture(self.pg_interfaces)
7599 capture = self.pg0.get_capture(len(pkts))
7600 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7602 ses_num_end = self.nat64_get_ses_num()
7604 self.assertEqual(ses_num_end - ses_num_start, 3)
7606 # tenant with specific VRF
7607 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr,
7609 vrf_id=self.vrf1_id)
7610 flags = self.config_flags.NAT_IS_INSIDE
7611 self.vapi.nat64_add_del_interface(1, flags, self.pg2.sw_if_index)
7613 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
7614 self.pg2.add_stream(pkts)
7615 self.pg_enable_capture(self.pg_interfaces)
7617 capture = self.pg1.get_capture(len(pkts))
7618 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7619 dst_ip=self.pg1.remote_ip4)
7621 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7622 self.pg1.add_stream(pkts)
7623 self.pg_enable_capture(self.pg_interfaces)
7625 capture = self.pg2.get_capture(len(pkts))
7626 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
7628 def test_static(self):
7629 """ NAT64 static translation test """
7630 self.tcp_port_in = 60303
7631 self.udp_port_in = 60304
7632 self.icmp_id_in = 60305
7633 self.tcp_port_out = 60303
7634 self.udp_port_out = 60304
7635 self.icmp_id_out = 60305
7637 ses_num_start = self.nat64_get_ses_num()
7639 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
7641 flags = self.config_flags.NAT_IS_INSIDE
7642 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
7643 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
7645 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7650 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7655 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7662 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7663 self.pg0.add_stream(pkts)
7664 self.pg_enable_capture(self.pg_interfaces)
7666 capture = self.pg1.get_capture(len(pkts))
7667 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7668 dst_ip=self.pg1.remote_ip4, same_port=True)
7671 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7672 self.pg1.add_stream(pkts)
7673 self.pg_enable_capture(self.pg_interfaces)
7675 capture = self.pg0.get_capture(len(pkts))
7676 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7677 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7679 ses_num_end = self.nat64_get_ses_num()
7681 self.assertEqual(ses_num_end - ses_num_start, 3)
7683 @unittest.skipUnless(running_extended_tests, "part of extended tests")
7684 def test_session_timeout(self):
7685 """ NAT64 session timeout """
7686 self.icmp_id_in = 1234
7687 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
7689 flags = self.config_flags.NAT_IS_INSIDE
7690 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
7691 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
7692 self.vapi.nat_set_timeouts(icmp=5, tcp_transitory=5, tcp_established=5)
7694 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7695 self.pg0.add_stream(pkts)
7696 self.pg_enable_capture(self.pg_interfaces)
7698 capture = self.pg1.get_capture(len(pkts))
7700 ses_num_before_timeout = self.nat64_get_ses_num()
7704 # ICMP and TCP session after timeout
7705 ses_num_after_timeout = self.nat64_get_ses_num()
7706 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
7708 def test_icmp_error(self):
7709 """ NAT64 ICMP Error message translation """
7710 self.tcp_port_in = 6303
7711 self.udp_port_in = 6304
7712 self.icmp_id_in = 6305
7714 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
7716 flags = self.config_flags.NAT_IS_INSIDE
7717 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
7718 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
7720 # send some packets to create sessions
7721 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7722 self.pg0.add_stream(pkts)
7723 self.pg_enable_capture(self.pg_interfaces)
7725 capture_ip4 = self.pg1.get_capture(len(pkts))
7726 self.verify_capture_out(capture_ip4,
7727 nat_ip=self.nat_addr,
7728 dst_ip=self.pg1.remote_ip4)
7730 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7731 self.pg1.add_stream(pkts)
7732 self.pg_enable_capture(self.pg_interfaces)
7734 capture_ip6 = self.pg0.get_capture(len(pkts))
7735 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7736 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
7737 self.pg0.remote_ip6)
7740 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7741 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
7742 ICMPv6DestUnreach(code=1) /
7743 packet[IPv6] for packet in capture_ip6]
7744 self.pg0.add_stream(pkts)
7745 self.pg_enable_capture(self.pg_interfaces)
7747 capture = self.pg1.get_capture(len(pkts))
7748 for packet in capture:
7750 self.assertEqual(packet[IP].src, self.nat_addr)
7751 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
7752 self.assertEqual(packet[ICMP].type, 3)
7753 self.assertEqual(packet[ICMP].code, 13)
7754 inner = packet[IPerror]
7755 self.assertEqual(inner.src, self.pg1.remote_ip4)
7756 self.assertEqual(inner.dst, self.nat_addr)
7757 self.assert_packet_checksums_valid(packet)
7758 if inner.haslayer(TCPerror):
7759 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
7760 elif inner.haslayer(UDPerror):
7761 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
7763 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
7765 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7769 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7770 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7771 ICMP(type=3, code=13) /
7772 packet[IP] for packet in capture_ip4]
7773 self.pg1.add_stream(pkts)
7774 self.pg_enable_capture(self.pg_interfaces)
7776 capture = self.pg0.get_capture(len(pkts))
7777 for packet in capture:
7779 self.assertEqual(packet[IPv6].src, ip.src)
7780 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7781 icmp = packet[ICMPv6DestUnreach]
7782 self.assertEqual(icmp.code, 1)
7783 inner = icmp[IPerror6]
7784 self.assertEqual(inner.src, self.pg0.remote_ip6)
7785 self.assertEqual(inner.dst, ip.src)
7786 self.assert_icmpv6_checksum_valid(packet)
7787 if inner.haslayer(TCPerror):
7788 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
7789 elif inner.haslayer(UDPerror):
7790 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
7792 self.assertEqual(inner[ICMPv6EchoRequest].id,
7795 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7798 def test_hairpinning(self):
7799 """ NAT64 hairpinning """
7801 client = self.pg0.remote_hosts[0]
7802 server = self.pg0.remote_hosts[1]
7803 server_tcp_in_port = 22
7804 server_tcp_out_port = 4022
7805 server_udp_in_port = 23
7806 server_udp_out_port = 4023
7807 client_tcp_in_port = 1234
7808 client_udp_in_port = 1235
7809 client_tcp_out_port = 0
7810 client_udp_out_port = 0
7811 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
7812 nat_addr_ip6 = ip.src
7814 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
7816 flags = self.config_flags.NAT_IS_INSIDE
7817 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
7818 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
7820 self.vapi.nat64_add_del_static_bib(server.ip6n,
7823 server_tcp_out_port,
7825 self.vapi.nat64_add_del_static_bib(server.ip6n,
7828 server_udp_out_port,
7833 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7834 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7835 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7837 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7838 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7839 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
7841 self.pg0.add_stream(pkts)
7842 self.pg_enable_capture(self.pg_interfaces)
7844 capture = self.pg0.get_capture(len(pkts))
7845 for packet in capture:
7847 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7848 self.assertEqual(packet[IPv6].dst, server.ip6)
7849 self.assert_packet_checksums_valid(packet)
7850 if packet.haslayer(TCP):
7851 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
7852 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
7853 client_tcp_out_port = packet[TCP].sport
7855 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
7856 self.assertEqual(packet[UDP].dport, server_udp_in_port)
7857 client_udp_out_port = packet[UDP].sport
7859 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7864 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7865 IPv6(src=server.ip6, dst=nat_addr_ip6) /
7866 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
7868 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7869 IPv6(src=server.ip6, dst=nat_addr_ip6) /
7870 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
7872 self.pg0.add_stream(pkts)
7873 self.pg_enable_capture(self.pg_interfaces)
7875 capture = self.pg0.get_capture(len(pkts))
7876 for packet in capture:
7878 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7879 self.assertEqual(packet[IPv6].dst, client.ip6)
7880 self.assert_packet_checksums_valid(packet)
7881 if packet.haslayer(TCP):
7882 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
7883 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
7885 self.assertEqual(packet[UDP].sport, server_udp_out_port)
7886 self.assertEqual(packet[UDP].dport, client_udp_in_port)
7888 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7893 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7894 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7895 ICMPv6DestUnreach(code=1) /
7896 packet[IPv6] for packet in capture]
7897 self.pg0.add_stream(pkts)
7898 self.pg_enable_capture(self.pg_interfaces)
7900 capture = self.pg0.get_capture(len(pkts))
7901 for packet in capture:
7903 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7904 self.assertEqual(packet[IPv6].dst, server.ip6)
7905 icmp = packet[ICMPv6DestUnreach]
7906 self.assertEqual(icmp.code, 1)
7907 inner = icmp[IPerror6]
7908 self.assertEqual(inner.src, server.ip6)
7909 self.assertEqual(inner.dst, nat_addr_ip6)
7910 self.assert_packet_checksums_valid(packet)
7911 if inner.haslayer(TCPerror):
7912 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
7913 self.assertEqual(inner[TCPerror].dport,
7914 client_tcp_out_port)
7916 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
7917 self.assertEqual(inner[UDPerror].dport,
7918 client_udp_out_port)
7920 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7923 def test_prefix(self):
7924 """ NAT64 Network-Specific Prefix """
7926 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
7928 flags = self.config_flags.NAT_IS_INSIDE
7929 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
7930 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
7931 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr,
7933 vrf_id=self.vrf1_id)
7934 self.vapi.nat64_add_del_interface(1, flags, self.pg2.sw_if_index)
7937 global_pref64 = "2001:db8::"
7938 global_pref64_len = 32
7939 global_pref64_str = "{}/{}".format(global_pref64, global_pref64_len)
7940 self.vapi.nat64_add_del_prefix(global_pref64_str)
7942 prefix = self.vapi.nat64_prefix_dump()
7943 self.assertEqual(len(prefix), 1)
7944 self.assertEqual(prefix[0].prefix,
7945 IPv6Network(unicode(global_pref64_str)))
7946 self.assertEqual(prefix[0].vrf_id, 0)
7948 # Add tenant specific prefix
7949 vrf1_pref64 = "2001:db8:122:300::"
7950 vrf1_pref64_len = 56
7951 vrf1_pref64_str = "{}/{}".format(vrf1_pref64, vrf1_pref64_len)
7952 self.vapi.nat64_add_del_prefix(vrf1_pref64_str, vrf_id=self.vrf1_id)
7954 prefix = self.vapi.nat64_prefix_dump()
7955 self.assertEqual(len(prefix), 2)
7958 pkts = self.create_stream_in_ip6(self.pg0,
7961 plen=global_pref64_len)
7962 self.pg0.add_stream(pkts)
7963 self.pg_enable_capture(self.pg_interfaces)
7965 capture = self.pg1.get_capture(len(pkts))
7966 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7967 dst_ip=self.pg1.remote_ip4)
7969 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7970 self.pg1.add_stream(pkts)
7971 self.pg_enable_capture(self.pg_interfaces)
7973 capture = self.pg0.get_capture(len(pkts))
7974 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7977 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
7979 # Tenant specific prefix
7980 pkts = self.create_stream_in_ip6(self.pg2,
7983 plen=vrf1_pref64_len)
7984 self.pg2.add_stream(pkts)
7985 self.pg_enable_capture(self.pg_interfaces)
7987 capture = self.pg1.get_capture(len(pkts))
7988 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7989 dst_ip=self.pg1.remote_ip4)
7991 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7992 self.pg1.add_stream(pkts)
7993 self.pg_enable_capture(self.pg_interfaces)
7995 capture = self.pg2.get_capture(len(pkts))
7996 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7999 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
8001 def test_unknown_proto(self):
8002 """ NAT64 translate packet with unknown protocol """
8004 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8006 flags = self.config_flags.NAT_IS_INSIDE
8007 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
8008 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
8009 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8012 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8013 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
8014 TCP(sport=self.tcp_port_in, dport=20))
8015 self.pg0.add_stream(p)
8016 self.pg_enable_capture(self.pg_interfaces)
8018 p = self.pg1.get_capture(1)
8020 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8021 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
8023 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8024 TCP(sport=1234, dport=1234))
8025 self.pg0.add_stream(p)
8026 self.pg_enable_capture(self.pg_interfaces)
8028 p = self.pg1.get_capture(1)
8031 self.assertEqual(packet[IP].src, self.nat_addr)
8032 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
8033 self.assertEqual(packet.haslayer(GRE), 1)
8034 self.assert_packet_checksums_valid(packet)
8036 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8040 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8041 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
8043 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8044 TCP(sport=1234, dport=1234))
8045 self.pg1.add_stream(p)
8046 self.pg_enable_capture(self.pg_interfaces)
8048 p = self.pg0.get_capture(1)
8051 self.assertEqual(packet[IPv6].src, remote_ip6)
8052 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8053 self.assertEqual(packet[IPv6].nh, 47)
8055 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8058 def test_hairpinning_unknown_proto(self):
8059 """ NAT64 translate packet with unknown protocol - hairpinning """
8061 client = self.pg0.remote_hosts[0]
8062 server = self.pg0.remote_hosts[1]
8063 server_tcp_in_port = 22
8064 server_tcp_out_port = 4022
8065 client_tcp_in_port = 1234
8066 client_tcp_out_port = 1235
8067 server_nat_ip = "10.0.0.100"
8068 client_nat_ip = "10.0.0.110"
8069 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
8070 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
8072 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip,
8074 flags = self.config_flags.NAT_IS_INSIDE
8075 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
8076 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
8078 self.vapi.nat64_add_del_static_bib(server.ip6n,
8081 server_tcp_out_port,
8084 self.vapi.nat64_add_del_static_bib(server.ip6n,
8090 self.vapi.nat64_add_del_static_bib(client.ip6n,
8093 client_tcp_out_port,
8097 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8098 IPv6(src=client.ip6, dst=server_nat_ip6) /
8099 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
8100 self.pg0.add_stream(p)
8101 self.pg_enable_capture(self.pg_interfaces)
8103 p = self.pg0.get_capture(1)
8105 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8106 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
8108 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
8109 TCP(sport=1234, dport=1234))
8110 self.pg0.add_stream(p)
8111 self.pg_enable_capture(self.pg_interfaces)
8113 p = self.pg0.get_capture(1)
8116 self.assertEqual(packet[IPv6].src, client_nat_ip6)
8117 self.assertEqual(packet[IPv6].dst, server.ip6)
8118 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
8120 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8124 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8125 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
8127 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
8128 TCP(sport=1234, dport=1234))
8129 self.pg0.add_stream(p)
8130 self.pg_enable_capture(self.pg_interfaces)
8132 p = self.pg0.get_capture(1)
8135 self.assertEqual(packet[IPv6].src, server_nat_ip6)
8136 self.assertEqual(packet[IPv6].dst, client.ip6)
8137 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
8139 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8142 def test_one_armed_nat64(self):
8143 """ One armed NAT64 """
8145 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
8149 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8151 flags = self.config_flags.NAT_IS_INSIDE
8152 self.vapi.nat64_add_del_interface(1, flags, self.pg3.sw_if_index)
8153 self.vapi.nat64_add_del_interface(1, 0, self.pg3.sw_if_index)
8156 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8157 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
8158 TCP(sport=12345, dport=80))
8159 self.pg3.add_stream(p)
8160 self.pg_enable_capture(self.pg_interfaces)
8162 capture = self.pg3.get_capture(1)
8167 self.assertEqual(ip.src, self.nat_addr)
8168 self.assertEqual(ip.dst, self.pg3.remote_ip4)
8169 self.assertNotEqual(tcp.sport, 12345)
8170 external_port = tcp.sport
8171 self.assertEqual(tcp.dport, 80)
8172 self.assert_packet_checksums_valid(p)
8174 self.logger.error(ppp("Unexpected or invalid packet:", p))
8178 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
8179 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
8180 TCP(sport=80, dport=external_port))
8181 self.pg3.add_stream(p)
8182 self.pg_enable_capture(self.pg_interfaces)
8184 capture = self.pg3.get_capture(1)
8189 self.assertEqual(ip.src, remote_host_ip6)
8190 self.assertEqual(ip.dst, self.pg3.remote_ip6)
8191 self.assertEqual(tcp.sport, 80)
8192 self.assertEqual(tcp.dport, 12345)
8193 self.assert_packet_checksums_valid(p)
8195 self.logger.error(ppp("Unexpected or invalid packet:", p))
8198 def test_frag_in_order(self):
8199 """ NAT64 translate fragments arriving in order """
8200 self.tcp_port_in = random.randint(1025, 65535)
8202 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8204 flags = self.config_flags.NAT_IS_INSIDE
8205 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
8206 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
8208 reass = self.vapi.nat_reass_dump()
8209 reass_n_start = len(reass)
8213 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8214 self.tcp_port_in, 20, data)
8215 self.pg0.add_stream(pkts)
8216 self.pg_enable_capture(self.pg_interfaces)
8218 frags = self.pg1.get_capture(len(pkts))
8219 p = self.reass_frags_and_verify(frags,
8221 self.pg1.remote_ip4)
8222 self.assertEqual(p[TCP].dport, 20)
8223 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8224 self.tcp_port_out = p[TCP].sport
8225 self.assertEqual(data, p[Raw].load)
8228 data = b"A" * 4 + b"b" * 16 + b"C" * 3
8229 pkts = self.create_stream_frag(self.pg1,
8234 self.pg1.add_stream(pkts)
8235 self.pg_enable_capture(self.pg_interfaces)
8237 frags = self.pg0.get_capture(len(pkts))
8238 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8239 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8240 self.assertEqual(p[TCP].sport, 20)
8241 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8242 self.assertEqual(data, p[Raw].load)
8244 reass = self.vapi.nat_reass_dump()
8245 reass_n_end = len(reass)
8247 self.assertEqual(reass_n_end - reass_n_start, 2)
8249 def test_reass_hairpinning(self):
8250 """ NAT64 fragments hairpinning """
8252 server = self.pg0.remote_hosts[1]
8253 server_in_port = random.randint(1025, 65535)
8254 server_out_port = random.randint(1025, 65535)
8255 client_in_port = random.randint(1025, 65535)
8256 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
8257 nat_addr_ip6 = ip.src
8259 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8261 flags = self.config_flags.NAT_IS_INSIDE
8262 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
8263 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
8265 # add static BIB entry for server
8266 self.vapi.nat64_add_del_static_bib(server.ip6n,
8272 # send packet from host to server
8273 pkts = self.create_stream_frag_ip6(self.pg0,
8278 self.pg0.add_stream(pkts)
8279 self.pg_enable_capture(self.pg_interfaces)
8281 frags = self.pg0.get_capture(len(pkts))
8282 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
8283 self.assertNotEqual(p[TCP].sport, client_in_port)
8284 self.assertEqual(p[TCP].dport, server_in_port)
8285 self.assertEqual(data, p[Raw].load)
8287 def test_frag_out_of_order(self):
8288 """ NAT64 translate fragments arriving out of order """
8289 self.tcp_port_in = random.randint(1025, 65535)
8291 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8293 flags = self.config_flags.NAT_IS_INSIDE
8294 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
8295 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
8299 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8300 self.tcp_port_in, 20, data)
8302 self.pg0.add_stream(pkts)
8303 self.pg_enable_capture(self.pg_interfaces)
8305 frags = self.pg1.get_capture(len(pkts))
8306 p = self.reass_frags_and_verify(frags,
8308 self.pg1.remote_ip4)
8309 self.assertEqual(p[TCP].dport, 20)
8310 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
8311 self.tcp_port_out = p[TCP].sport
8312 self.assertEqual(data, p[Raw].load)
8315 data = b"A" * 4 + b"B" * 16 + b"C" * 3
8316 pkts = self.create_stream_frag(self.pg1,
8322 self.pg1.add_stream(pkts)
8323 self.pg_enable_capture(self.pg_interfaces)
8325 frags = self.pg0.get_capture(len(pkts))
8326 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
8327 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
8328 self.assertEqual(p[TCP].sport, 20)
8329 self.assertEqual(p[TCP].dport, self.tcp_port_in)
8330 self.assertEqual(data, p[Raw].load)
8332 def test_interface_addr(self):
8333 """ Acquire NAT64 pool addresses from interface """
8334 self.vapi.nat64_add_del_interface_addr(self.pg4.sw_if_index)
8336 # no address in NAT64 pool
8337 addresses = self.vapi.nat44_address_dump()
8338 self.assertEqual(0, len(addresses))
8340 # configure interface address and check NAT64 address pool
8341 self.pg4.config_ip4()
8342 addresses = self.vapi.nat64_pool_addr_dump()
8343 self.assertEqual(len(addresses), 1)
8345 self.assertEqual(str(addresses[0].address),
8348 # remove interface address and check NAT64 address pool
8349 self.pg4.unconfig_ip4()
8350 addresses = self.vapi.nat64_pool_addr_dump()
8351 self.assertEqual(0, len(addresses))
8353 @unittest.skipUnless(running_extended_tests, "part of extended tests")
8354 def test_ipfix_max_bibs_sessions(self):
8355 """ IPFIX logging maximum session and BIB entries exceeded """
8358 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8362 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8364 flags = self.config_flags.NAT_IS_INSIDE
8365 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
8366 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
8370 for i in range(0, max_bibs):
8371 src = "fd01:aa::%x" % (i)
8372 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8373 IPv6(src=src, dst=remote_host_ip6) /
8374 TCP(sport=12345, dport=80))
8376 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8377 IPv6(src=src, dst=remote_host_ip6) /
8378 TCP(sport=12345, dport=22))
8380 self.pg0.add_stream(pkts)
8381 self.pg_enable_capture(self.pg_interfaces)
8383 self.pg1.get_capture(max_sessions)
8385 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8386 src_address=self.pg3.local_ip4n,
8388 template_interval=10)
8389 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8390 src_port=self.ipfix_src_port)
8392 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8393 IPv6(src=src, dst=remote_host_ip6) /
8394 TCP(sport=12345, dport=25))
8395 self.pg0.add_stream(p)
8396 self.pg_enable_capture(self.pg_interfaces)
8398 self.pg1.assert_nothing_captured()
8400 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8401 capture = self.pg3.get_capture(9)
8402 ipfix = IPFIXDecoder()
8403 # first load template
8405 self.assertTrue(p.haslayer(IPFIX))
8406 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8407 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8408 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8409 self.assertEqual(p[UDP].dport, 4739)
8410 self.assertEqual(p[IPFIX].observationDomainID,
8411 self.ipfix_domain_id)
8412 if p.haslayer(Template):
8413 ipfix.add_template(p.getlayer(Template))
8414 # verify events in data set
8416 if p.haslayer(Data):
8417 data = ipfix.decode_data_set(p.getlayer(Set))
8418 self.verify_ipfix_max_sessions(data, max_sessions)
8420 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8421 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8422 TCP(sport=12345, dport=80))
8423 self.pg0.add_stream(p)
8424 self.pg_enable_capture(self.pg_interfaces)
8426 self.pg1.assert_nothing_captured()
8428 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8429 capture = self.pg3.get_capture(1)
8430 # verify events in data set
8432 self.assertTrue(p.haslayer(IPFIX))
8433 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8434 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8435 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8436 self.assertEqual(p[UDP].dport, 4739)
8437 self.assertEqual(p[IPFIX].observationDomainID,
8438 self.ipfix_domain_id)
8439 if p.haslayer(Data):
8440 data = ipfix.decode_data_set(p.getlayer(Set))
8441 self.verify_ipfix_max_bibs(data, max_bibs)
8443 def test_ipfix_max_frags(self):
8444 """ IPFIX logging maximum fragments pending reassembly exceeded """
8445 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8447 flags = self.config_flags.NAT_IS_INSIDE
8448 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
8449 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
8450 self.vapi.nat_set_reass(max_frag=1, is_ip6=1)
8451 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8452 src_address=self.pg3.local_ip4n,
8454 template_interval=10)
8455 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8456 src_port=self.ipfix_src_port)
8459 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
8460 self.tcp_port_in, 20, data)
8462 self.pg0.add_stream(pkts)
8463 self.pg_enable_capture(self.pg_interfaces)
8465 self.pg1.assert_nothing_captured()
8467 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8468 capture = self.pg3.get_capture(9)
8469 ipfix = IPFIXDecoder()
8470 # first load template
8472 self.assertTrue(p.haslayer(IPFIX))
8473 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8474 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8475 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8476 self.assertEqual(p[UDP].dport, 4739)
8477 self.assertEqual(p[IPFIX].observationDomainID,
8478 self.ipfix_domain_id)
8479 if p.haslayer(Template):
8480 ipfix.add_template(p.getlayer(Template))
8481 # verify events in data set
8483 if p.haslayer(Data):
8484 data = ipfix.decode_data_set(p.getlayer(Set))
8485 self.verify_ipfix_max_fragments_ip6(data, 1,
8486 self.pg0.remote_ip6n)
8488 def test_ipfix_bib_ses(self):
8489 """ IPFIX logging NAT64 BIB/session create and delete events """
8490 self.tcp_port_in = random.randint(1025, 65535)
8491 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8495 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8497 flags = self.config_flags.NAT_IS_INSIDE
8498 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
8499 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
8500 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
8501 src_address=self.pg3.local_ip4n,
8503 template_interval=10)
8504 self.vapi.nat_ipfix_enable_disable(domain_id=self.ipfix_domain_id,
8505 src_port=self.ipfix_src_port)
8508 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8509 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8510 TCP(sport=self.tcp_port_in, dport=25))
8511 self.pg0.add_stream(p)
8512 self.pg_enable_capture(self.pg_interfaces)
8514 p = self.pg1.get_capture(1)
8515 self.tcp_port_out = p[0][TCP].sport
8516 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8517 capture = self.pg3.get_capture(10)
8518 ipfix = IPFIXDecoder()
8519 # first load template
8521 self.assertTrue(p.haslayer(IPFIX))
8522 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8523 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8524 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8525 self.assertEqual(p[UDP].dport, 4739)
8526 self.assertEqual(p[IPFIX].observationDomainID,
8527 self.ipfix_domain_id)
8528 if p.haslayer(Template):
8529 ipfix.add_template(p.getlayer(Template))
8530 # verify events in data set
8532 if p.haslayer(Data):
8533 data = ipfix.decode_data_set(p.getlayer(Set))
8534 if scapy.compat.orb(data[0][230]) == 10:
8535 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
8536 elif scapy.compat.orb(data[0][230]) == 6:
8537 self.verify_ipfix_nat64_ses(data,
8539 self.pg0.remote_ip6n,
8540 self.pg1.remote_ip4,
8543 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8546 self.pg_enable_capture(self.pg_interfaces)
8547 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8550 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8551 capture = self.pg3.get_capture(2)
8552 # verify events in data set
8554 self.assertTrue(p.haslayer(IPFIX))
8555 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8556 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8557 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8558 self.assertEqual(p[UDP].dport, 4739)
8559 self.assertEqual(p[IPFIX].observationDomainID,
8560 self.ipfix_domain_id)
8561 if p.haslayer(Data):
8562 data = ipfix.decode_data_set(p.getlayer(Set))
8563 if scapy.compat.orb(data[0][230]) == 11:
8564 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
8565 elif scapy.compat.orb(data[0][230]) == 7:
8566 self.verify_ipfix_nat64_ses(data,
8568 self.pg0.remote_ip6n,
8569 self.pg1.remote_ip4,
8572 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8574 def test_syslog_sess(self):
8575 """ Test syslog session creation and deletion """
8576 self.tcp_port_in = random.randint(1025, 65535)
8577 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8581 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8583 flags = self.config_flags.NAT_IS_INSIDE
8584 self.vapi.nat64_add_del_interface(1, flags, self.pg0.sw_if_index)
8585 self.vapi.nat64_add_del_interface(1, 0, self.pg1.sw_if_index)
8586 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
8587 self.vapi.syslog_set_sender(self.pg3.local_ip4n, self.pg3.remote_ip4n)
8589 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8590 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8591 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
8592 self.pg0.add_stream(p)
8593 self.pg_enable_capture(self.pg_interfaces)
8595 p = self.pg1.get_capture(1)
8596 self.tcp_port_out = p[0][TCP].sport
8597 capture = self.pg3.get_capture(1)
8598 self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
8600 self.pg_enable_capture(self.pg_interfaces)
8602 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr,
8605 capture = self.pg3.get_capture(1)
8606 self.verify_syslog_sess(capture[0][Raw].load, False, True)
8608 def nat64_get_ses_num(self):
8610 Return number of active NAT64 sessions.
8612 st = self.vapi.nat64_st_dump()
8615 def clear_nat64(self):
8617 Clear NAT64 configuration.
8619 self.vapi.nat_ipfix_enable_disable(enable=0,
8620 src_port=self.ipfix_src_port,
8621 domain_id=self.ipfix_domain_id)
8622 self.ipfix_src_port = 4739
8623 self.ipfix_domain_id = 1
8625 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
8627 self.vapi.nat_set_timeouts()
8629 interfaces = self.vapi.nat64_interface_dump()
8630 for intf in interfaces:
8631 self.vapi.nat64_add_del_interface(0,
8635 bib = self.vapi.nat64_bib_dump(255)
8637 if bibe.flags & self.config_flags.NAT_IS_STATIC:
8638 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
8646 adresses = self.vapi.nat64_pool_addr_dump()
8647 for addr in adresses:
8648 self.vapi.nat64_add_del_pool_addr_range(addr.address,
8653 prefixes = self.vapi.nat64_prefix_dump()
8654 for prefix in prefixes:
8655 self.vapi.nat64_add_del_prefix(str(prefix.prefix),
8656 vrf_id=prefix.vrf_id,
8659 bibs = self.statistics.get_counter('/nat64/total-bibs')
8660 self.assertEqual(bibs[0][0], 0)
8661 sessions = self.statistics.get_counter('/nat64/total-sessions')
8662 self.assertEqual(sessions[0][0], 0)
8665 super(TestNAT64, self).tearDown()
8666 if not self.vpp_dead:
8669 def show_commands_at_teardown(self):
8670 self.logger.info(self.vapi.cli("show nat64 pool"))
8671 self.logger.info(self.vapi.cli("show nat64 interfaces"))
8672 self.logger.info(self.vapi.cli("show nat64 prefix"))
8673 self.logger.info(self.vapi.cli("show nat64 bib all"))
8674 self.logger.info(self.vapi.cli("show nat64 session table all"))
8675 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
8678 class TestDSlite(MethodHolder):
8679 """ DS-Lite Test Cases """
8682 def setUpClass(cls):
8683 super(TestDSlite, cls).setUpClass()
8686 cls.nat_addr = '10.0.0.3'
8688 cls.create_pg_interfaces(range(3))
8690 cls.pg0.config_ip4()
8691 cls.pg0.resolve_arp()
8693 cls.pg1.config_ip6()
8694 cls.pg1.generate_remote_hosts(2)
8695 cls.pg1.configure_ipv6_neighbors()
8697 cls.pg2.config_ip4()
8698 cls.pg2.resolve_arp()
8701 super(TestDSlite, cls).tearDownClass()
8705 def tearDownClass(cls):
8706 super(TestDSlite, cls).tearDownClass()
8708 def verify_syslog_apmadd(self, data, isaddr, isport, xsaddr, xsport,
8710 message = data.decode('utf-8')
8712 message = SyslogMessage.parse(message)
8713 except ParseError as e:
8714 self.logger.error(e)
8716 self.assertEqual(message.severity, SyslogSeverity.info)
8717 self.assertEqual(message.appname, 'NAT')
8718 self.assertEqual(message.msgid, 'APMADD')
8719 sd_params = message.sd.get('napmap')
8720 self.assertTrue(sd_params is not None)
8721 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
8722 self.assertEqual(sd_params.get('ISADDR'), isaddr)
8723 self.assertEqual(sd_params.get('ISPORT'), "%d" % isport)
8724 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
8725 self.assertEqual(sd_params.get('XSADDR'), xsaddr)
8726 self.assertEqual(sd_params.get('XSPORT'), "%d" % xsport)
8727 self.assertEqual(sd_params.get('PROTO'), "%d" % proto)
8728 self.assertTrue(sd_params.get('SSUBIX') is not None)
8729 self.assertEqual(sd_params.get('SV6ENC'), sv6enc)
8731 def test_dslite(self):
8732 """ Test DS-Lite """
8733 nat_config = self.vapi.nat_show_config()
8734 self.assertEqual(0, nat_config.dslite_ce)
8736 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr,
8738 aftr_ip4 = '192.0.0.1'
8739 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
8740 self.vapi.dslite_set_aftr_addr(aftr_ip6, aftr_ip4)
8741 self.vapi.syslog_set_sender(self.pg2.local_ip4n, self.pg2.remote_ip4n)
8744 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8745 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
8746 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8747 UDP(sport=20000, dport=10000))
8748 self.pg1.add_stream(p)
8749 self.pg_enable_capture(self.pg_interfaces)
8751 capture = self.pg0.get_capture(1)
8752 capture = capture[0]
8753 self.assertFalse(capture.haslayer(IPv6))
8754 self.assertEqual(capture[IP].src, self.nat_addr)
8755 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8756 self.assertNotEqual(capture[UDP].sport, 20000)
8757 self.assertEqual(capture[UDP].dport, 10000)
8758 self.assert_packet_checksums_valid(capture)
8759 out_port = capture[UDP].sport
8760 capture = self.pg2.get_capture(1)
8761 self.verify_syslog_apmadd(capture[0][Raw].load, '192.168.1.1',
8762 20000, self.nat_addr, out_port,
8763 self.pg1.remote_hosts[0].ip6, IP_PROTOS.udp)
8765 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8766 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8767 UDP(sport=10000, dport=out_port))
8768 self.pg0.add_stream(p)
8769 self.pg_enable_capture(self.pg_interfaces)
8771 capture = self.pg1.get_capture(1)
8772 capture = capture[0]
8773 self.assertEqual(capture[IPv6].src, aftr_ip6)
8774 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8775 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8776 self.assertEqual(capture[IP].dst, '192.168.1.1')
8777 self.assertEqual(capture[UDP].sport, 10000)
8778 self.assertEqual(capture[UDP].dport, 20000)
8779 self.assert_packet_checksums_valid(capture)
8782 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8783 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8784 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8785 TCP(sport=20001, dport=10001))
8786 self.pg1.add_stream(p)
8787 self.pg_enable_capture(self.pg_interfaces)
8789 capture = self.pg0.get_capture(1)
8790 capture = capture[0]
8791 self.assertFalse(capture.haslayer(IPv6))
8792 self.assertEqual(capture[IP].src, self.nat_addr)
8793 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8794 self.assertNotEqual(capture[TCP].sport, 20001)
8795 self.assertEqual(capture[TCP].dport, 10001)
8796 self.assert_packet_checksums_valid(capture)
8797 out_port = capture[TCP].sport
8799 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8800 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8801 TCP(sport=10001, dport=out_port))
8802 self.pg0.add_stream(p)
8803 self.pg_enable_capture(self.pg_interfaces)
8805 capture = self.pg1.get_capture(1)
8806 capture = capture[0]
8807 self.assertEqual(capture[IPv6].src, aftr_ip6)
8808 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8809 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8810 self.assertEqual(capture[IP].dst, '192.168.1.1')
8811 self.assertEqual(capture[TCP].sport, 10001)
8812 self.assertEqual(capture[TCP].dport, 20001)
8813 self.assert_packet_checksums_valid(capture)
8816 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8817 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8818 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8819 ICMP(id=4000, type='echo-request'))
8820 self.pg1.add_stream(p)
8821 self.pg_enable_capture(self.pg_interfaces)
8823 capture = self.pg0.get_capture(1)
8824 capture = capture[0]
8825 self.assertFalse(capture.haslayer(IPv6))
8826 self.assertEqual(capture[IP].src, self.nat_addr)
8827 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8828 self.assertNotEqual(capture[ICMP].id, 4000)
8829 self.assert_packet_checksums_valid(capture)
8830 out_id = capture[ICMP].id
8832 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8833 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8834 ICMP(id=out_id, type='echo-reply'))
8835 self.pg0.add_stream(p)
8836 self.pg_enable_capture(self.pg_interfaces)
8838 capture = self.pg1.get_capture(1)
8839 capture = capture[0]
8840 self.assertEqual(capture[IPv6].src, aftr_ip6)
8841 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8842 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8843 self.assertEqual(capture[IP].dst, '192.168.1.1')
8844 self.assertEqual(capture[ICMP].id, 4000)
8845 self.assert_packet_checksums_valid(capture)
8847 # ping DS-Lite AFTR tunnel endpoint address
8848 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8849 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
8850 ICMPv6EchoRequest())
8851 self.pg1.add_stream(p)
8852 self.pg_enable_capture(self.pg_interfaces)
8854 capture = self.pg1.get_capture(1)
8855 capture = capture[0]
8856 self.assertEqual(capture[IPv6].src, aftr_ip6)
8857 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8858 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8860 b4s = self.statistics.get_counter('/dslite/total-b4s')
8861 self.assertEqual(b4s[0][0], 2)
8862 sessions = self.statistics.get_counter('/dslite/total-sessions')
8863 self.assertEqual(sessions[0][0], 3)
8866 super(TestDSlite, self).tearDown()
8868 def show_commands_at_teardown(self):
8869 self.logger.info(self.vapi.cli("show dslite pool"))
8871 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8872 self.logger.info(self.vapi.cli("show dslite sessions"))
8875 class TestDSliteCE(MethodHolder):
8876 """ DS-Lite CE Test Cases """
8879 def setUpConstants(cls):
8880 super(TestDSliteCE, cls).setUpConstants()
8881 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
8884 def setUpClass(cls):
8885 super(TestDSliteCE, cls).setUpClass()
8888 cls.create_pg_interfaces(range(2))
8890 cls.pg0.config_ip4()
8891 cls.pg0.resolve_arp()
8893 cls.pg1.config_ip6()
8894 cls.pg1.generate_remote_hosts(1)
8895 cls.pg1.configure_ipv6_neighbors()
8898 super(TestDSliteCE, cls).tearDownClass()
8902 def tearDownClass(cls):
8903 super(TestDSliteCE, cls).tearDownClass()
8905 def test_dslite_ce(self):
8906 """ Test DS-Lite CE """
8908 nat_config = self.vapi.nat_show_config()
8909 self.assertEqual(1, nat_config.dslite_ce)
8911 b4_ip4 = '192.0.0.2'
8912 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
8913 self.vapi.dslite_set_b4_addr(b4_ip6, b4_ip4)
8915 aftr_ip4 = '192.0.0.1'
8916 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
8917 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
8918 self.vapi.dslite_set_aftr_addr(aftr_ip6, aftr_ip4)
8920 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
8921 dst_address_length=128,
8922 next_hop_address=self.pg1.remote_ip6n,
8923 next_hop_sw_if_index=self.pg1.sw_if_index,
8927 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8928 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
8929 UDP(sport=10000, dport=20000))
8930 self.pg0.add_stream(p)
8931 self.pg_enable_capture(self.pg_interfaces)
8933 capture = self.pg1.get_capture(1)
8934 capture = capture[0]
8935 self.assertEqual(capture[IPv6].src, b4_ip6)
8936 self.assertEqual(capture[IPv6].dst, aftr_ip6)
8937 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8938 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
8939 self.assertEqual(capture[UDP].sport, 10000)
8940 self.assertEqual(capture[UDP].dport, 20000)
8941 self.assert_packet_checksums_valid(capture)
8944 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8945 IPv6(dst=b4_ip6, src=aftr_ip6) /
8946 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
8947 UDP(sport=20000, dport=10000))
8948 self.pg1.add_stream(p)
8949 self.pg_enable_capture(self.pg_interfaces)
8951 capture = self.pg0.get_capture(1)
8952 capture = capture[0]
8953 self.assertFalse(capture.haslayer(IPv6))
8954 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
8955 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8956 self.assertEqual(capture[UDP].sport, 20000)
8957 self.assertEqual(capture[UDP].dport, 10000)
8958 self.assert_packet_checksums_valid(capture)
8960 # ping DS-Lite B4 tunnel endpoint address
8961 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8962 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
8963 ICMPv6EchoRequest())
8964 self.pg1.add_stream(p)
8965 self.pg_enable_capture(self.pg_interfaces)
8967 capture = self.pg1.get_capture(1)
8968 capture = capture[0]
8969 self.assertEqual(capture[IPv6].src, b4_ip6)
8970 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8971 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8974 super(TestDSliteCE, self).tearDown()
8976 def show_commands_at_teardown(self):
8978 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8980 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
8983 class TestNAT66(MethodHolder):
8984 """ NAT66 Test Cases """
8987 def setUpClass(cls):
8988 super(TestNAT66, cls).setUpClass()
8991 cls.nat_addr = 'fd01:ff::2'
8993 cls.create_pg_interfaces(range(2))
8994 cls.interfaces = list(cls.pg_interfaces)
8996 for i in cls.interfaces:
8999 i.configure_ipv6_neighbors()
9002 super(TestNAT66, cls).tearDownClass()
9006 def tearDownClass(cls):
9007 super(TestNAT66, cls).tearDownClass()
9009 def test_static(self):
9010 """ 1:1 NAT66 test """
9011 flags = self.config_flags.NAT_IS_INSIDE
9012 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index, flags=flags)
9013 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
9014 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
9019 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9020 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9023 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9024 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9027 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9028 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9029 ICMPv6EchoRequest())
9031 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9032 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9033 GRE() / IP() / TCP())
9035 self.pg0.add_stream(pkts)
9036 self.pg_enable_capture(self.pg_interfaces)
9038 capture = self.pg1.get_capture(len(pkts))
9039 for packet in capture:
9041 self.assertEqual(packet[IPv6].src, self.nat_addr)
9042 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9043 self.assert_packet_checksums_valid(packet)
9045 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9050 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9051 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9054 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9055 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9058 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9059 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9062 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
9063 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
9064 GRE() / IP() / TCP())
9066 self.pg1.add_stream(pkts)
9067 self.pg_enable_capture(self.pg_interfaces)
9069 capture = self.pg0.get_capture(len(pkts))
9070 for packet in capture:
9072 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
9073 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
9074 self.assert_packet_checksums_valid(packet)
9076 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9079 sm = self.vapi.nat66_static_mapping_dump()
9080 self.assertEqual(len(sm), 1)
9081 self.assertEqual(sm[0].total_pkts, 8)
9083 def test_check_no_translate(self):
9084 """ NAT66 translate only when egress interface is outside interface """
9085 flags = self.config_flags.NAT_IS_INSIDE
9086 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index, flags=flags)
9087 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, flags=flags)
9088 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
9092 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
9093 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
9095 self.pg0.add_stream([p])
9096 self.pg_enable_capture(self.pg_interfaces)
9098 capture = self.pg1.get_capture(1)
9101 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
9102 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
9104 self.logger.error(ppp("Unexpected or invalid packet:", packet))
9107 def clear_nat66(self):
9109 Clear NAT66 configuration.
9111 interfaces = self.vapi.nat66_interface_dump()
9112 for intf in interfaces:
9113 self.vapi.nat66_add_del_interface(intf.sw_if_index,
9117 static_mappings = self.vapi.nat66_static_mapping_dump()
9118 for sm in static_mappings:
9119 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
9120 sm.external_ip_address,
9125 super(TestNAT66, self).tearDown()
9128 def show_commands_at_teardown(self):
9129 self.logger.info(self.vapi.cli("show nat66 interfaces"))
9130 self.logger.info(self.vapi.cli("show nat66 static mappings"))
9132 if __name__ == '__main__':
9133 unittest.main(testRunner=VppTestRunner)