8 from framework import VppTestCase, VppTestRunner, running_extended_tests
9 from scapy.layers.inet import IP, TCP, UDP, ICMP
10 from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror
11 from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply, \
12 ICMPv6ND_NS, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr, fragment6
13 from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment
14 from scapy.layers.l2 import Ether, ARP, GRE
15 from scapy.data import IP_PROTOS
16 from scapy.packet import bind_layers, Raw
18 from ipfix import IPFIX, Set, Template, Data, IPFIXDecoder
19 from time import sleep
20 from util import ip4_range
21 from vpp_papi import mac_pton
22 from syslog_rfc5424_parser import SyslogMessage, ParseError
23 from syslog_rfc5424_parser.constants import SyslogFacility, SyslogSeverity
24 from vpp_papi_provider import SYSLOG_SEVERITY
25 from io import BytesIO
26 from vpp_papi import VppEnum
29 class MethodHolder(VppTestCase):
30 """ NAT create capture and verify method holder """
32 def clear_nat44(self):
34 Clear NAT44 configuration.
36 if hasattr(self, 'pg7') and hasattr(self, 'pg8'):
37 # I found no elegant way to do this
38 self.vapi.ip_add_del_route(
39 dst_address=self.pg7.remote_ip4n,
40 dst_address_length=32,
41 next_hop_address=self.pg7.remote_ip4n,
42 next_hop_sw_if_index=self.pg7.sw_if_index,
44 self.vapi.ip_add_del_route(
45 dst_address=self.pg8.remote_ip4n,
46 dst_address_length=32,
47 next_hop_address=self.pg8.remote_ip4n,
48 next_hop_sw_if_index=self.pg8.sw_if_index,
51 for intf in [self.pg7, self.pg8]:
52 self.vapi.ip_neighbor_add_del(
56 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
57 IP_API_NEIGHBOR_FLAG_STATIC),
60 if self.pg7.has_ip4_config:
61 self.pg7.unconfig_ip4()
63 self.vapi.nat44_forwarding_enable_disable(0)
65 interfaces = self.vapi.nat44_interface_addr_dump()
66 for intf in interfaces:
67 self.vapi.nat44_add_interface_addr(intf.sw_if_index,
68 twice_nat=intf.twice_nat,
71 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
72 domain_id=self.ipfix_domain_id)
73 self.ipfix_src_port = 4739
74 self.ipfix_domain_id = 1
76 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
78 interfaces = self.vapi.nat44_interface_dump()
79 for intf in interfaces:
80 if intf.is_inside > 1:
81 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
84 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
88 interfaces = self.vapi.nat44_interface_output_feature_dump()
89 for intf in interfaces:
90 self.vapi.nat44_interface_add_del_output_feature(intf.sw_if_index,
94 static_mappings = self.vapi.nat44_static_mapping_dump()
95 for sm in static_mappings:
96 self.vapi.nat44_add_del_static_mapping(
98 sm.external_ip_address,
99 local_port=sm.local_port,
100 external_port=sm.external_port,
101 addr_only=sm.addr_only,
103 protocol=sm.protocol,
104 twice_nat=sm.twice_nat,
105 self_twice_nat=sm.self_twice_nat,
106 out2in_only=sm.out2in_only,
108 external_sw_if_index=sm.external_sw_if_index,
111 lb_static_mappings = self.vapi.nat44_lb_static_mapping_dump()
112 for lb_sm in lb_static_mappings:
113 self.vapi.nat44_add_del_lb_static_mapping(
117 twice_nat=lb_sm.twice_nat,
118 self_twice_nat=lb_sm.self_twice_nat,
119 out2in_only=lb_sm.out2in_only,
125 identity_mappings = self.vapi.nat44_identity_mapping_dump()
126 for id_m in identity_mappings:
127 self.vapi.nat44_add_del_identity_mapping(
128 addr_only=id_m.addr_only,
131 sw_if_index=id_m.sw_if_index,
133 protocol=id_m.protocol,
136 adresses = self.vapi.nat44_address_dump()
137 for addr in adresses:
138 self.vapi.nat44_add_del_address_range(addr.ip_address,
140 twice_nat=addr.twice_nat,
143 self.vapi.nat_set_reass()
144 self.vapi.nat_set_reass(is_ip6=1)
145 self.verify_no_nat44_user()
146 self.vapi.nat_set_timeouts()
147 self.vapi.nat_set_addr_and_port_alloc_alg()
148 self.vapi.nat_set_mss_clamping()
150 def nat44_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
151 local_port=0, external_port=0, vrf_id=0,
152 is_add=1, external_sw_if_index=0xFFFFFFFF,
153 proto=0, twice_nat=0, self_twice_nat=0,
154 out2in_only=0, tag=""):
156 Add/delete NAT44 static mapping
158 :param local_ip: Local IP address
159 :param external_ip: External IP address
160 :param local_port: Local port number (Optional)
161 :param external_port: External port number (Optional)
162 :param vrf_id: VRF ID (Default 0)
163 :param is_add: 1 if add, 0 if delete (Default add)
164 :param external_sw_if_index: External interface instead of IP address
165 :param proto: IP protocol (Mandatory if port specified)
166 :param twice_nat: 1 if translate external host address and port
167 :param self_twice_nat: 1 if translate external host address and port
168 whenever external host address equals
169 local address of internal host
170 :param out2in_only: if 1 rule is matching only out2in direction
171 :param tag: Opaque string tag
174 if local_port and external_port:
176 l_ip = socket.inet_pton(socket.AF_INET, local_ip)
177 e_ip = socket.inet_pton(socket.AF_INET, external_ip)
178 self.vapi.nat44_add_del_static_mapping(
181 external_sw_if_index,
193 def nat44_add_address(self, ip, is_add=1, vrf_id=0xFFFFFFFF, twice_nat=0):
195 Add/delete NAT44 address
197 :param ip: IP address
198 :param is_add: 1 if add, 0 if delete (Default add)
199 :param twice_nat: twice NAT address for extenal hosts
201 nat_addr = socket.inet_pton(socket.AF_INET, ip)
202 self.vapi.nat44_add_del_address_range(nat_addr, nat_addr, is_add,
206 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
208 Create packet stream for inside network
210 :param in_if: Inside interface
211 :param out_if: Outside interface
212 :param dst_ip: Destination address
213 :param ttl: TTL of generated packets
216 dst_ip = out_if.remote_ip4
220 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
221 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
222 TCP(sport=self.tcp_port_in, dport=20))
226 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
227 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
228 UDP(sport=self.udp_port_in, dport=20))
232 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
233 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
234 ICMP(id=self.icmp_id_in, type='echo-request'))
239 def compose_ip6(self, ip4, pref, plen):
241 Compose IPv4-embedded IPv6 addresses
243 :param ip4: IPv4 address
244 :param pref: IPv6 prefix
245 :param plen: IPv6 prefix length
246 :returns: IPv4-embedded IPv6 addresses
248 pref_n = list(socket.inet_pton(socket.AF_INET6, pref))
249 ip4_n = list(socket.inet_pton(socket.AF_INET, ip4))
264 pref_n[10] = ip4_n[3]
268 pref_n[10] = ip4_n[2]
269 pref_n[11] = ip4_n[3]
272 pref_n[10] = ip4_n[1]
273 pref_n[11] = ip4_n[2]
274 pref_n[12] = ip4_n[3]
276 pref_n[12] = ip4_n[0]
277 pref_n[13] = ip4_n[1]
278 pref_n[14] = ip4_n[2]
279 pref_n[15] = ip4_n[3]
280 return socket.inet_ntop(socket.AF_INET6, ''.join(pref_n))
282 def extract_ip4(self, ip6, plen):
284 Extract IPv4 address embedded in IPv6 addresses
286 :param ip6: IPv6 address
287 :param plen: IPv6 prefix length
288 :returns: extracted IPv4 address
290 ip6_n = list(socket.inet_pton(socket.AF_INET6, ip6))
322 return socket.inet_ntop(socket.AF_INET, ''.join(ip4_n))
324 def create_stream_in_ip6(self, in_if, out_if, hlim=64, pref=None, plen=0):
326 Create IPv6 packet stream for inside network
328 :param in_if: Inside interface
329 :param out_if: Outside interface
330 :param ttl: Hop Limit of generated packets
331 :param pref: NAT64 prefix
332 :param plen: NAT64 prefix length
336 dst = ''.join(['64:ff9b::', out_if.remote_ip4])
338 dst = self.compose_ip6(out_if.remote_ip4, pref, plen)
341 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
342 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
343 TCP(sport=self.tcp_port_in, dport=20))
347 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
348 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
349 UDP(sport=self.udp_port_in, dport=20))
353 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
354 IPv6(src=in_if.remote_ip6, dst=dst, hlim=hlim) /
355 ICMPv6EchoRequest(id=self.icmp_id_in))
360 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
361 use_inside_ports=False):
363 Create packet stream for outside network
365 :param out_if: Outside interface
366 :param dst_ip: Destination IP address (Default use global NAT address)
367 :param ttl: TTL of generated packets
368 :param use_inside_ports: Use inside NAT ports as destination ports
369 instead of outside ports
372 dst_ip = self.nat_addr
373 if not use_inside_ports:
374 tcp_port = self.tcp_port_out
375 udp_port = self.udp_port_out
376 icmp_id = self.icmp_id_out
378 tcp_port = self.tcp_port_in
379 udp_port = self.udp_port_in
380 icmp_id = self.icmp_id_in
383 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
384 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
385 TCP(dport=tcp_port, sport=20))
389 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
390 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
391 UDP(dport=udp_port, sport=20))
395 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
396 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
397 ICMP(id=icmp_id, type='echo-reply'))
402 def create_stream_out_ip6(self, out_if, src_ip, dst_ip, hl=64):
404 Create packet stream for outside network
406 :param out_if: Outside interface
407 :param dst_ip: Destination IP address (Default use global NAT address)
408 :param hl: HL of generated packets
412 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
413 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
414 TCP(dport=self.tcp_port_out, sport=20))
418 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
419 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
420 UDP(dport=self.udp_port_out, sport=20))
424 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
425 IPv6(src=src_ip, dst=dst_ip, hlim=hl) /
426 ICMPv6EchoReply(id=self.icmp_id_out))
431 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
432 dst_ip=None, is_ip6=False):
434 Verify captured packets on outside network
436 :param capture: Captured packets
437 :param nat_ip: Translated IP address (Default use global NAT address)
438 :param same_port: Sorce port number is not translated (Default False)
439 :param dst_ip: Destination IP address (Default do not verify)
440 :param is_ip6: If L3 protocol is IPv6 (Default False)
444 ICMP46 = ICMPv6EchoRequest
449 nat_ip = self.nat_addr
450 for packet in capture:
453 self.assert_packet_checksums_valid(packet)
454 self.assertEqual(packet[IP46].src, nat_ip)
455 if dst_ip is not None:
456 self.assertEqual(packet[IP46].dst, dst_ip)
457 if packet.haslayer(TCP):
459 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
462 packet[TCP].sport, self.tcp_port_in)
463 self.tcp_port_out = packet[TCP].sport
464 self.assert_packet_checksums_valid(packet)
465 elif packet.haslayer(UDP):
467 self.assertEqual(packet[UDP].sport, self.udp_port_in)
470 packet[UDP].sport, self.udp_port_in)
471 self.udp_port_out = packet[UDP].sport
474 self.assertEqual(packet[ICMP46].id, self.icmp_id_in)
476 self.assertNotEqual(packet[ICMP46].id, self.icmp_id_in)
477 self.icmp_id_out = packet[ICMP46].id
478 self.assert_packet_checksums_valid(packet)
480 self.logger.error(ppp("Unexpected or invalid packet "
481 "(outside network):", packet))
484 def verify_capture_out_ip6(self, capture, nat_ip, same_port=False,
487 Verify captured packets on outside network
489 :param capture: Captured packets
490 :param nat_ip: Translated IP address
491 :param same_port: Sorce port number is not translated (Default False)
492 :param dst_ip: Destination IP address (Default do not verify)
494 return self.verify_capture_out(capture, nat_ip, same_port, dst_ip,
497 def verify_capture_in(self, capture, in_if):
499 Verify captured packets on inside network
501 :param capture: Captured packets
502 :param in_if: Inside interface
504 for packet in capture:
506 self.assert_packet_checksums_valid(packet)
507 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
508 if packet.haslayer(TCP):
509 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
510 elif packet.haslayer(UDP):
511 self.assertEqual(packet[UDP].dport, self.udp_port_in)
513 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
515 self.logger.error(ppp("Unexpected or invalid packet "
516 "(inside network):", packet))
519 def verify_capture_in_ip6(self, capture, src_ip, dst_ip):
521 Verify captured IPv6 packets on inside network
523 :param capture: Captured packets
524 :param src_ip: Source IP
525 :param dst_ip: Destination IP address
527 for packet in capture:
529 self.assertEqual(packet[IPv6].src, src_ip)
530 self.assertEqual(packet[IPv6].dst, dst_ip)
531 self.assert_packet_checksums_valid(packet)
532 if packet.haslayer(TCP):
533 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
534 elif packet.haslayer(UDP):
535 self.assertEqual(packet[UDP].dport, self.udp_port_in)
537 self.assertEqual(packet[ICMPv6EchoReply].id,
540 self.logger.error(ppp("Unexpected or invalid packet "
541 "(inside network):", packet))
544 def verify_capture_no_translation(self, capture, ingress_if, egress_if):
546 Verify captured packet that don't have to be translated
548 :param capture: Captured packets
549 :param ingress_if: Ingress interface
550 :param egress_if: Egress interface
552 for packet in capture:
554 self.assertEqual(packet[IP].src, ingress_if.remote_ip4)
555 self.assertEqual(packet[IP].dst, egress_if.remote_ip4)
556 if packet.haslayer(TCP):
557 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
558 elif packet.haslayer(UDP):
559 self.assertEqual(packet[UDP].sport, self.udp_port_in)
561 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
563 self.logger.error(ppp("Unexpected or invalid packet "
564 "(inside network):", packet))
567 def verify_capture_out_with_icmp_errors(self, capture, src_ip=None,
570 Verify captured packets with ICMP errors on outside network
572 :param capture: Captured packets
573 :param src_ip: Translated IP address or IP address of VPP
574 (Default use global NAT address)
575 :param icmp_type: Type of error ICMP packet
576 we are expecting (Default 11)
579 src_ip = self.nat_addr
580 for packet in capture:
582 self.assertEqual(packet[IP].src, src_ip)
583 self.assertEqual(packet.haslayer(ICMP), 1)
585 self.assertEqual(icmp.type, icmp_type)
586 self.assertTrue(icmp.haslayer(IPerror))
587 inner_ip = icmp[IPerror]
588 if inner_ip.haslayer(TCPerror):
589 self.assertEqual(inner_ip[TCPerror].dport,
591 elif inner_ip.haslayer(UDPerror):
592 self.assertEqual(inner_ip[UDPerror].dport,
595 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_out)
597 self.logger.error(ppp("Unexpected or invalid packet "
598 "(outside network):", packet))
601 def verify_capture_in_with_icmp_errors(self, capture, in_if, icmp_type=11):
603 Verify captured packets with ICMP errors on inside network
605 :param capture: Captured packets
606 :param in_if: Inside interface
607 :param icmp_type: Type of error ICMP packet
608 we are expecting (Default 11)
610 for packet in capture:
612 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
613 self.assertEqual(packet.haslayer(ICMP), 1)
615 self.assertEqual(icmp.type, icmp_type)
616 self.assertTrue(icmp.haslayer(IPerror))
617 inner_ip = icmp[IPerror]
618 if inner_ip.haslayer(TCPerror):
619 self.assertEqual(inner_ip[TCPerror].sport,
621 elif inner_ip.haslayer(UDPerror):
622 self.assertEqual(inner_ip[UDPerror].sport,
625 self.assertEqual(inner_ip[ICMPerror].id, self.icmp_id_in)
627 self.logger.error(ppp("Unexpected or invalid packet "
628 "(inside network):", packet))
631 def create_stream_frag(self, src_if, dst, sport, dport, data,
632 proto=IP_PROTOS.tcp, echo_reply=False):
634 Create fragmented packet stream
636 :param src_if: Source interface
637 :param dst: Destination IPv4 address
638 :param sport: Source port
639 :param dport: Destination port
640 :param data: Payload data
641 :param proto: protocol (TCP, UDP, ICMP)
642 :param echo_reply: use echo_reply if protocol is ICMP
645 if proto == IP_PROTOS.tcp:
646 p = (IP(src=src_if.remote_ip4, dst=dst) /
647 TCP(sport=sport, dport=dport) /
649 p = p.__class__(str(p))
650 chksum = p['TCP'].chksum
651 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
652 elif proto == IP_PROTOS.udp:
653 proto_header = UDP(sport=sport, dport=dport)
654 elif proto == IP_PROTOS.icmp:
656 proto_header = ICMP(id=sport, type='echo-request')
658 proto_header = ICMP(id=sport, type='echo-reply')
660 raise Exception("Unsupported protocol")
661 id = random.randint(0, 65535)
663 if proto == IP_PROTOS.tcp:
666 raw = Raw(data[0:16])
667 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
668 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
672 if proto == IP_PROTOS.tcp:
673 raw = Raw(data[4:20])
675 raw = Raw(data[16:32])
676 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
677 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
681 if proto == IP_PROTOS.tcp:
685 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
686 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
692 def create_stream_frag_ip6(self, src_if, dst, sport, dport, data,
693 pref=None, plen=0, frag_size=128):
695 Create fragmented packet stream
697 :param src_if: Source interface
698 :param dst: Destination IPv4 address
699 :param sport: Source TCP port
700 :param dport: Destination TCP port
701 :param data: Payload data
702 :param pref: NAT64 prefix
703 :param plen: NAT64 prefix length
704 :param fragsize: size of fragments
708 dst_ip6 = ''.join(['64:ff9b::', dst])
710 dst_ip6 = self.compose_ip6(dst, pref, plen)
712 p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) /
713 IPv6(src=src_if.remote_ip6, dst=dst_ip6) /
714 IPv6ExtHdrFragment(id=random.randint(0, 65535)) /
715 TCP(sport=sport, dport=dport) /
718 return fragment6(p, frag_size)
720 def reass_frags_and_verify(self, frags, src, dst):
722 Reassemble and verify fragmented packet
724 :param frags: Captured fragments
725 :param src: Source IPv4 address to verify
726 :param dst: Destination IPv4 address to verify
728 :returns: Reassembled IPv4 packet
732 self.assertEqual(p[IP].src, src)
733 self.assertEqual(p[IP].dst, dst)
734 self.assert_ip_checksum_valid(p)
735 buffer.seek(p[IP].frag * 8)
736 buffer.write(bytes(p[IP].payload))
737 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
738 proto=frags[0][IP].proto)
739 if ip.proto == IP_PROTOS.tcp:
740 p = (ip / TCP(buffer.getvalue()))
741 self.assert_tcp_checksum_valid(p)
742 elif ip.proto == IP_PROTOS.udp:
743 p = (ip / UDP(buffer.getvalue()[:8]) /
744 Raw(buffer.getvalue()[8:]))
745 elif ip.proto == IP_PROTOS.icmp:
746 p = (ip / ICMP(buffer.getvalue()))
749 def reass_frags_and_verify_ip6(self, frags, src, dst):
751 Reassemble and verify fragmented packet
753 :param frags: Captured fragments
754 :param src: Source IPv6 address to verify
755 :param dst: Destination IPv6 address to verify
757 :returns: Reassembled IPv6 packet
761 self.assertEqual(p[IPv6].src, src)
762 self.assertEqual(p[IPv6].dst, dst)
763 buffer.seek(p[IPv6ExtHdrFragment].offset * 8)
764 buffer.write(bytes(p[IPv6ExtHdrFragment].payload))
765 ip = IPv6(src=frags[0][IPv6].src, dst=frags[0][IPv6].dst,
766 nh=frags[0][IPv6ExtHdrFragment].nh)
767 if ip.nh == IP_PROTOS.tcp:
768 p = (ip / TCP(buffer.getvalue()))
769 elif ip.nh == IP_PROTOS.udp:
770 p = (ip / UDP(buffer.getvalue()))
771 self.assert_packet_checksums_valid(p)
774 def initiate_tcp_session(self, in_if, out_if):
776 Initiates TCP session
778 :param in_if: Inside interface
779 :param out_if: Outside interface
783 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
784 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
785 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
788 self.pg_enable_capture(self.pg_interfaces)
790 capture = out_if.get_capture(1)
792 self.tcp_port_out = p[TCP].sport
794 # SYN + ACK packet out->in
795 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
796 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
797 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
800 self.pg_enable_capture(self.pg_interfaces)
805 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
806 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
807 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
810 self.pg_enable_capture(self.pg_interfaces)
812 out_if.get_capture(1)
815 self.logger.error("TCP 3 way handshake failed")
818 def verify_ipfix_nat44_ses(self, data):
820 Verify IPFIX NAT44 session create/delete event
822 :param data: Decoded IPFIX data records
824 nat44_ses_create_num = 0
825 nat44_ses_delete_num = 0
826 self.assertEqual(6, len(data))
829 self.assertIn(ord(record[230]), [4, 5])
830 if ord(record[230]) == 4:
831 nat44_ses_create_num += 1
833 nat44_ses_delete_num += 1
835 self.assertEqual(self.pg0.remote_ip4n, record[8])
836 # postNATSourceIPv4Address
837 self.assertEqual(socket.inet_pton(socket.AF_INET, self.nat_addr),
840 self.assertEqual(struct.pack("!I", 0), record[234])
841 # protocolIdentifier/sourceTransportPort/postNAPTSourceTransportPort
842 if IP_PROTOS.icmp == ord(record[4]):
843 self.assertEqual(struct.pack("!H", self.icmp_id_in), record[7])
844 self.assertEqual(struct.pack("!H", self.icmp_id_out),
846 elif IP_PROTOS.tcp == ord(record[4]):
847 self.assertEqual(struct.pack("!H", self.tcp_port_in),
849 self.assertEqual(struct.pack("!H", self.tcp_port_out),
851 elif IP_PROTOS.udp == ord(record[4]):
852 self.assertEqual(struct.pack("!H", self.udp_port_in),
854 self.assertEqual(struct.pack("!H", self.udp_port_out),
857 self.fail("Invalid protocol")
858 self.assertEqual(3, nat44_ses_create_num)
859 self.assertEqual(3, nat44_ses_delete_num)
861 def verify_ipfix_addr_exhausted(self, data):
863 Verify IPFIX NAT addresses event
865 :param data: Decoded IPFIX data records
867 self.assertEqual(1, len(data))
870 self.assertEqual(ord(record[230]), 3)
872 self.assertEqual(struct.pack("!I", 0), record[283])
874 def verify_ipfix_max_sessions(self, data, limit):
876 Verify IPFIX maximum session entries exceeded event
878 :param data: Decoded IPFIX data records
879 :param limit: Number of maximum session entries that can be created.
881 self.assertEqual(1, len(data))
884 self.assertEqual(ord(record[230]), 13)
885 # natQuotaExceededEvent
886 self.assertEqual(struct.pack("I", 1), record[466])
888 self.assertEqual(struct.pack("I", limit), record[471])
890 def verify_ipfix_max_bibs(self, data, limit):
892 Verify IPFIX maximum BIB entries exceeded event
894 :param data: Decoded IPFIX data records
895 :param limit: Number of maximum BIB entries that can be created.
897 self.assertEqual(1, len(data))
900 self.assertEqual(ord(record[230]), 13)
901 # natQuotaExceededEvent
902 self.assertEqual(struct.pack("I", 2), record[466])
904 self.assertEqual(struct.pack("I", limit), record[472])
906 def verify_ipfix_max_fragments_ip6(self, data, limit, src_addr):
908 Verify IPFIX maximum IPv6 fragments pending reassembly exceeded event
910 :param data: Decoded IPFIX data records
911 :param limit: Number of maximum fragments pending reassembly
912 :param src_addr: IPv6 source address
914 self.assertEqual(1, len(data))
917 self.assertEqual(ord(record[230]), 13)
918 # natQuotaExceededEvent
919 self.assertEqual(struct.pack("I", 5), record[466])
920 # maxFragmentsPendingReassembly
921 self.assertEqual(struct.pack("I", limit), record[475])
923 self.assertEqual(src_addr, record[27])
925 def verify_ipfix_max_fragments_ip4(self, data, limit, src_addr):
927 Verify IPFIX maximum IPv4 fragments pending reassembly exceeded event
929 :param data: Decoded IPFIX data records
930 :param limit: Number of maximum fragments pending reassembly
931 :param src_addr: IPv4 source address
933 self.assertEqual(1, len(data))
936 self.assertEqual(ord(record[230]), 13)
937 # natQuotaExceededEvent
938 self.assertEqual(struct.pack("I", 5), record[466])
939 # maxFragmentsPendingReassembly
940 self.assertEqual(struct.pack("I", limit), record[475])
942 self.assertEqual(src_addr, record[8])
944 def verify_ipfix_bib(self, data, is_create, src_addr):
946 Verify IPFIX NAT64 BIB create and delete events
948 :param data: Decoded IPFIX data records
949 :param is_create: Create event if nonzero value otherwise delete event
950 :param src_addr: IPv6 source address
952 self.assertEqual(1, len(data))
956 self.assertEqual(ord(record[230]), 10)
958 self.assertEqual(ord(record[230]), 11)
960 self.assertEqual(src_addr, record[27])
961 # postNATSourceIPv4Address
962 self.assertEqual(self.nat_addr_n, record[225])
964 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
966 self.assertEqual(struct.pack("!I", 0), record[234])
967 # sourceTransportPort
968 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
969 # postNAPTSourceTransportPort
970 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
972 def verify_ipfix_nat64_ses(self, data, is_create, src_addr, dst_addr,
975 Verify IPFIX NAT64 session create and delete events
977 :param data: Decoded IPFIX data records
978 :param is_create: Create event if nonzero value otherwise delete event
979 :param src_addr: IPv6 source address
980 :param dst_addr: IPv4 destination address
981 :param dst_port: destination TCP port
983 self.assertEqual(1, len(data))
987 self.assertEqual(ord(record[230]), 6)
989 self.assertEqual(ord(record[230]), 7)
991 self.assertEqual(src_addr, record[27])
992 # destinationIPv6Address
993 self.assertEqual(socket.inet_pton(socket.AF_INET6,
994 self.compose_ip6(dst_addr,
998 # postNATSourceIPv4Address
999 self.assertEqual(self.nat_addr_n, record[225])
1000 # postNATDestinationIPv4Address
1001 self.assertEqual(socket.inet_pton(socket.AF_INET, dst_addr),
1003 # protocolIdentifier
1004 self.assertEqual(IP_PROTOS.tcp, ord(record[4]))
1006 self.assertEqual(struct.pack("!I", 0), record[234])
1007 # sourceTransportPort
1008 self.assertEqual(struct.pack("!H", self.tcp_port_in), record[7])
1009 # postNAPTSourceTransportPort
1010 self.assertEqual(struct.pack("!H", self.tcp_port_out), record[227])
1011 # destinationTransportPort
1012 self.assertEqual(struct.pack("!H", dst_port), record[11])
1013 # postNAPTDestinationTransportPort
1014 self.assertEqual(struct.pack("!H", dst_port), record[228])
1016 def verify_no_nat44_user(self):
1017 """ Verify that there is no NAT44 user """
1018 users = self.vapi.nat44_user_dump()
1019 self.assertEqual(len(users), 0)
1020 users = self.statistics.get_counter('/nat44/total-users')
1021 self.assertEqual(users[0][0], 0)
1022 sessions = self.statistics.get_counter('/nat44/total-sessions')
1023 self.assertEqual(sessions[0][0], 0)
1025 def verify_ipfix_max_entries_per_user(self, data, limit, src_addr):
1027 Verify IPFIX maximum entries per user exceeded event
1029 :param data: Decoded IPFIX data records
1030 :param limit: Number of maximum entries per user
1031 :param src_addr: IPv4 source address
1033 self.assertEqual(1, len(data))
1036 self.assertEqual(ord(record[230]), 13)
1037 # natQuotaExceededEvent
1038 self.assertEqual(struct.pack("I", 3), record[466])
1040 self.assertEqual(struct.pack("I", limit), record[473])
1042 self.assertEqual(src_addr, record[8])
1044 def verify_syslog_apmap(self, data, is_add=True):
1045 message = data.decode('utf-8')
1047 message = SyslogMessage.parse(message)
1048 except ParseError as e:
1049 self.logger.error(e)
1052 self.assertEqual(message.severity, SyslogSeverity.info)
1053 self.assertEqual(message.appname, 'NAT')
1054 self.assertEqual(message.msgid, 'APMADD' if is_add else 'APMDEL')
1055 sd_params = message.sd.get('napmap')
1056 self.assertTrue(sd_params is not None)
1057 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1058 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1059 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1060 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1061 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1062 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1063 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1064 self.assertTrue(sd_params.get('SSUBIX') is not None)
1065 self.assertEqual(sd_params.get('SVLAN'), '0')
1067 def verify_syslog_sess(self, data, is_add=True, is_ip6=False):
1068 message = data.decode('utf-8')
1070 message = SyslogMessage.parse(message)
1071 except ParseError as e:
1072 self.logger.error(e)
1075 self.assertEqual(message.severity, SyslogSeverity.info)
1076 self.assertEqual(message.appname, 'NAT')
1077 self.assertEqual(message.msgid, 'SADD' if is_add else 'SDEL')
1078 sd_params = message.sd.get('nsess')
1079 self.assertTrue(sd_params is not None)
1081 self.assertEqual(sd_params.get('IATYP'), 'IPv6')
1082 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
1084 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
1085 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
1086 self.assertTrue(sd_params.get('SSUBIX') is not None)
1087 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
1088 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
1089 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
1090 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
1091 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
1092 self.assertEqual(sd_params.get('SVLAN'), '0')
1093 self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
1094 self.assertEqual(sd_params.get('XDPORT'),
1095 "%d" % self.tcp_external_port)
1097 def verify_mss_value(self, pkt, mss):
1099 Verify TCP MSS value
1104 if not pkt.haslayer(IP) or not pkt.haslayer(TCP):
1105 raise TypeError("Not a TCP/IP packet")
1107 for option in pkt[TCP].options:
1108 if option[0] == 'MSS':
1109 self.assertEqual(option[1], mss)
1110 self.assert_tcp_checksum_valid(pkt)
1113 def proto2layer(proto):
1114 if proto == IP_PROTOS.tcp:
1116 elif proto == IP_PROTOS.udp:
1118 elif proto == IP_PROTOS.icmp:
1121 raise Exception("Unsupported protocol")
1123 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1124 layer = self.proto2layer(proto)
1126 if proto == IP_PROTOS.tcp:
1127 data = "A" * 4 + "B" * 16 + "C" * 3
1129 data = "A" * 16 + "B" * 16 + "C" * 3
1130 self.port_in = random.randint(1025, 65535)
1132 reass = self.vapi.nat_reass_dump()
1133 reass_n_start = len(reass)
1136 pkts = self.create_stream_frag(self.pg0,
1137 self.pg1.remote_ip4,
1142 self.pg0.add_stream(pkts)
1143 self.pg_enable_capture(self.pg_interfaces)
1145 frags = self.pg1.get_capture(len(pkts))
1146 if not dont_translate:
1147 p = self.reass_frags_and_verify(frags,
1149 self.pg1.remote_ip4)
1151 p = self.reass_frags_and_verify(frags,
1152 self.pg0.remote_ip4,
1153 self.pg1.remote_ip4)
1154 if proto != IP_PROTOS.icmp:
1155 if not dont_translate:
1156 self.assertEqual(p[layer].dport, 20)
1157 self.assertNotEqual(p[layer].sport, self.port_in)
1159 self.assertEqual(p[layer].sport, self.port_in)
1161 if not dont_translate:
1162 self.assertNotEqual(p[layer].id, self.port_in)
1164 self.assertEqual(p[layer].id, self.port_in)
1165 self.assertEqual(data, p[Raw].load)
1168 if not dont_translate:
1169 dst_addr = self.nat_addr
1171 dst_addr = self.pg0.remote_ip4
1172 if proto != IP_PROTOS.icmp:
1174 dport = p[layer].sport
1178 pkts = self.create_stream_frag(self.pg1,
1185 self.pg1.add_stream(pkts)
1186 self.pg_enable_capture(self.pg_interfaces)
1188 frags = self.pg0.get_capture(len(pkts))
1189 p = self.reass_frags_and_verify(frags,
1190 self.pg1.remote_ip4,
1191 self.pg0.remote_ip4)
1192 if proto != IP_PROTOS.icmp:
1193 self.assertEqual(p[layer].sport, 20)
1194 self.assertEqual(p[layer].dport, self.port_in)
1196 self.assertEqual(p[layer].id, self.port_in)
1197 self.assertEqual(data, p[Raw].load)
1199 reass = self.vapi.nat_reass_dump()
1200 reass_n_end = len(reass)
1202 self.assertEqual(reass_n_end - reass_n_start, 2)
1204 def frag_in_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1205 layer = self.proto2layer(proto)
1207 if proto == IP_PROTOS.tcp:
1208 data = "A" * 4 + "B" * 16 + "C" * 3
1210 data = "A" * 16 + "B" * 16 + "C" * 3
1211 self.port_in = random.randint(1025, 65535)
1214 reass = self.vapi.nat_reass_dump()
1215 reass_n_start = len(reass)
1218 pkts = self.create_stream_frag(self.pg0,
1219 self.server_out_addr,
1221 self.server_out_port,
1224 self.pg0.add_stream(pkts)
1225 self.pg_enable_capture(self.pg_interfaces)
1227 frags = self.pg1.get_capture(len(pkts))
1228 p = self.reass_frags_and_verify(frags,
1229 self.pg0.remote_ip4,
1230 self.server_in_addr)
1231 if proto != IP_PROTOS.icmp:
1232 self.assertEqual(p[layer].sport, self.port_in)
1233 self.assertEqual(p[layer].dport, self.server_in_port)
1235 self.assertEqual(p[layer].id, self.port_in)
1236 self.assertEqual(data, p[Raw].load)
1239 if proto != IP_PROTOS.icmp:
1240 pkts = self.create_stream_frag(self.pg1,
1241 self.pg0.remote_ip4,
1242 self.server_in_port,
1247 pkts = self.create_stream_frag(self.pg1,
1248 self.pg0.remote_ip4,
1254 self.pg1.add_stream(pkts)
1255 self.pg_enable_capture(self.pg_interfaces)
1257 frags = self.pg0.get_capture(len(pkts))
1258 p = self.reass_frags_and_verify(frags,
1259 self.server_out_addr,
1260 self.pg0.remote_ip4)
1261 if proto != IP_PROTOS.icmp:
1262 self.assertEqual(p[layer].sport, self.server_out_port)
1263 self.assertEqual(p[layer].dport, self.port_in)
1265 self.assertEqual(p[layer].id, self.port_in)
1266 self.assertEqual(data, p[Raw].load)
1268 reass = self.vapi.nat_reass_dump()
1269 reass_n_end = len(reass)
1271 self.assertEqual(reass_n_end - reass_n_start, 2)
1273 def reass_hairpinning(self, proto=IP_PROTOS.tcp):
1274 layer = self.proto2layer(proto)
1276 if proto == IP_PROTOS.tcp:
1277 data = "A" * 4 + "B" * 16 + "C" * 3
1279 data = "A" * 16 + "B" * 16 + "C" * 3
1281 # send packet from host to server
1282 pkts = self.create_stream_frag(self.pg0,
1285 self.server_out_port,
1288 self.pg0.add_stream(pkts)
1289 self.pg_enable_capture(self.pg_interfaces)
1291 frags = self.pg0.get_capture(len(pkts))
1292 p = self.reass_frags_and_verify(frags,
1295 if proto != IP_PROTOS.icmp:
1296 self.assertNotEqual(p[layer].sport, self.host_in_port)
1297 self.assertEqual(p[layer].dport, self.server_in_port)
1299 self.assertNotEqual(p[layer].id, self.host_in_port)
1300 self.assertEqual(data, p[Raw].load)
1302 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False):
1303 layer = self.proto2layer(proto)
1305 if proto == IP_PROTOS.tcp:
1306 data = "A" * 4 + "B" * 16 + "C" * 3
1308 data = "A" * 16 + "B" * 16 + "C" * 3
1309 self.port_in = random.randint(1025, 65535)
1313 pkts = self.create_stream_frag(self.pg0,
1314 self.pg1.remote_ip4,
1320 self.pg0.add_stream(pkts)
1321 self.pg_enable_capture(self.pg_interfaces)
1323 frags = self.pg1.get_capture(len(pkts))
1324 if not dont_translate:
1325 p = self.reass_frags_and_verify(frags,
1327 self.pg1.remote_ip4)
1329 p = self.reass_frags_and_verify(frags,
1330 self.pg0.remote_ip4,
1331 self.pg1.remote_ip4)
1332 if proto != IP_PROTOS.icmp:
1333 if not dont_translate:
1334 self.assertEqual(p[layer].dport, 20)
1335 self.assertNotEqual(p[layer].sport, self.port_in)
1337 self.assertEqual(p[layer].sport, self.port_in)
1339 if not dont_translate:
1340 self.assertNotEqual(p[layer].id, self.port_in)
1342 self.assertEqual(p[layer].id, self.port_in)
1343 self.assertEqual(data, p[Raw].load)
1346 if not dont_translate:
1347 dst_addr = self.nat_addr
1349 dst_addr = self.pg0.remote_ip4
1350 if proto != IP_PROTOS.icmp:
1352 dport = p[layer].sport
1356 pkts = self.create_stream_frag(self.pg1,
1364 self.pg1.add_stream(pkts)
1365 self.pg_enable_capture(self.pg_interfaces)
1367 frags = self.pg0.get_capture(len(pkts))
1368 p = self.reass_frags_and_verify(frags,
1369 self.pg1.remote_ip4,
1370 self.pg0.remote_ip4)
1371 if proto != IP_PROTOS.icmp:
1372 self.assertEqual(p[layer].sport, 20)
1373 self.assertEqual(p[layer].dport, self.port_in)
1375 self.assertEqual(p[layer].id, self.port_in)
1376 self.assertEqual(data, p[Raw].load)
1378 def frag_out_of_order_in_plus_out(self, proto=IP_PROTOS.tcp):
1379 layer = self.proto2layer(proto)
1381 if proto == IP_PROTOS.tcp:
1382 data = "A" * 4 + "B" * 16 + "C" * 3
1384 data = "A" * 16 + "B" * 16 + "C" * 3
1385 self.port_in = random.randint(1025, 65535)
1389 pkts = self.create_stream_frag(self.pg0,
1390 self.server_out_addr,
1392 self.server_out_port,
1396 self.pg0.add_stream(pkts)
1397 self.pg_enable_capture(self.pg_interfaces)
1399 frags = self.pg1.get_capture(len(pkts))
1400 p = self.reass_frags_and_verify(frags,
1401 self.pg0.remote_ip4,
1402 self.server_in_addr)
1403 if proto != IP_PROTOS.icmp:
1404 self.assertEqual(p[layer].dport, self.server_in_port)
1405 self.assertEqual(p[layer].sport, self.port_in)
1406 self.assertEqual(p[layer].dport, self.server_in_port)
1408 self.assertEqual(p[layer].id, self.port_in)
1409 self.assertEqual(data, p[Raw].load)
1412 if proto != IP_PROTOS.icmp:
1413 pkts = self.create_stream_frag(self.pg1,
1414 self.pg0.remote_ip4,
1415 self.server_in_port,
1420 pkts = self.create_stream_frag(self.pg1,
1421 self.pg0.remote_ip4,
1428 self.pg1.add_stream(pkts)
1429 self.pg_enable_capture(self.pg_interfaces)
1431 frags = self.pg0.get_capture(len(pkts))
1432 p = self.reass_frags_and_verify(frags,
1433 self.server_out_addr,
1434 self.pg0.remote_ip4)
1435 if proto != IP_PROTOS.icmp:
1436 self.assertEqual(p[layer].sport, self.server_out_port)
1437 self.assertEqual(p[layer].dport, self.port_in)
1439 self.assertEqual(p[layer].id, self.port_in)
1440 self.assertEqual(data, p[Raw].load)
1443 class TestNAT44(MethodHolder):
1444 """ NAT44 Test Cases """
1447 def setUpClass(cls):
1448 super(TestNAT44, cls).setUpClass()
1449 cls.vapi.cli("set log class nat level debug")
1452 cls.tcp_port_in = 6303
1453 cls.tcp_port_out = 6303
1454 cls.udp_port_in = 6304
1455 cls.udp_port_out = 6304
1456 cls.icmp_id_in = 6305
1457 cls.icmp_id_out = 6305
1458 cls.nat_addr = '10.0.0.3'
1459 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
1460 cls.ipfix_src_port = 4739
1461 cls.ipfix_domain_id = 1
1462 cls.tcp_external_port = 80
1464 cls.create_pg_interfaces(range(10))
1465 cls.interfaces = list(cls.pg_interfaces[0:4])
1467 for i in cls.interfaces:
1472 cls.pg0.generate_remote_hosts(3)
1473 cls.pg0.configure_ipv4_neighbors()
1475 cls.pg1.generate_remote_hosts(1)
1476 cls.pg1.configure_ipv4_neighbors()
1478 cls.overlapping_interfaces = list(list(cls.pg_interfaces[4:7]))
1479 cls.vapi.ip_table_add_del(10, is_add=1)
1480 cls.vapi.ip_table_add_del(20, is_add=1)
1482 cls.pg4._local_ip4 = "172.16.255.1"
1483 cls.pg4._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1484 cls.pg4._remote_hosts[0]._ip4 = "172.16.255.2"
1485 cls.pg4.set_table_ip4(10)
1486 cls.pg5._local_ip4 = "172.17.255.3"
1487 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1488 cls.pg5._remote_hosts[0]._ip4 = "172.17.255.4"
1489 cls.pg5.set_table_ip4(10)
1490 cls.pg6._local_ip4 = "172.16.255.1"
1491 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET, i.local_ip4)
1492 cls.pg6._remote_hosts[0]._ip4 = "172.16.255.2"
1493 cls.pg6.set_table_ip4(20)
1494 for i in cls.overlapping_interfaces:
1502 cls.pg9.generate_remote_hosts(2)
1503 cls.pg9.config_ip4()
1504 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
1505 cls.vapi.sw_interface_add_del_address(cls.pg9.sw_if_index,
1509 cls.pg9.resolve_arp()
1510 cls.pg9._remote_hosts[1]._ip4 = cls.pg9._remote_hosts[0]._ip4
1511 cls.pg4._remote_ip4 = cls.pg9._remote_hosts[0]._ip4 = "10.0.0.2"
1512 cls.pg9.resolve_arp()
1515 super(TestNAT44, cls).tearDownClass()
1518 def test_dynamic(self):
1519 """ NAT44 dynamic translation test """
1520 self.nat44_add_address(self.nat_addr)
1521 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1522 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1526 tcpn = self.statistics.get_counter(
1527 '/err/nat44-in2out-slowpath/TCP packets')
1528 udpn = self.statistics.get_counter(
1529 '/err/nat44-in2out-slowpath/UDP packets')
1530 icmpn = self.statistics.get_counter(
1531 '/err/nat44-in2out-slowpath/ICMP packets')
1532 totaln = self.statistics.get_counter(
1533 '/err/nat44-in2out-slowpath/good in2out packets processed')
1535 pkts = self.create_stream_in(self.pg0, self.pg1)
1536 self.pg0.add_stream(pkts)
1537 self.pg_enable_capture(self.pg_interfaces)
1539 capture = self.pg1.get_capture(len(pkts))
1540 self.verify_capture_out(capture)
1542 err = self.statistics.get_counter(
1543 '/err/nat44-in2out-slowpath/TCP packets')
1544 self.assertEqual(err - tcpn, 1)
1545 err = self.statistics.get_counter(
1546 '/err/nat44-in2out-slowpath/UDP packets')
1547 self.assertEqual(err - udpn, 1)
1548 err = self.statistics.get_counter(
1549 '/err/nat44-in2out-slowpath/ICMP packets')
1550 self.assertEqual(err - icmpn, 1)
1551 err = self.statistics.get_counter(
1552 '/err/nat44-in2out-slowpath/good in2out packets processed')
1553 self.assertEqual(err - totaln, 3)
1556 tcpn = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
1557 udpn = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
1558 icmpn = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
1559 totaln = self.statistics.get_counter(
1560 '/err/nat44-out2in/good out2in packets processed')
1562 pkts = self.create_stream_out(self.pg1)
1563 self.pg1.add_stream(pkts)
1564 self.pg_enable_capture(self.pg_interfaces)
1566 capture = self.pg0.get_capture(len(pkts))
1567 self.verify_capture_in(capture, self.pg0)
1569 err = self.statistics.get_counter('/err/nat44-out2in/TCP packets')
1570 self.assertEqual(err - tcpn, 1)
1571 err = self.statistics.get_counter('/err/nat44-out2in/UDP packets')
1572 self.assertEqual(err - udpn, 1)
1573 err = self.statistics.get_counter('/err/nat44-out2in/ICMP packets')
1574 self.assertEqual(err - icmpn, 1)
1575 err = self.statistics.get_counter(
1576 '/err/nat44-out2in/good out2in packets processed')
1577 self.assertEqual(err - totaln, 3)
1579 users = self.statistics.get_counter('/nat44/total-users')
1580 self.assertEqual(users[0][0], 1)
1581 sessions = self.statistics.get_counter('/nat44/total-sessions')
1582 self.assertEqual(sessions[0][0], 3)
1584 def test_dynamic_icmp_errors_in2out_ttl_1(self):
1585 """ NAT44 handling of client packets with TTL=1 """
1587 self.nat44_add_address(self.nat_addr)
1588 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1589 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1592 # Client side - generate traffic
1593 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1594 self.pg0.add_stream(pkts)
1595 self.pg_enable_capture(self.pg_interfaces)
1598 # Client side - verify ICMP type 11 packets
1599 capture = self.pg0.get_capture(len(pkts))
1600 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1602 def test_dynamic_icmp_errors_out2in_ttl_1(self):
1603 """ NAT44 handling of server packets with TTL=1 """
1605 self.nat44_add_address(self.nat_addr)
1606 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1607 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1610 # Client side - create sessions
1611 pkts = self.create_stream_in(self.pg0, self.pg1)
1612 self.pg0.add_stream(pkts)
1613 self.pg_enable_capture(self.pg_interfaces)
1616 # Server side - generate traffic
1617 capture = self.pg1.get_capture(len(pkts))
1618 self.verify_capture_out(capture)
1619 pkts = self.create_stream_out(self.pg1, ttl=1)
1620 self.pg1.add_stream(pkts)
1621 self.pg_enable_capture(self.pg_interfaces)
1624 # Server side - verify ICMP type 11 packets
1625 capture = self.pg1.get_capture(len(pkts))
1626 self.verify_capture_out_with_icmp_errors(capture,
1627 src_ip=self.pg1.local_ip4)
1629 def test_dynamic_icmp_errors_in2out_ttl_2(self):
1630 """ NAT44 handling of error responses to client packets with TTL=2 """
1632 self.nat44_add_address(self.nat_addr)
1633 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1634 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1637 # Client side - generate traffic
1638 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1639 self.pg0.add_stream(pkts)
1640 self.pg_enable_capture(self.pg_interfaces)
1643 # Server side - simulate ICMP type 11 response
1644 capture = self.pg1.get_capture(len(pkts))
1645 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1646 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1647 ICMP(type=11) / packet[IP] for packet in capture]
1648 self.pg1.add_stream(pkts)
1649 self.pg_enable_capture(self.pg_interfaces)
1652 # Client side - verify ICMP type 11 packets
1653 capture = self.pg0.get_capture(len(pkts))
1654 self.verify_capture_in_with_icmp_errors(capture, self.pg0)
1656 def test_dynamic_icmp_errors_out2in_ttl_2(self):
1657 """ NAT44 handling of error responses to server packets with TTL=2 """
1659 self.nat44_add_address(self.nat_addr)
1660 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1661 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1664 # Client side - create sessions
1665 pkts = self.create_stream_in(self.pg0, self.pg1)
1666 self.pg0.add_stream(pkts)
1667 self.pg_enable_capture(self.pg_interfaces)
1670 # Server side - generate traffic
1671 capture = self.pg1.get_capture(len(pkts))
1672 self.verify_capture_out(capture)
1673 pkts = self.create_stream_out(self.pg1, ttl=2)
1674 self.pg1.add_stream(pkts)
1675 self.pg_enable_capture(self.pg_interfaces)
1678 # Client side - simulate ICMP type 11 response
1679 capture = self.pg0.get_capture(len(pkts))
1680 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1681 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1682 ICMP(type=11) / packet[IP] for packet in capture]
1683 self.pg0.add_stream(pkts)
1684 self.pg_enable_capture(self.pg_interfaces)
1687 # Server side - verify ICMP type 11 packets
1688 capture = self.pg1.get_capture(len(pkts))
1689 self.verify_capture_out_with_icmp_errors(capture)
1691 def test_ping_out_interface_from_outside(self):
1692 """ Ping NAT44 out interface from outside network """
1694 self.nat44_add_address(self.nat_addr)
1695 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1696 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1699 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1700 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
1701 ICMP(id=self.icmp_id_out, type='echo-request'))
1703 self.pg1.add_stream(pkts)
1704 self.pg_enable_capture(self.pg_interfaces)
1706 capture = self.pg1.get_capture(len(pkts))
1709 self.assertEqual(packet[IP].src, self.pg1.local_ip4)
1710 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
1711 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
1712 self.assertEqual(packet[ICMP].type, 0) # echo reply
1714 self.logger.error(ppp("Unexpected or invalid packet "
1715 "(outside network):", packet))
1718 def test_ping_internal_host_from_outside(self):
1719 """ Ping internal host from outside network """
1721 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr)
1722 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1723 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1727 pkt = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1728 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, ttl=64) /
1729 ICMP(id=self.icmp_id_out, type='echo-request'))
1730 self.pg1.add_stream(pkt)
1731 self.pg_enable_capture(self.pg_interfaces)
1733 capture = self.pg0.get_capture(1)
1734 self.verify_capture_in(capture, self.pg0)
1735 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1738 pkt = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1739 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
1740 ICMP(id=self.icmp_id_in, type='echo-reply'))
1741 self.pg0.add_stream(pkt)
1742 self.pg_enable_capture(self.pg_interfaces)
1744 capture = self.pg1.get_capture(1)
1745 self.verify_capture_out(capture, same_port=True)
1746 self.assert_equal(capture[0][IP].proto, IP_PROTOS.icmp)
1748 def test_forwarding(self):
1749 """ NAT44 forwarding test """
1751 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1752 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1754 self.vapi.nat44_forwarding_enable_disable(1)
1756 real_ip = self.pg0.remote_ip4n
1757 alias_ip = self.nat_addr_n
1758 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1759 external_ip=alias_ip)
1762 # static mapping match
1764 pkts = self.create_stream_out(self.pg1)
1765 self.pg1.add_stream(pkts)
1766 self.pg_enable_capture(self.pg_interfaces)
1768 capture = self.pg0.get_capture(len(pkts))
1769 self.verify_capture_in(capture, self.pg0)
1771 pkts = self.create_stream_in(self.pg0, self.pg1)
1772 self.pg0.add_stream(pkts)
1773 self.pg_enable_capture(self.pg_interfaces)
1775 capture = self.pg1.get_capture(len(pkts))
1776 self.verify_capture_out(capture, same_port=True)
1778 # no static mapping match
1780 host0 = self.pg0.remote_hosts[0]
1781 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1783 pkts = self.create_stream_out(self.pg1,
1784 dst_ip=self.pg0.remote_ip4,
1785 use_inside_ports=True)
1786 self.pg1.add_stream(pkts)
1787 self.pg_enable_capture(self.pg_interfaces)
1789 capture = self.pg0.get_capture(len(pkts))
1790 self.verify_capture_in(capture, self.pg0)
1792 pkts = self.create_stream_in(self.pg0, self.pg1)
1793 self.pg0.add_stream(pkts)
1794 self.pg_enable_capture(self.pg_interfaces)
1796 capture = self.pg1.get_capture(len(pkts))
1797 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1800 self.pg0.remote_hosts[0] = host0
1803 self.vapi.nat44_forwarding_enable_disable(0)
1804 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
1805 external_ip=alias_ip,
1808 def test_static_in(self):
1809 """ 1:1 NAT initialized from inside network """
1811 nat_ip = "10.0.0.10"
1812 self.tcp_port_out = 6303
1813 self.udp_port_out = 6304
1814 self.icmp_id_out = 6305
1816 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
1817 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1818 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1820 sm = self.vapi.nat44_static_mapping_dump()
1821 self.assertEqual(len(sm), 1)
1822 self.assertEqual((sm[0].tag).split('\0', 1)[0], '')
1823 self.assertEqual(sm[0].protocol, 0)
1824 self.assertEqual(sm[0].local_port, 0)
1825 self.assertEqual(sm[0].external_port, 0)
1828 pkts = self.create_stream_in(self.pg0, self.pg1)
1829 self.pg0.add_stream(pkts)
1830 self.pg_enable_capture(self.pg_interfaces)
1832 capture = self.pg1.get_capture(len(pkts))
1833 self.verify_capture_out(capture, nat_ip, True)
1836 pkts = self.create_stream_out(self.pg1, nat_ip)
1837 self.pg1.add_stream(pkts)
1838 self.pg_enable_capture(self.pg_interfaces)
1840 capture = self.pg0.get_capture(len(pkts))
1841 self.verify_capture_in(capture, self.pg0)
1843 def test_static_out(self):
1844 """ 1:1 NAT initialized from outside network """
1846 nat_ip = "10.0.0.20"
1847 self.tcp_port_out = 6303
1848 self.udp_port_out = 6304
1849 self.icmp_id_out = 6305
1852 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip, tag=tag)
1853 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1854 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1856 sm = self.vapi.nat44_static_mapping_dump()
1857 self.assertEqual(len(sm), 1)
1858 self.assertEqual((sm[0].tag).split('\0', 1)[0], tag)
1861 pkts = self.create_stream_out(self.pg1, nat_ip)
1862 self.pg1.add_stream(pkts)
1863 self.pg_enable_capture(self.pg_interfaces)
1865 capture = self.pg0.get_capture(len(pkts))
1866 self.verify_capture_in(capture, self.pg0)
1869 pkts = self.create_stream_in(self.pg0, self.pg1)
1870 self.pg0.add_stream(pkts)
1871 self.pg_enable_capture(self.pg_interfaces)
1873 capture = self.pg1.get_capture(len(pkts))
1874 self.verify_capture_out(capture, nat_ip, True)
1876 def test_static_with_port_in(self):
1877 """ 1:1 NAPT initialized from inside network """
1879 self.tcp_port_out = 3606
1880 self.udp_port_out = 3607
1881 self.icmp_id_out = 3608
1883 self.nat44_add_address(self.nat_addr)
1884 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1885 self.tcp_port_in, self.tcp_port_out,
1886 proto=IP_PROTOS.tcp)
1887 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1888 self.udp_port_in, self.udp_port_out,
1889 proto=IP_PROTOS.udp)
1890 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1891 self.icmp_id_in, self.icmp_id_out,
1892 proto=IP_PROTOS.icmp)
1893 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1894 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1898 pkts = self.create_stream_in(self.pg0, self.pg1)
1899 self.pg0.add_stream(pkts)
1900 self.pg_enable_capture(self.pg_interfaces)
1902 capture = self.pg1.get_capture(len(pkts))
1903 self.verify_capture_out(capture)
1906 pkts = self.create_stream_out(self.pg1)
1907 self.pg1.add_stream(pkts)
1908 self.pg_enable_capture(self.pg_interfaces)
1910 capture = self.pg0.get_capture(len(pkts))
1911 self.verify_capture_in(capture, self.pg0)
1913 def test_static_with_port_out(self):
1914 """ 1:1 NAPT initialized from outside network """
1916 self.tcp_port_out = 30606
1917 self.udp_port_out = 30607
1918 self.icmp_id_out = 30608
1920 self.nat44_add_address(self.nat_addr)
1921 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1922 self.tcp_port_in, self.tcp_port_out,
1923 proto=IP_PROTOS.tcp)
1924 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1925 self.udp_port_in, self.udp_port_out,
1926 proto=IP_PROTOS.udp)
1927 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1928 self.icmp_id_in, self.icmp_id_out,
1929 proto=IP_PROTOS.icmp)
1930 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1931 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1935 pkts = self.create_stream_out(self.pg1)
1936 self.pg1.add_stream(pkts)
1937 self.pg_enable_capture(self.pg_interfaces)
1939 capture = self.pg0.get_capture(len(pkts))
1940 self.verify_capture_in(capture, self.pg0)
1943 pkts = self.create_stream_in(self.pg0, self.pg1)
1944 self.pg0.add_stream(pkts)
1945 self.pg_enable_capture(self.pg_interfaces)
1947 capture = self.pg1.get_capture(len(pkts))
1948 self.verify_capture_out(capture)
1950 def test_static_vrf_aware(self):
1951 """ 1:1 NAT VRF awareness """
1953 nat_ip1 = "10.0.0.30"
1954 nat_ip2 = "10.0.0.40"
1955 self.tcp_port_out = 6303
1956 self.udp_port_out = 6304
1957 self.icmp_id_out = 6305
1959 self.nat44_add_static_mapping(self.pg4.remote_ip4, nat_ip1,
1961 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip2,
1963 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
1965 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1966 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
1968 # inside interface VRF match NAT44 static mapping VRF
1969 pkts = self.create_stream_in(self.pg4, self.pg3)
1970 self.pg4.add_stream(pkts)
1971 self.pg_enable_capture(self.pg_interfaces)
1973 capture = self.pg3.get_capture(len(pkts))
1974 self.verify_capture_out(capture, nat_ip1, True)
1976 # inside interface VRF don't match NAT44 static mapping VRF (packets
1978 pkts = self.create_stream_in(self.pg0, self.pg3)
1979 self.pg0.add_stream(pkts)
1980 self.pg_enable_capture(self.pg_interfaces)
1982 self.pg3.assert_nothing_captured()
1984 def test_dynamic_to_static(self):
1985 """ Switch from dynamic translation to 1:1NAT """
1986 nat_ip = "10.0.0.10"
1987 self.tcp_port_out = 6303
1988 self.udp_port_out = 6304
1989 self.icmp_id_out = 6305
1991 self.nat44_add_address(self.nat_addr)
1992 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
1993 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
1997 pkts = self.create_stream_in(self.pg0, self.pg1)
1998 self.pg0.add_stream(pkts)
1999 self.pg_enable_capture(self.pg_interfaces)
2001 capture = self.pg1.get_capture(len(pkts))
2002 self.verify_capture_out(capture)
2005 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
2006 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2007 self.assertEqual(len(sessions), 0)
2008 pkts = self.create_stream_in(self.pg0, self.pg1)
2009 self.pg0.add_stream(pkts)
2010 self.pg_enable_capture(self.pg_interfaces)
2012 capture = self.pg1.get_capture(len(pkts))
2013 self.verify_capture_out(capture, nat_ip, True)
2015 def test_identity_nat(self):
2016 """ Identity NAT """
2018 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n)
2019 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2020 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2023 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2024 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2025 TCP(sport=12345, dport=56789))
2026 self.pg1.add_stream(p)
2027 self.pg_enable_capture(self.pg_interfaces)
2029 capture = self.pg0.get_capture(1)
2034 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2035 self.assertEqual(ip.src, self.pg1.remote_ip4)
2036 self.assertEqual(tcp.dport, 56789)
2037 self.assertEqual(tcp.sport, 12345)
2038 self.assert_packet_checksums_valid(p)
2040 self.logger.error(ppp("Unexpected or invalid packet:", p))
2043 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
2044 self.assertEqual(len(sessions), 0)
2045 self.vapi.nat44_add_del_identity_mapping(ip=self.pg0.remote_ip4n,
2047 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2048 self.assertEqual(len(identity_mappings), 2)
2050 def test_multiple_inside_interfaces(self):
2051 """ NAT44 multiple non-overlapping address space inside interfaces """
2053 self.nat44_add_address(self.nat_addr)
2054 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2055 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2056 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2059 # between two NAT44 inside interfaces (no translation)
2060 pkts = self.create_stream_in(self.pg0, self.pg1)
2061 self.pg0.add_stream(pkts)
2062 self.pg_enable_capture(self.pg_interfaces)
2064 capture = self.pg1.get_capture(len(pkts))
2065 self.verify_capture_no_translation(capture, self.pg0, self.pg1)
2067 # from NAT44 inside to interface without NAT44 feature (no translation)
2068 pkts = self.create_stream_in(self.pg0, self.pg2)
2069 self.pg0.add_stream(pkts)
2070 self.pg_enable_capture(self.pg_interfaces)
2072 capture = self.pg2.get_capture(len(pkts))
2073 self.verify_capture_no_translation(capture, self.pg0, self.pg2)
2075 # in2out 1st interface
2076 pkts = self.create_stream_in(self.pg0, self.pg3)
2077 self.pg0.add_stream(pkts)
2078 self.pg_enable_capture(self.pg_interfaces)
2080 capture = self.pg3.get_capture(len(pkts))
2081 self.verify_capture_out(capture)
2083 # out2in 1st interface
2084 pkts = self.create_stream_out(self.pg3)
2085 self.pg3.add_stream(pkts)
2086 self.pg_enable_capture(self.pg_interfaces)
2088 capture = self.pg0.get_capture(len(pkts))
2089 self.verify_capture_in(capture, self.pg0)
2091 # in2out 2nd interface
2092 pkts = self.create_stream_in(self.pg1, self.pg3)
2093 self.pg1.add_stream(pkts)
2094 self.pg_enable_capture(self.pg_interfaces)
2096 capture = self.pg3.get_capture(len(pkts))
2097 self.verify_capture_out(capture)
2099 # out2in 2nd interface
2100 pkts = self.create_stream_out(self.pg3)
2101 self.pg3.add_stream(pkts)
2102 self.pg_enable_capture(self.pg_interfaces)
2104 capture = self.pg1.get_capture(len(pkts))
2105 self.verify_capture_in(capture, self.pg1)
2107 def test_inside_overlapping_interfaces(self):
2108 """ NAT44 multiple inside interfaces with overlapping address space """
2110 static_nat_ip = "10.0.0.10"
2111 self.nat44_add_address(self.nat_addr)
2112 self.vapi.nat44_interface_add_del_feature(self.pg3.sw_if_index,
2114 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
2115 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
2116 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index)
2117 self.nat44_add_static_mapping(self.pg6.remote_ip4, static_nat_ip,
2120 # between NAT44 inside interfaces with same VRF (no translation)
2121 pkts = self.create_stream_in(self.pg4, self.pg5)
2122 self.pg4.add_stream(pkts)
2123 self.pg_enable_capture(self.pg_interfaces)
2125 capture = self.pg5.get_capture(len(pkts))
2126 self.verify_capture_no_translation(capture, self.pg4, self.pg5)
2128 # between NAT44 inside interfaces with different VRF (hairpinning)
2129 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
2130 IP(src=self.pg4.remote_ip4, dst=static_nat_ip) /
2131 TCP(sport=1234, dport=5678))
2132 self.pg4.add_stream(p)
2133 self.pg_enable_capture(self.pg_interfaces)
2135 capture = self.pg6.get_capture(1)
2140 self.assertEqual(ip.src, self.nat_addr)
2141 self.assertEqual(ip.dst, self.pg6.remote_ip4)
2142 self.assertNotEqual(tcp.sport, 1234)
2143 self.assertEqual(tcp.dport, 5678)
2145 self.logger.error(ppp("Unexpected or invalid packet:", p))
2148 # in2out 1st interface
2149 pkts = self.create_stream_in(self.pg4, self.pg3)
2150 self.pg4.add_stream(pkts)
2151 self.pg_enable_capture(self.pg_interfaces)
2153 capture = self.pg3.get_capture(len(pkts))
2154 self.verify_capture_out(capture)
2156 # out2in 1st interface
2157 pkts = self.create_stream_out(self.pg3)
2158 self.pg3.add_stream(pkts)
2159 self.pg_enable_capture(self.pg_interfaces)
2161 capture = self.pg4.get_capture(len(pkts))
2162 self.verify_capture_in(capture, self.pg4)
2164 # in2out 2nd interface
2165 pkts = self.create_stream_in(self.pg5, self.pg3)
2166 self.pg5.add_stream(pkts)
2167 self.pg_enable_capture(self.pg_interfaces)
2169 capture = self.pg3.get_capture(len(pkts))
2170 self.verify_capture_out(capture)
2172 # out2in 2nd interface
2173 pkts = self.create_stream_out(self.pg3)
2174 self.pg3.add_stream(pkts)
2175 self.pg_enable_capture(self.pg_interfaces)
2177 capture = self.pg5.get_capture(len(pkts))
2178 self.verify_capture_in(capture, self.pg5)
2181 addresses = self.vapi.nat44_address_dump()
2182 self.assertEqual(len(addresses), 1)
2183 sessions = self.vapi.nat44_user_session_dump(self.pg5.remote_ip4n, 10)
2184 self.assertEqual(len(sessions), 3)
2185 for session in sessions:
2186 self.assertFalse(session.is_static)
2187 self.assertEqual(session.inside_ip_address[0:4],
2188 self.pg5.remote_ip4n)
2189 self.assertEqual(session.outside_ip_address,
2190 addresses[0].ip_address)
2191 self.assertEqual(sessions[0].protocol, IP_PROTOS.tcp)
2192 self.assertEqual(sessions[1].protocol, IP_PROTOS.udp)
2193 self.assertEqual(sessions[2].protocol, IP_PROTOS.icmp)
2194 self.assertEqual(sessions[0].inside_port, self.tcp_port_in)
2195 self.assertEqual(sessions[1].inside_port, self.udp_port_in)
2196 self.assertEqual(sessions[2].inside_port, self.icmp_id_in)
2197 self.assertEqual(sessions[0].outside_port, self.tcp_port_out)
2198 self.assertEqual(sessions[1].outside_port, self.udp_port_out)
2199 self.assertEqual(sessions[2].outside_port, self.icmp_id_out)
2201 # in2out 3rd interface
2202 pkts = self.create_stream_in(self.pg6, self.pg3)
2203 self.pg6.add_stream(pkts)
2204 self.pg_enable_capture(self.pg_interfaces)
2206 capture = self.pg3.get_capture(len(pkts))
2207 self.verify_capture_out(capture, static_nat_ip, True)
2209 # out2in 3rd interface
2210 pkts = self.create_stream_out(self.pg3, static_nat_ip)
2211 self.pg3.add_stream(pkts)
2212 self.pg_enable_capture(self.pg_interfaces)
2214 capture = self.pg6.get_capture(len(pkts))
2215 self.verify_capture_in(capture, self.pg6)
2217 # general user and session dump verifications
2218 users = self.vapi.nat44_user_dump()
2219 self.assertGreaterEqual(len(users), 3)
2220 addresses = self.vapi.nat44_address_dump()
2221 self.assertEqual(len(addresses), 1)
2223 sessions = self.vapi.nat44_user_session_dump(user.ip_address,
2225 for session in sessions:
2226 self.assertEqual(user.ip_address, session.inside_ip_address)
2227 self.assertTrue(session.total_bytes > session.total_pkts > 0)
2228 self.assertTrue(session.protocol in
2229 [IP_PROTOS.tcp, IP_PROTOS.udp,
2231 self.assertFalse(session.ext_host_valid)
2234 sessions = self.vapi.nat44_user_session_dump(self.pg4.remote_ip4n, 10)
2235 self.assertGreaterEqual(len(sessions), 4)
2236 for session in sessions:
2237 self.assertFalse(session.is_static)
2238 self.assertEqual(session.inside_ip_address[0:4],
2239 self.pg4.remote_ip4n)
2240 self.assertEqual(session.outside_ip_address,
2241 addresses[0].ip_address)
2244 sessions = self.vapi.nat44_user_session_dump(self.pg6.remote_ip4n, 20)
2245 self.assertGreaterEqual(len(sessions), 3)
2246 for session in sessions:
2247 self.assertTrue(session.is_static)
2248 self.assertEqual(session.inside_ip_address[0:4],
2249 self.pg6.remote_ip4n)
2250 self.assertEqual(map(ord, session.outside_ip_address[0:4]),
2251 map(int, static_nat_ip.split('.')))
2252 self.assertTrue(session.inside_port in
2253 [self.tcp_port_in, self.udp_port_in,
2256 def test_hairpinning(self):
2257 """ NAT44 hairpinning - 1:1 NAPT """
2259 host = self.pg0.remote_hosts[0]
2260 server = self.pg0.remote_hosts[1]
2263 server_in_port = 5678
2264 server_out_port = 8765
2266 self.nat44_add_address(self.nat_addr)
2267 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2268 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2270 # add static mapping for server
2271 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
2272 server_in_port, server_out_port,
2273 proto=IP_PROTOS.tcp)
2275 # send packet from host to server
2276 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2277 IP(src=host.ip4, dst=self.nat_addr) /
2278 TCP(sport=host_in_port, dport=server_out_port))
2279 self.pg0.add_stream(p)
2280 self.pg_enable_capture(self.pg_interfaces)
2282 capture = self.pg0.get_capture(1)
2287 self.assertEqual(ip.src, self.nat_addr)
2288 self.assertEqual(ip.dst, server.ip4)
2289 self.assertNotEqual(tcp.sport, host_in_port)
2290 self.assertEqual(tcp.dport, server_in_port)
2291 self.assert_packet_checksums_valid(p)
2292 host_out_port = tcp.sport
2294 self.logger.error(ppp("Unexpected or invalid packet:", p))
2297 # send reply from server to host
2298 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
2299 IP(src=server.ip4, dst=self.nat_addr) /
2300 TCP(sport=server_in_port, dport=host_out_port))
2301 self.pg0.add_stream(p)
2302 self.pg_enable_capture(self.pg_interfaces)
2304 capture = self.pg0.get_capture(1)
2309 self.assertEqual(ip.src, self.nat_addr)
2310 self.assertEqual(ip.dst, host.ip4)
2311 self.assertEqual(tcp.sport, server_out_port)
2312 self.assertEqual(tcp.dport, host_in_port)
2313 self.assert_packet_checksums_valid(p)
2315 self.logger.error(ppp("Unexpected or invalid packet:", p))
2318 def test_hairpinning2(self):
2319 """ NAT44 hairpinning - 1:1 NAT"""
2321 server1_nat_ip = "10.0.0.10"
2322 server2_nat_ip = "10.0.0.11"
2323 host = self.pg0.remote_hosts[0]
2324 server1 = self.pg0.remote_hosts[1]
2325 server2 = self.pg0.remote_hosts[2]
2326 server_tcp_port = 22
2327 server_udp_port = 20
2329 self.nat44_add_address(self.nat_addr)
2330 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2331 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2334 # add static mapping for servers
2335 self.nat44_add_static_mapping(server1.ip4, server1_nat_ip)
2336 self.nat44_add_static_mapping(server2.ip4, server2_nat_ip)
2340 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2341 IP(src=host.ip4, dst=server1_nat_ip) /
2342 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2344 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2345 IP(src=host.ip4, dst=server1_nat_ip) /
2346 UDP(sport=self.udp_port_in, dport=server_udp_port))
2348 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2349 IP(src=host.ip4, dst=server1_nat_ip) /
2350 ICMP(id=self.icmp_id_in, type='echo-request'))
2352 self.pg0.add_stream(pkts)
2353 self.pg_enable_capture(self.pg_interfaces)
2355 capture = self.pg0.get_capture(len(pkts))
2356 for packet in capture:
2358 self.assertEqual(packet[IP].src, self.nat_addr)
2359 self.assertEqual(packet[IP].dst, server1.ip4)
2360 if packet.haslayer(TCP):
2361 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
2362 self.assertEqual(packet[TCP].dport, server_tcp_port)
2363 self.tcp_port_out = packet[TCP].sport
2364 self.assert_packet_checksums_valid(packet)
2365 elif packet.haslayer(UDP):
2366 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
2367 self.assertEqual(packet[UDP].dport, server_udp_port)
2368 self.udp_port_out = packet[UDP].sport
2370 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
2371 self.icmp_id_out = packet[ICMP].id
2373 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2378 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2379 IP(src=server1.ip4, dst=self.nat_addr) /
2380 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2382 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2383 IP(src=server1.ip4, dst=self.nat_addr) /
2384 UDP(sport=server_udp_port, dport=self.udp_port_out))
2386 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2387 IP(src=server1.ip4, dst=self.nat_addr) /
2388 ICMP(id=self.icmp_id_out, type='echo-reply'))
2390 self.pg0.add_stream(pkts)
2391 self.pg_enable_capture(self.pg_interfaces)
2393 capture = self.pg0.get_capture(len(pkts))
2394 for packet in capture:
2396 self.assertEqual(packet[IP].src, server1_nat_ip)
2397 self.assertEqual(packet[IP].dst, host.ip4)
2398 if packet.haslayer(TCP):
2399 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2400 self.assertEqual(packet[TCP].sport, server_tcp_port)
2401 self.assert_packet_checksums_valid(packet)
2402 elif packet.haslayer(UDP):
2403 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2404 self.assertEqual(packet[UDP].sport, server_udp_port)
2406 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2408 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2411 # server2 to server1
2413 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2414 IP(src=server2.ip4, dst=server1_nat_ip) /
2415 TCP(sport=self.tcp_port_in, dport=server_tcp_port))
2417 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2418 IP(src=server2.ip4, dst=server1_nat_ip) /
2419 UDP(sport=self.udp_port_in, dport=server_udp_port))
2421 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2422 IP(src=server2.ip4, dst=server1_nat_ip) /
2423 ICMP(id=self.icmp_id_in, type='echo-request'))
2425 self.pg0.add_stream(pkts)
2426 self.pg_enable_capture(self.pg_interfaces)
2428 capture = self.pg0.get_capture(len(pkts))
2429 for packet in capture:
2431 self.assertEqual(packet[IP].src, server2_nat_ip)
2432 self.assertEqual(packet[IP].dst, server1.ip4)
2433 if packet.haslayer(TCP):
2434 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
2435 self.assertEqual(packet[TCP].dport, server_tcp_port)
2436 self.tcp_port_out = packet[TCP].sport
2437 self.assert_packet_checksums_valid(packet)
2438 elif packet.haslayer(UDP):
2439 self.assertEqual(packet[UDP].sport, self.udp_port_in)
2440 self.assertEqual(packet[UDP].dport, server_udp_port)
2441 self.udp_port_out = packet[UDP].sport
2443 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2444 self.icmp_id_out = packet[ICMP].id
2446 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2449 # server1 to server2
2451 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2452 IP(src=server1.ip4, dst=server2_nat_ip) /
2453 TCP(sport=server_tcp_port, dport=self.tcp_port_out))
2455 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2456 IP(src=server1.ip4, dst=server2_nat_ip) /
2457 UDP(sport=server_udp_port, dport=self.udp_port_out))
2459 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2460 IP(src=server1.ip4, dst=server2_nat_ip) /
2461 ICMP(id=self.icmp_id_out, type='echo-reply'))
2463 self.pg0.add_stream(pkts)
2464 self.pg_enable_capture(self.pg_interfaces)
2466 capture = self.pg0.get_capture(len(pkts))
2467 for packet in capture:
2469 self.assertEqual(packet[IP].src, server1_nat_ip)
2470 self.assertEqual(packet[IP].dst, server2.ip4)
2471 if packet.haslayer(TCP):
2472 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
2473 self.assertEqual(packet[TCP].sport, server_tcp_port)
2474 self.assert_packet_checksums_valid(packet)
2475 elif packet.haslayer(UDP):
2476 self.assertEqual(packet[UDP].dport, self.udp_port_in)
2477 self.assertEqual(packet[UDP].sport, server_udp_port)
2479 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
2481 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2484 def test_max_translations_per_user(self):
2485 """ MAX translations per user - recycle the least recently used """
2487 self.nat44_add_address(self.nat_addr)
2488 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2489 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2492 # get maximum number of translations per user
2493 nat44_config = self.vapi.nat_show_config()
2495 # send more than maximum number of translations per user packets
2496 pkts_num = nat44_config.max_translations_per_user + 5
2498 for port in range(0, pkts_num):
2499 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2500 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2501 TCP(sport=1025 + port))
2503 self.pg0.add_stream(pkts)
2504 self.pg_enable_capture(self.pg_interfaces)
2507 # verify number of translated packet
2508 self.pg1.get_capture(pkts_num)
2510 users = self.vapi.nat44_user_dump()
2512 if user.ip_address == self.pg0.remote_ip4n:
2513 self.assertEqual(user.nsessions,
2514 nat44_config.max_translations_per_user)
2515 self.assertEqual(user.nstaticsessions, 0)
2518 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
2520 proto=IP_PROTOS.tcp)
2521 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2522 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2523 TCP(sport=tcp_port))
2524 self.pg0.add_stream(p)
2525 self.pg_enable_capture(self.pg_interfaces)
2527 self.pg1.get_capture(1)
2528 users = self.vapi.nat44_user_dump()
2530 if user.ip_address == self.pg0.remote_ip4n:
2531 self.assertEqual(user.nsessions,
2532 nat44_config.max_translations_per_user - 1)
2533 self.assertEqual(user.nstaticsessions, 1)
2535 def test_interface_addr(self):
2536 """ Acquire NAT44 addresses from interface """
2537 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2539 # no address in NAT pool
2540 adresses = self.vapi.nat44_address_dump()
2541 self.assertEqual(0, len(adresses))
2543 # configure interface address and check NAT address pool
2544 self.pg7.config_ip4()
2545 adresses = self.vapi.nat44_address_dump()
2546 self.assertEqual(1, len(adresses))
2547 self.assertEqual(adresses[0].ip_address[0:4], self.pg7.local_ip4n)
2549 # remove interface address and check NAT address pool
2550 self.pg7.unconfig_ip4()
2551 adresses = self.vapi.nat44_address_dump()
2552 self.assertEqual(0, len(adresses))
2554 def test_interface_addr_static_mapping(self):
2555 """ Static mapping with addresses from interface """
2558 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2559 self.nat44_add_static_mapping(
2561 external_sw_if_index=self.pg7.sw_if_index,
2564 # static mappings with external interface
2565 static_mappings = self.vapi.nat44_static_mapping_dump()
2566 self.assertEqual(1, len(static_mappings))
2567 self.assertEqual(self.pg7.sw_if_index,
2568 static_mappings[0].external_sw_if_index)
2569 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2571 # configure interface address and check static mappings
2572 self.pg7.config_ip4()
2573 static_mappings = self.vapi.nat44_static_mapping_dump()
2574 self.assertEqual(2, len(static_mappings))
2576 for sm in static_mappings:
2577 if sm.external_sw_if_index == 0xFFFFFFFF:
2578 self.assertEqual(sm.external_ip_address[0:4],
2579 self.pg7.local_ip4n)
2580 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2582 self.assertTrue(resolved)
2584 # remove interface address and check static mappings
2585 self.pg7.unconfig_ip4()
2586 static_mappings = self.vapi.nat44_static_mapping_dump()
2587 self.assertEqual(1, len(static_mappings))
2588 self.assertEqual(self.pg7.sw_if_index,
2589 static_mappings[0].external_sw_if_index)
2590 self.assertEqual((static_mappings[0].tag).split('\0', 1)[0], tag)
2592 # configure interface address again and check static mappings
2593 self.pg7.config_ip4()
2594 static_mappings = self.vapi.nat44_static_mapping_dump()
2595 self.assertEqual(2, len(static_mappings))
2597 for sm in static_mappings:
2598 if sm.external_sw_if_index == 0xFFFFFFFF:
2599 self.assertEqual(sm.external_ip_address[0:4],
2600 self.pg7.local_ip4n)
2601 self.assertEqual((sm.tag).split('\0', 1)[0], tag)
2603 self.assertTrue(resolved)
2605 # remove static mapping
2606 self.nat44_add_static_mapping(
2608 external_sw_if_index=self.pg7.sw_if_index,
2611 static_mappings = self.vapi.nat44_static_mapping_dump()
2612 self.assertEqual(0, len(static_mappings))
2614 def test_interface_addr_identity_nat(self):
2615 """ Identity NAT with addresses from interface """
2618 self.vapi.nat44_add_interface_addr(self.pg7.sw_if_index)
2619 self.vapi.nat44_add_del_identity_mapping(
2620 sw_if_index=self.pg7.sw_if_index,
2622 protocol=IP_PROTOS.tcp,
2625 # identity mappings with external interface
2626 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2627 self.assertEqual(1, len(identity_mappings))
2628 self.assertEqual(self.pg7.sw_if_index,
2629 identity_mappings[0].sw_if_index)
2631 # configure interface address and check identity mappings
2632 self.pg7.config_ip4()
2633 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2635 self.assertEqual(2, len(identity_mappings))
2636 for sm in identity_mappings:
2637 if sm.sw_if_index == 0xFFFFFFFF:
2638 self.assertEqual(identity_mappings[0].ip_address,
2639 self.pg7.local_ip4n)
2640 self.assertEqual(port, identity_mappings[0].port)
2641 self.assertEqual(IP_PROTOS.tcp, identity_mappings[0].protocol)
2643 self.assertTrue(resolved)
2645 # remove interface address and check identity mappings
2646 self.pg7.unconfig_ip4()
2647 identity_mappings = self.vapi.nat44_identity_mapping_dump()
2648 self.assertEqual(1, len(identity_mappings))
2649 self.assertEqual(self.pg7.sw_if_index,
2650 identity_mappings[0].sw_if_index)
2652 def test_ipfix_nat44_sess(self):
2653 """ IPFIX logging NAT44 session created/delted """
2654 self.ipfix_domain_id = 10
2655 self.ipfix_src_port = 20202
2656 colector_port = 30303
2657 bind_layers(UDP, IPFIX, dport=30303)
2658 self.nat44_add_address(self.nat_addr)
2659 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2660 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2662 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2663 src_address=self.pg3.local_ip4n,
2665 template_interval=10,
2666 collector_port=colector_port)
2667 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2668 src_port=self.ipfix_src_port)
2670 pkts = self.create_stream_in(self.pg0, self.pg1)
2671 self.pg0.add_stream(pkts)
2672 self.pg_enable_capture(self.pg_interfaces)
2674 capture = self.pg1.get_capture(len(pkts))
2675 self.verify_capture_out(capture)
2676 self.nat44_add_address(self.nat_addr, is_add=0)
2677 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2678 capture = self.pg3.get_capture(9)
2679 ipfix = IPFIXDecoder()
2680 # first load template
2682 self.assertTrue(p.haslayer(IPFIX))
2683 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2684 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2685 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2686 self.assertEqual(p[UDP].dport, colector_port)
2687 self.assertEqual(p[IPFIX].observationDomainID,
2688 self.ipfix_domain_id)
2689 if p.haslayer(Template):
2690 ipfix.add_template(p.getlayer(Template))
2691 # verify events in data set
2693 if p.haslayer(Data):
2694 data = ipfix.decode_data_set(p.getlayer(Set))
2695 self.verify_ipfix_nat44_ses(data)
2697 def test_ipfix_addr_exhausted(self):
2698 """ IPFIX logging NAT addresses exhausted """
2699 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2700 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2702 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2703 src_address=self.pg3.local_ip4n,
2705 template_interval=10)
2706 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2707 src_port=self.ipfix_src_port)
2709 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2710 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2712 self.pg0.add_stream(p)
2713 self.pg_enable_capture(self.pg_interfaces)
2715 self.pg1.assert_nothing_captured()
2717 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2718 capture = self.pg3.get_capture(9)
2719 ipfix = IPFIXDecoder()
2720 # first load template
2722 self.assertTrue(p.haslayer(IPFIX))
2723 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2724 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2725 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2726 self.assertEqual(p[UDP].dport, 4739)
2727 self.assertEqual(p[IPFIX].observationDomainID,
2728 self.ipfix_domain_id)
2729 if p.haslayer(Template):
2730 ipfix.add_template(p.getlayer(Template))
2731 # verify events in data set
2733 if p.haslayer(Data):
2734 data = ipfix.decode_data_set(p.getlayer(Set))
2735 self.verify_ipfix_addr_exhausted(data)
2737 @unittest.skipUnless(running_extended_tests, "part of extended tests")
2738 def test_ipfix_max_sessions(self):
2739 """ IPFIX logging maximum session entries exceeded """
2740 self.nat44_add_address(self.nat_addr)
2741 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2742 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2745 nat44_config = self.vapi.nat_show_config()
2746 max_sessions = 10 * nat44_config.translation_buckets
2749 for i in range(0, max_sessions):
2750 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
2751 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2752 IP(src=src, dst=self.pg1.remote_ip4) /
2755 self.pg0.add_stream(pkts)
2756 self.pg_enable_capture(self.pg_interfaces)
2759 self.pg1.get_capture(max_sessions)
2760 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
2761 src_address=self.pg3.local_ip4n,
2763 template_interval=10)
2764 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
2765 src_port=self.ipfix_src_port)
2767 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2768 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2770 self.pg0.add_stream(p)
2771 self.pg_enable_capture(self.pg_interfaces)
2773 self.pg1.assert_nothing_captured()
2775 self.vapi.cli("ipfix flush") # FIXME this should be an API call
2776 capture = self.pg3.get_capture(9)
2777 ipfix = IPFIXDecoder()
2778 # first load template
2780 self.assertTrue(p.haslayer(IPFIX))
2781 self.assertEqual(p[IP].src, self.pg3.local_ip4)
2782 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
2783 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
2784 self.assertEqual(p[UDP].dport, 4739)
2785 self.assertEqual(p[IPFIX].observationDomainID,
2786 self.ipfix_domain_id)
2787 if p.haslayer(Template):
2788 ipfix.add_template(p.getlayer(Template))
2789 # verify events in data set
2791 if p.haslayer(Data):
2792 data = ipfix.decode_data_set(p.getlayer(Set))
2793 self.verify_ipfix_max_sessions(data, max_sessions)
2795 def test_syslog_apmap(self):
2796 """ Test syslog address and port mapping creation and deletion """
2797 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
2798 self.vapi.syslog_set_sender(self.pg3.remote_ip4n, self.pg3.local_ip4n)
2799 self.nat44_add_address(self.nat_addr)
2800 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2801 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2804 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2805 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2806 TCP(sport=self.tcp_port_in, dport=20))
2807 self.pg0.add_stream(p)
2808 self.pg_enable_capture(self.pg_interfaces)
2810 capture = self.pg1.get_capture(1)
2811 self.tcp_port_out = capture[0][TCP].sport
2812 capture = self.pg3.get_capture(1)
2813 self.verify_syslog_apmap(capture[0][Raw].load)
2815 self.pg_enable_capture(self.pg_interfaces)
2817 self.nat44_add_address(self.nat_addr, is_add=0)
2818 capture = self.pg3.get_capture(1)
2819 self.verify_syslog_apmap(capture[0][Raw].load, False)
2821 def test_pool_addr_fib(self):
2822 """ NAT44 add pool addresses to FIB """
2823 static_addr = '10.0.0.10'
2824 self.nat44_add_address(self.nat_addr)
2825 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2826 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
2828 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr)
2831 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2832 ARP(op=ARP.who_has, pdst=self.nat_addr,
2833 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2834 self.pg1.add_stream(p)
2835 self.pg_enable_capture(self.pg_interfaces)
2837 capture = self.pg1.get_capture(1)
2838 self.assertTrue(capture[0].haslayer(ARP))
2839 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2842 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2843 ARP(op=ARP.who_has, pdst=static_addr,
2844 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2845 self.pg1.add_stream(p)
2846 self.pg_enable_capture(self.pg_interfaces)
2848 capture = self.pg1.get_capture(1)
2849 self.assertTrue(capture[0].haslayer(ARP))
2850 self.assertTrue(capture[0][ARP].op, ARP.is_at)
2852 # send ARP to non-NAT44 interface
2853 p = (Ether(src=self.pg2.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2854 ARP(op=ARP.who_has, pdst=self.nat_addr,
2855 psrc=self.pg2.remote_ip4, hwsrc=self.pg2.remote_mac))
2856 self.pg2.add_stream(p)
2857 self.pg_enable_capture(self.pg_interfaces)
2859 self.pg1.assert_nothing_captured()
2861 # remove addresses and verify
2862 self.nat44_add_address(self.nat_addr, is_add=0)
2863 self.nat44_add_static_mapping(self.pg0.remote_ip4, static_addr,
2866 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2867 ARP(op=ARP.who_has, pdst=self.nat_addr,
2868 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2869 self.pg1.add_stream(p)
2870 self.pg_enable_capture(self.pg_interfaces)
2872 self.pg1.assert_nothing_captured()
2874 p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
2875 ARP(op=ARP.who_has, pdst=static_addr,
2876 psrc=self.pg1.remote_ip4, hwsrc=self.pg1.remote_mac))
2877 self.pg1.add_stream(p)
2878 self.pg_enable_capture(self.pg_interfaces)
2880 self.pg1.assert_nothing_captured()
2882 def test_vrf_mode(self):
2883 """ NAT44 tenant VRF aware address pool mode """
2887 nat_ip1 = "10.0.0.10"
2888 nat_ip2 = "10.0.0.11"
2890 self.pg0.unconfig_ip4()
2891 self.pg1.unconfig_ip4()
2892 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
2893 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
2894 self.pg0.set_table_ip4(vrf_id1)
2895 self.pg1.set_table_ip4(vrf_id2)
2896 self.pg0.config_ip4()
2897 self.pg1.config_ip4()
2898 self.pg0.resolve_arp()
2899 self.pg1.resolve_arp()
2901 self.nat44_add_address(nat_ip1, vrf_id=vrf_id1)
2902 self.nat44_add_address(nat_ip2, vrf_id=vrf_id2)
2903 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2904 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2905 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2910 pkts = self.create_stream_in(self.pg0, self.pg2)
2911 self.pg0.add_stream(pkts)
2912 self.pg_enable_capture(self.pg_interfaces)
2914 capture = self.pg2.get_capture(len(pkts))
2915 self.verify_capture_out(capture, nat_ip1)
2918 pkts = self.create_stream_in(self.pg1, self.pg2)
2919 self.pg1.add_stream(pkts)
2920 self.pg_enable_capture(self.pg_interfaces)
2922 capture = self.pg2.get_capture(len(pkts))
2923 self.verify_capture_out(capture, nat_ip2)
2926 self.pg0.unconfig_ip4()
2927 self.pg1.unconfig_ip4()
2928 self.pg0.set_table_ip4(0)
2929 self.pg1.set_table_ip4(0)
2930 self.pg0.config_ip4()
2931 self.pg1.config_ip4()
2932 self.pg0.resolve_arp()
2933 self.pg1.resolve_arp()
2934 self.vapi.ip_table_add_del(vrf_id1, is_add=0)
2935 self.vapi.ip_table_add_del(vrf_id2, is_add=0)
2937 def test_vrf_feature_independent(self):
2938 """ NAT44 tenant VRF independent address pool mode """
2940 nat_ip1 = "10.0.0.10"
2941 nat_ip2 = "10.0.0.11"
2943 self.nat44_add_address(nat_ip1)
2944 self.nat44_add_address(nat_ip2, vrf_id=99)
2945 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
2946 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
2947 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
2951 pkts = self.create_stream_in(self.pg0, self.pg2)
2952 self.pg0.add_stream(pkts)
2953 self.pg_enable_capture(self.pg_interfaces)
2955 capture = self.pg2.get_capture(len(pkts))
2956 self.verify_capture_out(capture, nat_ip1)
2959 pkts = self.create_stream_in(self.pg1, self.pg2)
2960 self.pg1.add_stream(pkts)
2961 self.pg_enable_capture(self.pg_interfaces)
2963 capture = self.pg2.get_capture(len(pkts))
2964 self.verify_capture_out(capture, nat_ip1)
2966 def test_dynamic_ipless_interfaces(self):
2967 """ NAT44 interfaces without configured IP address """
2969 self.vapi.ip_neighbor_add_del(
2970 self.pg7.sw_if_index,
2971 self.pg7.remote_mac,
2972 self.pg7.remote_ip4,
2973 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
2974 IP_API_NEIGHBOR_FLAG_STATIC))
2975 self.vapi.ip_neighbor_add_del(
2976 self.pg8.sw_if_index,
2977 self.pg8.remote_mac,
2978 self.pg8.remote_ip4,
2979 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
2980 IP_API_NEIGHBOR_FLAG_STATIC))
2982 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
2983 dst_address_length=32,
2984 next_hop_address=self.pg7.remote_ip4n,
2985 next_hop_sw_if_index=self.pg7.sw_if_index)
2986 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
2987 dst_address_length=32,
2988 next_hop_address=self.pg8.remote_ip4n,
2989 next_hop_sw_if_index=self.pg8.sw_if_index)
2991 self.nat44_add_address(self.nat_addr)
2992 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
2993 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
2997 pkts = self.create_stream_in(self.pg7, self.pg8)
2998 self.pg7.add_stream(pkts)
2999 self.pg_enable_capture(self.pg_interfaces)
3001 capture = self.pg8.get_capture(len(pkts))
3002 self.verify_capture_out(capture)
3005 pkts = self.create_stream_out(self.pg8, self.nat_addr)
3006 self.pg8.add_stream(pkts)
3007 self.pg_enable_capture(self.pg_interfaces)
3009 capture = self.pg7.get_capture(len(pkts))
3010 self.verify_capture_in(capture, self.pg7)
3012 def test_static_ipless_interfaces(self):
3013 """ NAT44 interfaces without configured IP address - 1:1 NAT """
3015 self.vapi.ip_neighbor_add_del(
3016 self.pg7.sw_if_index,
3017 self.pg7.remote_mac,
3018 self.pg7.remote_ip4,
3019 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3020 IP_API_NEIGHBOR_FLAG_STATIC))
3021 self.vapi.ip_neighbor_add_del(
3022 self.pg8.sw_if_index,
3023 self.pg8.remote_mac,
3024 self.pg8.remote_ip4,
3025 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3026 IP_API_NEIGHBOR_FLAG_STATIC))
3028 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3029 dst_address_length=32,
3030 next_hop_address=self.pg7.remote_ip4n,
3031 next_hop_sw_if_index=self.pg7.sw_if_index)
3032 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3033 dst_address_length=32,
3034 next_hop_address=self.pg8.remote_ip4n,
3035 next_hop_sw_if_index=self.pg8.sw_if_index)
3037 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr)
3038 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
3039 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
3043 pkts = self.create_stream_out(self.pg8)
3044 self.pg8.add_stream(pkts)
3045 self.pg_enable_capture(self.pg_interfaces)
3047 capture = self.pg7.get_capture(len(pkts))
3048 self.verify_capture_in(capture, self.pg7)
3051 pkts = self.create_stream_in(self.pg7, self.pg8)
3052 self.pg7.add_stream(pkts)
3053 self.pg_enable_capture(self.pg_interfaces)
3055 capture = self.pg8.get_capture(len(pkts))
3056 self.verify_capture_out(capture, self.nat_addr, True)
3058 def test_static_with_port_ipless_interfaces(self):
3059 """ NAT44 interfaces without configured IP address - 1:1 NAPT """
3061 self.tcp_port_out = 30606
3062 self.udp_port_out = 30607
3063 self.icmp_id_out = 30608
3065 self.vapi.ip_neighbor_add_del(
3066 self.pg7.sw_if_index,
3067 self.pg7.remote_mac,
3068 self.pg7.remote_ip4,
3069 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3070 IP_API_NEIGHBOR_FLAG_STATIC))
3071 self.vapi.ip_neighbor_add_del(
3072 self.pg8.sw_if_index,
3073 self.pg8.remote_mac,
3074 self.pg8.remote_ip4,
3075 flags=(VppEnum.vl_api_ip_neighbor_flags_t.
3076 IP_API_NEIGHBOR_FLAG_STATIC))
3078 self.vapi.ip_add_del_route(dst_address=self.pg7.remote_ip4n,
3079 dst_address_length=32,
3080 next_hop_address=self.pg7.remote_ip4n,
3081 next_hop_sw_if_index=self.pg7.sw_if_index)
3082 self.vapi.ip_add_del_route(dst_address=self.pg8.remote_ip4n,
3083 dst_address_length=32,
3084 next_hop_address=self.pg8.remote_ip4n,
3085 next_hop_sw_if_index=self.pg8.sw_if_index)
3087 self.nat44_add_address(self.nat_addr)
3088 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3089 self.tcp_port_in, self.tcp_port_out,
3090 proto=IP_PROTOS.tcp)
3091 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3092 self.udp_port_in, self.udp_port_out,
3093 proto=IP_PROTOS.udp)
3094 self.nat44_add_static_mapping(self.pg7.remote_ip4, self.nat_addr,
3095 self.icmp_id_in, self.icmp_id_out,
3096 proto=IP_PROTOS.icmp)
3097 self.vapi.nat44_interface_add_del_feature(self.pg7.sw_if_index)
3098 self.vapi.nat44_interface_add_del_feature(self.pg8.sw_if_index,
3102 pkts = self.create_stream_out(self.pg8)
3103 self.pg8.add_stream(pkts)
3104 self.pg_enable_capture(self.pg_interfaces)
3106 capture = self.pg7.get_capture(len(pkts))
3107 self.verify_capture_in(capture, self.pg7)
3110 pkts = self.create_stream_in(self.pg7, self.pg8)
3111 self.pg7.add_stream(pkts)
3112 self.pg_enable_capture(self.pg_interfaces)
3114 capture = self.pg8.get_capture(len(pkts))
3115 self.verify_capture_out(capture)
3117 def test_static_unknown_proto(self):
3118 """ 1:1 NAT translate packet with unknown protocol """
3119 nat_ip = "10.0.0.10"
3120 self.nat44_add_static_mapping(self.pg0.remote_ip4, nat_ip)
3121 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3122 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3126 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3127 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3129 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3130 TCP(sport=1234, dport=1234))
3131 self.pg0.add_stream(p)
3132 self.pg_enable_capture(self.pg_interfaces)
3134 p = self.pg1.get_capture(1)
3137 self.assertEqual(packet[IP].src, nat_ip)
3138 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3139 self.assertEqual(packet.haslayer(GRE), 1)
3140 self.assert_packet_checksums_valid(packet)
3142 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3146 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3147 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
3149 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3150 TCP(sport=1234, dport=1234))
3151 self.pg1.add_stream(p)
3152 self.pg_enable_capture(self.pg_interfaces)
3154 p = self.pg0.get_capture(1)
3157 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3158 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3159 self.assertEqual(packet.haslayer(GRE), 1)
3160 self.assert_packet_checksums_valid(packet)
3162 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3165 def test_hairpinning_static_unknown_proto(self):
3166 """ 1:1 NAT translate packet with unknown protocol - hairpinning """
3168 host = self.pg0.remote_hosts[0]
3169 server = self.pg0.remote_hosts[1]
3171 host_nat_ip = "10.0.0.10"
3172 server_nat_ip = "10.0.0.11"
3174 self.nat44_add_static_mapping(host.ip4, host_nat_ip)
3175 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
3176 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3177 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3181 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
3182 IP(src=host.ip4, dst=server_nat_ip) /
3184 IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4) /
3185 TCP(sport=1234, dport=1234))
3186 self.pg0.add_stream(p)
3187 self.pg_enable_capture(self.pg_interfaces)
3189 p = self.pg0.get_capture(1)
3192 self.assertEqual(packet[IP].src, host_nat_ip)
3193 self.assertEqual(packet[IP].dst, server.ip4)
3194 self.assertEqual(packet.haslayer(GRE), 1)
3195 self.assert_packet_checksums_valid(packet)
3197 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3201 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
3202 IP(src=server.ip4, dst=host_nat_ip) /
3204 IP(src=self.pg3.remote_ip4, dst=self.pg2.remote_ip4) /
3205 TCP(sport=1234, dport=1234))
3206 self.pg0.add_stream(p)
3207 self.pg_enable_capture(self.pg_interfaces)
3209 p = self.pg0.get_capture(1)
3212 self.assertEqual(packet[IP].src, server_nat_ip)
3213 self.assertEqual(packet[IP].dst, host.ip4)
3214 self.assertEqual(packet.haslayer(GRE), 1)
3215 self.assert_packet_checksums_valid(packet)
3217 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3220 def test_output_feature(self):
3221 """ NAT44 interface output feature (in2out postrouting) """
3222 self.nat44_add_address(self.nat_addr)
3223 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3224 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index)
3225 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3229 pkts = self.create_stream_in(self.pg0, self.pg3)
3230 self.pg0.add_stream(pkts)
3231 self.pg_enable_capture(self.pg_interfaces)
3233 capture = self.pg3.get_capture(len(pkts))
3234 self.verify_capture_out(capture)
3237 pkts = self.create_stream_out(self.pg3)
3238 self.pg3.add_stream(pkts)
3239 self.pg_enable_capture(self.pg_interfaces)
3241 capture = self.pg0.get_capture(len(pkts))
3242 self.verify_capture_in(capture, self.pg0)
3244 # from non-NAT interface to NAT inside interface
3245 pkts = self.create_stream_in(self.pg2, self.pg0)
3246 self.pg2.add_stream(pkts)
3247 self.pg_enable_capture(self.pg_interfaces)
3249 capture = self.pg0.get_capture(len(pkts))
3250 self.verify_capture_no_translation(capture, self.pg2, self.pg0)
3252 def test_output_feature_vrf_aware(self):
3253 """ NAT44 interface output feature VRF aware (in2out postrouting) """
3254 nat_ip_vrf10 = "10.0.0.10"
3255 nat_ip_vrf20 = "10.0.0.20"
3257 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3258 dst_address_length=32,
3259 next_hop_address=self.pg3.remote_ip4n,
3260 next_hop_sw_if_index=self.pg3.sw_if_index,
3262 self.vapi.ip_add_del_route(dst_address=self.pg3.remote_ip4n,
3263 dst_address_length=32,
3264 next_hop_address=self.pg3.remote_ip4n,
3265 next_hop_sw_if_index=self.pg3.sw_if_index,
3268 self.nat44_add_address(nat_ip_vrf10, vrf_id=10)
3269 self.nat44_add_address(nat_ip_vrf20, vrf_id=20)
3270 self.vapi.nat44_interface_add_del_output_feature(self.pg4.sw_if_index)
3271 self.vapi.nat44_interface_add_del_output_feature(self.pg6.sw_if_index)
3272 self.vapi.nat44_interface_add_del_output_feature(self.pg3.sw_if_index,
3276 pkts = self.create_stream_in(self.pg4, self.pg3)
3277 self.pg4.add_stream(pkts)
3278 self.pg_enable_capture(self.pg_interfaces)
3280 capture = self.pg3.get_capture(len(pkts))
3281 self.verify_capture_out(capture, nat_ip=nat_ip_vrf10)
3284 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf10)
3285 self.pg3.add_stream(pkts)
3286 self.pg_enable_capture(self.pg_interfaces)
3288 capture = self.pg4.get_capture(len(pkts))
3289 self.verify_capture_in(capture, self.pg4)
3292 pkts = self.create_stream_in(self.pg6, self.pg3)
3293 self.pg6.add_stream(pkts)
3294 self.pg_enable_capture(self.pg_interfaces)
3296 capture = self.pg3.get_capture(len(pkts))
3297 self.verify_capture_out(capture, nat_ip=nat_ip_vrf20)
3300 pkts = self.create_stream_out(self.pg3, dst_ip=nat_ip_vrf20)
3301 self.pg3.add_stream(pkts)
3302 self.pg_enable_capture(self.pg_interfaces)
3304 capture = self.pg6.get_capture(len(pkts))
3305 self.verify_capture_in(capture, self.pg6)
3307 def test_output_feature_hairpinning(self):
3308 """ NAT44 interface output feature hairpinning (in2out postrouting) """
3309 host = self.pg0.remote_hosts[0]
3310 server = self.pg0.remote_hosts[1]
3313 server_in_port = 5678
3314 server_out_port = 8765
3316 self.nat44_add_address(self.nat_addr)
3317 self.vapi.nat44_interface_add_del_output_feature(self.pg0.sw_if_index)
3318 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
3321 # add static mapping for server
3322 self.nat44_add_static_mapping(server.ip4, self.nat_addr,
3323 server_in_port, server_out_port,
3324 proto=IP_PROTOS.tcp)
3326 # send packet from host to server
3327 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
3328 IP(src=host.ip4, dst=self.nat_addr) /
3329 TCP(sport=host_in_port, dport=server_out_port))
3330 self.pg0.add_stream(p)
3331 self.pg_enable_capture(self.pg_interfaces)
3333 capture = self.pg0.get_capture(1)
3338 self.assertEqual(ip.src, self.nat_addr)
3339 self.assertEqual(ip.dst, server.ip4)
3340 self.assertNotEqual(tcp.sport, host_in_port)
3341 self.assertEqual(tcp.dport, server_in_port)
3342 self.assert_packet_checksums_valid(p)
3343 host_out_port = tcp.sport
3345 self.logger.error(ppp("Unexpected or invalid packet:", p))
3348 # send reply from server to host
3349 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
3350 IP(src=server.ip4, dst=self.nat_addr) /
3351 TCP(sport=server_in_port, dport=host_out_port))
3352 self.pg0.add_stream(p)
3353 self.pg_enable_capture(self.pg_interfaces)
3355 capture = self.pg0.get_capture(1)
3360 self.assertEqual(ip.src, self.nat_addr)
3361 self.assertEqual(ip.dst, host.ip4)
3362 self.assertEqual(tcp.sport, server_out_port)
3363 self.assertEqual(tcp.dport, host_in_port)
3364 self.assert_packet_checksums_valid(p)
3366 self.logger.error(ppp("Unexpected or invalid packet:", p))
3369 def test_one_armed_nat44(self):
3370 """ One armed NAT44 """
3371 remote_host = self.pg9.remote_hosts[0]
3372 local_host = self.pg9.remote_hosts[1]
3375 self.nat44_add_address(self.nat_addr)
3376 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index)
3377 self.vapi.nat44_interface_add_del_feature(self.pg9.sw_if_index,
3381 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3382 IP(src=local_host.ip4, dst=remote_host.ip4) /
3383 TCP(sport=12345, dport=80))
3384 self.pg9.add_stream(p)
3385 self.pg_enable_capture(self.pg_interfaces)
3387 capture = self.pg9.get_capture(1)
3392 self.assertEqual(ip.src, self.nat_addr)
3393 self.assertEqual(ip.dst, remote_host.ip4)
3394 self.assertNotEqual(tcp.sport, 12345)
3395 external_port = tcp.sport
3396 self.assertEqual(tcp.dport, 80)
3397 self.assert_packet_checksums_valid(p)
3399 self.logger.error(ppp("Unexpected or invalid packet:", p))
3403 p = (Ether(src=self.pg9.remote_mac, dst=self.pg9.local_mac) /
3404 IP(src=remote_host.ip4, dst=self.nat_addr) /
3405 TCP(sport=80, dport=external_port))
3406 self.pg9.add_stream(p)
3407 self.pg_enable_capture(self.pg_interfaces)
3409 capture = self.pg9.get_capture(1)
3414 self.assertEqual(ip.src, remote_host.ip4)
3415 self.assertEqual(ip.dst, local_host.ip4)
3416 self.assertEqual(tcp.sport, 80)
3417 self.assertEqual(tcp.dport, 12345)
3418 self.assert_packet_checksums_valid(p)
3420 self.logger.error(ppp("Unexpected or invalid packet:", p))
3423 err = self.statistics.get_counter('/err/nat44-classify/next in2out')
3424 self.assertEqual(err, 1)
3425 err = self.statistics.get_counter('/err/nat44-classify/next out2in')
3426 self.assertEqual(err, 1)
3428 def test_del_session(self):
3429 """ Delete NAT44 session """
3430 self.nat44_add_address(self.nat_addr)
3431 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3432 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3435 pkts = self.create_stream_in(self.pg0, self.pg1)
3436 self.pg0.add_stream(pkts)
3437 self.pg_enable_capture(self.pg_interfaces)
3439 self.pg1.get_capture(len(pkts))
3441 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3442 nsessions = len(sessions)
3444 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3445 sessions[0].inside_port,
3446 sessions[0].protocol)
3447 self.vapi.nat44_del_session(sessions[1].outside_ip_address,
3448 sessions[1].outside_port,
3449 sessions[1].protocol,
3452 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
3453 self.assertEqual(nsessions - len(sessions), 2)
3455 self.vapi.nat44_del_session(sessions[0].inside_ip_address,
3456 sessions[0].inside_port,
3457 sessions[0].protocol)
3459 self.verify_no_nat44_user()
3461 def test_set_get_reass(self):
3462 """ NAT44 set/get virtual fragmentation reassembly """
3463 reas_cfg1 = self.vapi.nat_get_reass()
3465 self.vapi.nat_set_reass(timeout=reas_cfg1.ip4_timeout + 5,
3466 max_reass=reas_cfg1.ip4_max_reass * 2,
3467 max_frag=reas_cfg1.ip4_max_frag * 2)
3469 reas_cfg2 = self.vapi.nat_get_reass()
3471 self.assertEqual(reas_cfg1.ip4_timeout + 5, reas_cfg2.ip4_timeout)
3472 self.assertEqual(reas_cfg1.ip4_max_reass * 2, reas_cfg2.ip4_max_reass)
3473 self.assertEqual(reas_cfg1.ip4_max_frag * 2, reas_cfg2.ip4_max_frag)
3475 self.vapi.nat_set_reass(drop_frag=1)
3476 self.assertTrue(self.vapi.nat_get_reass().ip4_drop_frag)
3478 def test_frag_in_order(self):
3479 """ NAT44 translate fragments arriving in order """
3481 self.nat44_add_address(self.nat_addr)
3482 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3483 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3486 self.frag_in_order(proto=IP_PROTOS.tcp)
3487 self.frag_in_order(proto=IP_PROTOS.udp)
3488 self.frag_in_order(proto=IP_PROTOS.icmp)
3490 def test_frag_forwarding(self):
3491 """ NAT44 forwarding fragment test """
3492 self.vapi.nat44_add_interface_addr(self.pg1.sw_if_index)
3493 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3494 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3496 self.vapi.nat44_forwarding_enable_disable(1)
3498 data = "A" * 16 + "B" * 16 + "C" * 3
3499 pkts = self.create_stream_frag(self.pg1,
3500 self.pg0.remote_ip4,
3504 proto=IP_PROTOS.udp)
3505 self.pg1.add_stream(pkts)
3506 self.pg_enable_capture(self.pg_interfaces)
3508 frags = self.pg0.get_capture(len(pkts))
3509 p = self.reass_frags_and_verify(frags,
3510 self.pg1.remote_ip4,
3511 self.pg0.remote_ip4)
3512 self.assertEqual(p[UDP].sport, 4789)
3513 self.assertEqual(p[UDP].dport, 4789)
3514 self.assertEqual(data, p[Raw].load)
3516 def test_reass_hairpinning(self):
3517 """ NAT44 fragments hairpinning """
3519 self.server = self.pg0.remote_hosts[1]
3520 self.host_in_port = random.randint(1025, 65535)
3521 self.server_in_port = random.randint(1025, 65535)
3522 self.server_out_port = random.randint(1025, 65535)
3524 self.nat44_add_address(self.nat_addr)
3525 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3526 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3528 # add static mapping for server
3529 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3530 self.server_in_port,
3531 self.server_out_port,
3532 proto=IP_PROTOS.tcp)
3533 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
3534 self.server_in_port,
3535 self.server_out_port,
3536 proto=IP_PROTOS.udp)
3537 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
3539 self.reass_hairpinning(proto=IP_PROTOS.tcp)
3540 self.reass_hairpinning(proto=IP_PROTOS.udp)
3541 self.reass_hairpinning(proto=IP_PROTOS.icmp)
3543 def test_frag_out_of_order(self):
3544 """ NAT44 translate fragments arriving out of order """
3546 self.nat44_add_address(self.nat_addr)
3547 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3548 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3551 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3552 self.frag_out_of_order(proto=IP_PROTOS.udp)
3553 self.frag_out_of_order(proto=IP_PROTOS.icmp)
3555 def test_port_restricted(self):
3556 """ Port restricted NAT44 (MAP-E CE) """
3557 self.nat44_add_address(self.nat_addr)
3558 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3559 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3561 self.vapi.nat_set_addr_and_port_alloc_alg(alg=1,
3566 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3567 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3568 TCP(sport=4567, dport=22))
3569 self.pg0.add_stream(p)
3570 self.pg_enable_capture(self.pg_interfaces)
3572 capture = self.pg1.get_capture(1)
3577 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3578 self.assertEqual(ip.src, self.nat_addr)
3579 self.assertEqual(tcp.dport, 22)
3580 self.assertNotEqual(tcp.sport, 4567)
3581 self.assertEqual((tcp.sport >> 6) & 63, 10)
3582 self.assert_packet_checksums_valid(p)
3584 self.logger.error(ppp("Unexpected or invalid packet:", p))
3587 def test_port_range(self):
3588 """ External address port range """
3589 self.nat44_add_address(self.nat_addr)
3590 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3591 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3593 self.vapi.nat_set_addr_and_port_alloc_alg(alg=2,
3598 for port in range(0, 5):
3599 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3600 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3601 TCP(sport=1125 + port))
3603 self.pg0.add_stream(pkts)
3604 self.pg_enable_capture(self.pg_interfaces)
3606 capture = self.pg1.get_capture(3)
3609 self.assertGreaterEqual(tcp.sport, 1025)
3610 self.assertLessEqual(tcp.sport, 1027)
3612 def test_ipfix_max_frags(self):
3613 """ IPFIX logging maximum fragments pending reassembly exceeded """
3614 self.nat44_add_address(self.nat_addr)
3615 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3616 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3618 self.vapi.nat_set_reass(max_frag=1)
3619 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
3620 src_address=self.pg3.local_ip4n,
3622 template_interval=10)
3623 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
3624 src_port=self.ipfix_src_port)
3626 data = "A" * 4 + "B" * 16 + "C" * 3
3627 self.tcp_port_in = random.randint(1025, 65535)
3628 pkts = self.create_stream_frag(self.pg0,
3629 self.pg1.remote_ip4,
3634 self.pg0.add_stream(pkts)
3635 self.pg_enable_capture(self.pg_interfaces)
3637 self.pg1.assert_nothing_captured()
3639 self.vapi.cli("ipfix flush") # FIXME this should be an API call
3640 capture = self.pg3.get_capture(9)
3641 ipfix = IPFIXDecoder()
3642 # first load template
3644 self.assertTrue(p.haslayer(IPFIX))
3645 self.assertEqual(p[IP].src, self.pg3.local_ip4)
3646 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
3647 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
3648 self.assertEqual(p[UDP].dport, 4739)
3649 self.assertEqual(p[IPFIX].observationDomainID,
3650 self.ipfix_domain_id)
3651 if p.haslayer(Template):
3652 ipfix.add_template(p.getlayer(Template))
3653 # verify events in data set
3655 if p.haslayer(Data):
3656 data = ipfix.decode_data_set(p.getlayer(Set))
3657 self.verify_ipfix_max_fragments_ip4(data, 1,
3658 self.pg0.remote_ip4n)
3660 def test_multiple_outside_vrf(self):
3661 """ Multiple outside VRF """
3665 self.pg1.unconfig_ip4()
3666 self.pg2.unconfig_ip4()
3667 self.vapi.ip_table_add_del(vrf_id1, is_add=1)
3668 self.vapi.ip_table_add_del(vrf_id2, is_add=1)
3669 self.pg1.set_table_ip4(vrf_id1)
3670 self.pg2.set_table_ip4(vrf_id2)
3671 self.pg1.config_ip4()
3672 self.pg2.config_ip4()
3673 self.pg1.resolve_arp()
3674 self.pg2.resolve_arp()
3676 self.nat44_add_address(self.nat_addr)
3677 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3678 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3680 self.vapi.nat44_interface_add_del_feature(self.pg2.sw_if_index,
3685 pkts = self.create_stream_in(self.pg0, self.pg1)
3686 self.pg0.add_stream(pkts)
3687 self.pg_enable_capture(self.pg_interfaces)
3689 capture = self.pg1.get_capture(len(pkts))
3690 self.verify_capture_out(capture, self.nat_addr)
3692 pkts = self.create_stream_out(self.pg1, self.nat_addr)
3693 self.pg1.add_stream(pkts)
3694 self.pg_enable_capture(self.pg_interfaces)
3696 capture = self.pg0.get_capture(len(pkts))
3697 self.verify_capture_in(capture, self.pg0)
3699 self.tcp_port_in = 60303
3700 self.udp_port_in = 60304
3701 self.icmp_id_in = 60305
3704 pkts = self.create_stream_in(self.pg0, self.pg2)
3705 self.pg0.add_stream(pkts)
3706 self.pg_enable_capture(self.pg_interfaces)
3708 capture = self.pg2.get_capture(len(pkts))
3709 self.verify_capture_out(capture, self.nat_addr)
3711 pkts = self.create_stream_out(self.pg2, self.nat_addr)
3712 self.pg2.add_stream(pkts)
3713 self.pg_enable_capture(self.pg_interfaces)
3715 capture = self.pg0.get_capture(len(pkts))
3716 self.verify_capture_in(capture, self.pg0)
3719 self.pg1.unconfig_ip4()
3720 self.pg2.unconfig_ip4()
3721 self.pg1.set_table_ip4(0)
3722 self.pg2.set_table_ip4(0)
3723 self.pg1.config_ip4()
3724 self.pg2.config_ip4()
3725 self.pg1.resolve_arp()
3726 self.pg2.resolve_arp()
3728 @unittest.skipUnless(running_extended_tests, "part of extended tests")
3729 def test_session_timeout(self):
3730 """ NAT44 session timeouts """
3731 self.nat44_add_address(self.nat_addr)
3732 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3733 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3735 self.vapi.nat_set_timeouts(udp=5)
3739 for i in range(0, max_sessions):
3740 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3741 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3742 IP(src=src, dst=self.pg1.remote_ip4) /
3743 UDP(sport=1025, dport=53))
3745 self.pg0.add_stream(pkts)
3746 self.pg_enable_capture(self.pg_interfaces)
3748 self.pg1.get_capture(max_sessions)
3753 for i in range(0, max_sessions):
3754 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
3755 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3756 IP(src=src, dst=self.pg1.remote_ip4) /
3757 UDP(sport=1026, dport=53))
3759 self.pg0.add_stream(pkts)
3760 self.pg_enable_capture(self.pg_interfaces)
3762 self.pg1.get_capture(max_sessions)
3765 users = self.vapi.nat44_user_dump()
3767 nsessions = nsessions + user.nsessions
3768 self.assertLess(nsessions, 2 * max_sessions)
3770 def test_mss_clamping(self):
3771 """ TCP MSS clamping """
3772 self.nat44_add_address(self.nat_addr)
3773 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3774 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3777 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3778 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3779 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3780 flags="S", options=[('MSS', 1400)]))
3782 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1000)
3783 self.pg0.add_stream(p)
3784 self.pg_enable_capture(self.pg_interfaces)
3786 capture = self.pg1.get_capture(1)
3787 # Negotiated MSS value greater than configured - changed
3788 self.verify_mss_value(capture[0], 1000)
3790 self.vapi.nat_set_mss_clamping(enable=0)
3791 self.pg0.add_stream(p)
3792 self.pg_enable_capture(self.pg_interfaces)
3794 capture = self.pg1.get_capture(1)
3795 # MSS clamping disabled - negotiated MSS unchanged
3796 self.verify_mss_value(capture[0], 1400)
3798 self.vapi.nat_set_mss_clamping(enable=1, mss_value=1500)
3799 self.pg0.add_stream(p)
3800 self.pg_enable_capture(self.pg_interfaces)
3802 capture = self.pg1.get_capture(1)
3803 # Negotiated MSS value smaller than configured - unchanged
3804 self.verify_mss_value(capture[0], 1400)
3807 super(TestNAT44, self).tearDown()
3808 if not self.vpp_dead:
3809 self.logger.info(self.vapi.cli("show nat44 addresses"))
3810 self.logger.info(self.vapi.cli("show nat44 interfaces"))
3811 self.logger.info(self.vapi.cli("show nat44 static mappings"))
3812 self.logger.info(self.vapi.cli("show nat44 interface address"))
3813 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
3814 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
3815 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
3816 self.logger.info(self.vapi.cli("show nat timeouts"))
3818 self.vapi.cli("show nat addr-port-assignment-alg"))
3820 self.vapi.cli("clear logging")
3823 class TestNAT44EndpointDependent(MethodHolder):
3824 """ Endpoint-Dependent mapping and filtering test cases """
3827 def setUpConstants(cls):
3828 super(TestNAT44EndpointDependent, cls).setUpConstants()
3829 cls.vpp_cmdline.extend(["nat", "{", "endpoint-dependent", "}"])
3832 def setUpClass(cls):
3833 super(TestNAT44EndpointDependent, cls).setUpClass()
3834 cls.vapi.cli("set log class nat level debug")
3836 cls.tcp_port_in = 6303
3837 cls.tcp_port_out = 6303
3838 cls.udp_port_in = 6304
3839 cls.udp_port_out = 6304
3840 cls.icmp_id_in = 6305
3841 cls.icmp_id_out = 6305
3842 cls.nat_addr = '10.0.0.3'
3843 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
3844 cls.ipfix_src_port = 4739
3845 cls.ipfix_domain_id = 1
3846 cls.tcp_external_port = 80
3848 cls.create_pg_interfaces(range(7))
3849 cls.interfaces = list(cls.pg_interfaces[0:3])
3851 for i in cls.interfaces:
3856 cls.pg0.generate_remote_hosts(3)
3857 cls.pg0.configure_ipv4_neighbors()
3861 cls.pg4.generate_remote_hosts(2)
3862 cls.pg4.config_ip4()
3863 ip_addr_n = socket.inet_pton(socket.AF_INET, "10.0.0.1")
3864 cls.vapi.sw_interface_add_del_address(cls.pg4.sw_if_index,
3868 cls.pg4.resolve_arp()
3869 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
3870 cls.pg4.resolve_arp()
3872 zero_ip4n = socket.inet_pton(socket.AF_INET, "0.0.0.0")
3873 cls.vapi.ip_table_add_del(1, is_add=1)
3875 cls.pg5._local_ip4 = "10.1.1.1"
3876 cls.pg5._local_ip4n = socket.inet_pton(socket.AF_INET,
3878 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
3879 cls.pg5._remote_hosts[0]._ip4n = socket.inet_pton(
3880 socket.AF_INET, cls.pg5.remote_ip4)
3881 cls.pg5.set_table_ip4(1)
3882 cls.pg5.config_ip4()
3884 cls.vapi.ip_add_del_route(dst_address=cls.pg5.remote_ip4n,
3885 dst_address_length=32,
3887 next_hop_sw_if_index=cls.pg5.sw_if_index,
3888 next_hop_address=zero_ip4n)
3890 cls.pg6._local_ip4 = "10.1.2.1"
3891 cls.pg6._local_ip4n = socket.inet_pton(socket.AF_INET,
3893 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
3894 cls.pg6._remote_hosts[0]._ip4n = socket.inet_pton(
3895 socket.AF_INET, cls.pg6.remote_ip4)
3896 cls.pg6.set_table_ip4(1)
3897 cls.pg6.config_ip4()
3899 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
3900 dst_address_length=32,
3902 next_hop_sw_if_index=cls.pg6.sw_if_index,
3903 next_hop_address=zero_ip4n)
3905 cls.vapi.ip_add_del_route(dst_address=cls.pg6.remote_ip4n,
3906 dst_address_length=16,
3907 next_hop_address=zero_ip4n,
3909 next_hop_table_id=1)
3910 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
3911 dst_address_length=0,
3912 next_hop_address=zero_ip4n,
3914 next_hop_table_id=0)
3915 cls.vapi.ip_add_del_route(dst_address=zero_ip4n,
3916 dst_address_length=0,
3918 next_hop_sw_if_index=cls.pg1.sw_if_index,
3919 next_hop_address=cls.pg1.local_ip4n)
3921 cls.pg5.resolve_arp()
3922 cls.pg6.resolve_arp()
3925 super(TestNAT44EndpointDependent, cls).tearDownClass()
3928 def test_frag_in_order(self):
3929 """ NAT44 translate fragments arriving in order """
3930 self.nat44_add_address(self.nat_addr)
3931 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3932 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3934 self.frag_in_order(proto=IP_PROTOS.tcp)
3935 self.frag_in_order(proto=IP_PROTOS.udp)
3936 self.frag_in_order(proto=IP_PROTOS.icmp)
3938 def test_frag_in_order_dont_translate(self):
3939 """ NAT44 don't translate fragments arriving in order """
3940 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3941 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3943 self.vapi.nat44_forwarding_enable_disable(enable=True)
3944 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
3946 def test_frag_out_of_order(self):
3947 """ NAT44 translate fragments arriving out of order """
3948 self.nat44_add_address(self.nat_addr)
3949 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3950 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3952 self.frag_out_of_order(proto=IP_PROTOS.tcp)
3953 self.frag_out_of_order(proto=IP_PROTOS.udp)
3954 self.frag_out_of_order(proto=IP_PROTOS.icmp)
3956 def test_frag_out_of_order_dont_translate(self):
3957 """ NAT44 don't translate fragments arriving out of order """
3958 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3959 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3961 self.vapi.nat44_forwarding_enable_disable(enable=True)
3962 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
3964 def test_frag_in_order_in_plus_out(self):
3965 """ in+out interface fragments in order """
3966 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
3967 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
3969 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
3970 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
3973 self.server = self.pg1.remote_hosts[0]
3975 self.server_in_addr = self.server.ip4
3976 self.server_out_addr = '11.11.11.11'
3977 self.server_in_port = random.randint(1025, 65535)
3978 self.server_out_port = random.randint(1025, 65535)
3980 self.nat44_add_address(self.server_out_addr)
3982 # add static mappings for server
3983 self.nat44_add_static_mapping(self.server_in_addr,
3984 self.server_out_addr,
3985 self.server_in_port,
3986 self.server_out_port,
3987 proto=IP_PROTOS.tcp)
3988 self.nat44_add_static_mapping(self.server_in_addr,
3989 self.server_out_addr,
3990 self.server_in_port,
3991 self.server_out_port,
3992 proto=IP_PROTOS.udp)
3993 self.nat44_add_static_mapping(self.server_in_addr,
3994 self.server_out_addr,
3995 proto=IP_PROTOS.icmp)
3997 self.vapi.nat_set_reass(timeout=10)
3999 self.frag_in_order_in_plus_out(proto=IP_PROTOS.tcp)
4000 self.frag_in_order_in_plus_out(proto=IP_PROTOS.udp)
4001 self.frag_in_order_in_plus_out(proto=IP_PROTOS.icmp)
4003 def test_frag_out_of_order_in_plus_out(self):
4004 """ in+out interface fragments out of order """
4005 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4006 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4008 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index)
4009 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4012 self.server = self.pg1.remote_hosts[0]
4014 self.server_in_addr = self.server.ip4
4015 self.server_out_addr = '11.11.11.11'
4016 self.server_in_port = random.randint(1025, 65535)
4017 self.server_out_port = random.randint(1025, 65535)
4019 self.nat44_add_address(self.server_out_addr)
4021 # add static mappings for server
4022 self.nat44_add_static_mapping(self.server_in_addr,
4023 self.server_out_addr,
4024 self.server_in_port,
4025 self.server_out_port,
4026 proto=IP_PROTOS.tcp)
4027 self.nat44_add_static_mapping(self.server_in_addr,
4028 self.server_out_addr,
4029 self.server_in_port,
4030 self.server_out_port,
4031 proto=IP_PROTOS.udp)
4032 self.nat44_add_static_mapping(self.server_in_addr,
4033 self.server_out_addr,
4034 proto=IP_PROTOS.icmp)
4036 self.vapi.nat_set_reass(timeout=10)
4038 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.tcp)
4039 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.udp)
4040 self.frag_out_of_order_in_plus_out(proto=IP_PROTOS.icmp)
4042 def test_reass_hairpinning(self):
4043 """ NAT44 fragments hairpinning """
4044 self.server = self.pg0.remote_hosts[1]
4045 self.host_in_port = random.randint(1025, 65535)
4046 self.server_in_port = random.randint(1025, 65535)
4047 self.server_out_port = random.randint(1025, 65535)
4049 self.nat44_add_address(self.nat_addr)
4050 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4051 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4053 # add static mapping for server
4054 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4055 self.server_in_port,
4056 self.server_out_port,
4057 proto=IP_PROTOS.tcp)
4058 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr,
4059 self.server_in_port,
4060 self.server_out_port,
4061 proto=IP_PROTOS.udp)
4062 self.nat44_add_static_mapping(self.server.ip4, self.nat_addr)
4064 self.reass_hairpinning(proto=IP_PROTOS.tcp)
4065 self.reass_hairpinning(proto=IP_PROTOS.udp)
4066 self.reass_hairpinning(proto=IP_PROTOS.icmp)
4068 def test_dynamic(self):
4069 """ NAT44 dynamic translation test """
4071 self.nat44_add_address(self.nat_addr)
4072 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4073 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4076 nat_config = self.vapi.nat_show_config()
4077 self.assertEqual(1, nat_config.endpoint_dependent)
4080 tcpn = self.statistics.get_counter(
4081 '/err/nat44-ed-in2out-slowpath/TCP packets')
4082 udpn = self.statistics.get_counter(
4083 '/err/nat44-ed-in2out-slowpath/UDP packets')
4084 icmpn = self.statistics.get_counter(
4085 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4086 totaln = self.statistics.get_counter(
4087 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4089 pkts = self.create_stream_in(self.pg0, self.pg1)
4090 self.pg0.add_stream(pkts)
4091 self.pg_enable_capture(self.pg_interfaces)
4093 capture = self.pg1.get_capture(len(pkts))
4094 self.verify_capture_out(capture)
4096 err = self.statistics.get_counter(
4097 '/err/nat44-ed-in2out-slowpath/TCP packets')
4098 self.assertEqual(err - tcpn, 1)
4099 err = self.statistics.get_counter(
4100 '/err/nat44-ed-in2out-slowpath/UDP packets')
4101 self.assertEqual(err - udpn, 1)
4102 err = self.statistics.get_counter(
4103 '/err/nat44-ed-in2out-slowpath/ICMP packets')
4104 self.assertEqual(err - icmpn, 1)
4105 err = self.statistics.get_counter(
4106 '/err/nat44-ed-in2out-slowpath/good in2out packets processed')
4107 self.assertEqual(err - totaln, 3)
4110 tcpn = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4111 udpn = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4112 icmpn = self.statistics.get_counter(
4113 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4114 totaln = self.statistics.get_counter(
4115 '/err/nat44-ed-out2in/good out2in packets processed')
4117 pkts = self.create_stream_out(self.pg1)
4118 self.pg1.add_stream(pkts)
4119 self.pg_enable_capture(self.pg_interfaces)
4121 capture = self.pg0.get_capture(len(pkts))
4122 self.verify_capture_in(capture, self.pg0)
4124 err = self.statistics.get_counter('/err/nat44-ed-out2in/TCP packets')
4125 self.assertEqual(err - tcpn, 1)
4126 err = self.statistics.get_counter('/err/nat44-ed-out2in/UDP packets')
4127 self.assertEqual(err - udpn, 1)
4128 err = self.statistics.get_counter(
4129 '/err/nat44-ed-out2in-slowpath/ICMP packets')
4130 self.assertEqual(err - icmpn, 1)
4131 err = self.statistics.get_counter(
4132 '/err/nat44-ed-out2in/good out2in packets processed')
4133 self.assertEqual(err - totaln, 2)
4135 users = self.statistics.get_counter('/nat44/total-users')
4136 self.assertEqual(users[0][0], 1)
4137 sessions = self.statistics.get_counter('/nat44/total-sessions')
4138 self.assertEqual(sessions[0][0], 3)
4140 def test_forwarding(self):
4141 """ NAT44 forwarding test """
4143 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4144 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4146 self.vapi.nat44_forwarding_enable_disable(1)
4148 real_ip = self.pg0.remote_ip4n
4149 alias_ip = self.nat_addr_n
4150 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4151 external_ip=alias_ip)
4154 # in2out - static mapping match
4156 pkts = self.create_stream_out(self.pg1)
4157 self.pg1.add_stream(pkts)
4158 self.pg_enable_capture(self.pg_interfaces)
4160 capture = self.pg0.get_capture(len(pkts))
4161 self.verify_capture_in(capture, self.pg0)
4163 pkts = self.create_stream_in(self.pg0, self.pg1)
4164 self.pg0.add_stream(pkts)
4165 self.pg_enable_capture(self.pg_interfaces)
4167 capture = self.pg1.get_capture(len(pkts))
4168 self.verify_capture_out(capture, same_port=True)
4170 # in2out - no static mapping match
4172 host0 = self.pg0.remote_hosts[0]
4173 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
4175 pkts = self.create_stream_out(self.pg1,
4176 dst_ip=self.pg0.remote_ip4,
4177 use_inside_ports=True)
4178 self.pg1.add_stream(pkts)
4179 self.pg_enable_capture(self.pg_interfaces)
4181 capture = self.pg0.get_capture(len(pkts))
4182 self.verify_capture_in(capture, self.pg0)
4184 pkts = self.create_stream_in(self.pg0, self.pg1)
4185 self.pg0.add_stream(pkts)
4186 self.pg_enable_capture(self.pg_interfaces)
4188 capture = self.pg1.get_capture(len(pkts))
4189 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4192 self.pg0.remote_hosts[0] = host0
4194 user = self.pg0.remote_hosts[1]
4195 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4196 self.assertEqual(len(sessions), 3)
4197 self.assertTrue(sessions[0].ext_host_valid)
4198 self.vapi.nat44_del_session(
4199 sessions[0].inside_ip_address,
4200 sessions[0].inside_port,
4201 sessions[0].protocol,
4202 ext_host_address=sessions[0].ext_host_address,
4203 ext_host_port=sessions[0].ext_host_port)
4204 sessions = self.vapi.nat44_user_session_dump(user.ip4n, 0)
4205 self.assertEqual(len(sessions), 2)
4208 self.vapi.nat44_forwarding_enable_disable(0)
4209 self.vapi.nat44_add_del_static_mapping(local_ip=real_ip,
4210 external_ip=alias_ip,
4213 def test_static_lb(self):
4214 """ NAT44 local service load balancing """
4215 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4218 server1 = self.pg0.remote_hosts[0]
4219 server2 = self.pg0.remote_hosts[1]
4221 locals = [{'addr': server1.ip4n,
4225 {'addr': server2.ip4n,
4230 self.nat44_add_address(self.nat_addr)
4231 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4234 local_num=len(locals),
4236 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4237 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4240 # from client to service
4241 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4242 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4243 TCP(sport=12345, dport=external_port))
4244 self.pg1.add_stream(p)
4245 self.pg_enable_capture(self.pg_interfaces)
4247 capture = self.pg0.get_capture(1)
4253 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4254 if ip.dst == server1.ip4:
4258 self.assertEqual(tcp.dport, local_port)
4259 self.assert_packet_checksums_valid(p)
4261 self.logger.error(ppp("Unexpected or invalid packet:", p))
4264 # from service back to client
4265 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4266 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4267 TCP(sport=local_port, dport=12345))
4268 self.pg0.add_stream(p)
4269 self.pg_enable_capture(self.pg_interfaces)
4271 capture = self.pg1.get_capture(1)
4276 self.assertEqual(ip.src, self.nat_addr)
4277 self.assertEqual(tcp.sport, external_port)
4278 self.assert_packet_checksums_valid(p)
4280 self.logger.error(ppp("Unexpected or invalid packet:", p))
4283 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4284 self.assertEqual(len(sessions), 1)
4285 self.assertTrue(sessions[0].ext_host_valid)
4286 self.vapi.nat44_del_session(
4287 sessions[0].inside_ip_address,
4288 sessions[0].inside_port,
4289 sessions[0].protocol,
4290 ext_host_address=sessions[0].ext_host_address,
4291 ext_host_port=sessions[0].ext_host_port)
4292 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
4293 self.assertEqual(len(sessions), 0)
4295 @unittest.skipUnless(running_extended_tests, "part of extended tests")
4296 def test_static_lb_multi_clients(self):
4297 """ NAT44 local service load balancing - multiple clients"""
4299 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4302 server1 = self.pg0.remote_hosts[0]
4303 server2 = self.pg0.remote_hosts[1]
4304 server3 = self.pg0.remote_hosts[2]
4306 locals = [{'addr': server1.ip4n,
4310 {'addr': server2.ip4n,
4315 self.nat44_add_address(self.nat_addr)
4316 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4319 local_num=len(locals),
4321 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4322 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4327 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
4329 for client in clients:
4330 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4331 IP(src=client, dst=self.nat_addr) /
4332 TCP(sport=12345, dport=external_port))
4334 self.pg1.add_stream(pkts)
4335 self.pg_enable_capture(self.pg_interfaces)
4337 capture = self.pg0.get_capture(len(pkts))
4339 if p[IP].dst == server1.ip4:
4343 self.assertGreater(server1_n, server2_n)
4346 self.vapi.nat44_lb_static_mapping_add_del_local(external_addr_n,
4355 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
4357 for client in clients:
4358 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4359 IP(src=client, dst=self.nat_addr) /
4360 TCP(sport=12346, dport=external_port))
4362 self.assertGreater(len(pkts), 0)
4363 self.pg1.add_stream(pkts)
4364 self.pg_enable_capture(self.pg_interfaces)
4366 capture = self.pg0.get_capture(len(pkts))
4368 if p[IP].dst == server1.ip4:
4370 elif p[IP].dst == server2.ip4:
4374 self.assertGreater(server1_n, 0)
4375 self.assertGreater(server2_n, 0)
4376 self.assertGreater(server3_n, 0)
4378 # remove one back-end
4379 self.vapi.nat44_lb_static_mapping_add_del_local(external_addr_n,
4389 self.pg1.add_stream(pkts)
4390 self.pg_enable_capture(self.pg_interfaces)
4392 capture = self.pg0.get_capture(len(pkts))
4394 if p[IP].dst == server1.ip4:
4396 elif p[IP].dst == server2.ip4:
4400 self.assertGreater(server1_n, 0)
4401 self.assertEqual(server2_n, 0)
4402 self.assertGreater(server3_n, 0)
4404 def test_static_lb_2(self):
4405 """ NAT44 local service load balancing (asymmetrical rule) """
4406 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4409 server1 = self.pg0.remote_hosts[0]
4410 server2 = self.pg0.remote_hosts[1]
4412 locals = [{'addr': server1.ip4n,
4416 {'addr': server2.ip4n,
4421 self.vapi.nat44_forwarding_enable_disable(1)
4422 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4426 local_num=len(locals),
4428 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4429 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4432 # from client to service
4433 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4434 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4435 TCP(sport=12345, dport=external_port))
4436 self.pg1.add_stream(p)
4437 self.pg_enable_capture(self.pg_interfaces)
4439 capture = self.pg0.get_capture(1)
4445 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
4446 if ip.dst == server1.ip4:
4450 self.assertEqual(tcp.dport, local_port)
4451 self.assert_packet_checksums_valid(p)
4453 self.logger.error(ppp("Unexpected or invalid packet:", p))
4456 # from service back to client
4457 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
4458 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
4459 TCP(sport=local_port, dport=12345))
4460 self.pg0.add_stream(p)
4461 self.pg_enable_capture(self.pg_interfaces)
4463 capture = self.pg1.get_capture(1)
4468 self.assertEqual(ip.src, self.nat_addr)
4469 self.assertEqual(tcp.sport, external_port)
4470 self.assert_packet_checksums_valid(p)
4472 self.logger.error(ppp("Unexpected or invalid packet:", p))
4475 # from client to server (no translation)
4476 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4477 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
4478 TCP(sport=12346, dport=local_port))
4479 self.pg1.add_stream(p)
4480 self.pg_enable_capture(self.pg_interfaces)
4482 capture = self.pg0.get_capture(1)
4488 self.assertEqual(ip.dst, server1.ip4)
4489 self.assertEqual(tcp.dport, local_port)
4490 self.assert_packet_checksums_valid(p)
4492 self.logger.error(ppp("Unexpected or invalid packet:", p))
4495 # from service back to client (no translation)
4496 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
4497 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
4498 TCP(sport=local_port, dport=12346))
4499 self.pg0.add_stream(p)
4500 self.pg_enable_capture(self.pg_interfaces)
4502 capture = self.pg1.get_capture(1)
4507 self.assertEqual(ip.src, server1.ip4)
4508 self.assertEqual(tcp.sport, local_port)
4509 self.assert_packet_checksums_valid(p)
4511 self.logger.error(ppp("Unexpected or invalid packet:", p))
4514 def test_lb_affinity(self):
4515 """ NAT44 local service load balancing affinity """
4516 external_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4519 server1 = self.pg0.remote_hosts[0]
4520 server2 = self.pg0.remote_hosts[1]
4522 locals = [{'addr': server1.ip4n,
4526 {'addr': server2.ip4n,
4531 self.nat44_add_address(self.nat_addr)
4532 self.vapi.nat44_add_del_lb_static_mapping(external_addr_n,
4536 local_num=len(locals),
4538 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4539 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4542 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4543 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4544 TCP(sport=1025, dport=external_port))
4545 self.pg1.add_stream(p)
4546 self.pg_enable_capture(self.pg_interfaces)
4548 capture = self.pg0.get_capture(1)
4549 backend = capture[0][IP].dst
4551 sessions = self.vapi.nat44_user_session_dump(
4552 socket.inet_pton(socket.AF_INET, backend), 0)
4553 self.assertEqual(len(sessions), 1)
4554 self.assertTrue(sessions[0].ext_host_valid)
4555 self.vapi.nat44_del_session(
4556 sessions[0].inside_ip_address,
4557 sessions[0].inside_port,
4558 sessions[0].protocol,
4559 ext_host_address=sessions[0].ext_host_address,
4560 ext_host_port=sessions[0].ext_host_port)
4563 for port in range(1030, 1100):
4564 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4565 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4566 TCP(sport=port, dport=external_port))
4568 self.pg1.add_stream(pkts)
4569 self.pg_enable_capture(self.pg_interfaces)
4571 capture = self.pg0.get_capture(len(pkts))
4573 self.assertEqual(p[IP].dst, backend)
4575 def test_unknown_proto(self):
4576 """ NAT44 translate packet with unknown protocol """
4577 self.nat44_add_address(self.nat_addr)
4578 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4579 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4583 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4584 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4585 TCP(sport=self.tcp_port_in, dport=20))
4586 self.pg0.add_stream(p)
4587 self.pg_enable_capture(self.pg_interfaces)
4589 p = self.pg1.get_capture(1)
4591 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
4592 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4594 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4595 TCP(sport=1234, dport=1234))
4596 self.pg0.add_stream(p)
4597 self.pg_enable_capture(self.pg_interfaces)
4599 p = self.pg1.get_capture(1)
4602 self.assertEqual(packet[IP].src, self.nat_addr)
4603 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
4604 self.assertEqual(packet.haslayer(GRE), 1)
4605 self.assert_packet_checksums_valid(packet)
4607 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4611 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
4612 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4614 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4615 TCP(sport=1234, dport=1234))
4616 self.pg1.add_stream(p)
4617 self.pg_enable_capture(self.pg_interfaces)
4619 p = self.pg0.get_capture(1)
4622 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
4623 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
4624 self.assertEqual(packet.haslayer(GRE), 1)
4625 self.assert_packet_checksums_valid(packet)
4627 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4630 def test_hairpinning_unknown_proto(self):
4631 """ NAT44 translate packet with unknown protocol - hairpinning """
4632 host = self.pg0.remote_hosts[0]
4633 server = self.pg0.remote_hosts[1]
4635 server_out_port = 8765
4636 server_nat_ip = "10.0.0.11"
4638 self.nat44_add_address(self.nat_addr)
4639 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4640 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
4643 # add static mapping for server
4644 self.nat44_add_static_mapping(server.ip4, server_nat_ip)
4647 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
4648 IP(src=host.ip4, dst=server_nat_ip) /
4649 TCP(sport=host_in_port, dport=server_out_port))
4650 self.pg0.add_stream(p)
4651 self.pg_enable_capture(self.pg_interfaces)
4653 self.pg0.get_capture(1)
4655 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
4656 IP(src=host.ip4, dst=server_nat_ip) /
4658 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4659 TCP(sport=1234, dport=1234))
4660 self.pg0.add_stream(p)
4661 self.pg_enable_capture(self.pg_interfaces)
4663 p = self.pg0.get_capture(1)
4666 self.assertEqual(packet[IP].src, self.nat_addr)
4667 self.assertEqual(packet[IP].dst, server.ip4)
4668 self.assertEqual(packet.haslayer(GRE), 1)
4669 self.assert_packet_checksums_valid(packet)
4671 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4675 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
4676 IP(src=server.ip4, dst=self.nat_addr) /
4678 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
4679 TCP(sport=1234, dport=1234))
4680 self.pg0.add_stream(p)
4681 self.pg_enable_capture(self.pg_interfaces)
4683 p = self.pg0.get_capture(1)
4686 self.assertEqual(packet[IP].src, server_nat_ip)
4687 self.assertEqual(packet[IP].dst, host.ip4)
4688 self.assertEqual(packet.haslayer(GRE), 1)
4689 self.assert_packet_checksums_valid(packet)
4691 self.logger.error(ppp("Unexpected or invalid packet:", packet))
4694 def test_output_feature_and_service(self):
4695 """ NAT44 interface output feature and services """
4696 external_addr = '1.2.3.4'
4700 self.vapi.nat44_forwarding_enable_disable(1)
4701 self.nat44_add_address(self.nat_addr)
4702 self.vapi.nat44_add_del_identity_mapping(ip=self.pg1.remote_ip4n)
4703 self.nat44_add_static_mapping(self.pg0.remote_ip4, external_addr,
4704 local_port, external_port,
4705 proto=IP_PROTOS.tcp, out2in_only=1)
4706 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4707 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4709 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4712 # from client to service
4713 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4714 IP(src=self.pg1.remote_ip4, dst=external_addr) /
4715 TCP(sport=12345, dport=external_port))
4716 self.pg1.add_stream(p)
4717 self.pg_enable_capture(self.pg_interfaces)
4719 capture = self.pg0.get_capture(1)
4724 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4725 self.assertEqual(tcp.dport, local_port)
4726 self.assert_packet_checksums_valid(p)
4728 self.logger.error(ppp("Unexpected or invalid packet:", p))
4731 # from service back to client
4732 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4733 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4734 TCP(sport=local_port, dport=12345))
4735 self.pg0.add_stream(p)
4736 self.pg_enable_capture(self.pg_interfaces)
4738 capture = self.pg1.get_capture(1)
4743 self.assertEqual(ip.src, external_addr)
4744 self.assertEqual(tcp.sport, external_port)
4745 self.assert_packet_checksums_valid(p)
4747 self.logger.error(ppp("Unexpected or invalid packet:", p))
4750 # from local network host to external network
4751 pkts = self.create_stream_in(self.pg0, self.pg1)
4752 self.pg0.add_stream(pkts)
4753 self.pg_enable_capture(self.pg_interfaces)
4755 capture = self.pg1.get_capture(len(pkts))
4756 self.verify_capture_out(capture)
4757 pkts = self.create_stream_in(self.pg0, self.pg1)
4758 self.pg0.add_stream(pkts)
4759 self.pg_enable_capture(self.pg_interfaces)
4761 capture = self.pg1.get_capture(len(pkts))
4762 self.verify_capture_out(capture)
4764 # from external network back to local network host
4765 pkts = self.create_stream_out(self.pg1)
4766 self.pg1.add_stream(pkts)
4767 self.pg_enable_capture(self.pg_interfaces)
4769 capture = self.pg0.get_capture(len(pkts))
4770 self.verify_capture_in(capture, self.pg0)
4772 def test_output_feature_and_service2(self):
4773 """ NAT44 interface output feature and service host direct access """
4774 self.vapi.nat44_forwarding_enable_disable(1)
4775 self.nat44_add_address(self.nat_addr)
4776 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4779 # session initiaded from service host - translate
4780 pkts = self.create_stream_in(self.pg0, self.pg1)
4781 self.pg0.add_stream(pkts)
4782 self.pg_enable_capture(self.pg_interfaces)
4784 capture = self.pg1.get_capture(len(pkts))
4785 self.verify_capture_out(capture)
4787 pkts = self.create_stream_out(self.pg1)
4788 self.pg1.add_stream(pkts)
4789 self.pg_enable_capture(self.pg_interfaces)
4791 capture = self.pg0.get_capture(len(pkts))
4792 self.verify_capture_in(capture, self.pg0)
4794 # session initiaded from remote host - do not translate
4795 self.tcp_port_in = 60303
4796 self.udp_port_in = 60304
4797 self.icmp_id_in = 60305
4798 pkts = self.create_stream_out(self.pg1,
4799 self.pg0.remote_ip4,
4800 use_inside_ports=True)
4801 self.pg1.add_stream(pkts)
4802 self.pg_enable_capture(self.pg_interfaces)
4804 capture = self.pg0.get_capture(len(pkts))
4805 self.verify_capture_in(capture, self.pg0)
4807 pkts = self.create_stream_in(self.pg0, self.pg1)
4808 self.pg0.add_stream(pkts)
4809 self.pg_enable_capture(self.pg_interfaces)
4811 capture = self.pg1.get_capture(len(pkts))
4812 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
4815 def test_output_feature_and_service3(self):
4816 """ NAT44 interface output feature and DST NAT """
4817 external_addr = '1.2.3.4'
4821 self.vapi.nat44_forwarding_enable_disable(1)
4822 self.nat44_add_address(self.nat_addr)
4823 self.nat44_add_static_mapping(self.pg1.remote_ip4, external_addr,
4824 local_port, external_port,
4825 proto=IP_PROTOS.tcp, out2in_only=1)
4826 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
4827 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
4829 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
4832 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4833 IP(src=self.pg0.remote_ip4, dst=external_addr) /
4834 TCP(sport=12345, dport=external_port))
4835 self.pg0.add_stream(p)
4836 self.pg_enable_capture(self.pg_interfaces)
4838 capture = self.pg1.get_capture(1)
4843 self.assertEqual(ip.src, self.pg0.remote_ip4)
4844 self.assertEqual(tcp.sport, 12345)
4845 self.assertEqual(ip.dst, self.pg1.remote_ip4)
4846 self.assertEqual(tcp.dport, local_port)
4847 self.assert_packet_checksums_valid(p)
4849 self.logger.error(ppp("Unexpected or invalid packet:", p))
4852 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4853 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
4854 TCP(sport=local_port, dport=12345))
4855 self.pg1.add_stream(p)
4856 self.pg_enable_capture(self.pg_interfaces)
4858 capture = self.pg0.get_capture(1)
4863 self.assertEqual(ip.src, external_addr)
4864 self.assertEqual(tcp.sport, external_port)
4865 self.assertEqual(ip.dst, self.pg0.remote_ip4)
4866 self.assertEqual(tcp.dport, 12345)
4867 self.assert_packet_checksums_valid(p)
4869 self.logger.error(ppp("Unexpected or invalid packet:", p))
4872 def test_next_src_nat(self):
4873 """ On way back forward packet to nat44-in2out node. """
4874 twice_nat_addr = '10.0.1.3'
4877 post_twice_nat_port = 0
4879 self.vapi.nat44_forwarding_enable_disable(1)
4880 self.nat44_add_address(twice_nat_addr, twice_nat=1)
4881 self.nat44_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
4882 local_port, external_port,
4883 proto=IP_PROTOS.tcp, out2in_only=1,
4884 self_twice_nat=1, vrf_id=1)
4885 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
4888 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4889 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
4890 TCP(sport=12345, dport=external_port))
4891 self.pg6.add_stream(p)
4892 self.pg_enable_capture(self.pg_interfaces)
4894 capture = self.pg6.get_capture(1)
4899 self.assertEqual(ip.src, twice_nat_addr)
4900 self.assertNotEqual(tcp.sport, 12345)
4901 post_twice_nat_port = tcp.sport
4902 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4903 self.assertEqual(tcp.dport, local_port)
4904 self.assert_packet_checksums_valid(p)
4906 self.logger.error(ppp("Unexpected or invalid packet:", p))
4909 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
4910 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
4911 TCP(sport=local_port, dport=post_twice_nat_port))
4912 self.pg6.add_stream(p)
4913 self.pg_enable_capture(self.pg_interfaces)
4915 capture = self.pg6.get_capture(1)
4920 self.assertEqual(ip.src, self.pg1.remote_ip4)
4921 self.assertEqual(tcp.sport, external_port)
4922 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4923 self.assertEqual(tcp.dport, 12345)
4924 self.assert_packet_checksums_valid(p)
4926 self.logger.error(ppp("Unexpected or invalid packet:", p))
4929 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
4931 twice_nat_addr = '10.0.1.3'
4939 port_in1 = port_in+1
4940 port_in2 = port_in+2
4945 server1 = self.pg0.remote_hosts[0]
4946 server2 = self.pg0.remote_hosts[1]
4958 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
4961 self.nat44_add_address(self.nat_addr)
4962 self.nat44_add_address(twice_nat_addr, twice_nat=1)
4964 self.nat44_add_static_mapping(pg0.remote_ip4, self.nat_addr,
4966 proto=IP_PROTOS.tcp,
4967 twice_nat=int(not self_twice_nat),
4968 self_twice_nat=int(self_twice_nat))
4970 locals = [{'addr': server1.ip4n,
4974 {'addr': server2.ip4n,
4978 out_addr_n = socket.inet_pton(socket.AF_INET, self.nat_addr)
4979 self.vapi.nat44_add_del_lb_static_mapping(out_addr_n,
4983 not self_twice_nat),
4986 local_num=len(locals),
4988 self.vapi.nat44_interface_add_del_feature(pg0.sw_if_index)
4989 self.vapi.nat44_interface_add_del_feature(pg1.sw_if_index,
4996 assert client_id is not None
4998 client = self.pg0.remote_hosts[0]
4999 elif client_id == 2:
5000 client = self.pg0.remote_hosts[1]
5002 client = pg1.remote_hosts[0]
5003 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
5004 IP(src=client.ip4, dst=self.nat_addr) /
5005 TCP(sport=eh_port_out, dport=port_out))
5007 self.pg_enable_capture(self.pg_interfaces)
5009 capture = pg0.get_capture(1)
5015 if ip.dst == server1.ip4:
5021 self.assertEqual(ip.dst, server.ip4)
5023 self.assertIn(tcp.dport, [port_in1, port_in2])
5025 self.assertEqual(tcp.dport, port_in)
5027 self.assertEqual(ip.src, twice_nat_addr)
5028 self.assertNotEqual(tcp.sport, eh_port_out)
5030 self.assertEqual(ip.src, client.ip4)
5031 self.assertEqual(tcp.sport, eh_port_out)
5033 eh_port_in = tcp.sport
5034 saved_port_in = tcp.dport
5035 self.assert_packet_checksums_valid(p)
5037 self.logger.error(ppp("Unexpected or invalid packet:", p))
5040 p = (Ether(src=server.mac, dst=pg0.local_mac) /
5041 IP(src=server.ip4, dst=eh_addr_in) /
5042 TCP(sport=saved_port_in, dport=eh_port_in))
5044 self.pg_enable_capture(self.pg_interfaces)
5046 capture = pg1.get_capture(1)
5051 self.assertEqual(ip.dst, client.ip4)
5052 self.assertEqual(ip.src, self.nat_addr)
5053 self.assertEqual(tcp.dport, eh_port_out)
5054 self.assertEqual(tcp.sport, port_out)
5055 self.assert_packet_checksums_valid(p)
5057 self.logger.error(ppp("Unexpected or invalid packet:", p))
5061 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5062 self.assertEqual(len(sessions), 1)
5063 self.assertTrue(sessions[0].ext_host_valid)
5064 self.assertTrue(sessions[0].is_twicenat)
5065 self.vapi.nat44_del_session(
5066 sessions[0].inside_ip_address,
5067 sessions[0].inside_port,
5068 sessions[0].protocol,
5069 ext_host_address=sessions[0].ext_host_nat_address,
5070 ext_host_port=sessions[0].ext_host_nat_port)
5071 sessions = self.vapi.nat44_user_session_dump(server.ip4n, 0)
5072 self.assertEqual(len(sessions), 0)
5074 def test_twice_nat(self):
5076 self.twice_nat_common()
5078 def test_self_twice_nat_positive(self):
5079 """ Self Twice NAT44 (positive test) """
5080 self.twice_nat_common(self_twice_nat=True, same_pg=True)
5082 def test_self_twice_nat_negative(self):
5083 """ Self Twice NAT44 (negative test) """
5084 self.twice_nat_common(self_twice_nat=True)
5086 def test_twice_nat_lb(self):
5087 """ Twice NAT44 local service load balancing """
5088 self.twice_nat_common(lb=True)
5090 def test_self_twice_nat_lb_positive(self):
5091 """ Self Twice NAT44 local service load balancing (positive test) """
5092 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5095 def test_self_twice_nat_lb_negative(self):
5096 """ Self Twice NAT44 local service load balancing (negative test) """
5097 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
5100 def test_twice_nat_interface_addr(self):
5101 """ Acquire twice NAT44 addresses from interface """
5102 self.vapi.nat44_add_interface_addr(self.pg3.sw_if_index, twice_nat=1)
5104 # no address in NAT pool
5105 adresses = self.vapi.nat44_address_dump()
5106 self.assertEqual(0, len(adresses))
5108 # configure interface address and check NAT address pool
5109 self.pg3.config_ip4()
5110 adresses = self.vapi.nat44_address_dump()
5111 self.assertEqual(1, len(adresses))
5112 self.assertEqual(adresses[0].ip_address[0:4], self.pg3.local_ip4n)
5113 self.assertEqual(adresses[0].twice_nat, 1)
5115 # remove interface address and check NAT address pool
5116 self.pg3.unconfig_ip4()
5117 adresses = self.vapi.nat44_address_dump()
5118 self.assertEqual(0, len(adresses))
5120 def test_tcp_close(self):
5121 """ Close TCP session from inside network - output feature """
5122 self.vapi.nat44_forwarding_enable_disable(1)
5123 self.nat44_add_address(self.pg1.local_ip4)
5124 twice_nat_addr = '10.0.1.3'
5125 service_ip = '192.168.16.150'
5126 self.nat44_add_address(twice_nat_addr, twice_nat=1)
5127 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5128 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5130 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5132 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5136 proto=IP_PROTOS.tcp,
5139 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5140 start_sessnum = len(sessions)
5142 # SYN packet out->in
5143 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5144 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5145 TCP(sport=33898, dport=80, flags="S"))
5146 self.pg1.add_stream(p)
5147 self.pg_enable_capture(self.pg_interfaces)
5149 capture = self.pg0.get_capture(1)
5151 tcp_port = p[TCP].sport
5153 # SYN + ACK packet in->out
5154 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5155 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5156 TCP(sport=80, dport=tcp_port, flags="SA"))
5157 self.pg0.add_stream(p)
5158 self.pg_enable_capture(self.pg_interfaces)
5160 self.pg1.get_capture(1)
5162 # ACK packet out->in
5163 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5164 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5165 TCP(sport=33898, dport=80, flags="A"))
5166 self.pg1.add_stream(p)
5167 self.pg_enable_capture(self.pg_interfaces)
5169 self.pg0.get_capture(1)
5171 # FIN packet in -> out
5172 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5173 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5174 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
5175 self.pg0.add_stream(p)
5176 self.pg_enable_capture(self.pg_interfaces)
5178 self.pg1.get_capture(1)
5180 # FIN+ACK packet out -> in
5181 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5182 IP(src=self.pg1.remote_ip4, dst=service_ip) /
5183 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
5184 self.pg1.add_stream(p)
5185 self.pg_enable_capture(self.pg_interfaces)
5187 self.pg0.get_capture(1)
5189 # ACK packet in -> out
5190 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5191 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
5192 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
5193 self.pg0.add_stream(p)
5194 self.pg_enable_capture(self.pg_interfaces)
5196 self.pg1.get_capture(1)
5198 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5200 self.assertEqual(len(sessions) - start_sessnum, 0)
5202 def test_tcp_session_close_in(self):
5203 """ Close TCP session from inside network """
5204 self.tcp_port_out = 10505
5205 self.nat44_add_address(self.nat_addr)
5206 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5210 proto=IP_PROTOS.tcp,
5212 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5213 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5216 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5217 start_sessnum = len(sessions)
5219 self.initiate_tcp_session(self.pg0, self.pg1)
5221 # FIN packet in -> out
5222 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5223 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5224 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5225 flags="FA", seq=100, ack=300))
5226 self.pg0.add_stream(p)
5227 self.pg_enable_capture(self.pg_interfaces)
5229 self.pg1.get_capture(1)
5233 # ACK packet out -> in
5234 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5235 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5236 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5237 flags="A", seq=300, ack=101))
5240 # FIN packet out -> in
5241 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5242 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5243 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5244 flags="FA", seq=300, ack=101))
5247 self.pg1.add_stream(pkts)
5248 self.pg_enable_capture(self.pg_interfaces)
5250 self.pg0.get_capture(2)
5252 # ACK packet in -> out
5253 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5254 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5255 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5256 flags="A", seq=101, ack=301))
5257 self.pg0.add_stream(p)
5258 self.pg_enable_capture(self.pg_interfaces)
5260 self.pg1.get_capture(1)
5262 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5264 self.assertEqual(len(sessions) - start_sessnum, 0)
5266 def test_tcp_session_close_out(self):
5267 """ Close TCP session from outside network """
5268 self.tcp_port_out = 10505
5269 self.nat44_add_address(self.nat_addr)
5270 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5274 proto=IP_PROTOS.tcp,
5276 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5277 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5280 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5281 start_sessnum = len(sessions)
5283 self.initiate_tcp_session(self.pg0, self.pg1)
5285 # FIN packet out -> in
5286 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5287 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5288 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5289 flags="FA", seq=100, ack=300))
5290 self.pg1.add_stream(p)
5291 self.pg_enable_capture(self.pg_interfaces)
5293 self.pg0.get_capture(1)
5295 # FIN+ACK packet in -> out
5296 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5297 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5298 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5299 flags="FA", seq=300, ack=101))
5301 self.pg0.add_stream(p)
5302 self.pg_enable_capture(self.pg_interfaces)
5304 self.pg1.get_capture(1)
5306 # ACK packet out -> in
5307 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5308 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5309 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5310 flags="A", seq=101, ack=301))
5311 self.pg1.add_stream(p)
5312 self.pg_enable_capture(self.pg_interfaces)
5314 self.pg0.get_capture(1)
5316 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5318 self.assertEqual(len(sessions) - start_sessnum, 0)
5320 def test_tcp_session_close_simultaneous(self):
5321 """ Close TCP session from inside network """
5322 self.tcp_port_out = 10505
5323 self.nat44_add_address(self.nat_addr)
5324 self.nat44_add_static_mapping(self.pg0.remote_ip4,
5328 proto=IP_PROTOS.tcp,
5330 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5331 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5334 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
5335 start_sessnum = len(sessions)
5337 self.initiate_tcp_session(self.pg0, self.pg1)
5339 # FIN packet in -> out
5340 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5341 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5342 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5343 flags="FA", seq=100, ack=300))
5344 self.pg0.add_stream(p)
5345 self.pg_enable_capture(self.pg_interfaces)
5347 self.pg1.get_capture(1)
5349 # FIN packet out -> in
5350 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5351 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5352 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5353 flags="FA", seq=300, ack=100))
5354 self.pg1.add_stream(p)
5355 self.pg_enable_capture(self.pg_interfaces)
5357 self.pg0.get_capture(1)
5359 # ACK packet in -> out
5360 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5361 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5362 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5363 flags="A", seq=101, ack=301))
5364 self.pg0.add_stream(p)
5365 self.pg_enable_capture(self.pg_interfaces)
5367 self.pg1.get_capture(1)
5369 # ACK packet out -> in
5370 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5371 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5372 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
5373 flags="A", seq=301, ack=101))
5374 self.pg1.add_stream(p)
5375 self.pg_enable_capture(self.pg_interfaces)
5377 self.pg0.get_capture(1)
5379 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
5381 self.assertEqual(len(sessions) - start_sessnum, 0)
5383 def test_one_armed_nat44_static(self):
5384 """ One armed NAT44 and 1:1 NAPT asymmetrical rule """
5385 remote_host = self.pg4.remote_hosts[0]
5386 local_host = self.pg4.remote_hosts[1]
5391 self.vapi.nat44_forwarding_enable_disable(1)
5392 self.nat44_add_address(self.nat_addr, twice_nat=1)
5393 self.nat44_add_static_mapping(local_host.ip4, self.nat_addr,
5394 local_port, external_port,
5395 proto=IP_PROTOS.tcp, out2in_only=1,
5397 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index)
5398 self.vapi.nat44_interface_add_del_feature(self.pg4.sw_if_index,
5401 # from client to service
5402 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5403 IP(src=remote_host.ip4, dst=self.nat_addr) /
5404 TCP(sport=12345, dport=external_port))
5405 self.pg4.add_stream(p)
5406 self.pg_enable_capture(self.pg_interfaces)
5408 capture = self.pg4.get_capture(1)
5413 self.assertEqual(ip.dst, local_host.ip4)
5414 self.assertEqual(ip.src, self.nat_addr)
5415 self.assertEqual(tcp.dport, local_port)
5416 self.assertNotEqual(tcp.sport, 12345)
5417 eh_port_in = tcp.sport
5418 self.assert_packet_checksums_valid(p)
5420 self.logger.error(ppp("Unexpected or invalid packet:", p))
5423 # from service back to client
5424 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
5425 IP(src=local_host.ip4, dst=self.nat_addr) /
5426 TCP(sport=local_port, dport=eh_port_in))
5427 self.pg4.add_stream(p)
5428 self.pg_enable_capture(self.pg_interfaces)
5430 capture = self.pg4.get_capture(1)
5435 self.assertEqual(ip.src, self.nat_addr)
5436 self.assertEqual(ip.dst, remote_host.ip4)
5437 self.assertEqual(tcp.sport, external_port)
5438 self.assertEqual(tcp.dport, 12345)
5439 self.assert_packet_checksums_valid(p)
5441 self.logger.error(ppp("Unexpected or invalid packet:", p))
5444 def test_static_with_port_out2(self):
5445 """ 1:1 NAPT asymmetrical rule """
5450 self.vapi.nat44_forwarding_enable_disable(1)
5451 self.nat44_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
5452 local_port, external_port,
5453 proto=IP_PROTOS.tcp, out2in_only=1)
5454 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5455 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5458 # from client to service
5459 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5460 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5461 TCP(sport=12345, dport=external_port))
5462 self.pg1.add_stream(p)
5463 self.pg_enable_capture(self.pg_interfaces)
5465 capture = self.pg0.get_capture(1)
5470 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5471 self.assertEqual(tcp.dport, local_port)
5472 self.assert_packet_checksums_valid(p)
5474 self.logger.error(ppp("Unexpected or invalid packet:", p))
5478 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5479 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5480 ICMP(type=11) / capture[0][IP])
5481 self.pg0.add_stream(p)
5482 self.pg_enable_capture(self.pg_interfaces)
5484 capture = self.pg1.get_capture(1)
5487 self.assertEqual(p[IP].src, self.nat_addr)
5489 self.assertEqual(inner.dst, self.nat_addr)
5490 self.assertEqual(inner[TCPerror].dport, external_port)
5492 self.logger.error(ppp("Unexpected or invalid packet:", p))
5495 # from service back to client
5496 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5497 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5498 TCP(sport=local_port, dport=12345))
5499 self.pg0.add_stream(p)
5500 self.pg_enable_capture(self.pg_interfaces)
5502 capture = self.pg1.get_capture(1)
5507 self.assertEqual(ip.src, self.nat_addr)
5508 self.assertEqual(tcp.sport, external_port)
5509 self.assert_packet_checksums_valid(p)
5511 self.logger.error(ppp("Unexpected or invalid packet:", p))
5515 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
5516 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5517 ICMP(type=11) / capture[0][IP])
5518 self.pg1.add_stream(p)
5519 self.pg_enable_capture(self.pg_interfaces)
5521 capture = self.pg0.get_capture(1)
5524 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
5526 self.assertEqual(inner.src, self.pg0.remote_ip4)
5527 self.assertEqual(inner[TCPerror].sport, local_port)
5529 self.logger.error(ppp("Unexpected or invalid packet:", p))
5532 # from client to server (no translation)
5533 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5534 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
5535 TCP(sport=12346, dport=local_port))
5536 self.pg1.add_stream(p)
5537 self.pg_enable_capture(self.pg_interfaces)
5539 capture = self.pg0.get_capture(1)
5544 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5545 self.assertEqual(tcp.dport, local_port)
5546 self.assert_packet_checksums_valid(p)
5548 self.logger.error(ppp("Unexpected or invalid packet:", p))
5551 # from service back to client (no translation)
5552 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5553 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5554 TCP(sport=local_port, dport=12346))
5555 self.pg0.add_stream(p)
5556 self.pg_enable_capture(self.pg_interfaces)
5558 capture = self.pg1.get_capture(1)
5563 self.assertEqual(ip.src, self.pg0.remote_ip4)
5564 self.assertEqual(tcp.sport, local_port)
5565 self.assert_packet_checksums_valid(p)
5567 self.logger.error(ppp("Unexpected or invalid packet:", p))
5570 def test_output_feature(self):
5571 """ NAT44 interface output feature (in2out postrouting) """
5572 self.vapi.nat44_forwarding_enable_disable(1)
5573 self.nat44_add_address(self.nat_addr)
5574 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5576 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5580 pkts = self.create_stream_in(self.pg0, self.pg1)
5581 self.pg0.add_stream(pkts)
5582 self.pg_enable_capture(self.pg_interfaces)
5584 capture = self.pg1.get_capture(len(pkts))
5585 self.verify_capture_out(capture)
5588 pkts = self.create_stream_out(self.pg1)
5589 self.pg1.add_stream(pkts)
5590 self.pg_enable_capture(self.pg_interfaces)
5592 capture = self.pg0.get_capture(len(pkts))
5593 self.verify_capture_in(capture, self.pg0)
5595 def test_multiple_vrf(self):
5596 """ Multiple VRF setup """
5597 external_addr = '1.2.3.4'
5602 self.vapi.nat44_forwarding_enable_disable(1)
5603 self.nat44_add_address(self.nat_addr)
5604 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5605 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
5607 self.vapi.nat44_interface_add_del_output_feature(self.pg1.sw_if_index,
5609 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index)
5610 self.vapi.nat44_interface_add_del_feature(self.pg5.sw_if_index,
5612 self.vapi.nat44_interface_add_del_feature(self.pg6.sw_if_index,
5614 self.nat44_add_static_mapping(self.pg5.remote_ip4, external_addr,
5615 local_port, external_port, vrf_id=1,
5616 proto=IP_PROTOS.tcp, out2in_only=1)
5617 self.nat44_add_static_mapping(
5618 self.pg0.remote_ip4, external_sw_if_index=self.pg0.sw_if_index,
5619 local_port=local_port, vrf_id=0, external_port=external_port,
5620 proto=IP_PROTOS.tcp, out2in_only=1)
5622 # from client to service (both VRF1)
5623 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5624 IP(src=self.pg6.remote_ip4, dst=external_addr) /
5625 TCP(sport=12345, dport=external_port))
5626 self.pg6.add_stream(p)
5627 self.pg_enable_capture(self.pg_interfaces)
5629 capture = self.pg5.get_capture(1)
5634 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5635 self.assertEqual(tcp.dport, local_port)
5636 self.assert_packet_checksums_valid(p)
5638 self.logger.error(ppp("Unexpected or invalid packet:", p))
5641 # from service back to client (both VRF1)
5642 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5643 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
5644 TCP(sport=local_port, dport=12345))
5645 self.pg5.add_stream(p)
5646 self.pg_enable_capture(self.pg_interfaces)
5648 capture = self.pg6.get_capture(1)
5653 self.assertEqual(ip.src, external_addr)
5654 self.assertEqual(tcp.sport, external_port)
5655 self.assert_packet_checksums_valid(p)
5657 self.logger.error(ppp("Unexpected or invalid packet:", p))
5660 # dynamic NAT from VRF1 to VRF0 (output-feature)
5661 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5662 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
5663 TCP(sport=2345, dport=22))
5664 self.pg5.add_stream(p)
5665 self.pg_enable_capture(self.pg_interfaces)
5667 capture = self.pg1.get_capture(1)
5672 self.assertEqual(ip.src, self.nat_addr)
5673 self.assertNotEqual(tcp.sport, 2345)
5674 self.assert_packet_checksums_valid(p)
5677 self.logger.error(ppp("Unexpected or invalid packet:", p))
5680 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
5681 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
5682 TCP(sport=22, dport=port))
5683 self.pg1.add_stream(p)
5684 self.pg_enable_capture(self.pg_interfaces)
5686 capture = self.pg5.get_capture(1)
5691 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5692 self.assertEqual(tcp.dport, 2345)
5693 self.assert_packet_checksums_valid(p)
5695 self.logger.error(ppp("Unexpected or invalid packet:", p))
5698 # from client VRF1 to service VRF0
5699 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5700 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
5701 TCP(sport=12346, dport=external_port))
5702 self.pg6.add_stream(p)
5703 self.pg_enable_capture(self.pg_interfaces)
5705 capture = self.pg0.get_capture(1)
5710 self.assertEqual(ip.dst, self.pg0.remote_ip4)
5711 self.assertEqual(tcp.dport, local_port)
5712 self.assert_packet_checksums_valid(p)
5714 self.logger.error(ppp("Unexpected or invalid packet:", p))
5717 # from service VRF0 back to client VRF1
5718 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5719 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
5720 TCP(sport=local_port, dport=12346))
5721 self.pg0.add_stream(p)
5722 self.pg_enable_capture(self.pg_interfaces)
5724 capture = self.pg6.get_capture(1)
5729 self.assertEqual(ip.src, self.pg0.local_ip4)
5730 self.assertEqual(tcp.sport, external_port)
5731 self.assert_packet_checksums_valid(p)
5733 self.logger.error(ppp("Unexpected or invalid packet:", p))
5736 # from client VRF0 to service VRF1
5737 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5738 IP(src=self.pg0.remote_ip4, dst=external_addr) /
5739 TCP(sport=12347, dport=external_port))
5740 self.pg0.add_stream(p)
5741 self.pg_enable_capture(self.pg_interfaces)
5743 capture = self.pg5.get_capture(1)
5748 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5749 self.assertEqual(tcp.dport, local_port)
5750 self.assert_packet_checksums_valid(p)
5752 self.logger.error(ppp("Unexpected or invalid packet:", p))
5755 # from service VRF1 back to client VRF0
5756 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5757 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
5758 TCP(sport=local_port, dport=12347))
5759 self.pg5.add_stream(p)
5760 self.pg_enable_capture(self.pg_interfaces)
5762 capture = self.pg0.get_capture(1)
5767 self.assertEqual(ip.src, external_addr)
5768 self.assertEqual(tcp.sport, external_port)
5769 self.assert_packet_checksums_valid(p)
5771 self.logger.error(ppp("Unexpected or invalid packet:", p))
5774 # from client to server (both VRF1, no translation)
5775 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
5776 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
5777 TCP(sport=12348, dport=local_port))
5778 self.pg6.add_stream(p)
5779 self.pg_enable_capture(self.pg_interfaces)
5781 capture = self.pg5.get_capture(1)
5786 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5787 self.assertEqual(tcp.dport, local_port)
5788 self.assert_packet_checksums_valid(p)
5790 self.logger.error(ppp("Unexpected or invalid packet:", p))
5793 # from server back to client (both VRF1, no translation)
5794 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5795 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
5796 TCP(sport=local_port, dport=12348))
5797 self.pg5.add_stream(p)
5798 self.pg_enable_capture(self.pg_interfaces)
5800 capture = self.pg6.get_capture(1)
5805 self.assertEqual(ip.src, self.pg5.remote_ip4)
5806 self.assertEqual(tcp.sport, local_port)
5807 self.assert_packet_checksums_valid(p)
5809 self.logger.error(ppp("Unexpected or invalid packet:", p))
5812 # from client VRF1 to server VRF0 (no translation)
5813 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5814 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
5815 TCP(sport=local_port, dport=12349))
5816 self.pg0.add_stream(p)
5817 self.pg_enable_capture(self.pg_interfaces)
5819 capture = self.pg6.get_capture(1)
5824 self.assertEqual(ip.src, self.pg0.remote_ip4)
5825 self.assertEqual(tcp.sport, local_port)
5826 self.assert_packet_checksums_valid(p)
5828 self.logger.error(ppp("Unexpected or invalid packet:", p))
5831 # from server VRF0 back to client VRF1 (no translation)
5832 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5833 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
5834 TCP(sport=local_port, dport=12349))
5835 self.pg0.add_stream(p)
5836 self.pg_enable_capture(self.pg_interfaces)
5838 capture = self.pg6.get_capture(1)
5843 self.assertEqual(ip.src, self.pg0.remote_ip4)
5844 self.assertEqual(tcp.sport, local_port)
5845 self.assert_packet_checksums_valid(p)
5847 self.logger.error(ppp("Unexpected or invalid packet:", p))
5850 # from client VRF0 to server VRF1 (no translation)
5851 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5852 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
5853 TCP(sport=12344, dport=local_port))
5854 self.pg0.add_stream(p)
5855 self.pg_enable_capture(self.pg_interfaces)
5857 capture = self.pg5.get_capture(1)
5862 self.assertEqual(ip.dst, self.pg5.remote_ip4)
5863 self.assertEqual(tcp.dport, local_port)
5864 self.assert_packet_checksums_valid(p)
5866 self.logger.error(ppp("Unexpected or invalid packet:", p))
5869 # from server VRF1 back to client VRF0 (no translation)
5870 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
5871 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
5872 TCP(sport=local_port, dport=12344))
5873 self.pg5.add_stream(p)
5874 self.pg_enable_capture(self.pg_interfaces)
5876 capture = self.pg0.get_capture(1)
5881 self.assertEqual(ip.src, self.pg5.remote_ip4)
5882 self.assertEqual(tcp.sport, local_port)
5883 self.assert_packet_checksums_valid(p)
5885 self.logger.error(ppp("Unexpected or invalid packet:", p))
5888 @unittest.skipUnless(running_extended_tests, "part of extended tests")
5889 def test_session_timeout(self):
5890 """ NAT44 session timeouts """
5891 self.nat44_add_address(self.nat_addr)
5892 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5893 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5895 self.vapi.nat_set_timeouts(icmp=5)
5899 for i in range(0, max_sessions):
5900 src = "10.10.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
5901 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5902 IP(src=src, dst=self.pg1.remote_ip4) /
5903 ICMP(id=1025, type='echo-request'))
5905 self.pg0.add_stream(pkts)
5906 self.pg_enable_capture(self.pg_interfaces)
5908 self.pg1.get_capture(max_sessions)
5913 for i in range(0, max_sessions):
5914 src = "10.11.%u.%u" % ((i & 0xFF00) >> 8, i & 0xFF)
5915 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
5916 IP(src=src, dst=self.pg1.remote_ip4) /
5917 ICMP(id=1026, type='echo-request'))
5919 self.pg0.add_stream(pkts)
5920 self.pg_enable_capture(self.pg_interfaces)
5922 self.pg1.get_capture(max_sessions)
5925 users = self.vapi.nat44_user_dump()
5927 nsessions = nsessions + user.nsessions
5928 self.assertLess(nsessions, 2 * max_sessions)
5930 @unittest.skipUnless(running_extended_tests, "part of extended tests")
5931 def test_session_rst_timeout(self):
5932 """ NAT44 session RST timeouts """
5933 self.nat44_add_address(self.nat_addr)
5934 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5935 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5937 self.vapi.nat_set_timeouts(tcp_transitory=5)
5939 self.initiate_tcp_session(self.pg0, self.pg1)
5940 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5941 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5942 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
5944 self.pg0.add_stream(p)
5945 self.pg_enable_capture(self.pg_interfaces)
5947 self.pg1.get_capture(1)
5951 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5952 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5953 TCP(sport=self.tcp_port_in + 1, dport=self.tcp_external_port + 1,
5955 self.pg0.add_stream(p)
5956 self.pg_enable_capture(self.pg_interfaces)
5958 self.pg1.get_capture(1)
5961 users = self.vapi.nat44_user_dump()
5962 self.assertEqual(len(users), 1)
5963 self.assertEqual(users[0].ip_address, self.pg0.remote_ip4n)
5964 self.assertEqual(users[0].nsessions, 1)
5966 @unittest.skipUnless(running_extended_tests, "part of extended tests")
5967 def test_session_limit_per_user(self):
5968 """ Maximum sessions per user limit """
5969 self.nat44_add_address(self.nat_addr)
5970 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
5971 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
5973 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
5974 src_address=self.pg2.local_ip4n,
5976 template_interval=10)
5977 self.vapi.nat_set_timeouts(udp=5)
5979 # get maximum number of translations per user
5980 nat44_config = self.vapi.nat_show_config()
5983 for port in range(0, nat44_config.max_translations_per_user):
5984 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5985 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5986 UDP(sport=1025 + port, dport=1025 + port))
5989 self.pg0.add_stream(pkts)
5990 self.pg_enable_capture(self.pg_interfaces)
5992 capture = self.pg1.get_capture(len(pkts))
5994 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
5995 src_port=self.ipfix_src_port)
5997 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
5998 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
5999 UDP(sport=3001, dport=3002))
6000 self.pg0.add_stream(p)
6001 self.pg_enable_capture(self.pg_interfaces)
6003 capture = self.pg1.assert_nothing_captured()
6005 # verify IPFIX logging
6006 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6008 capture = self.pg2.get_capture(10)
6009 ipfix = IPFIXDecoder()
6010 # first load template
6012 self.assertTrue(p.haslayer(IPFIX))
6013 if p.haslayer(Template):
6014 ipfix.add_template(p.getlayer(Template))
6015 # verify events in data set
6017 if p.haslayer(Data):
6018 data = ipfix.decode_data_set(p.getlayer(Set))
6019 self.verify_ipfix_max_entries_per_user(
6021 nat44_config.max_translations_per_user,
6022 self.pg0.remote_ip4n)
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 UDP(sport=3001, dport=3002))
6028 self.pg0.add_stream(p)
6029 self.pg_enable_capture(self.pg_interfaces)
6031 self.pg1.get_capture(1)
6033 def test_syslog_sess(self):
6034 """ Test syslog session creation and deletion """
6035 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
6036 self.vapi.syslog_set_sender(self.pg2.remote_ip4n, self.pg2.local_ip4n)
6037 self.nat44_add_address(self.nat_addr)
6038 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6039 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6042 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
6043 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6044 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6045 self.pg0.add_stream(p)
6046 self.pg_enable_capture(self.pg_interfaces)
6048 capture = self.pg1.get_capture(1)
6049 self.tcp_port_out = capture[0][TCP].sport
6050 capture = self.pg2.get_capture(1)
6051 self.verify_syslog_sess(capture[0][Raw].load)
6053 self.pg_enable_capture(self.pg_interfaces)
6055 self.nat44_add_address(self.nat_addr, is_add=0)
6056 capture = self.pg2.get_capture(1)
6057 self.verify_syslog_sess(capture[0][Raw].load, False)
6060 super(TestNAT44EndpointDependent, self).tearDown()
6061 if not self.vpp_dead:
6062 self.logger.info(self.vapi.cli("show nat44 addresses"))
6063 self.logger.info(self.vapi.cli("show nat44 interfaces"))
6064 self.logger.info(self.vapi.cli("show nat44 static mappings"))
6065 self.logger.info(self.vapi.cli("show nat44 interface address"))
6066 self.logger.info(self.vapi.cli("show nat44 sessions detail"))
6067 self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
6068 self.logger.info(self.vapi.cli("show nat timeouts"))
6070 self.vapi.cli("clear logging")
6073 class TestNAT44Out2InDPO(MethodHolder):
6074 """ NAT44 Test Cases using out2in DPO """
6077 def setUpConstants(cls):
6078 super(TestNAT44Out2InDPO, cls).setUpConstants()
6079 cls.vpp_cmdline.extend(["nat", "{", "out2in dpo", "}"])
6082 def setUpClass(cls):
6083 super(TestNAT44Out2InDPO, cls).setUpClass()
6084 cls.vapi.cli("set log class nat level debug")
6087 cls.tcp_port_in = 6303
6088 cls.tcp_port_out = 6303
6089 cls.udp_port_in = 6304
6090 cls.udp_port_out = 6304
6091 cls.icmp_id_in = 6305
6092 cls.icmp_id_out = 6305
6093 cls.nat_addr = '10.0.0.3'
6094 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
6095 cls.dst_ip4 = '192.168.70.1'
6097 cls.create_pg_interfaces(range(2))
6100 cls.pg0.config_ip4()
6101 cls.pg0.resolve_arp()
6104 cls.pg1.config_ip6()
6105 cls.pg1.resolve_ndp()
6107 cls.vapi.ip_add_del_route(is_ipv6=True, dst_address='\x00'*16,
6108 dst_address_length=0,
6109 next_hop_address=cls.pg1.remote_ip6n,
6110 next_hop_sw_if_index=cls.pg1.sw_if_index)
6113 super(TestNAT44Out2InDPO, cls).tearDownClass()
6116 def configure_xlat(self):
6117 self.dst_ip6_pfx = '1:2:3::'
6118 self.dst_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6120 self.dst_ip6_pfx_len = 96
6121 self.src_ip6_pfx = '4:5:6::'
6122 self.src_ip6_pfx_n = socket.inet_pton(socket.AF_INET6,
6124 self.src_ip6_pfx_len = 96
6125 self.vapi.map_add_domain(self.dst_ip6_pfx_n, self.dst_ip6_pfx_len,
6126 self.src_ip6_pfx_n, self.src_ip6_pfx_len,
6127 '\x00\x00\x00\x00', 0)
6129 @unittest.skip('Temporary disabled')
6130 def test_464xlat_ce(self):
6131 """ Test 464XLAT CE with NAT44 """
6133 nat_config = self.vapi.nat_show_config()
6134 self.assertEqual(1, nat_config.out2in_dpo)
6136 self.configure_xlat()
6138 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6139 self.vapi.nat44_add_del_address_range(self.nat_addr_n, self.nat_addr_n)
6141 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6142 self.dst_ip6_pfx_len)
6143 out_dst_ip6 = self.compose_ip6(self.nat_addr, self.src_ip6_pfx,
6144 self.src_ip6_pfx_len)
6147 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6148 self.pg0.add_stream(pkts)
6149 self.pg_enable_capture(self.pg_interfaces)
6151 capture = self.pg1.get_capture(len(pkts))
6152 self.verify_capture_out_ip6(capture, nat_ip=out_dst_ip6,
6155 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6,
6157 self.pg1.add_stream(pkts)
6158 self.pg_enable_capture(self.pg_interfaces)
6160 capture = self.pg0.get_capture(len(pkts))
6161 self.verify_capture_in(capture, self.pg0)
6163 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index,
6165 self.vapi.nat44_add_del_address_range(self.nat_addr_n,
6166 self.nat_addr_n, is_add=0)
6168 @unittest.skip('Temporary disabled')
6169 def test_464xlat_ce_no_nat(self):
6170 """ Test 464XLAT CE without NAT44 """
6172 self.configure_xlat()
6174 out_src_ip6 = self.compose_ip6(self.dst_ip4, self.dst_ip6_pfx,
6175 self.dst_ip6_pfx_len)
6176 out_dst_ip6 = self.compose_ip6(self.pg0.remote_ip4, self.src_ip6_pfx,
6177 self.src_ip6_pfx_len)
6179 pkts = self.create_stream_in(self.pg0, self.pg1, self.dst_ip4)
6180 self.pg0.add_stream(pkts)
6181 self.pg_enable_capture(self.pg_interfaces)
6183 capture = self.pg1.get_capture(len(pkts))
6184 self.verify_capture_out_ip6(capture, dst_ip=out_src_ip6,
6185 nat_ip=out_dst_ip6, same_port=True)
6187 pkts = self.create_stream_out_ip6(self.pg1, out_src_ip6, out_dst_ip6)
6188 self.pg1.add_stream(pkts)
6189 self.pg_enable_capture(self.pg_interfaces)
6191 capture = self.pg0.get_capture(len(pkts))
6192 self.verify_capture_in(capture, self.pg0)
6195 class TestDeterministicNAT(MethodHolder):
6196 """ Deterministic NAT Test Cases """
6199 def setUpConstants(cls):
6200 super(TestDeterministicNAT, cls).setUpConstants()
6201 cls.vpp_cmdline.extend(["nat", "{", "deterministic", "}"])
6204 def setUpClass(cls):
6205 super(TestDeterministicNAT, cls).setUpClass()
6206 cls.vapi.cli("set log class nat level debug")
6209 cls.tcp_port_in = 6303
6210 cls.tcp_external_port = 6303
6211 cls.udp_port_in = 6304
6212 cls.udp_external_port = 6304
6213 cls.icmp_id_in = 6305
6214 cls.nat_addr = '10.0.0.3'
6216 cls.create_pg_interfaces(range(3))
6217 cls.interfaces = list(cls.pg_interfaces)
6219 for i in cls.interfaces:
6224 cls.pg0.generate_remote_hosts(2)
6225 cls.pg0.configure_ipv4_neighbors()
6228 super(TestDeterministicNAT, cls).tearDownClass()
6231 def create_stream_in(self, in_if, out_if, ttl=64):
6233 Create packet stream for inside network
6235 :param in_if: Inside interface
6236 :param out_if: Outside interface
6237 :param ttl: TTL of generated packets
6241 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6242 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
6243 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
6247 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6248 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
6249 UDP(sport=self.udp_port_in, dport=self.udp_external_port))
6253 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
6254 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=ttl) /
6255 ICMP(id=self.icmp_id_in, type='echo-request'))
6260 def create_stream_out(self, out_if, dst_ip=None, ttl=64):
6262 Create packet stream for outside network
6264 :param out_if: Outside interface
6265 :param dst_ip: Destination IP address (Default use global NAT address)
6266 :param ttl: TTL of generated packets
6269 dst_ip = self.nat_addr
6272 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6273 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
6274 TCP(dport=self.tcp_port_out, sport=self.tcp_external_port))
6278 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6279 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
6280 UDP(dport=self.udp_port_out, sport=self.udp_external_port))
6284 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
6285 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
6286 ICMP(id=self.icmp_external_id, type='echo-reply'))
6291 def verify_capture_out(self, capture, nat_ip=None):
6293 Verify captured packets on outside network
6295 :param capture: Captured packets
6296 :param nat_ip: Translated IP address (Default use global NAT address)
6297 :param same_port: Sorce port number is not translated (Default False)
6300 nat_ip = self.nat_addr
6301 for packet in capture:
6303 self.assertEqual(packet[IP].src, nat_ip)
6304 if packet.haslayer(TCP):
6305 self.tcp_port_out = packet[TCP].sport
6306 elif packet.haslayer(UDP):
6307 self.udp_port_out = packet[UDP].sport
6309 self.icmp_external_id = packet[ICMP].id
6311 self.logger.error(ppp("Unexpected or invalid packet "
6312 "(outside network):", packet))
6315 def test_deterministic_mode(self):
6316 """ NAT plugin run deterministic mode """
6317 in_addr = '172.16.255.0'
6318 out_addr = '172.17.255.50'
6319 in_addr_t = '172.16.255.20'
6320 in_addr_n = socket.inet_aton(in_addr)
6321 out_addr_n = socket.inet_aton(out_addr)
6322 in_addr_t_n = socket.inet_aton(in_addr_t)
6326 nat_config = self.vapi.nat_show_config()
6327 self.assertEqual(1, nat_config.deterministic)
6329 self.vapi.nat_det_add_del_map(in_addr_n, in_plen, out_addr_n, out_plen)
6331 rep1 = self.vapi.nat_det_forward(in_addr_t_n)
6332 self.assertEqual(rep1.out_addr[:4], out_addr_n)
6333 rep2 = self.vapi.nat_det_reverse(out_addr_n, rep1.out_port_hi)
6334 self.assertEqual(rep2.in_addr[:4], in_addr_t_n)
6336 deterministic_mappings = self.vapi.nat_det_map_dump()
6337 self.assertEqual(len(deterministic_mappings), 1)
6338 dsm = deterministic_mappings[0]
6339 self.assertEqual(in_addr_n, dsm.in_addr[:4])
6340 self.assertEqual(in_plen, dsm.in_plen)
6341 self.assertEqual(out_addr_n, dsm.out_addr[:4])
6342 self.assertEqual(out_plen, dsm.out_plen)
6344 self.clear_nat_det()
6345 deterministic_mappings = self.vapi.nat_det_map_dump()
6346 self.assertEqual(len(deterministic_mappings), 0)
6348 def test_set_timeouts(self):
6349 """ Set deterministic NAT timeouts """
6350 timeouts_before = self.vapi.nat_get_timeouts()
6352 self.vapi.nat_set_timeouts(timeouts_before.udp + 10,
6353 timeouts_before.tcp_established + 10,
6354 timeouts_before.tcp_transitory + 10,
6355 timeouts_before.icmp + 10)
6357 timeouts_after = self.vapi.nat_get_timeouts()
6359 self.assertNotEqual(timeouts_before.udp, timeouts_after.udp)
6360 self.assertNotEqual(timeouts_before.icmp, timeouts_after.icmp)
6361 self.assertNotEqual(timeouts_before.tcp_established,
6362 timeouts_after.tcp_established)
6363 self.assertNotEqual(timeouts_before.tcp_transitory,
6364 timeouts_after.tcp_transitory)
6366 def test_det_in(self):
6367 """ Deterministic NAT translation test (TCP, UDP, ICMP) """
6369 nat_ip = "10.0.0.10"
6371 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6373 socket.inet_aton(nat_ip),
6375 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6376 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6380 pkts = self.create_stream_in(self.pg0, self.pg1)
6381 self.pg0.add_stream(pkts)
6382 self.pg_enable_capture(self.pg_interfaces)
6384 capture = self.pg1.get_capture(len(pkts))
6385 self.verify_capture_out(capture, nat_ip)
6388 pkts = self.create_stream_out(self.pg1, nat_ip)
6389 self.pg1.add_stream(pkts)
6390 self.pg_enable_capture(self.pg_interfaces)
6392 capture = self.pg0.get_capture(len(pkts))
6393 self.verify_capture_in(capture, self.pg0)
6396 sessions = self.vapi.nat_det_session_dump(self.pg0.remote_ip4n)
6397 self.assertEqual(len(sessions), 3)
6401 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6402 self.assertEqual(s.in_port, self.tcp_port_in)
6403 self.assertEqual(s.out_port, self.tcp_port_out)
6404 self.assertEqual(s.ext_port, self.tcp_external_port)
6408 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6409 self.assertEqual(s.in_port, self.udp_port_in)
6410 self.assertEqual(s.out_port, self.udp_port_out)
6411 self.assertEqual(s.ext_port, self.udp_external_port)
6415 self.assertEqual(s.ext_addr[:4], self.pg1.remote_ip4n)
6416 self.assertEqual(s.in_port, self.icmp_id_in)
6417 self.assertEqual(s.out_port, self.icmp_external_id)
6419 def test_multiple_users(self):
6420 """ Deterministic NAT multiple users """
6422 nat_ip = "10.0.0.10"
6424 external_port = 6303
6426 host0 = self.pg0.remote_hosts[0]
6427 host1 = self.pg0.remote_hosts[1]
6429 self.vapi.nat_det_add_del_map(host0.ip4n,
6431 socket.inet_aton(nat_ip),
6433 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6434 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6438 p = (Ether(src=host0.mac, dst=self.pg0.local_mac) /
6439 IP(src=host0.ip4, dst=self.pg1.remote_ip4) /
6440 TCP(sport=port_in, dport=external_port))
6441 self.pg0.add_stream(p)
6442 self.pg_enable_capture(self.pg_interfaces)
6444 capture = self.pg1.get_capture(1)
6449 self.assertEqual(ip.src, nat_ip)
6450 self.assertEqual(ip.dst, self.pg1.remote_ip4)
6451 self.assertEqual(tcp.dport, external_port)
6452 port_out0 = tcp.sport
6454 self.logger.error(ppp("Unexpected or invalid packet:", p))
6458 p = (Ether(src=host1.mac, dst=self.pg0.local_mac) /
6459 IP(src=host1.ip4, dst=self.pg1.remote_ip4) /
6460 TCP(sport=port_in, dport=external_port))
6461 self.pg0.add_stream(p)
6462 self.pg_enable_capture(self.pg_interfaces)
6464 capture = self.pg1.get_capture(1)
6469 self.assertEqual(ip.src, nat_ip)
6470 self.assertEqual(ip.dst, self.pg1.remote_ip4)
6471 self.assertEqual(tcp.dport, external_port)
6472 port_out1 = tcp.sport
6474 self.logger.error(ppp("Unexpected or invalid packet:", p))
6477 dms = self.vapi.nat_det_map_dump()
6478 self.assertEqual(1, len(dms))
6479 self.assertEqual(2, dms[0].ses_num)
6482 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6483 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
6484 TCP(sport=external_port, dport=port_out0))
6485 self.pg1.add_stream(p)
6486 self.pg_enable_capture(self.pg_interfaces)
6488 capture = self.pg0.get_capture(1)
6493 self.assertEqual(ip.src, self.pg1.remote_ip4)
6494 self.assertEqual(ip.dst, host0.ip4)
6495 self.assertEqual(tcp.dport, port_in)
6496 self.assertEqual(tcp.sport, external_port)
6498 self.logger.error(ppp("Unexpected or invalid packet:", p))
6502 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6503 IP(src=self.pg1.remote_ip4, dst=nat_ip) /
6504 TCP(sport=external_port, dport=port_out1))
6505 self.pg1.add_stream(p)
6506 self.pg_enable_capture(self.pg_interfaces)
6508 capture = self.pg0.get_capture(1)
6513 self.assertEqual(ip.src, self.pg1.remote_ip4)
6514 self.assertEqual(ip.dst, host1.ip4)
6515 self.assertEqual(tcp.dport, port_in)
6516 self.assertEqual(tcp.sport, external_port)
6518 self.logger.error(ppp("Unexpected or invalid packet", p))
6521 # session close api test
6522 self.vapi.nat_det_close_session_out(socket.inet_aton(nat_ip),
6524 self.pg1.remote_ip4n,
6526 dms = self.vapi.nat_det_map_dump()
6527 self.assertEqual(dms[0].ses_num, 1)
6529 self.vapi.nat_det_close_session_in(host0.ip4n,
6531 self.pg1.remote_ip4n,
6533 dms = self.vapi.nat_det_map_dump()
6534 self.assertEqual(dms[0].ses_num, 0)
6536 def test_tcp_session_close_detection_in(self):
6537 """ Deterministic NAT TCP session close from inside network """
6538 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6540 socket.inet_aton(self.nat_addr),
6542 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6543 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6546 self.initiate_tcp_session(self.pg0, self.pg1)
6548 # close the session from inside
6550 # FIN packet in -> out
6551 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6552 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6553 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6555 self.pg0.add_stream(p)
6556 self.pg_enable_capture(self.pg_interfaces)
6558 self.pg1.get_capture(1)
6562 # ACK packet out -> in
6563 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6564 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6565 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6569 # FIN packet out -> in
6570 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6571 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6572 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6576 self.pg1.add_stream(pkts)
6577 self.pg_enable_capture(self.pg_interfaces)
6579 self.pg0.get_capture(2)
6581 # ACK packet in -> out
6582 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6583 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6584 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6586 self.pg0.add_stream(p)
6587 self.pg_enable_capture(self.pg_interfaces)
6589 self.pg1.get_capture(1)
6591 # Check if deterministic NAT44 closed the session
6592 dms = self.vapi.nat_det_map_dump()
6593 self.assertEqual(0, dms[0].ses_num)
6595 self.logger.error("TCP session termination failed")
6598 def test_tcp_session_close_detection_out(self):
6599 """ Deterministic NAT TCP session close from outside network """
6600 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6602 socket.inet_aton(self.nat_addr),
6604 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6605 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6608 self.initiate_tcp_session(self.pg0, self.pg1)
6610 # close the session from outside
6612 # FIN packet out -> in
6613 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6614 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6615 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6617 self.pg1.add_stream(p)
6618 self.pg_enable_capture(self.pg_interfaces)
6620 self.pg0.get_capture(1)
6624 # ACK packet in -> out
6625 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6626 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6627 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6631 # ACK packet in -> out
6632 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6633 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6634 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
6638 self.pg0.add_stream(pkts)
6639 self.pg_enable_capture(self.pg_interfaces)
6641 self.pg1.get_capture(2)
6643 # ACK packet out -> in
6644 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
6645 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
6646 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
6648 self.pg1.add_stream(p)
6649 self.pg_enable_capture(self.pg_interfaces)
6651 self.pg0.get_capture(1)
6653 # Check if deterministic NAT44 closed the session
6654 dms = self.vapi.nat_det_map_dump()
6655 self.assertEqual(0, dms[0].ses_num)
6657 self.logger.error("TCP session termination failed")
6660 @unittest.skipUnless(running_extended_tests, "part of extended tests")
6661 def test_session_timeout(self):
6662 """ Deterministic NAT session timeouts """
6663 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6665 socket.inet_aton(self.nat_addr),
6667 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6668 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6671 self.initiate_tcp_session(self.pg0, self.pg1)
6672 self.vapi.nat_set_timeouts(5, 5, 5, 5)
6673 pkts = self.create_stream_in(self.pg0, self.pg1)
6674 self.pg0.add_stream(pkts)
6675 self.pg_enable_capture(self.pg_interfaces)
6677 capture = self.pg1.get_capture(len(pkts))
6680 dms = self.vapi.nat_det_map_dump()
6681 self.assertEqual(0, dms[0].ses_num)
6683 @unittest.skipUnless(running_extended_tests, "part of extended tests")
6684 def test_session_limit_per_user(self):
6685 """ Deterministic NAT maximum sessions per user limit """
6686 self.vapi.nat_det_add_del_map(self.pg0.remote_ip4n,
6688 socket.inet_aton(self.nat_addr),
6690 self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
6691 self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
6693 self.vapi.set_ipfix_exporter(collector_address=self.pg2.remote_ip4n,
6694 src_address=self.pg2.local_ip4n,
6696 template_interval=10)
6697 self.vapi.nat_ipfix()
6700 for port in range(1025, 2025):
6701 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6702 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6703 UDP(sport=port, dport=port))
6706 self.pg0.add_stream(pkts)
6707 self.pg_enable_capture(self.pg_interfaces)
6709 capture = self.pg1.get_capture(len(pkts))
6711 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
6712 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
6713 UDP(sport=3001, dport=3002))
6714 self.pg0.add_stream(p)
6715 self.pg_enable_capture(self.pg_interfaces)
6717 capture = self.pg1.assert_nothing_captured()
6719 # verify ICMP error packet
6720 capture = self.pg0.get_capture(1)
6722 self.assertTrue(p.haslayer(ICMP))
6724 self.assertEqual(icmp.type, 3)
6725 self.assertEqual(icmp.code, 1)
6726 self.assertTrue(icmp.haslayer(IPerror))
6727 inner_ip = icmp[IPerror]
6728 self.assertEqual(inner_ip[UDPerror].sport, 3001)
6729 self.assertEqual(inner_ip[UDPerror].dport, 3002)
6731 dms = self.vapi.nat_det_map_dump()
6733 self.assertEqual(1000, dms[0].ses_num)
6735 # verify IPFIX logging
6736 self.vapi.cli("ipfix flush") # FIXME this should be an API call
6738 capture = self.pg2.get_capture(2)
6739 ipfix = IPFIXDecoder()
6740 # first load template
6742 self.assertTrue(p.haslayer(IPFIX))
6743 if p.haslayer(Template):
6744 ipfix.add_template(p.getlayer(Template))
6745 # verify events in data set
6747 if p.haslayer(Data):
6748 data = ipfix.decode_data_set(p.getlayer(Set))
6749 self.verify_ipfix_max_entries_per_user(data,
6751 self.pg0.remote_ip4n)
6753 def clear_nat_det(self):
6755 Clear deterministic NAT configuration.
6757 self.vapi.nat_ipfix(enable=0)
6758 self.vapi.nat_set_timeouts()
6759 deterministic_mappings = self.vapi.nat_det_map_dump()
6760 for dsm in deterministic_mappings:
6761 self.vapi.nat_det_add_del_map(dsm.in_addr,
6767 interfaces = self.vapi.nat44_interface_dump()
6768 for intf in interfaces:
6769 self.vapi.nat44_interface_add_del_feature(intf.sw_if_index,
6774 super(TestDeterministicNAT, self).tearDown()
6775 if not self.vpp_dead:
6776 self.logger.info(self.vapi.cli("show nat44 interfaces"))
6777 self.logger.info(self.vapi.cli("show nat timeouts"))
6779 self.vapi.cli("show nat44 deterministic mappings"))
6781 self.vapi.cli("show nat44 deterministic sessions"))
6782 self.clear_nat_det()
6785 class TestNAT64(MethodHolder):
6786 """ NAT64 Test Cases """
6789 def setUpConstants(cls):
6790 super(TestNAT64, cls).setUpConstants()
6791 cls.vpp_cmdline.extend(["nat", "{", "nat64 bib hash buckets 128",
6792 "nat64 st hash buckets 256", "}"])
6795 def setUpClass(cls):
6796 super(TestNAT64, cls).setUpClass()
6799 cls.tcp_port_in = 6303
6800 cls.tcp_port_out = 6303
6801 cls.udp_port_in = 6304
6802 cls.udp_port_out = 6304
6803 cls.icmp_id_in = 6305
6804 cls.icmp_id_out = 6305
6805 cls.tcp_external_port = 80
6806 cls.nat_addr = '10.0.0.3'
6807 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
6809 cls.vrf1_nat_addr = '10.0.10.3'
6810 cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
6812 cls.ipfix_src_port = 4739
6813 cls.ipfix_domain_id = 1
6815 cls.create_pg_interfaces(range(6))
6816 cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
6817 cls.ip6_interfaces.append(cls.pg_interfaces[2])
6818 cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
6820 cls.vapi.ip_table_add_del(cls.vrf1_id, is_add=1, is_ipv6=1)
6822 cls.pg_interfaces[2].set_table_ip6(cls.vrf1_id)
6824 cls.pg0.generate_remote_hosts(2)
6826 for i in cls.ip6_interfaces:
6829 i.configure_ipv6_neighbors()
6831 for i in cls.ip4_interfaces:
6837 cls.pg3.config_ip4()
6838 cls.pg3.resolve_arp()
6839 cls.pg3.config_ip6()
6840 cls.pg3.configure_ipv6_neighbors()
6843 cls.pg5.config_ip6()
6846 super(TestNAT64, cls).tearDownClass()
6849 def test_nat64_inside_interface_handles_neighbor_advertisement(self):
6850 """ NAT64 inside interface handles Neighbor Advertisement """
6852 self.vapi.nat64_add_del_interface(self.pg5.sw_if_index)
6855 ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
6856 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
6857 ICMPv6EchoRequest())
6859 self.pg5.add_stream(pkts)
6860 self.pg_enable_capture(self.pg_interfaces)
6863 # Wait for Neighbor Solicitation
6864 capture = self.pg5.get_capture(len(pkts))
6867 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
6868 self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
6869 tgt = packet[ICMPv6ND_NS].tgt
6871 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6874 # Send Neighbor Advertisement
6875 p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) /
6876 IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) /
6877 ICMPv6ND_NA(tgt=tgt) /
6878 ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac))
6880 self.pg5.add_stream(pkts)
6881 self.pg_enable_capture(self.pg_interfaces)
6884 # Try to send ping again
6886 self.pg5.add_stream(pkts)
6887 self.pg_enable_capture(self.pg_interfaces)
6890 # Wait for ping reply
6891 capture = self.pg5.get_capture(len(pkts))
6894 self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
6895 self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6)
6896 self.assertEqual(packet.haslayer(ICMPv6EchoReply), 1)
6898 self.logger.error(ppp("Unexpected or invalid packet:", packet))
6901 def test_pool(self):
6902 """ Add/delete address to NAT64 pool """
6903 nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4')
6905 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr)
6907 addresses = self.vapi.nat64_pool_addr_dump()
6908 self.assertEqual(len(addresses), 1)
6909 self.assertEqual(addresses[0].address, nat_addr)
6911 self.vapi.nat64_add_del_pool_addr_range(nat_addr, nat_addr, is_add=0)
6913 addresses = self.vapi.nat64_pool_addr_dump()
6914 self.assertEqual(len(addresses), 0)
6916 def test_interface(self):
6917 """ Enable/disable NAT64 feature on the interface """
6918 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
6919 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
6921 interfaces = self.vapi.nat64_interface_dump()
6922 self.assertEqual(len(interfaces), 2)
6925 for intf in interfaces:
6926 if intf.sw_if_index == self.pg0.sw_if_index:
6927 self.assertEqual(intf.is_inside, 1)
6929 elif intf.sw_if_index == self.pg1.sw_if_index:
6930 self.assertEqual(intf.is_inside, 0)
6932 self.assertTrue(pg0_found)
6933 self.assertTrue(pg1_found)
6935 features = self.vapi.cli("show interface features pg0")
6936 self.assertNotEqual(features.find('nat64-in2out'), -1)
6937 features = self.vapi.cli("show interface features pg1")
6938 self.assertNotEqual(features.find('nat64-out2in'), -1)
6940 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index, is_add=0)
6941 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_add=0)
6943 interfaces = self.vapi.nat64_interface_dump()
6944 self.assertEqual(len(interfaces), 0)
6946 def test_static_bib(self):
6947 """ Add/delete static BIB entry """
6948 in_addr = socket.inet_pton(socket.AF_INET6,
6949 '2001:db8:85a3::8a2e:370:7334')
6950 out_addr = socket.inet_pton(socket.AF_INET, '10.1.1.3')
6953 proto = IP_PROTOS.tcp
6955 self.vapi.nat64_add_del_static_bib(in_addr,
6960 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
6965 self.assertEqual(bibe.i_addr, in_addr)
6966 self.assertEqual(bibe.o_addr, out_addr)
6967 self.assertEqual(bibe.i_port, in_port)
6968 self.assertEqual(bibe.o_port, out_port)
6969 self.assertEqual(static_bib_num, 1)
6970 bibs = self.statistics.get_counter('/nat64/total-bibs')
6971 self.assertEqual(bibs[0][0], 1)
6973 self.vapi.nat64_add_del_static_bib(in_addr,
6979 bib = self.vapi.nat64_bib_dump(IP_PROTOS.tcp)
6984 self.assertEqual(static_bib_num, 0)
6985 bibs = self.statistics.get_counter('/nat64/total-bibs')
6986 self.assertEqual(bibs[0][0], 0)
6988 def test_set_timeouts(self):
6989 """ Set NAT64 timeouts """
6990 # verify default values
6991 timeouts = self.vapi.nat_get_timeouts()
6992 self.assertEqual(timeouts.udp, 300)
6993 self.assertEqual(timeouts.icmp, 60)
6994 self.assertEqual(timeouts.tcp_transitory, 240)
6995 self.assertEqual(timeouts.tcp_established, 7440)
6997 # set and verify custom values
6998 self.vapi.nat_set_timeouts(udp=200, icmp=30, tcp_transitory=250,
6999 tcp_established=7450)
7000 timeouts = self.vapi.nat_get_timeouts()
7001 self.assertEqual(timeouts.udp, 200)
7002 self.assertEqual(timeouts.icmp, 30)
7003 self.assertEqual(timeouts.tcp_transitory, 250)
7004 self.assertEqual(timeouts.tcp_established, 7450)
7006 def test_dynamic(self):
7007 """ NAT64 dynamic translation test """
7008 self.tcp_port_in = 6303
7009 self.udp_port_in = 6304
7010 self.icmp_id_in = 6305
7012 ses_num_start = self.nat64_get_ses_num()
7014 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7016 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7017 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7020 tcpn = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7021 udpn = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7022 icmpn = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7023 totaln = self.statistics.get_counter(
7024 '/err/nat64-in2out/good in2out packets processed')
7026 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7027 self.pg0.add_stream(pkts)
7028 self.pg_enable_capture(self.pg_interfaces)
7030 capture = self.pg1.get_capture(len(pkts))
7031 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7032 dst_ip=self.pg1.remote_ip4)
7034 err = self.statistics.get_counter('/err/nat64-in2out/TCP packets')
7035 self.assertEqual(err - tcpn, 1)
7036 err = self.statistics.get_counter('/err/nat64-in2out/UDP packets')
7037 self.assertEqual(err - udpn, 1)
7038 err = self.statistics.get_counter('/err/nat64-in2out/ICMP packets')
7039 self.assertEqual(err - icmpn, 1)
7040 err = self.statistics.get_counter(
7041 '/err/nat64-in2out/good in2out packets processed')
7042 self.assertEqual(err - totaln, 3)
7045 tcpn = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7046 udpn = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7047 icmpn = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7048 totaln = self.statistics.get_counter(
7049 '/err/nat64-out2in/good out2in packets processed')
7051 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7052 self.pg1.add_stream(pkts)
7053 self.pg_enable_capture(self.pg_interfaces)
7055 capture = self.pg0.get_capture(len(pkts))
7056 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7057 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7059 err = self.statistics.get_counter('/err/nat64-out2in/TCP packets')
7060 self.assertEqual(err - tcpn, 1)
7061 err = self.statistics.get_counter('/err/nat64-out2in/UDP packets')
7062 self.assertEqual(err - udpn, 1)
7063 err = self.statistics.get_counter('/err/nat64-out2in/ICMP packets')
7064 self.assertEqual(err - icmpn, 1)
7065 err = self.statistics.get_counter(
7066 '/err/nat64-out2in/good out2in packets processed')
7067 self.assertEqual(err - totaln, 3)
7069 bibs = self.statistics.get_counter('/nat64/total-bibs')
7070 self.assertEqual(bibs[0][0], 3)
7071 sessions = self.statistics.get_counter('/nat64/total-sessions')
7072 self.assertEqual(sessions[0][0], 3)
7075 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7076 self.pg0.add_stream(pkts)
7077 self.pg_enable_capture(self.pg_interfaces)
7079 capture = self.pg1.get_capture(len(pkts))
7080 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7081 dst_ip=self.pg1.remote_ip4)
7084 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7085 self.pg1.add_stream(pkts)
7086 self.pg_enable_capture(self.pg_interfaces)
7088 capture = self.pg0.get_capture(len(pkts))
7089 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7091 ses_num_end = self.nat64_get_ses_num()
7093 self.assertEqual(ses_num_end - ses_num_start, 3)
7095 # tenant with specific VRF
7096 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
7097 self.vrf1_nat_addr_n,
7098 vrf_id=self.vrf1_id)
7099 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
7101 pkts = self.create_stream_in_ip6(self.pg2, self.pg1)
7102 self.pg2.add_stream(pkts)
7103 self.pg_enable_capture(self.pg_interfaces)
7105 capture = self.pg1.get_capture(len(pkts))
7106 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7107 dst_ip=self.pg1.remote_ip4)
7109 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7110 self.pg1.add_stream(pkts)
7111 self.pg_enable_capture(self.pg_interfaces)
7113 capture = self.pg2.get_capture(len(pkts))
7114 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg2.remote_ip6)
7116 def test_static(self):
7117 """ NAT64 static translation test """
7118 self.tcp_port_in = 60303
7119 self.udp_port_in = 60304
7120 self.icmp_id_in = 60305
7121 self.tcp_port_out = 60303
7122 self.udp_port_out = 60304
7123 self.icmp_id_out = 60305
7125 ses_num_start = self.nat64_get_ses_num()
7127 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7129 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7130 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7132 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7137 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7142 self.vapi.nat64_add_del_static_bib(self.pg0.remote_ip6n,
7149 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7150 self.pg0.add_stream(pkts)
7151 self.pg_enable_capture(self.pg_interfaces)
7153 capture = self.pg1.get_capture(len(pkts))
7154 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7155 dst_ip=self.pg1.remote_ip4, same_port=True)
7158 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7159 self.pg1.add_stream(pkts)
7160 self.pg_enable_capture(self.pg_interfaces)
7162 capture = self.pg0.get_capture(len(pkts))
7163 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7164 self.verify_capture_in_ip6(capture, ip[IPv6].src, self.pg0.remote_ip6)
7166 ses_num_end = self.nat64_get_ses_num()
7168 self.assertEqual(ses_num_end - ses_num_start, 3)
7170 @unittest.skipUnless(running_extended_tests, "part of extended tests")
7171 def test_session_timeout(self):
7172 """ NAT64 session timeout """
7173 self.icmp_id_in = 1234
7174 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7176 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7177 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7178 self.vapi.nat_set_timeouts(icmp=5, tcp_transitory=5, tcp_established=5)
7180 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7181 self.pg0.add_stream(pkts)
7182 self.pg_enable_capture(self.pg_interfaces)
7184 capture = self.pg1.get_capture(len(pkts))
7186 ses_num_before_timeout = self.nat64_get_ses_num()
7190 # ICMP and TCP session after timeout
7191 ses_num_after_timeout = self.nat64_get_ses_num()
7192 self.assertEqual(ses_num_before_timeout - ses_num_after_timeout, 2)
7194 def test_icmp_error(self):
7195 """ NAT64 ICMP Error message translation """
7196 self.tcp_port_in = 6303
7197 self.udp_port_in = 6304
7198 self.icmp_id_in = 6305
7200 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7202 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7203 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7205 # send some packets to create sessions
7206 pkts = self.create_stream_in_ip6(self.pg0, self.pg1)
7207 self.pg0.add_stream(pkts)
7208 self.pg_enable_capture(self.pg_interfaces)
7210 capture_ip4 = self.pg1.get_capture(len(pkts))
7211 self.verify_capture_out(capture_ip4,
7212 nat_ip=self.nat_addr,
7213 dst_ip=self.pg1.remote_ip4)
7215 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7216 self.pg1.add_stream(pkts)
7217 self.pg_enable_capture(self.pg_interfaces)
7219 capture_ip6 = self.pg0.get_capture(len(pkts))
7220 ip = IPv6(src=''.join(['64:ff9b::', self.pg1.remote_ip4]))
7221 self.verify_capture_in_ip6(capture_ip6, ip[IPv6].src,
7222 self.pg0.remote_ip6)
7225 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7226 IPv6(src=self.pg0.remote_ip6, dst=ip[IPv6].src) /
7227 ICMPv6DestUnreach(code=1) /
7228 packet[IPv6] for packet in capture_ip6]
7229 self.pg0.add_stream(pkts)
7230 self.pg_enable_capture(self.pg_interfaces)
7232 capture = self.pg1.get_capture(len(pkts))
7233 for packet in capture:
7235 self.assertEqual(packet[IP].src, self.nat_addr)
7236 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
7237 self.assertEqual(packet[ICMP].type, 3)
7238 self.assertEqual(packet[ICMP].code, 13)
7239 inner = packet[IPerror]
7240 self.assertEqual(inner.src, self.pg1.remote_ip4)
7241 self.assertEqual(inner.dst, self.nat_addr)
7242 self.assert_packet_checksums_valid(packet)
7243 if inner.haslayer(TCPerror):
7244 self.assertEqual(inner[TCPerror].dport, self.tcp_port_out)
7245 elif inner.haslayer(UDPerror):
7246 self.assertEqual(inner[UDPerror].dport, self.udp_port_out)
7248 self.assertEqual(inner[ICMPerror].id, self.icmp_id_out)
7250 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7254 pkts = [Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7255 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7256 ICMP(type=3, code=13) /
7257 packet[IP] for packet in capture_ip4]
7258 self.pg1.add_stream(pkts)
7259 self.pg_enable_capture(self.pg_interfaces)
7261 capture = self.pg0.get_capture(len(pkts))
7262 for packet in capture:
7264 self.assertEqual(packet[IPv6].src, ip.src)
7265 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7266 icmp = packet[ICMPv6DestUnreach]
7267 self.assertEqual(icmp.code, 1)
7268 inner = icmp[IPerror6]
7269 self.assertEqual(inner.src, self.pg0.remote_ip6)
7270 self.assertEqual(inner.dst, ip.src)
7271 self.assert_icmpv6_checksum_valid(packet)
7272 if inner.haslayer(TCPerror):
7273 self.assertEqual(inner[TCPerror].sport, self.tcp_port_in)
7274 elif inner.haslayer(UDPerror):
7275 self.assertEqual(inner[UDPerror].sport, self.udp_port_in)
7277 self.assertEqual(inner[ICMPv6EchoRequest].id,
7280 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7283 def test_hairpinning(self):
7284 """ NAT64 hairpinning """
7286 client = self.pg0.remote_hosts[0]
7287 server = self.pg0.remote_hosts[1]
7288 server_tcp_in_port = 22
7289 server_tcp_out_port = 4022
7290 server_udp_in_port = 23
7291 server_udp_out_port = 4023
7292 client_tcp_in_port = 1234
7293 client_udp_in_port = 1235
7294 client_tcp_out_port = 0
7295 client_udp_out_port = 0
7296 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
7297 nat_addr_ip6 = ip.src
7299 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7301 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7302 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7304 self.vapi.nat64_add_del_static_bib(server.ip6n,
7307 server_tcp_out_port,
7309 self.vapi.nat64_add_del_static_bib(server.ip6n,
7312 server_udp_out_port,
7317 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7318 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7319 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7321 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7322 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7323 UDP(sport=client_udp_in_port, dport=server_udp_out_port))
7325 self.pg0.add_stream(pkts)
7326 self.pg_enable_capture(self.pg_interfaces)
7328 capture = self.pg0.get_capture(len(pkts))
7329 for packet in capture:
7331 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7332 self.assertEqual(packet[IPv6].dst, server.ip6)
7333 self.assert_packet_checksums_valid(packet)
7334 if packet.haslayer(TCP):
7335 self.assertNotEqual(packet[TCP].sport, client_tcp_in_port)
7336 self.assertEqual(packet[TCP].dport, server_tcp_in_port)
7337 client_tcp_out_port = packet[TCP].sport
7339 self.assertNotEqual(packet[UDP].sport, client_udp_in_port)
7340 self.assertEqual(packet[UDP].dport, server_udp_in_port)
7341 client_udp_out_port = packet[UDP].sport
7343 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7348 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7349 IPv6(src=server.ip6, dst=nat_addr_ip6) /
7350 TCP(sport=server_tcp_in_port, dport=client_tcp_out_port))
7352 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7353 IPv6(src=server.ip6, dst=nat_addr_ip6) /
7354 UDP(sport=server_udp_in_port, dport=client_udp_out_port))
7356 self.pg0.add_stream(pkts)
7357 self.pg_enable_capture(self.pg_interfaces)
7359 capture = self.pg0.get_capture(len(pkts))
7360 for packet in capture:
7362 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7363 self.assertEqual(packet[IPv6].dst, client.ip6)
7364 self.assert_packet_checksums_valid(packet)
7365 if packet.haslayer(TCP):
7366 self.assertEqual(packet[TCP].sport, server_tcp_out_port)
7367 self.assertEqual(packet[TCP].dport, client_tcp_in_port)
7369 self.assertEqual(packet[UDP].sport, server_udp_out_port)
7370 self.assertEqual(packet[UDP].dport, client_udp_in_port)
7372 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7377 pkts = [Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7378 IPv6(src=client.ip6, dst=nat_addr_ip6) /
7379 ICMPv6DestUnreach(code=1) /
7380 packet[IPv6] for packet in capture]
7381 self.pg0.add_stream(pkts)
7382 self.pg_enable_capture(self.pg_interfaces)
7384 capture = self.pg0.get_capture(len(pkts))
7385 for packet in capture:
7387 self.assertEqual(packet[IPv6].src, nat_addr_ip6)
7388 self.assertEqual(packet[IPv6].dst, server.ip6)
7389 icmp = packet[ICMPv6DestUnreach]
7390 self.assertEqual(icmp.code, 1)
7391 inner = icmp[IPerror6]
7392 self.assertEqual(inner.src, server.ip6)
7393 self.assertEqual(inner.dst, nat_addr_ip6)
7394 self.assert_packet_checksums_valid(packet)
7395 if inner.haslayer(TCPerror):
7396 self.assertEqual(inner[TCPerror].sport, server_tcp_in_port)
7397 self.assertEqual(inner[TCPerror].dport,
7398 client_tcp_out_port)
7400 self.assertEqual(inner[UDPerror].sport, server_udp_in_port)
7401 self.assertEqual(inner[UDPerror].dport,
7402 client_udp_out_port)
7404 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7407 def test_prefix(self):
7408 """ NAT64 Network-Specific Prefix """
7410 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7412 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7413 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7414 self.vapi.nat64_add_del_pool_addr_range(self.vrf1_nat_addr_n,
7415 self.vrf1_nat_addr_n,
7416 vrf_id=self.vrf1_id)
7417 self.vapi.nat64_add_del_interface(self.pg2.sw_if_index)
7420 global_pref64 = "2001:db8::"
7421 global_pref64_n = socket.inet_pton(socket.AF_INET6, global_pref64)
7422 global_pref64_len = 32
7423 self.vapi.nat64_add_del_prefix(global_pref64_n, global_pref64_len)
7425 prefix = self.vapi.nat64_prefix_dump()
7426 self.assertEqual(len(prefix), 1)
7427 self.assertEqual(prefix[0].prefix, global_pref64_n)
7428 self.assertEqual(prefix[0].prefix_len, global_pref64_len)
7429 self.assertEqual(prefix[0].vrf_id, 0)
7431 # Add tenant specific prefix
7432 vrf1_pref64 = "2001:db8:122:300::"
7433 vrf1_pref64_n = socket.inet_pton(socket.AF_INET6, vrf1_pref64)
7434 vrf1_pref64_len = 56
7435 self.vapi.nat64_add_del_prefix(vrf1_pref64_n,
7437 vrf_id=self.vrf1_id)
7438 prefix = self.vapi.nat64_prefix_dump()
7439 self.assertEqual(len(prefix), 2)
7442 pkts = self.create_stream_in_ip6(self.pg0,
7445 plen=global_pref64_len)
7446 self.pg0.add_stream(pkts)
7447 self.pg_enable_capture(self.pg_interfaces)
7449 capture = self.pg1.get_capture(len(pkts))
7450 self.verify_capture_out(capture, nat_ip=self.nat_addr,
7451 dst_ip=self.pg1.remote_ip4)
7453 pkts = self.create_stream_out(self.pg1, dst_ip=self.nat_addr)
7454 self.pg1.add_stream(pkts)
7455 self.pg_enable_capture(self.pg_interfaces)
7457 capture = self.pg0.get_capture(len(pkts))
7458 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7461 self.verify_capture_in_ip6(capture, dst_ip, self.pg0.remote_ip6)
7463 # Tenant specific prefix
7464 pkts = self.create_stream_in_ip6(self.pg2,
7467 plen=vrf1_pref64_len)
7468 self.pg2.add_stream(pkts)
7469 self.pg_enable_capture(self.pg_interfaces)
7471 capture = self.pg1.get_capture(len(pkts))
7472 self.verify_capture_out(capture, nat_ip=self.vrf1_nat_addr,
7473 dst_ip=self.pg1.remote_ip4)
7475 pkts = self.create_stream_out(self.pg1, dst_ip=self.vrf1_nat_addr)
7476 self.pg1.add_stream(pkts)
7477 self.pg_enable_capture(self.pg_interfaces)
7479 capture = self.pg2.get_capture(len(pkts))
7480 dst_ip = self.compose_ip6(self.pg1.remote_ip4,
7483 self.verify_capture_in_ip6(capture, dst_ip, self.pg2.remote_ip6)
7485 def test_unknown_proto(self):
7486 """ NAT64 translate packet with unknown protocol """
7488 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7490 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7491 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7492 remote_ip6 = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7495 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7496 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6) /
7497 TCP(sport=self.tcp_port_in, dport=20))
7498 self.pg0.add_stream(p)
7499 self.pg_enable_capture(self.pg_interfaces)
7501 p = self.pg1.get_capture(1)
7503 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7504 IPv6(src=self.pg0.remote_ip6, dst=remote_ip6, nh=47) /
7506 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7507 TCP(sport=1234, dport=1234))
7508 self.pg0.add_stream(p)
7509 self.pg_enable_capture(self.pg_interfaces)
7511 p = self.pg1.get_capture(1)
7514 self.assertEqual(packet[IP].src, self.nat_addr)
7515 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
7516 self.assertEqual(packet.haslayer(GRE), 1)
7517 self.assert_packet_checksums_valid(packet)
7519 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7523 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
7524 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
7526 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7527 TCP(sport=1234, dport=1234))
7528 self.pg1.add_stream(p)
7529 self.pg_enable_capture(self.pg_interfaces)
7531 p = self.pg0.get_capture(1)
7534 self.assertEqual(packet[IPv6].src, remote_ip6)
7535 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
7536 self.assertEqual(packet[IPv6].nh, 47)
7538 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7541 def test_hairpinning_unknown_proto(self):
7542 """ NAT64 translate packet with unknown protocol - hairpinning """
7544 client = self.pg0.remote_hosts[0]
7545 server = self.pg0.remote_hosts[1]
7546 server_tcp_in_port = 22
7547 server_tcp_out_port = 4022
7548 client_tcp_in_port = 1234
7549 client_tcp_out_port = 1235
7550 server_nat_ip = "10.0.0.100"
7551 client_nat_ip = "10.0.0.110"
7552 server_nat_ip_n = socket.inet_pton(socket.AF_INET, server_nat_ip)
7553 client_nat_ip_n = socket.inet_pton(socket.AF_INET, client_nat_ip)
7554 server_nat_ip6 = self.compose_ip6(server_nat_ip, '64:ff9b::', 96)
7555 client_nat_ip6 = self.compose_ip6(client_nat_ip, '64:ff9b::', 96)
7557 self.vapi.nat64_add_del_pool_addr_range(server_nat_ip_n,
7559 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7560 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7562 self.vapi.nat64_add_del_static_bib(server.ip6n,
7565 server_tcp_out_port,
7568 self.vapi.nat64_add_del_static_bib(server.ip6n,
7574 self.vapi.nat64_add_del_static_bib(client.ip6n,
7577 client_tcp_out_port,
7581 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7582 IPv6(src=client.ip6, dst=server_nat_ip6) /
7583 TCP(sport=client_tcp_in_port, dport=server_tcp_out_port))
7584 self.pg0.add_stream(p)
7585 self.pg_enable_capture(self.pg_interfaces)
7587 p = self.pg0.get_capture(1)
7589 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7590 IPv6(src=client.ip6, dst=server_nat_ip6, nh=IP_PROTOS.gre) /
7592 IP(src=self.pg2.local_ip4, dst=self.pg2.remote_ip4) /
7593 TCP(sport=1234, dport=1234))
7594 self.pg0.add_stream(p)
7595 self.pg_enable_capture(self.pg_interfaces)
7597 p = self.pg0.get_capture(1)
7600 self.assertEqual(packet[IPv6].src, client_nat_ip6)
7601 self.assertEqual(packet[IPv6].dst, server.ip6)
7602 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
7604 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7608 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
7609 IPv6(src=server.ip6, dst=client_nat_ip6, nh=IP_PROTOS.gre) /
7611 IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
7612 TCP(sport=1234, dport=1234))
7613 self.pg0.add_stream(p)
7614 self.pg_enable_capture(self.pg_interfaces)
7616 p = self.pg0.get_capture(1)
7619 self.assertEqual(packet[IPv6].src, server_nat_ip6)
7620 self.assertEqual(packet[IPv6].dst, client.ip6)
7621 self.assertEqual(packet[IPv6].nh, IP_PROTOS.gre)
7623 self.logger.error(ppp("Unexpected or invalid packet:", packet))
7626 def test_one_armed_nat64(self):
7627 """ One armed NAT64 """
7629 remote_host_ip6 = self.compose_ip6(self.pg3.remote_ip4,
7633 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7635 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index)
7636 self.vapi.nat64_add_del_interface(self.pg3.sw_if_index, is_inside=0)
7639 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
7640 IPv6(src=self.pg3.remote_ip6, dst=remote_host_ip6) /
7641 TCP(sport=12345, dport=80))
7642 self.pg3.add_stream(p)
7643 self.pg_enable_capture(self.pg_interfaces)
7645 capture = self.pg3.get_capture(1)
7650 self.assertEqual(ip.src, self.nat_addr)
7651 self.assertEqual(ip.dst, self.pg3.remote_ip4)
7652 self.assertNotEqual(tcp.sport, 12345)
7653 external_port = tcp.sport
7654 self.assertEqual(tcp.dport, 80)
7655 self.assert_packet_checksums_valid(p)
7657 self.logger.error(ppp("Unexpected or invalid packet:", p))
7661 p = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) /
7662 IP(src=self.pg3.remote_ip4, dst=self.nat_addr) /
7663 TCP(sport=80, dport=external_port))
7664 self.pg3.add_stream(p)
7665 self.pg_enable_capture(self.pg_interfaces)
7667 capture = self.pg3.get_capture(1)
7672 self.assertEqual(ip.src, remote_host_ip6)
7673 self.assertEqual(ip.dst, self.pg3.remote_ip6)
7674 self.assertEqual(tcp.sport, 80)
7675 self.assertEqual(tcp.dport, 12345)
7676 self.assert_packet_checksums_valid(p)
7678 self.logger.error(ppp("Unexpected or invalid packet:", p))
7681 def test_frag_in_order(self):
7682 """ NAT64 translate fragments arriving in order """
7683 self.tcp_port_in = random.randint(1025, 65535)
7685 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7687 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7688 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7690 reass = self.vapi.nat_reass_dump()
7691 reass_n_start = len(reass)
7695 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
7696 self.tcp_port_in, 20, data)
7697 self.pg0.add_stream(pkts)
7698 self.pg_enable_capture(self.pg_interfaces)
7700 frags = self.pg1.get_capture(len(pkts))
7701 p = self.reass_frags_and_verify(frags,
7703 self.pg1.remote_ip4)
7704 self.assertEqual(p[TCP].dport, 20)
7705 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
7706 self.tcp_port_out = p[TCP].sport
7707 self.assertEqual(data, p[Raw].load)
7710 data = "A" * 4 + "b" * 16 + "C" * 3
7711 pkts = self.create_stream_frag(self.pg1,
7716 self.pg1.add_stream(pkts)
7717 self.pg_enable_capture(self.pg_interfaces)
7719 frags = self.pg0.get_capture(len(pkts))
7720 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7721 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
7722 self.assertEqual(p[TCP].sport, 20)
7723 self.assertEqual(p[TCP].dport, self.tcp_port_in)
7724 self.assertEqual(data, p[Raw].load)
7726 reass = self.vapi.nat_reass_dump()
7727 reass_n_end = len(reass)
7729 self.assertEqual(reass_n_end - reass_n_start, 2)
7731 def test_reass_hairpinning(self):
7732 """ NAT64 fragments hairpinning """
7734 server = self.pg0.remote_hosts[1]
7735 server_in_port = random.randint(1025, 65535)
7736 server_out_port = random.randint(1025, 65535)
7737 client_in_port = random.randint(1025, 65535)
7738 ip = IPv6(src=''.join(['64:ff9b::', self.nat_addr]))
7739 nat_addr_ip6 = ip.src
7741 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7743 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7744 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7746 # add static BIB entry for server
7747 self.vapi.nat64_add_del_static_bib(server.ip6n,
7753 # send packet from host to server
7754 pkts = self.create_stream_frag_ip6(self.pg0,
7759 self.pg0.add_stream(pkts)
7760 self.pg_enable_capture(self.pg_interfaces)
7762 frags = self.pg0.get_capture(len(pkts))
7763 p = self.reass_frags_and_verify_ip6(frags, nat_addr_ip6, server.ip6)
7764 self.assertNotEqual(p[TCP].sport, client_in_port)
7765 self.assertEqual(p[TCP].dport, server_in_port)
7766 self.assertEqual(data, p[Raw].load)
7768 def test_frag_out_of_order(self):
7769 """ NAT64 translate fragments arriving out of order """
7770 self.tcp_port_in = random.randint(1025, 65535)
7772 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7774 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7775 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7779 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
7780 self.tcp_port_in, 20, data)
7782 self.pg0.add_stream(pkts)
7783 self.pg_enable_capture(self.pg_interfaces)
7785 frags = self.pg1.get_capture(len(pkts))
7786 p = self.reass_frags_and_verify(frags,
7788 self.pg1.remote_ip4)
7789 self.assertEqual(p[TCP].dport, 20)
7790 self.assertNotEqual(p[TCP].sport, self.tcp_port_in)
7791 self.tcp_port_out = p[TCP].sport
7792 self.assertEqual(data, p[Raw].load)
7795 data = "A" * 4 + "B" * 16 + "C" * 3
7796 pkts = self.create_stream_frag(self.pg1,
7802 self.pg1.add_stream(pkts)
7803 self.pg_enable_capture(self.pg_interfaces)
7805 frags = self.pg0.get_capture(len(pkts))
7806 src = self.compose_ip6(self.pg1.remote_ip4, '64:ff9b::', 96)
7807 p = self.reass_frags_and_verify_ip6(frags, src, self.pg0.remote_ip6)
7808 self.assertEqual(p[TCP].sport, 20)
7809 self.assertEqual(p[TCP].dport, self.tcp_port_in)
7810 self.assertEqual(data, p[Raw].load)
7812 def test_interface_addr(self):
7813 """ Acquire NAT64 pool addresses from interface """
7814 self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
7816 # no address in NAT64 pool
7817 adresses = self.vapi.nat44_address_dump()
7818 self.assertEqual(0, len(adresses))
7820 # configure interface address and check NAT64 address pool
7821 self.pg4.config_ip4()
7822 addresses = self.vapi.nat64_pool_addr_dump()
7823 self.assertEqual(len(addresses), 1)
7824 self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
7826 # remove interface address and check NAT64 address pool
7827 self.pg4.unconfig_ip4()
7828 addresses = self.vapi.nat64_pool_addr_dump()
7829 self.assertEqual(0, len(adresses))
7831 @unittest.skipUnless(running_extended_tests, "part of extended tests")
7832 def test_ipfix_max_bibs_sessions(self):
7833 """ IPFIX logging maximum session and BIB entries exceeded """
7836 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
7840 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7842 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7843 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7847 for i in range(0, max_bibs):
7848 src = "fd01:aa::%x" % (i)
7849 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7850 IPv6(src=src, dst=remote_host_ip6) /
7851 TCP(sport=12345, dport=80))
7853 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7854 IPv6(src=src, dst=remote_host_ip6) /
7855 TCP(sport=12345, dport=22))
7857 self.pg0.add_stream(pkts)
7858 self.pg_enable_capture(self.pg_interfaces)
7860 self.pg1.get_capture(max_sessions)
7862 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
7863 src_address=self.pg3.local_ip4n,
7865 template_interval=10)
7866 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
7867 src_port=self.ipfix_src_port)
7869 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7870 IPv6(src=src, dst=remote_host_ip6) /
7871 TCP(sport=12345, dport=25))
7872 self.pg0.add_stream(p)
7873 self.pg_enable_capture(self.pg_interfaces)
7875 self.pg1.assert_nothing_captured()
7877 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7878 capture = self.pg3.get_capture(9)
7879 ipfix = IPFIXDecoder()
7880 # first load template
7882 self.assertTrue(p.haslayer(IPFIX))
7883 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7884 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7885 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7886 self.assertEqual(p[UDP].dport, 4739)
7887 self.assertEqual(p[IPFIX].observationDomainID,
7888 self.ipfix_domain_id)
7889 if p.haslayer(Template):
7890 ipfix.add_template(p.getlayer(Template))
7891 # verify events in data set
7893 if p.haslayer(Data):
7894 data = ipfix.decode_data_set(p.getlayer(Set))
7895 self.verify_ipfix_max_sessions(data, max_sessions)
7897 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7898 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
7899 TCP(sport=12345, dport=80))
7900 self.pg0.add_stream(p)
7901 self.pg_enable_capture(self.pg_interfaces)
7903 self.pg1.assert_nothing_captured()
7905 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7906 capture = self.pg3.get_capture(1)
7907 # verify events in data set
7909 self.assertTrue(p.haslayer(IPFIX))
7910 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7911 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7912 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7913 self.assertEqual(p[UDP].dport, 4739)
7914 self.assertEqual(p[IPFIX].observationDomainID,
7915 self.ipfix_domain_id)
7916 if p.haslayer(Data):
7917 data = ipfix.decode_data_set(p.getlayer(Set))
7918 self.verify_ipfix_max_bibs(data, max_bibs)
7920 def test_ipfix_max_frags(self):
7921 """ IPFIX logging maximum fragments pending reassembly exceeded """
7922 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7924 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7925 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7926 self.vapi.nat_set_reass(max_frag=1, is_ip6=1)
7927 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
7928 src_address=self.pg3.local_ip4n,
7930 template_interval=10)
7931 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
7932 src_port=self.ipfix_src_port)
7935 pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
7936 self.tcp_port_in, 20, data)
7938 self.pg0.add_stream(pkts)
7939 self.pg_enable_capture(self.pg_interfaces)
7941 self.pg1.assert_nothing_captured()
7943 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7944 capture = self.pg3.get_capture(9)
7945 ipfix = IPFIXDecoder()
7946 # first load template
7948 self.assertTrue(p.haslayer(IPFIX))
7949 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7950 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7951 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
7952 self.assertEqual(p[UDP].dport, 4739)
7953 self.assertEqual(p[IPFIX].observationDomainID,
7954 self.ipfix_domain_id)
7955 if p.haslayer(Template):
7956 ipfix.add_template(p.getlayer(Template))
7957 # verify events in data set
7959 if p.haslayer(Data):
7960 data = ipfix.decode_data_set(p.getlayer(Set))
7961 self.verify_ipfix_max_fragments_ip6(data, 1,
7962 self.pg0.remote_ip6n)
7964 def test_ipfix_bib_ses(self):
7965 """ IPFIX logging NAT64 BIB/session create and delete events """
7966 self.tcp_port_in = random.randint(1025, 65535)
7967 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
7971 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
7973 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
7974 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
7975 self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
7976 src_address=self.pg3.local_ip4n,
7978 template_interval=10)
7979 self.vapi.nat_ipfix(domain_id=self.ipfix_domain_id,
7980 src_port=self.ipfix_src_port)
7983 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
7984 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
7985 TCP(sport=self.tcp_port_in, dport=25))
7986 self.pg0.add_stream(p)
7987 self.pg_enable_capture(self.pg_interfaces)
7989 p = self.pg1.get_capture(1)
7990 self.tcp_port_out = p[0][TCP].sport
7991 self.vapi.cli("ipfix flush") # FIXME this should be an API call
7992 capture = self.pg3.get_capture(10)
7993 ipfix = IPFIXDecoder()
7994 # first load template
7996 self.assertTrue(p.haslayer(IPFIX))
7997 self.assertEqual(p[IP].src, self.pg3.local_ip4)
7998 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
7999 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8000 self.assertEqual(p[UDP].dport, 4739)
8001 self.assertEqual(p[IPFIX].observationDomainID,
8002 self.ipfix_domain_id)
8003 if p.haslayer(Template):
8004 ipfix.add_template(p.getlayer(Template))
8005 # verify events in data set
8007 if p.haslayer(Data):
8008 data = ipfix.decode_data_set(p.getlayer(Set))
8009 if ord(data[0][230]) == 10:
8010 self.verify_ipfix_bib(data, 1, self.pg0.remote_ip6n)
8011 elif ord(data[0][230]) == 6:
8012 self.verify_ipfix_nat64_ses(data,
8014 self.pg0.remote_ip6n,
8015 self.pg1.remote_ip4,
8018 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8021 self.pg_enable_capture(self.pg_interfaces)
8022 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8025 self.vapi.cli("ipfix flush") # FIXME this should be an API call
8026 capture = self.pg3.get_capture(2)
8027 # verify events in data set
8029 self.assertTrue(p.haslayer(IPFIX))
8030 self.assertEqual(p[IP].src, self.pg3.local_ip4)
8031 self.assertEqual(p[IP].dst, self.pg3.remote_ip4)
8032 self.assertEqual(p[UDP].sport, self.ipfix_src_port)
8033 self.assertEqual(p[UDP].dport, 4739)
8034 self.assertEqual(p[IPFIX].observationDomainID,
8035 self.ipfix_domain_id)
8036 if p.haslayer(Data):
8037 data = ipfix.decode_data_set(p.getlayer(Set))
8038 if ord(data[0][230]) == 11:
8039 self.verify_ipfix_bib(data, 0, self.pg0.remote_ip6n)
8040 elif ord(data[0][230]) == 7:
8041 self.verify_ipfix_nat64_ses(data,
8043 self.pg0.remote_ip6n,
8044 self.pg1.remote_ip4,
8047 self.logger.error(ppp("Unexpected or invalid packet: ", p))
8049 def test_syslog_sess(self):
8050 """ Test syslog session creation and deletion """
8051 self.tcp_port_in = random.randint(1025, 65535)
8052 remote_host_ip6 = self.compose_ip6(self.pg1.remote_ip4,
8056 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8058 self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
8059 self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8060 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.INFO)
8061 self.vapi.syslog_set_sender(self.pg3.remote_ip4n, self.pg3.local_ip4n)
8063 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
8064 IPv6(src=self.pg0.remote_ip6, dst=remote_host_ip6) /
8065 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
8066 self.pg0.add_stream(p)
8067 self.pg_enable_capture(self.pg_interfaces)
8069 p = self.pg1.get_capture(1)
8070 self.tcp_port_out = p[0][TCP].sport
8071 capture = self.pg3.get_capture(1)
8072 self.verify_syslog_sess(capture[0][Raw].load, is_ip6=True)
8074 self.pg_enable_capture(self.pg_interfaces)
8076 self.vapi.nat64_add_del_pool_addr_range(self.nat_addr_n,
8079 capture = self.pg3.get_capture(1)
8080 self.verify_syslog_sess(capture[0][Raw].load, False, True)
8082 def nat64_get_ses_num(self):
8084 Return number of active NAT64 sessions.
8086 st = self.vapi.nat64_st_dump()
8089 def clear_nat64(self):
8091 Clear NAT64 configuration.
8093 self.vapi.nat_ipfix(enable=0, src_port=self.ipfix_src_port,
8094 domain_id=self.ipfix_domain_id)
8095 self.ipfix_src_port = 4739
8096 self.ipfix_domain_id = 1
8098 self.vapi.syslog_set_filter(SYSLOG_SEVERITY.EMERG)
8100 self.vapi.nat_set_timeouts()
8102 interfaces = self.vapi.nat64_interface_dump()
8103 for intf in interfaces:
8104 if intf.is_inside > 1:
8105 self.vapi.nat64_add_del_interface(intf.sw_if_index,
8108 self.vapi.nat64_add_del_interface(intf.sw_if_index,
8112 bib = self.vapi.nat64_bib_dump(255)
8115 self.vapi.nat64_add_del_static_bib(bibe.i_addr,
8123 adresses = self.vapi.nat64_pool_addr_dump()
8124 for addr in adresses:
8125 self.vapi.nat64_add_del_pool_addr_range(addr.address,
8130 prefixes = self.vapi.nat64_prefix_dump()
8131 for prefix in prefixes:
8132 self.vapi.nat64_add_del_prefix(prefix.prefix,
8134 vrf_id=prefix.vrf_id,
8137 bibs = self.statistics.get_counter('/nat64/total-bibs')
8138 self.assertEqual(bibs[0][0], 0)
8139 sessions = self.statistics.get_counter('/nat64/total-sessions')
8140 self.assertEqual(sessions[0][0], 0)
8143 super(TestNAT64, self).tearDown()
8144 if not self.vpp_dead:
8145 self.logger.info(self.vapi.cli("show nat64 pool"))
8146 self.logger.info(self.vapi.cli("show nat64 interfaces"))
8147 self.logger.info(self.vapi.cli("show nat64 prefix"))
8148 self.logger.info(self.vapi.cli("show nat64 bib all"))
8149 self.logger.info(self.vapi.cli("show nat64 session table all"))
8150 self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
8154 class TestDSlite(MethodHolder):
8155 """ DS-Lite Test Cases """
8158 def setUpClass(cls):
8159 super(TestDSlite, cls).setUpClass()
8162 cls.nat_addr = '10.0.0.3'
8163 cls.nat_addr_n = socket.inet_pton(socket.AF_INET, cls.nat_addr)
8165 cls.create_pg_interfaces(range(3))
8167 cls.pg0.config_ip4()
8168 cls.pg0.resolve_arp()
8170 cls.pg1.config_ip6()
8171 cls.pg1.generate_remote_hosts(2)
8172 cls.pg1.configure_ipv6_neighbors()
8174 cls.pg2.config_ip4()
8175 cls.pg2.resolve_arp()
8178 super(TestDSlite, cls).tearDownClass()
8181 def verify_syslog_apmadd(self, data, isaddr, isport, xsaddr, xsport,
8183 message = data.decode('utf-8')
8185 message = SyslogMessage.parse(message)
8186 except ParseError as e:
8187 self.logger.error(e)
8189 self.assertEqual(message.severity, SyslogSeverity.info)
8190 self.assertEqual(message.appname, 'NAT')
8191 self.assertEqual(message.msgid, 'APMADD')
8192 sd_params = message.sd.get('napmap')
8193 self.assertTrue(sd_params is not None)
8194 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
8195 self.assertEqual(sd_params.get('ISADDR'), isaddr)
8196 self.assertEqual(sd_params.get('ISPORT'), "%d" % isport)
8197 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
8198 self.assertEqual(sd_params.get('XSADDR'), xsaddr)
8199 self.assertEqual(sd_params.get('XSPORT'), "%d" % xsport)
8200 self.assertEqual(sd_params.get('PROTO'), "%d" % proto)
8201 self.assertTrue(sd_params.get('SSUBIX') is not None)
8202 self.assertEqual(sd_params.get('SV6ENC'), sv6enc)
8204 def test_dslite(self):
8205 """ Test DS-Lite """
8206 nat_config = self.vapi.nat_show_config()
8207 self.assertEqual(0, nat_config.dslite_ce)
8209 self.vapi.dslite_add_del_pool_addr_range(self.nat_addr_n,
8211 aftr_ip4 = '192.0.0.1'
8212 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
8213 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
8214 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
8215 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
8216 self.vapi.syslog_set_sender(self.pg2.remote_ip4n, self.pg2.local_ip4n)
8219 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8220 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[0].ip6) /
8221 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8222 UDP(sport=20000, dport=10000))
8223 self.pg1.add_stream(p)
8224 self.pg_enable_capture(self.pg_interfaces)
8226 capture = self.pg0.get_capture(1)
8227 capture = capture[0]
8228 self.assertFalse(capture.haslayer(IPv6))
8229 self.assertEqual(capture[IP].src, self.nat_addr)
8230 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8231 self.assertNotEqual(capture[UDP].sport, 20000)
8232 self.assertEqual(capture[UDP].dport, 10000)
8233 self.assert_packet_checksums_valid(capture)
8234 out_port = capture[UDP].sport
8235 capture = self.pg2.get_capture(1)
8236 self.verify_syslog_apmadd(capture[0][Raw].load, '192.168.1.1',
8237 20000, self.nat_addr, out_port,
8238 self.pg1.remote_hosts[0].ip6, IP_PROTOS.udp)
8240 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8241 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8242 UDP(sport=10000, dport=out_port))
8243 self.pg0.add_stream(p)
8244 self.pg_enable_capture(self.pg_interfaces)
8246 capture = self.pg1.get_capture(1)
8247 capture = capture[0]
8248 self.assertEqual(capture[IPv6].src, aftr_ip6)
8249 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8250 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8251 self.assertEqual(capture[IP].dst, '192.168.1.1')
8252 self.assertEqual(capture[UDP].sport, 10000)
8253 self.assertEqual(capture[UDP].dport, 20000)
8254 self.assert_packet_checksums_valid(capture)
8257 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8258 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8259 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8260 TCP(sport=20001, dport=10001))
8261 self.pg1.add_stream(p)
8262 self.pg_enable_capture(self.pg_interfaces)
8264 capture = self.pg0.get_capture(1)
8265 capture = capture[0]
8266 self.assertFalse(capture.haslayer(IPv6))
8267 self.assertEqual(capture[IP].src, self.nat_addr)
8268 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8269 self.assertNotEqual(capture[TCP].sport, 20001)
8270 self.assertEqual(capture[TCP].dport, 10001)
8271 self.assert_packet_checksums_valid(capture)
8272 out_port = capture[TCP].sport
8274 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8275 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8276 TCP(sport=10001, dport=out_port))
8277 self.pg0.add_stream(p)
8278 self.pg_enable_capture(self.pg_interfaces)
8280 capture = self.pg1.get_capture(1)
8281 capture = capture[0]
8282 self.assertEqual(capture[IPv6].src, aftr_ip6)
8283 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8284 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8285 self.assertEqual(capture[IP].dst, '192.168.1.1')
8286 self.assertEqual(capture[TCP].sport, 10001)
8287 self.assertEqual(capture[TCP].dport, 20001)
8288 self.assert_packet_checksums_valid(capture)
8291 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8292 IPv6(dst=aftr_ip6, src=self.pg1.remote_hosts[1].ip6) /
8293 IP(dst=self.pg0.remote_ip4, src='192.168.1.1') /
8294 ICMP(id=4000, type='echo-request'))
8295 self.pg1.add_stream(p)
8296 self.pg_enable_capture(self.pg_interfaces)
8298 capture = self.pg0.get_capture(1)
8299 capture = capture[0]
8300 self.assertFalse(capture.haslayer(IPv6))
8301 self.assertEqual(capture[IP].src, self.nat_addr)
8302 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8303 self.assertNotEqual(capture[ICMP].id, 4000)
8304 self.assert_packet_checksums_valid(capture)
8305 out_id = capture[ICMP].id
8307 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8308 IP(dst=self.nat_addr, src=self.pg0.remote_ip4) /
8309 ICMP(id=out_id, type='echo-reply'))
8310 self.pg0.add_stream(p)
8311 self.pg_enable_capture(self.pg_interfaces)
8313 capture = self.pg1.get_capture(1)
8314 capture = capture[0]
8315 self.assertEqual(capture[IPv6].src, aftr_ip6)
8316 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8317 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8318 self.assertEqual(capture[IP].dst, '192.168.1.1')
8319 self.assertEqual(capture[ICMP].id, 4000)
8320 self.assert_packet_checksums_valid(capture)
8322 # ping DS-Lite AFTR tunnel endpoint address
8323 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8324 IPv6(src=self.pg1.remote_hosts[1].ip6, dst=aftr_ip6) /
8325 ICMPv6EchoRequest())
8326 self.pg1.add_stream(p)
8327 self.pg_enable_capture(self.pg_interfaces)
8329 capture = self.pg1.get_capture(1)
8330 capture = capture[0]
8331 self.assertEqual(capture[IPv6].src, aftr_ip6)
8332 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[1].ip6)
8333 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8335 b4s = self.statistics.get_counter('/dslite/total-b4s')
8336 self.assertEqual(b4s[0][0], 2)
8337 sessions = self.statistics.get_counter('/dslite/total-sessions')
8338 self.assertEqual(sessions[0][0], 3)
8341 super(TestDSlite, self).tearDown()
8342 if not self.vpp_dead:
8343 self.logger.info(self.vapi.cli("show dslite pool"))
8345 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8346 self.logger.info(self.vapi.cli("show dslite sessions"))
8349 class TestDSliteCE(MethodHolder):
8350 """ DS-Lite CE Test Cases """
8353 def setUpConstants(cls):
8354 super(TestDSliteCE, cls).setUpConstants()
8355 cls.vpp_cmdline.extend(["nat", "{", "dslite ce", "}"])
8358 def setUpClass(cls):
8359 super(TestDSliteCE, cls).setUpClass()
8362 cls.create_pg_interfaces(range(2))
8364 cls.pg0.config_ip4()
8365 cls.pg0.resolve_arp()
8367 cls.pg1.config_ip6()
8368 cls.pg1.generate_remote_hosts(1)
8369 cls.pg1.configure_ipv6_neighbors()
8372 super(TestDSliteCE, cls).tearDownClass()
8375 def test_dslite_ce(self):
8376 """ Test DS-Lite CE """
8378 nat_config = self.vapi.nat_show_config()
8379 self.assertEqual(1, nat_config.dslite_ce)
8381 b4_ip4 = '192.0.0.2'
8382 b4_ip4_n = socket.inet_pton(socket.AF_INET, b4_ip4)
8383 b4_ip6 = '2001:db8:62aa::375e:f4c1:1'
8384 b4_ip6_n = socket.inet_pton(socket.AF_INET6, b4_ip6)
8385 self.vapi.dslite_set_b4_addr(b4_ip6_n, b4_ip4_n)
8387 aftr_ip4 = '192.0.0.1'
8388 aftr_ip4_n = socket.inet_pton(socket.AF_INET, aftr_ip4)
8389 aftr_ip6 = '2001:db8:85a3::8a2e:370:1'
8390 aftr_ip6_n = socket.inet_pton(socket.AF_INET6, aftr_ip6)
8391 self.vapi.dslite_set_aftr_addr(aftr_ip6_n, aftr_ip4_n)
8393 self.vapi.ip_add_del_route(dst_address=aftr_ip6_n,
8394 dst_address_length=128,
8395 next_hop_address=self.pg1.remote_ip6n,
8396 next_hop_sw_if_index=self.pg1.sw_if_index,
8400 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8401 IP(dst=self.pg1.remote_ip4, src=self.pg0.remote_ip4) /
8402 UDP(sport=10000, dport=20000))
8403 self.pg0.add_stream(p)
8404 self.pg_enable_capture(self.pg_interfaces)
8406 capture = self.pg1.get_capture(1)
8407 capture = capture[0]
8408 self.assertEqual(capture[IPv6].src, b4_ip6)
8409 self.assertEqual(capture[IPv6].dst, aftr_ip6)
8410 self.assertEqual(capture[IP].src, self.pg0.remote_ip4)
8411 self.assertEqual(capture[IP].dst, self.pg1.remote_ip4)
8412 self.assertEqual(capture[UDP].sport, 10000)
8413 self.assertEqual(capture[UDP].dport, 20000)
8414 self.assert_packet_checksums_valid(capture)
8417 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8418 IPv6(dst=b4_ip6, src=aftr_ip6) /
8419 IP(dst=self.pg0.remote_ip4, src=self.pg1.remote_ip4) /
8420 UDP(sport=20000, dport=10000))
8421 self.pg1.add_stream(p)
8422 self.pg_enable_capture(self.pg_interfaces)
8424 capture = self.pg0.get_capture(1)
8425 capture = capture[0]
8426 self.assertFalse(capture.haslayer(IPv6))
8427 self.assertEqual(capture[IP].src, self.pg1.remote_ip4)
8428 self.assertEqual(capture[IP].dst, self.pg0.remote_ip4)
8429 self.assertEqual(capture[UDP].sport, 20000)
8430 self.assertEqual(capture[UDP].dport, 10000)
8431 self.assert_packet_checksums_valid(capture)
8433 # ping DS-Lite B4 tunnel endpoint address
8434 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8435 IPv6(src=self.pg1.remote_hosts[0].ip6, dst=b4_ip6) /
8436 ICMPv6EchoRequest())
8437 self.pg1.add_stream(p)
8438 self.pg_enable_capture(self.pg_interfaces)
8440 capture = self.pg1.get_capture(1)
8441 capture = capture[0]
8442 self.assertEqual(capture[IPv6].src, b4_ip6)
8443 self.assertEqual(capture[IPv6].dst, self.pg1.remote_hosts[0].ip6)
8444 self.assertTrue(capture.haslayer(ICMPv6EchoReply))
8447 super(TestDSliteCE, self).tearDown()
8448 if not self.vpp_dead:
8450 self.vapi.cli("show dslite aftr-tunnel-endpoint-address"))
8452 self.vapi.cli("show dslite b4-tunnel-endpoint-address"))
8455 class TestNAT66(MethodHolder):
8456 """ NAT66 Test Cases """
8459 def setUpClass(cls):
8460 super(TestNAT66, cls).setUpClass()
8463 cls.nat_addr = 'fd01:ff::2'
8464 cls.nat_addr_n = socket.inet_pton(socket.AF_INET6, cls.nat_addr)
8466 cls.create_pg_interfaces(range(2))
8467 cls.interfaces = list(cls.pg_interfaces)
8469 for i in cls.interfaces:
8472 i.configure_ipv6_neighbors()
8475 super(TestNAT66, cls).tearDownClass()
8478 def test_static(self):
8479 """ 1:1 NAT66 test """
8480 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8481 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index, is_inside=0)
8482 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8487 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8488 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8491 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8492 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8495 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8496 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8497 ICMPv6EchoRequest())
8499 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8500 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8501 GRE() / IP() / TCP())
8503 self.pg0.add_stream(pkts)
8504 self.pg_enable_capture(self.pg_interfaces)
8506 capture = self.pg1.get_capture(len(pkts))
8507 for packet in capture:
8509 self.assertEqual(packet[IPv6].src, self.nat_addr)
8510 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
8511 self.assert_packet_checksums_valid(packet)
8513 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8518 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8519 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8522 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8523 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8526 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8527 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8530 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
8531 IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) /
8532 GRE() / IP() / TCP())
8534 self.pg1.add_stream(pkts)
8535 self.pg_enable_capture(self.pg_interfaces)
8537 capture = self.pg0.get_capture(len(pkts))
8538 for packet in capture:
8540 self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6)
8541 self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6)
8542 self.assert_packet_checksums_valid(packet)
8544 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8547 sm = self.vapi.nat66_static_mapping_dump()
8548 self.assertEqual(len(sm), 1)
8549 self.assertEqual(sm[0].total_pkts, 8)
8551 def test_check_no_translate(self):
8552 """ NAT66 translate only when egress interface is outside interface """
8553 self.vapi.nat66_add_del_interface(self.pg0.sw_if_index)
8554 self.vapi.nat66_add_del_interface(self.pg1.sw_if_index)
8555 self.vapi.nat66_add_del_static_mapping(self.pg0.remote_ip6n,
8559 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
8560 IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) /
8562 self.pg0.add_stream([p])
8563 self.pg_enable_capture(self.pg_interfaces)
8565 capture = self.pg1.get_capture(1)
8568 self.assertEqual(packet[IPv6].src, self.pg0.remote_ip6)
8569 self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6)
8571 self.logger.error(ppp("Unexpected or invalid packet:", packet))
8574 def clear_nat66(self):
8576 Clear NAT66 configuration.
8578 interfaces = self.vapi.nat66_interface_dump()
8579 for intf in interfaces:
8580 self.vapi.nat66_add_del_interface(intf.sw_if_index,
8584 static_mappings = self.vapi.nat66_static_mapping_dump()
8585 for sm in static_mappings:
8586 self.vapi.nat66_add_del_static_mapping(sm.local_ip_address,
8587 sm.external_ip_address,
8592 super(TestNAT66, self).tearDown()
8593 if not self.vpp_dead:
8594 self.logger.info(self.vapi.cli("show nat66 interfaces"))
8595 self.logger.info(self.vapi.cli("show nat66 static mappings"))
8599 if __name__ == '__main__':
8600 unittest.main(testRunner=VppTestRunner)