5 from random import randint, choice
9 from framework import tag_fixme_ubuntu2204, is_distro_ubuntu2204
10 from framework import VppTestCase, VppTestRunner, VppLoInterface
11 from scapy.data import IP_PROTOS
12 from scapy.layers.inet import IP, TCP, UDP, ICMP, GRE
13 from scapy.layers.inet import IPerror, TCPerror
14 from scapy.layers.l2 import Ether
15 from scapy.packet import Raw
16 from statistics import variance
17 from syslog_rfc5424_parser import SyslogMessage, ParseError
18 from syslog_rfc5424_parser.constants import SyslogSeverity
19 from util import ppp, pr, ip4_range
20 from vpp_acl import AclRule, VppAcl, VppAclInterface
21 from vpp_ip_route import VppIpRoute, VppRoutePath
22 from vpp_papi import VppEnum
23 from util import StatsDiff
26 class TestNAT44ED(VppTestCase):
27 """NAT44ED Test Case"""
29 nat_addr = "10.0.10.3"
40 tcp_external_port = 80
53 def plugin_enable(self, max_sessions=None):
54 max_sessions = max_sessions or self.max_sessions
55 self.vapi.nat44_ed_plugin_enable_disable(sessions=max_sessions, enable=1)
57 def plugin_disable(self):
58 self.vapi.nat44_ed_plugin_enable_disable(enable=0)
61 def config_flags(self):
62 return VppEnum.vl_api_nat_config_flags_t
65 def nat44_config_flags(self):
66 return VppEnum.vl_api_nat44_config_flags_t
69 def syslog_severity(self):
70 return VppEnum.vl_api_syslog_severity_t
73 def server_addr(self):
74 return self.pg1.remote_hosts[0].ip4
78 return randint(1024, 65535)
81 def proto2layer(proto):
82 if proto == IP_PROTOS.tcp:
84 elif proto == IP_PROTOS.udp:
86 elif proto == IP_PROTOS.icmp:
89 raise Exception("Unsupported protocol")
92 def create_and_add_ip4_table(cls, i, table_id=0):
93 cls.vapi.ip_table_add_del(is_add=1, table={"table_id": table_id})
94 i.set_table_ip4(table_id)
97 def configure_ip4_interface(cls, i, hosts=0, table_id=None):
99 cls.create_and_add_ip4_table(i, table_id)
106 i.generate_remote_hosts(hosts)
107 i.configure_ipv4_neighbors()
110 def nat_add_interface_address(cls, i):
111 cls.vapi.nat44_add_del_interface_addr(sw_if_index=i.sw_if_index, is_add=1)
113 def nat_add_inside_interface(self, i):
114 self.vapi.nat44_interface_add_del_feature(
115 flags=self.config_flags.NAT_IS_INSIDE, sw_if_index=i.sw_if_index, is_add=1
118 def nat_add_outside_interface(self, i):
119 self.vapi.nat44_interface_add_del_feature(
120 flags=self.config_flags.NAT_IS_OUTSIDE, sw_if_index=i.sw_if_index, is_add=1
123 def nat_add_address(self, address, twice_nat=0, vrf_id=0xFFFFFFFF, is_add=1):
124 flags = self.config_flags.NAT_IS_TWICE_NAT if twice_nat else 0
125 self.vapi.nat44_add_del_address_range(
126 first_ip_address=address,
127 last_ip_address=address,
133 def nat_add_static_mapping(
136 external_ip="0.0.0.0",
141 external_sw_if_index=0xFFFFFFFF,
146 if not (local_port and external_port):
147 flags |= self.config_flags.NAT_IS_ADDR_ONLY
149 self.vapi.nat44_add_del_static_mapping(
151 local_ip_address=local_ip,
152 external_ip_address=external_ip,
153 external_sw_if_index=external_sw_if_index,
154 local_port=local_port,
155 external_port=external_port,
165 if is_distro_ubuntu2204 == True and not hasattr(cls, "vpp"):
168 cls.create_pg_interfaces(range(12))
169 cls.interfaces = list(cls.pg_interfaces[:4])
171 cls.create_and_add_ip4_table(cls.pg2, 10)
173 for i in cls.interfaces:
174 cls.configure_ip4_interface(i, hosts=3)
176 # test specific (test-multiple-vrf)
177 cls.vapi.ip_table_add_del(is_add=1, table={"table_id": 1})
179 # test specific (test-one-armed-nat44-static)
180 cls.pg4.generate_remote_hosts(2)
182 cls.vapi.sw_interface_add_del_address(
183 sw_if_index=cls.pg4.sw_if_index, prefix="10.0.0.1/24"
186 cls.pg4.resolve_arp()
187 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
188 cls.pg4.resolve_arp()
190 # test specific interface (pg5)
191 cls.pg5._local_ip4 = "10.1.1.1"
192 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
193 cls.pg5.set_table_ip4(1)
196 cls.pg5.resolve_arp()
198 # test specific interface (pg6)
199 cls.pg6._local_ip4 = "10.1.2.1"
200 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
201 cls.pg6.set_table_ip4(1)
204 cls.pg6.resolve_arp()
213 [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=0)],
223 [VppRoutePath(cls.pg1.local_ip4, cls.pg1.sw_if_index)],
232 [VppRoutePath("0.0.0.0", cls.pg5.sw_if_index)],
242 [VppRoutePath("0.0.0.0", cls.pg6.sw_if_index)],
252 [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=1)],
261 cls.no_diff = StatsDiff(
264 "/nat44-ed/in2out/fastpath/tcp": 0,
265 "/nat44-ed/in2out/fastpath/udp": 0,
266 "/nat44-ed/in2out/fastpath/icmp": 0,
267 "/nat44-ed/in2out/fastpath/drops": 0,
268 "/nat44-ed/in2out/slowpath/tcp": 0,
269 "/nat44-ed/in2out/slowpath/udp": 0,
270 "/nat44-ed/in2out/slowpath/icmp": 0,
271 "/nat44-ed/in2out/slowpath/drops": 0,
272 "/nat44-ed/in2out/fastpath/tcp": 0,
273 "/nat44-ed/in2out/fastpath/udp": 0,
274 "/nat44-ed/in2out/fastpath/icmp": 0,
275 "/nat44-ed/in2out/fastpath/drops": 0,
276 "/nat44-ed/in2out/slowpath/tcp": 0,
277 "/nat44-ed/in2out/slowpath/udp": 0,
278 "/nat44-ed/in2out/slowpath/icmp": 0,
279 "/nat44-ed/in2out/slowpath/drops": 0,
281 for pg in cls.pg_interfaces
285 def get_err_counter(self, path):
286 return self.statistics.get_err_counter(path)
288 def reass_hairpinning(
297 layer = self.proto2layer(proto)
299 if proto == IP_PROTOS.tcp:
300 data = b"A" * 4 + b"B" * 16 + b"C" * 3
302 data = b"A" * 16 + b"B" * 16 + b"C" * 3
304 # send packet from host to server
305 pkts = self.create_stream_frag(
306 self.pg0, self.nat_addr, host_in_port, server_out_port, data, proto
308 self.pg0.add_stream(pkts)
309 self.pg_enable_capture(self.pg_interfaces)
311 frags = self.pg0.get_capture(len(pkts))
312 p = self.reass_frags_and_verify(frags, self.nat_addr, server_addr)
313 if proto != IP_PROTOS.icmp:
315 self.assertNotEqual(p[layer].sport, host_in_port)
316 self.assertEqual(p[layer].dport, server_in_port)
319 self.assertNotEqual(p[layer].id, host_in_port)
320 self.assertEqual(data, p[Raw].load)
322 def frag_out_of_order(
323 self, proto=IP_PROTOS.tcp, dont_translate=False, ignore_port=False
325 layer = self.proto2layer(proto)
327 if proto == IP_PROTOS.tcp:
328 data = b"A" * 4 + b"B" * 16 + b"C" * 3
330 data = b"A" * 16 + b"B" * 16 + b"C" * 3
331 self.port_in = self.random_port()
335 pkts = self.create_stream_frag(
336 self.pg0, self.pg1.remote_ip4, self.port_in, 20, data, proto
339 self.pg0.add_stream(pkts)
340 self.pg_enable_capture(self.pg_interfaces)
342 frags = self.pg1.get_capture(len(pkts))
343 if not dont_translate:
344 p = self.reass_frags_and_verify(
345 frags, self.nat_addr, self.pg1.remote_ip4
348 p = self.reass_frags_and_verify(
349 frags, self.pg0.remote_ip4, self.pg1.remote_ip4
351 if proto != IP_PROTOS.icmp:
352 if not dont_translate:
353 self.assertEqual(p[layer].dport, 20)
355 self.assertNotEqual(p[layer].sport, self.port_in)
357 self.assertEqual(p[layer].sport, self.port_in)
360 if not dont_translate:
361 self.assertNotEqual(p[layer].id, self.port_in)
363 self.assertEqual(p[layer].id, self.port_in)
364 self.assertEqual(data, p[Raw].load)
367 if not dont_translate:
368 dst_addr = self.nat_addr
370 dst_addr = self.pg0.remote_ip4
371 if proto != IP_PROTOS.icmp:
373 dport = p[layer].sport
377 pkts = self.create_stream_frag(
378 self.pg1, dst_addr, sport, dport, data, proto, echo_reply=True
381 self.pg1.add_stream(pkts)
382 self.pg_enable_capture(self.pg_interfaces)
383 self.logger.info(self.vapi.cli("show trace"))
385 frags = self.pg0.get_capture(len(pkts))
386 p = self.reass_frags_and_verify(
387 frags, self.pg1.remote_ip4, self.pg0.remote_ip4
389 if proto != IP_PROTOS.icmp:
390 self.assertEqual(p[layer].sport, 20)
391 self.assertEqual(p[layer].dport, self.port_in)
393 self.assertEqual(p[layer].id, self.port_in)
394 self.assertEqual(data, p[Raw].load)
396 def reass_frags_and_verify(self, frags, src, dst):
399 self.assertEqual(p[IP].src, src)
400 self.assertEqual(p[IP].dst, dst)
401 self.assert_ip_checksum_valid(p)
402 buffer.seek(p[IP].frag * 8)
403 buffer.write(bytes(p[IP].payload))
404 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst, proto=frags[0][IP].proto)
405 if ip.proto == IP_PROTOS.tcp:
406 p = ip / TCP(buffer.getvalue())
407 self.logger.debug(ppp("Reassembled:", p))
408 self.assert_tcp_checksum_valid(p)
409 elif ip.proto == IP_PROTOS.udp:
410 p = ip / UDP(buffer.getvalue()[:8]) / Raw(buffer.getvalue()[8:])
411 elif ip.proto == IP_PROTOS.icmp:
412 p = ip / ICMP(buffer.getvalue())
416 self, proto=IP_PROTOS.tcp, dont_translate=False, ignore_port=False
418 layer = self.proto2layer(proto)
420 if proto == IP_PROTOS.tcp:
421 data = b"A" * 4 + b"B" * 16 + b"C" * 3
423 data = b"A" * 16 + b"B" * 16 + b"C" * 3
424 self.port_in = self.random_port()
427 pkts = self.create_stream_frag(
428 self.pg0, self.pg1.remote_ip4, self.port_in, 20, data, proto
430 self.pg0.add_stream(pkts)
431 self.pg_enable_capture(self.pg_interfaces)
433 frags = self.pg1.get_capture(len(pkts))
434 if not dont_translate:
435 p = self.reass_frags_and_verify(frags, self.nat_addr, self.pg1.remote_ip4)
437 p = self.reass_frags_and_verify(
438 frags, self.pg0.remote_ip4, self.pg1.remote_ip4
440 if proto != IP_PROTOS.icmp:
441 if not dont_translate:
442 self.assertEqual(p[layer].dport, 20)
444 self.assertNotEqual(p[layer].sport, self.port_in)
446 self.assertEqual(p[layer].sport, self.port_in)
449 if not dont_translate:
450 self.assertNotEqual(p[layer].id, self.port_in)
452 self.assertEqual(p[layer].id, self.port_in)
453 self.assertEqual(data, p[Raw].load)
456 if not dont_translate:
457 dst_addr = self.nat_addr
459 dst_addr = self.pg0.remote_ip4
460 if proto != IP_PROTOS.icmp:
462 dport = p[layer].sport
466 pkts = self.create_stream_frag(
467 self.pg1, dst_addr, sport, dport, data, proto, echo_reply=True
469 self.pg1.add_stream(pkts)
470 self.pg_enable_capture(self.pg_interfaces)
472 frags = self.pg0.get_capture(len(pkts))
473 p = self.reass_frags_and_verify(frags, self.pg1.remote_ip4, self.pg0.remote_ip4)
474 if proto != IP_PROTOS.icmp:
475 self.assertEqual(p[layer].sport, 20)
476 self.assertEqual(p[layer].dport, self.port_in)
478 self.assertEqual(p[layer].id, self.port_in)
479 self.assertEqual(data, p[Raw].load)
481 def verify_capture_out(
482 self, capture, nat_ip=None, same_port=False, dst_ip=None, ignore_port=False
485 nat_ip = self.nat_addr
486 for packet in capture:
488 self.assert_packet_checksums_valid(packet)
489 self.assertEqual(packet[IP].src, nat_ip)
490 if dst_ip is not None:
491 self.assertEqual(packet[IP].dst, dst_ip)
492 if packet.haslayer(TCP):
495 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
497 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
498 self.tcp_port_out = packet[TCP].sport
499 self.assert_packet_checksums_valid(packet)
500 elif packet.haslayer(UDP):
503 self.assertEqual(packet[UDP].sport, self.udp_port_in)
505 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
506 self.udp_port_out = packet[UDP].sport
510 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
512 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
513 self.icmp_id_out = packet[ICMP].id
514 self.assert_packet_checksums_valid(packet)
517 ppp("Unexpected or invalid packet (outside network):", packet)
521 def verify_capture_in(self, capture, in_if):
522 for packet in capture:
524 self.assert_packet_checksums_valid(packet)
525 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
526 if packet.haslayer(TCP):
527 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
528 elif packet.haslayer(UDP):
529 self.assertEqual(packet[UDP].dport, self.udp_port_in)
531 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
534 ppp("Unexpected or invalid packet (inside network):", packet)
538 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
540 dst_ip = out_if.remote_ip4
545 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
546 / IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl)
547 / TCP(sport=self.tcp_port_in, dport=20)
553 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
554 / IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl)
555 / UDP(sport=self.udp_port_in, dport=20)
561 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
562 / IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl)
563 / ICMP(id=self.icmp_id_in, type="echo-request")
569 def create_stream_out(self, out_if, dst_ip=None, ttl=64, use_inside_ports=False):
571 dst_ip = self.nat_addr
572 if not use_inside_ports:
573 tcp_port = self.tcp_port_out
574 udp_port = self.udp_port_out
575 icmp_id = self.icmp_id_out
577 tcp_port = self.tcp_port_in
578 udp_port = self.udp_port_in
579 icmp_id = self.icmp_id_in
583 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
584 / IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl)
585 / TCP(dport=tcp_port, sport=20)
591 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
592 / IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl)
593 / UDP(dport=udp_port, sport=20)
599 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
600 / IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl)
601 / ICMP(id=icmp_id, type="echo-reply")
607 def create_tcp_stream(self, in_if, out_if, count):
611 for i in range(count):
613 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
614 / IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=64)
615 / TCP(sport=port + i, dport=20)
621 def create_udp_stream(self, in_if, out_if, count, base_port=6303):
624 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
625 / IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=64)
626 / UDP(sport=base_port + i, dport=20)
628 for i in range(count)
631 def create_stream_frag(
632 self, src_if, dst, sport, dport, data, proto=IP_PROTOS.tcp, echo_reply=False
634 if proto == IP_PROTOS.tcp:
636 IP(src=src_if.remote_ip4, dst=dst)
637 / TCP(sport=sport, dport=dport)
640 p = p.__class__(scapy.compat.raw(p))
641 chksum = p[TCP].chksum
642 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
643 elif proto == IP_PROTOS.udp:
644 proto_header = UDP(sport=sport, dport=dport)
645 elif proto == IP_PROTOS.icmp:
647 proto_header = ICMP(id=sport, type="echo-request")
649 proto_header = ICMP(id=sport, type="echo-reply")
651 raise Exception("Unsupported protocol")
652 id = self.random_port()
654 if proto == IP_PROTOS.tcp:
657 raw = Raw(data[0:16])
659 Ether(src=src_if.remote_mac, dst=src_if.local_mac)
660 / IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id)
665 if proto == IP_PROTOS.tcp:
666 raw = Raw(data[4:20])
668 raw = Raw(data[16:32])
670 Ether(src=src_if.remote_mac, dst=src_if.local_mac)
671 / IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id, proto=proto)
675 if proto == IP_PROTOS.tcp:
680 Ether(src=src_if.remote_mac, dst=src_if.local_mac)
681 / IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto, id=id)
687 def frag_in_order_in_plus_out(
688 self, in_addr, out_addr, in_port, out_port, proto=IP_PROTOS.tcp
690 layer = self.proto2layer(proto)
692 if proto == IP_PROTOS.tcp:
693 data = b"A" * 4 + b"B" * 16 + b"C" * 3
695 data = b"A" * 16 + b"B" * 16 + b"C" * 3
696 port_in = self.random_port()
700 pkts = self.create_stream_frag(
701 self.pg0, out_addr, port_in, out_port, data, proto
703 self.pg0.add_stream(pkts)
704 self.pg_enable_capture(self.pg_interfaces)
706 frags = self.pg1.get_capture(len(pkts))
707 p = self.reass_frags_and_verify(frags, self.pg0.remote_ip4, in_addr)
708 if proto != IP_PROTOS.icmp:
709 self.assertEqual(p[layer].sport, port_in)
710 self.assertEqual(p[layer].dport, in_port)
712 self.assertEqual(p[layer].id, port_in)
713 self.assertEqual(data, p[Raw].load)
716 if proto != IP_PROTOS.icmp:
717 pkts = self.create_stream_frag(
718 self.pg1, self.pg0.remote_ip4, in_port, p[layer].sport, data, proto
721 pkts = self.create_stream_frag(
730 self.pg1.add_stream(pkts)
731 self.pg_enable_capture(self.pg_interfaces)
733 frags = self.pg0.get_capture(len(pkts))
734 p = self.reass_frags_and_verify(frags, out_addr, self.pg0.remote_ip4)
735 if proto != IP_PROTOS.icmp:
736 self.assertEqual(p[layer].sport, out_port)
737 self.assertEqual(p[layer].dport, port_in)
739 self.assertEqual(p[layer].id, port_in)
740 self.assertEqual(data, p[Raw].load)
742 def frag_out_of_order_in_plus_out(
743 self, in_addr, out_addr, in_port, out_port, proto=IP_PROTOS.tcp
745 layer = self.proto2layer(proto)
747 if proto == IP_PROTOS.tcp:
748 data = b"A" * 4 + b"B" * 16 + b"C" * 3
750 data = b"A" * 16 + b"B" * 16 + b"C" * 3
751 port_in = self.random_port()
755 pkts = self.create_stream_frag(
756 self.pg0, out_addr, port_in, out_port, data, proto
759 self.pg0.add_stream(pkts)
760 self.pg_enable_capture(self.pg_interfaces)
762 frags = self.pg1.get_capture(len(pkts))
763 p = self.reass_frags_and_verify(frags, self.pg0.remote_ip4, in_addr)
764 if proto != IP_PROTOS.icmp:
765 self.assertEqual(p[layer].dport, in_port)
766 self.assertEqual(p[layer].sport, port_in)
767 self.assertEqual(p[layer].dport, in_port)
769 self.assertEqual(p[layer].id, port_in)
770 self.assertEqual(data, p[Raw].load)
773 if proto != IP_PROTOS.icmp:
774 pkts = self.create_stream_frag(
775 self.pg1, self.pg0.remote_ip4, in_port, p[layer].sport, data, proto
778 pkts = self.create_stream_frag(
788 self.pg1.add_stream(pkts)
789 self.pg_enable_capture(self.pg_interfaces)
791 frags = self.pg0.get_capture(len(pkts))
792 p = self.reass_frags_and_verify(frags, out_addr, self.pg0.remote_ip4)
793 if proto != IP_PROTOS.icmp:
794 self.assertEqual(p[layer].sport, out_port)
795 self.assertEqual(p[layer].dport, port_in)
797 self.assertEqual(p[layer].id, port_in)
798 self.assertEqual(data, p[Raw].load)
800 def init_tcp_session(self, in_if, out_if, in_port, ext_port):
803 Ether(src=in_if.remote_mac, dst=in_if.local_mac)
804 / IP(src=in_if.remote_ip4, dst=out_if.remote_ip4)
805 / TCP(sport=in_port, dport=ext_port, flags="S")
808 self.pg_enable_capture(self.pg_interfaces)
810 capture = out_if.get_capture(1)
812 out_port = p[TCP].sport
814 # SYN + ACK packet out->in
816 Ether(src=out_if.remote_mac, dst=out_if.local_mac)
817 / IP(src=out_if.remote_ip4, dst=self.nat_addr)
818 / TCP(sport=ext_port, dport=out_port, flags="SA")
821 self.pg_enable_capture(self.pg_interfaces)
827 Ether(src=in_if.remote_mac, dst=in_if.local_mac)
828 / IP(src=in_if.remote_ip4, dst=out_if.remote_ip4)
829 / TCP(sport=in_port, dport=ext_port, flags="A")
832 self.pg_enable_capture(self.pg_interfaces)
834 out_if.get_capture(1)
838 def twice_nat_common(
839 self, self_twice_nat=False, same_pg=False, lb=False, client_id=None
841 twice_nat_addr = "10.0.1.3"
849 port_in1 = port_in + 1
850 port_in2 = port_in + 2
855 server1 = self.pg0.remote_hosts[0]
856 server2 = self.pg0.remote_hosts[1]
868 eh_translate = (not self_twice_nat) or (not lb and same_pg) or client_id == 1
870 self.nat_add_address(self.nat_addr)
871 self.nat_add_address(twice_nat_addr, twice_nat=1)
875 flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
877 flags |= self.config_flags.NAT_IS_TWICE_NAT
880 self.nat_add_static_mapping(
890 {"addr": server1.ip4, "port": port_in1, "probability": 50, "vrf_id": 0},
891 {"addr": server2.ip4, "port": port_in2, "probability": 50, "vrf_id": 0},
893 out_addr = self.nat_addr
895 self.vapi.nat44_add_del_lb_static_mapping(
898 external_addr=out_addr,
899 external_port=port_out,
900 protocol=IP_PROTOS.tcp,
901 local_num=len(locals),
904 self.nat_add_inside_interface(pg0)
905 self.nat_add_outside_interface(pg1)
911 assert client_id is not None
913 client = self.pg0.remote_hosts[0]
915 client = self.pg0.remote_hosts[1]
917 client = pg1.remote_hosts[0]
919 Ether(src=pg1.remote_mac, dst=pg1.local_mac)
920 / IP(src=client.ip4, dst=self.nat_addr)
921 / TCP(sport=eh_port_out, dport=port_out)
924 self.pg_enable_capture(self.pg_interfaces)
926 capture = pg0.get_capture(1)
932 if ip.dst == server1.ip4:
938 self.assertEqual(ip.dst, server.ip4)
940 self.assertIn(tcp.dport, [port_in1, port_in2])
942 self.assertEqual(tcp.dport, port_in)
944 self.assertEqual(ip.src, twice_nat_addr)
945 self.assertNotEqual(tcp.sport, eh_port_out)
947 self.assertEqual(ip.src, client.ip4)
948 self.assertEqual(tcp.sport, eh_port_out)
950 eh_port_in = tcp.sport
951 saved_port_in = tcp.dport
952 self.assert_packet_checksums_valid(p)
954 self.logger.error(ppp("Unexpected or invalid packet:", p))
958 Ether(src=server.mac, dst=pg0.local_mac)
959 / IP(src=server.ip4, dst=eh_addr_in)
960 / TCP(sport=saved_port_in, dport=eh_port_in)
963 self.pg_enable_capture(self.pg_interfaces)
965 capture = pg1.get_capture(1)
970 self.assertEqual(ip.dst, client.ip4)
971 self.assertEqual(ip.src, self.nat_addr)
972 self.assertEqual(tcp.dport, eh_port_out)
973 self.assertEqual(tcp.sport, port_out)
974 self.assert_packet_checksums_valid(p)
976 self.logger.error(ppp("Unexpected or invalid packet:", p))
980 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
981 self.assertEqual(len(sessions), 1)
982 self.assertTrue(sessions[0].flags & self.config_flags.NAT_IS_EXT_HOST_VALID)
983 self.assertTrue(sessions[0].flags & self.config_flags.NAT_IS_TWICE_NAT)
984 self.logger.info(self.vapi.cli("show nat44 sessions"))
985 self.vapi.nat44_del_session(
986 address=sessions[0].inside_ip_address,
987 port=sessions[0].inside_port,
988 protocol=sessions[0].protocol,
990 self.config_flags.NAT_IS_INSIDE
991 | self.config_flags.NAT_IS_EXT_HOST_VALID
993 ext_host_address=sessions[0].ext_host_nat_address,
994 ext_host_port=sessions[0].ext_host_nat_port,
996 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
997 self.assertEqual(len(sessions), 0)
999 def verify_syslog_sess(self, data, msgid, is_ip6=False):
1000 message = data.decode("utf-8")
1002 message = SyslogMessage.parse(message)
1003 except ParseError as e:
1004 self.logger.error(e)
1007 self.assertEqual(message.severity, SyslogSeverity.info)
1008 self.assertEqual(message.appname, "NAT")
1009 self.assertEqual(message.msgid, msgid)
1010 sd_params = message.sd.get("nsess")
1011 self.assertTrue(sd_params is not None)
1013 self.assertEqual(sd_params.get("IATYP"), "IPv6")
1014 self.assertEqual(sd_params.get("ISADDR"), self.pg0.remote_ip6)
1016 self.assertEqual(sd_params.get("IATYP"), "IPv4")
1017 self.assertEqual(sd_params.get("ISADDR"), self.pg0.remote_ip4)
1018 self.assertTrue(sd_params.get("SSUBIX") is not None)
1019 self.assertEqual(sd_params.get("ISPORT"), "%d" % self.tcp_port_in)
1020 self.assertEqual(sd_params.get("XATYP"), "IPv4")
1021 self.assertEqual(sd_params.get("XSADDR"), self.nat_addr)
1022 self.assertEqual(sd_params.get("XSPORT"), "%d" % self.tcp_port_out)
1023 self.assertEqual(sd_params.get("PROTO"), "%d" % IP_PROTOS.tcp)
1024 self.assertEqual(sd_params.get("SVLAN"), "0")
1025 self.assertEqual(sd_params.get("XDADDR"), self.pg1.remote_ip4)
1026 self.assertEqual(sd_params.get("XDPORT"), "%d" % self.tcp_external_port)
1028 def test_icmp_error(self):
1029 """NAT44ED test ICMP error message with inner header"""
1033 self.nat_add_address(self.nat_addr)
1034 self.nat_add_inside_interface(self.pg0)
1035 self.nat_add_outside_interface(self.pg1)
1037 # in2out (initiate connection)
1039 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1040 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1041 / UDP(sport=21, dport=20)
1043 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1044 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1045 / TCP(sport=21, dport=20, flags="S")
1047 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1048 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1049 / ICMP(type="echo-request", id=7777)
1053 capture = self.send_and_expect(self.pg0, p1, self.pg1)
1055 # out2in (send error message)
1057 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1058 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1059 / ICMP(type="dest-unreach", code="port-unreachable")
1064 capture = self.send_and_expect(self.pg1, p2, self.pg0)
1068 assert c[IP].dst == self.pg0.remote_ip4
1069 assert c[IPerror].src == self.pg0.remote_ip4
1070 except AssertionError as a:
1071 raise AssertionError(f"Packet {pr(c)} not translated properly") from a
1073 def test_icmp_echo_reply_trailer(self):
1074 """ICMP echo reply with ethernet trailer"""
1076 self.nat_add_address(self.nat_addr)
1077 self.nat_add_inside_interface(self.pg0)
1078 self.nat_add_outside_interface(self.pg1)
1082 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1083 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1084 / ICMP(type=8, id=0xABCD, seq=0)
1087 self.pg0.add_stream(p1)
1088 self.pg_enable_capture(self.pg_interfaces)
1090 c = self.pg1.get_capture(1)[0]
1092 self.logger.debug(self.vapi.cli("show trace"))
1096 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1097 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr, id=0xEE59)
1098 / ICMP(type=0, id=c[ICMP].id, seq=0)
1101 # force checksum calculation
1102 p2 = p2.__class__(bytes(p2))
1104 self.logger.debug(ppp("Packet before modification:", p2))
1106 # hex representation of vss monitoring ethernet trailer
1107 # this seems to be just added to end of packet without modifying
1108 # IP or ICMP lengths / checksums
1109 p2 = p2 / Raw("\x00\x00\x52\x54\x00\x46\xab\x04\x84\x18")
1110 # change it so that IP/ICMP is unaffected
1113 self.logger.debug(ppp("Packet with added trailer:", p2))
1115 self.pg1.add_stream(p2)
1116 self.pg_enable_capture(self.pg_interfaces)
1119 self.pg0.get_capture(1)
1121 def test_users_dump(self):
1122 """NAT44ED API test - nat44_user_dump"""
1124 self.nat_add_address(self.nat_addr)
1125 self.nat_add_inside_interface(self.pg0)
1126 self.nat_add_outside_interface(self.pg1)
1128 self.vapi.nat44_forwarding_enable_disable(enable=1)
1130 local_ip = self.pg0.remote_ip4
1131 external_ip = self.nat_addr
1132 self.nat_add_static_mapping(local_ip, external_ip)
1134 users = self.vapi.nat44_user_dump()
1135 self.assertEqual(len(users), 0)
1137 # in2out - static mapping match
1139 pkts = self.create_stream_out(self.pg1)
1140 self.pg1.add_stream(pkts)
1141 self.pg_enable_capture(self.pg_interfaces)
1143 capture = self.pg0.get_capture(len(pkts))
1144 self.verify_capture_in(capture, self.pg0)
1146 pkts = self.create_stream_in(self.pg0, self.pg1)
1147 self.pg0.add_stream(pkts)
1148 self.pg_enable_capture(self.pg_interfaces)
1150 capture = self.pg1.get_capture(len(pkts))
1151 self.verify_capture_out(capture, same_port=True)
1153 users = self.vapi.nat44_user_dump()
1154 self.assertEqual(len(users), 1)
1155 static_user = users[0]
1156 self.assertEqual(static_user.nstaticsessions, 3)
1157 self.assertEqual(static_user.nsessions, 0)
1159 # in2out - no static mapping match (forwarding test)
1161 host0 = self.pg0.remote_hosts[0]
1162 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1164 pkts = self.create_stream_out(
1165 self.pg1, dst_ip=self.pg0.remote_ip4, use_inside_ports=True
1167 self.pg1.add_stream(pkts)
1168 self.pg_enable_capture(self.pg_interfaces)
1170 capture = self.pg0.get_capture(len(pkts))
1171 self.verify_capture_in(capture, self.pg0)
1173 pkts = self.create_stream_in(self.pg0, self.pg1)
1174 self.pg0.add_stream(pkts)
1175 self.pg_enable_capture(self.pg_interfaces)
1177 capture = self.pg1.get_capture(len(pkts))
1178 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4, same_port=True)
1180 self.pg0.remote_hosts[0] = host0
1182 users = self.vapi.nat44_user_dump()
1183 self.assertEqual(len(users), 2)
1184 if str(users[0].ip_address) == self.pg0.remote_hosts[0].ip4:
1185 non_static_user = users[1]
1186 static_user = users[0]
1188 non_static_user = users[0]
1189 static_user = users[1]
1190 self.assertEqual(static_user.nstaticsessions, 3)
1191 self.assertEqual(static_user.nsessions, 0)
1192 self.assertEqual(non_static_user.nstaticsessions, 0)
1193 self.assertEqual(non_static_user.nsessions, 3)
1195 users = self.vapi.nat44_user_dump()
1196 self.assertEqual(len(users), 2)
1197 if str(users[0].ip_address) == self.pg0.remote_hosts[0].ip4:
1198 non_static_user = users[1]
1199 static_user = users[0]
1201 non_static_user = users[0]
1202 static_user = users[1]
1203 self.assertEqual(static_user.nstaticsessions, 3)
1204 self.assertEqual(static_user.nsessions, 0)
1205 self.assertEqual(non_static_user.nstaticsessions, 0)
1206 self.assertEqual(non_static_user.nsessions, 3)
1208 def test_frag_out_of_order_do_not_translate(self):
1209 """NAT44ED don't translate fragments arriving out of order"""
1210 self.nat_add_inside_interface(self.pg0)
1211 self.nat_add_outside_interface(self.pg1)
1212 self.vapi.nat44_forwarding_enable_disable(enable=True)
1213 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
1215 def test_forwarding(self):
1216 """NAT44ED forwarding test"""
1218 self.nat_add_inside_interface(self.pg0)
1219 self.nat_add_outside_interface(self.pg1)
1220 self.vapi.nat44_forwarding_enable_disable(enable=1)
1222 real_ip = self.pg0.remote_ip4
1223 alias_ip = self.nat_addr
1224 flags = self.config_flags.NAT_IS_ADDR_ONLY
1225 self.vapi.nat44_add_del_static_mapping(
1227 local_ip_address=real_ip,
1228 external_ip_address=alias_ip,
1229 external_sw_if_index=0xFFFFFFFF,
1234 # in2out - static mapping match
1236 pkts = self.create_stream_out(self.pg1)
1237 self.pg1.add_stream(pkts)
1238 self.pg_enable_capture(self.pg_interfaces)
1240 capture = self.pg0.get_capture(len(pkts))
1241 self.verify_capture_in(capture, self.pg0)
1243 pkts = self.create_stream_in(self.pg0, self.pg1)
1244 self.pg0.add_stream(pkts)
1245 self.pg_enable_capture(self.pg_interfaces)
1247 capture = self.pg1.get_capture(len(pkts))
1248 self.verify_capture_out(capture, same_port=True)
1250 # in2out - no static mapping match
1252 host0 = self.pg0.remote_hosts[0]
1253 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1255 pkts = self.create_stream_out(
1256 self.pg1, dst_ip=self.pg0.remote_ip4, use_inside_ports=True
1258 self.pg1.add_stream(pkts)
1259 self.pg_enable_capture(self.pg_interfaces)
1261 capture = self.pg0.get_capture(len(pkts))
1262 self.verify_capture_in(capture, self.pg0)
1264 pkts = self.create_stream_in(self.pg0, self.pg1)
1265 self.pg0.add_stream(pkts)
1266 self.pg_enable_capture(self.pg_interfaces)
1268 capture = self.pg1.get_capture(len(pkts))
1269 self.verify_capture_out(
1270 capture, nat_ip=self.pg0.remote_ip4, same_port=True
1273 self.pg0.remote_hosts[0] = host0
1275 user = self.pg0.remote_hosts[1]
1276 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
1277 self.assertEqual(len(sessions), 3)
1278 self.assertTrue(sessions[0].flags & self.config_flags.NAT_IS_EXT_HOST_VALID)
1279 self.vapi.nat44_del_session(
1280 address=sessions[0].inside_ip_address,
1281 port=sessions[0].inside_port,
1282 protocol=sessions[0].protocol,
1284 self.config_flags.NAT_IS_INSIDE
1285 | self.config_flags.NAT_IS_EXT_HOST_VALID
1287 ext_host_address=sessions[0].ext_host_address,
1288 ext_host_port=sessions[0].ext_host_port,
1290 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
1291 self.assertEqual(len(sessions), 2)
1294 self.vapi.nat44_forwarding_enable_disable(enable=0)
1295 flags = self.config_flags.NAT_IS_ADDR_ONLY
1296 self.vapi.nat44_add_del_static_mapping(
1298 local_ip_address=real_ip,
1299 external_ip_address=alias_ip,
1300 external_sw_if_index=0xFFFFFFFF,
1304 def test_output_feature_and_service2(self):
1305 """NAT44ED interface output feature and service host direct access"""
1306 self.vapi.nat44_forwarding_enable_disable(enable=1)
1307 self.nat_add_address(self.nat_addr)
1309 self.vapi.nat44_ed_add_del_output_interface(
1310 sw_if_index=self.pg1.sw_if_index, is_add=1
1313 # session initiated from service host - translate
1314 pkts = self.create_stream_in(self.pg0, self.pg1)
1315 self.pg0.add_stream(pkts)
1316 self.pg_enable_capture(self.pg_interfaces)
1318 capture = self.pg1.get_capture(len(pkts))
1319 self.verify_capture_out(capture, ignore_port=True)
1321 pkts = self.create_stream_out(self.pg1)
1322 self.pg1.add_stream(pkts)
1323 self.pg_enable_capture(self.pg_interfaces)
1325 capture = self.pg0.get_capture(len(pkts))
1326 self.verify_capture_in(capture, self.pg0)
1328 # session initiated from remote host - do not translate
1329 tcp_port_in = self.tcp_port_in
1330 udp_port_in = self.udp_port_in
1331 icmp_id_in = self.icmp_id_in
1333 self.tcp_port_in = 60303
1334 self.udp_port_in = 60304
1335 self.icmp_id_in = 60305
1338 pkts = self.create_stream_out(
1339 self.pg1, self.pg0.remote_ip4, use_inside_ports=True
1341 self.pg1.add_stream(pkts)
1342 self.pg_enable_capture(self.pg_interfaces)
1344 capture = self.pg0.get_capture(len(pkts))
1345 self.verify_capture_in(capture, self.pg0)
1347 pkts = self.create_stream_in(self.pg0, self.pg1)
1348 self.pg0.add_stream(pkts)
1349 self.pg_enable_capture(self.pg_interfaces)
1351 capture = self.pg1.get_capture(len(pkts))
1352 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4, same_port=True)
1354 self.tcp_port_in = tcp_port_in
1355 self.udp_port_in = udp_port_in
1356 self.icmp_id_in = icmp_id_in
1358 def test_twice_nat(self):
1359 """NAT44ED Twice NAT"""
1360 self.twice_nat_common()
1362 def test_self_twice_nat_positive(self):
1363 """NAT44ED Self Twice NAT (positive test)"""
1364 self.twice_nat_common(self_twice_nat=True, same_pg=True)
1366 def test_self_twice_nat_lb_positive(self):
1367 """NAT44ED Self Twice NAT local service load balancing (positive test)"""
1368 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True, client_id=1)
1370 def test_twice_nat_lb(self):
1371 """NAT44ED Twice NAT local service load balancing"""
1372 self.twice_nat_common(lb=True)
1374 def test_output_feature(self):
1375 """NAT44ED interface output feature (in2out postrouting)"""
1376 self.vapi.nat44_forwarding_enable_disable(enable=1)
1377 self.nat_add_address(self.nat_addr)
1379 self.nat_add_outside_interface(self.pg0)
1380 self.vapi.nat44_ed_add_del_output_interface(
1381 sw_if_index=self.pg1.sw_if_index, is_add=1
1385 pkts = self.create_stream_in(self.pg0, self.pg1)
1386 self.pg0.add_stream(pkts)
1387 self.pg_enable_capture(self.pg_interfaces)
1389 capture = self.pg1.get_capture(len(pkts))
1390 self.verify_capture_out(capture, ignore_port=True)
1391 self.logger.debug(self.vapi.cli("show trace"))
1394 pkts = self.create_stream_out(self.pg1)
1395 self.pg1.add_stream(pkts)
1396 self.pg_enable_capture(self.pg_interfaces)
1398 capture = self.pg0.get_capture(len(pkts))
1399 self.verify_capture_in(capture, self.pg0)
1400 self.logger.debug(self.vapi.cli("show trace"))
1403 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1404 self.pg0.add_stream(pkts)
1405 self.pg_enable_capture(self.pg_interfaces)
1407 capture = self.pg1.get_capture(len(pkts))
1408 self.verify_capture_out(capture, ignore_port=True)
1409 self.logger.debug(self.vapi.cli("show trace"))
1412 pkts = self.create_stream_out(self.pg1, ttl=2)
1413 self.pg1.add_stream(pkts)
1414 self.pg_enable_capture(self.pg_interfaces)
1416 capture = self.pg0.get_capture(len(pkts))
1417 self.verify_capture_in(capture, self.pg0)
1418 self.logger.debug(self.vapi.cli("show trace"))
1421 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1422 capture = self.send_and_expect_some(self.pg0, pkts, self.pg0)
1424 self.assertIn(ICMP, p)
1425 self.assertEqual(p[ICMP].type, 11) # 11 == time-exceeded
1427 def test_static_with_port_out2(self):
1428 """NAT44ED 1:1 NAPT asymmetrical rule"""
1433 self.vapi.nat44_forwarding_enable_disable(enable=1)
1434 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1435 self.nat_add_static_mapping(
1436 self.pg0.remote_ip4,
1440 proto=IP_PROTOS.tcp,
1444 self.nat_add_inside_interface(self.pg0)
1445 self.nat_add_outside_interface(self.pg1)
1447 # from client to service
1449 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1450 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1451 / TCP(sport=12345, dport=external_port)
1453 self.pg1.add_stream(p)
1454 self.pg_enable_capture(self.pg_interfaces)
1456 capture = self.pg0.get_capture(1)
1461 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1462 self.assertEqual(tcp.dport, local_port)
1463 self.assert_packet_checksums_valid(p)
1465 self.logger.error(ppp("Unexpected or invalid packet:", p))
1470 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1471 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1475 self.pg0.add_stream(p)
1476 self.pg_enable_capture(self.pg_interfaces)
1478 capture = self.pg1.get_capture(1)
1481 self.assertEqual(p[IP].src, self.nat_addr)
1483 self.assertEqual(inner.dst, self.nat_addr)
1484 self.assertEqual(inner[TCPerror].dport, external_port)
1486 self.logger.error(ppp("Unexpected or invalid packet:", p))
1489 # from service back to client
1491 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1492 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1493 / TCP(sport=local_port, dport=12345)
1495 self.pg0.add_stream(p)
1496 self.pg_enable_capture(self.pg_interfaces)
1498 capture = self.pg1.get_capture(1)
1503 self.assertEqual(ip.src, self.nat_addr)
1504 self.assertEqual(tcp.sport, external_port)
1505 self.assert_packet_checksums_valid(p)
1507 self.logger.error(ppp("Unexpected or invalid packet:", p))
1512 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1513 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1517 self.pg1.add_stream(p)
1518 self.pg_enable_capture(self.pg_interfaces)
1520 capture = self.pg0.get_capture(1)
1523 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
1525 self.assertEqual(inner.src, self.pg0.remote_ip4)
1526 self.assertEqual(inner[TCPerror].sport, local_port)
1528 self.logger.error(ppp("Unexpected or invalid packet:", p))
1531 # from client to server (no translation)
1533 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1534 / IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4)
1535 / TCP(sport=12346, dport=local_port)
1537 self.pg1.add_stream(p)
1538 self.pg_enable_capture(self.pg_interfaces)
1540 capture = self.pg0.get_capture(1)
1545 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1546 self.assertEqual(tcp.dport, local_port)
1547 self.assert_packet_checksums_valid(p)
1549 self.logger.error(ppp("Unexpected or invalid packet:", p))
1552 # from service back to client (no translation)
1554 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1555 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1556 / TCP(sport=local_port, dport=12346)
1558 self.pg0.add_stream(p)
1559 self.pg_enable_capture(self.pg_interfaces)
1561 capture = self.pg1.get_capture(1)
1566 self.assertEqual(ip.src, self.pg0.remote_ip4)
1567 self.assertEqual(tcp.sport, local_port)
1568 self.assert_packet_checksums_valid(p)
1570 self.logger.error(ppp("Unexpected or invalid packet:", p))
1573 def test_static_lb(self):
1574 """NAT44ED local service load balancing"""
1575 external_addr_n = self.nat_addr
1578 server1 = self.pg0.remote_hosts[0]
1579 server2 = self.pg0.remote_hosts[1]
1582 {"addr": server1.ip4, "port": local_port, "probability": 70, "vrf_id": 0},
1583 {"addr": server2.ip4, "port": local_port, "probability": 30, "vrf_id": 0},
1586 self.nat_add_address(self.nat_addr)
1587 self.vapi.nat44_add_del_lb_static_mapping(
1589 external_addr=external_addr_n,
1590 external_port=external_port,
1591 protocol=IP_PROTOS.tcp,
1592 local_num=len(locals),
1595 flags = self.config_flags.NAT_IS_INSIDE
1596 self.vapi.nat44_interface_add_del_feature(
1597 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1599 self.vapi.nat44_interface_add_del_feature(
1600 sw_if_index=self.pg1.sw_if_index, is_add=1
1603 # from client to service
1605 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1606 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1607 / TCP(sport=12345, dport=external_port)
1609 self.pg1.add_stream(p)
1610 self.pg_enable_capture(self.pg_interfaces)
1612 capture = self.pg0.get_capture(1)
1618 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1619 if ip.dst == server1.ip4:
1623 self.assertEqual(tcp.dport, local_port)
1624 self.assert_packet_checksums_valid(p)
1626 self.logger.error(ppp("Unexpected or invalid packet:", p))
1629 # from service back to client
1631 Ether(src=server.mac, dst=self.pg0.local_mac)
1632 / IP(src=server.ip4, dst=self.pg1.remote_ip4)
1633 / TCP(sport=local_port, dport=12345)
1635 self.pg0.add_stream(p)
1636 self.pg_enable_capture(self.pg_interfaces)
1638 capture = self.pg1.get_capture(1)
1643 self.assertEqual(ip.src, self.nat_addr)
1644 self.assertEqual(tcp.sport, external_port)
1645 self.assert_packet_checksums_valid(p)
1647 self.logger.error(ppp("Unexpected or invalid packet:", p))
1650 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
1651 self.assertEqual(len(sessions), 1)
1652 self.assertTrue(sessions[0].flags & self.config_flags.NAT_IS_EXT_HOST_VALID)
1653 self.vapi.nat44_del_session(
1654 address=sessions[0].inside_ip_address,
1655 port=sessions[0].inside_port,
1656 protocol=sessions[0].protocol,
1658 self.config_flags.NAT_IS_INSIDE
1659 | self.config_flags.NAT_IS_EXT_HOST_VALID
1661 ext_host_address=sessions[0].ext_host_address,
1662 ext_host_port=sessions[0].ext_host_port,
1664 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
1665 self.assertEqual(len(sessions), 0)
1667 def test_static_lb_2(self):
1668 """NAT44ED local service load balancing (asymmetrical rule)"""
1669 external_addr = self.nat_addr
1672 server1 = self.pg0.remote_hosts[0]
1673 server2 = self.pg0.remote_hosts[1]
1676 {"addr": server1.ip4, "port": local_port, "probability": 70, "vrf_id": 0},
1677 {"addr": server2.ip4, "port": local_port, "probability": 30, "vrf_id": 0},
1680 self.vapi.nat44_forwarding_enable_disable(enable=1)
1681 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1682 self.vapi.nat44_add_del_lb_static_mapping(
1685 external_addr=external_addr,
1686 external_port=external_port,
1687 protocol=IP_PROTOS.tcp,
1688 local_num=len(locals),
1691 flags = self.config_flags.NAT_IS_INSIDE
1692 self.vapi.nat44_interface_add_del_feature(
1693 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1695 self.vapi.nat44_interface_add_del_feature(
1696 sw_if_index=self.pg1.sw_if_index, is_add=1
1699 # from client to service
1701 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1702 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1703 / TCP(sport=12345, dport=external_port)
1705 self.pg1.add_stream(p)
1706 self.pg_enable_capture(self.pg_interfaces)
1708 capture = self.pg0.get_capture(1)
1714 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1715 if ip.dst == server1.ip4:
1719 self.assertEqual(tcp.dport, local_port)
1720 self.assert_packet_checksums_valid(p)
1722 self.logger.error(ppp("Unexpected or invalid packet:", p))
1725 # from service back to client
1727 Ether(src=server.mac, dst=self.pg0.local_mac)
1728 / IP(src=server.ip4, dst=self.pg1.remote_ip4)
1729 / TCP(sport=local_port, dport=12345)
1731 self.pg0.add_stream(p)
1732 self.pg_enable_capture(self.pg_interfaces)
1734 capture = self.pg1.get_capture(1)
1739 self.assertEqual(ip.src, self.nat_addr)
1740 self.assertEqual(tcp.sport, external_port)
1741 self.assert_packet_checksums_valid(p)
1743 self.logger.error(ppp("Unexpected or invalid packet:", p))
1746 # from client to server (no translation)
1748 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1749 / IP(src=self.pg1.remote_ip4, dst=server1.ip4)
1750 / TCP(sport=12346, dport=local_port)
1752 self.pg1.add_stream(p)
1753 self.pg_enable_capture(self.pg_interfaces)
1755 capture = self.pg0.get_capture(1)
1761 self.assertEqual(ip.dst, server1.ip4)
1762 self.assertEqual(tcp.dport, local_port)
1763 self.assert_packet_checksums_valid(p)
1765 self.logger.error(ppp("Unexpected or invalid packet:", p))
1768 # from service back to client (no translation)
1770 Ether(src=server1.mac, dst=self.pg0.local_mac)
1771 / IP(src=server1.ip4, dst=self.pg1.remote_ip4)
1772 / TCP(sport=local_port, dport=12346)
1774 self.pg0.add_stream(p)
1775 self.pg_enable_capture(self.pg_interfaces)
1777 capture = self.pg1.get_capture(1)
1782 self.assertEqual(ip.src, server1.ip4)
1783 self.assertEqual(tcp.sport, local_port)
1784 self.assert_packet_checksums_valid(p)
1786 self.logger.error(ppp("Unexpected or invalid packet:", p))
1789 def test_lb_affinity(self):
1790 """NAT44ED local service load balancing affinity"""
1791 external_addr = self.nat_addr
1794 server1 = self.pg0.remote_hosts[0]
1795 server2 = self.pg0.remote_hosts[1]
1798 {"addr": server1.ip4, "port": local_port, "probability": 50, "vrf_id": 0},
1799 {"addr": server2.ip4, "port": local_port, "probability": 50, "vrf_id": 0},
1802 self.nat_add_address(self.nat_addr)
1803 self.vapi.nat44_add_del_lb_static_mapping(
1805 external_addr=external_addr,
1806 external_port=external_port,
1807 protocol=IP_PROTOS.tcp,
1809 local_num=len(locals),
1812 flags = self.config_flags.NAT_IS_INSIDE
1813 self.vapi.nat44_interface_add_del_feature(
1814 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1816 self.vapi.nat44_interface_add_del_feature(
1817 sw_if_index=self.pg1.sw_if_index, is_add=1
1821 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1822 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1823 / TCP(sport=1025, dport=external_port)
1825 self.pg1.add_stream(p)
1826 self.pg_enable_capture(self.pg_interfaces)
1828 capture = self.pg0.get_capture(1)
1829 backend = capture[0][IP].dst
1831 sessions = self.vapi.nat44_user_session_dump(backend, 0)
1832 self.assertEqual(len(sessions), 1)
1833 self.assertTrue(sessions[0].flags & self.config_flags.NAT_IS_EXT_HOST_VALID)
1834 self.vapi.nat44_del_session(
1835 address=sessions[0].inside_ip_address,
1836 port=sessions[0].inside_port,
1837 protocol=sessions[0].protocol,
1839 self.config_flags.NAT_IS_INSIDE
1840 | self.config_flags.NAT_IS_EXT_HOST_VALID
1842 ext_host_address=sessions[0].ext_host_address,
1843 ext_host_port=sessions[0].ext_host_port,
1847 for port in range(1030, 1100):
1849 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1850 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1851 / TCP(sport=port, dport=external_port)
1854 self.pg1.add_stream(pkts)
1855 self.pg_enable_capture(self.pg_interfaces)
1857 capture = self.pg0.get_capture(len(pkts))
1859 self.assertEqual(p[IP].dst, backend)
1861 def test_multiple_vrf_1(self):
1862 """Multiple VRF - both client & service in VRF1"""
1864 external_addr = "1.2.3.4"
1869 flags = self.config_flags.NAT_IS_INSIDE
1870 self.vapi.nat44_interface_add_del_feature(
1871 sw_if_index=self.pg5.sw_if_index, is_add=1
1873 self.vapi.nat44_interface_add_del_feature(
1874 sw_if_index=self.pg5.sw_if_index, is_add=1, flags=flags
1876 self.vapi.nat44_interface_add_del_feature(
1877 sw_if_index=self.pg6.sw_if_index, is_add=1
1879 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1880 self.nat_add_static_mapping(
1881 self.pg5.remote_ip4,
1886 proto=IP_PROTOS.tcp,
1891 Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac)
1892 / IP(src=self.pg6.remote_ip4, dst=external_addr)
1893 / TCP(sport=12345, dport=external_port)
1895 self.pg6.add_stream(p)
1896 self.pg_enable_capture(self.pg_interfaces)
1898 capture = self.pg5.get_capture(1)
1903 self.assertEqual(ip.dst, self.pg5.remote_ip4)
1904 self.assertEqual(tcp.dport, local_port)
1905 self.assert_packet_checksums_valid(p)
1907 self.logger.error(ppp("Unexpected or invalid packet:", p))
1911 Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac)
1912 / IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4)
1913 / TCP(sport=local_port, dport=12345)
1915 self.pg5.add_stream(p)
1916 self.pg_enable_capture(self.pg_interfaces)
1918 capture = self.pg6.get_capture(1)
1923 self.assertEqual(ip.src, external_addr)
1924 self.assertEqual(tcp.sport, external_port)
1925 self.assert_packet_checksums_valid(p)
1927 self.logger.error(ppp("Unexpected or invalid packet:", p))
1930 def test_multiple_vrf_2(self):
1931 """Multiple VRF - dynamic NAT from VRF1 to VRF0 (output-feature)"""
1933 external_addr = "1.2.3.4"
1938 self.nat_add_address(self.nat_addr)
1939 flags = self.config_flags.NAT_IS_INSIDE
1940 self.vapi.nat44_ed_add_del_output_interface(
1941 sw_if_index=self.pg1.sw_if_index, is_add=1
1943 self.vapi.nat44_interface_add_del_feature(
1944 sw_if_index=self.pg5.sw_if_index, is_add=1
1946 self.vapi.nat44_interface_add_del_feature(
1947 sw_if_index=self.pg5.sw_if_index, is_add=1, flags=flags
1949 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1950 self.nat_add_static_mapping(
1951 self.pg5.remote_ip4,
1956 proto=IP_PROTOS.tcp,
1961 Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac)
1962 / IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4)
1963 / TCP(sport=2345, dport=22)
1965 self.pg5.add_stream(p)
1966 self.pg_enable_capture(self.pg_interfaces)
1968 capture = self.pg1.get_capture(1)
1973 self.assertEqual(ip.src, self.nat_addr)
1974 self.assert_packet_checksums_valid(p)
1977 self.logger.error(ppp("Unexpected or invalid packet:", p))
1981 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1982 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1983 / TCP(sport=22, dport=port)
1985 self.pg1.add_stream(p)
1986 self.pg_enable_capture(self.pg_interfaces)
1988 capture = self.pg5.get_capture(1)
1993 self.assertEqual(ip.dst, self.pg5.remote_ip4)
1994 self.assertEqual(tcp.dport, 2345)
1995 self.assert_packet_checksums_valid(p)
1997 self.logger.error(ppp("Unexpected or invalid packet:", p))
2000 def test_multiple_vrf_3(self):
2001 """Multiple VRF - client in VRF1, service in VRF0"""
2003 external_addr = "1.2.3.4"
2008 flags = self.config_flags.NAT_IS_INSIDE
2009 self.vapi.nat44_interface_add_del_feature(
2010 sw_if_index=self.pg0.sw_if_index, is_add=1
2012 self.vapi.nat44_interface_add_del_feature(
2013 sw_if_index=self.pg0.sw_if_index, is_add=1, flags=flags
2015 self.vapi.nat44_interface_add_del_feature(
2016 sw_if_index=self.pg6.sw_if_index, is_add=1
2018 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2019 self.nat_add_static_mapping(
2020 self.pg0.remote_ip4,
2021 external_sw_if_index=self.pg0.sw_if_index,
2022 local_port=local_port,
2024 external_port=external_port,
2025 proto=IP_PROTOS.tcp,
2029 # from client VRF1 to service VRF0
2031 Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac)
2032 / IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4)
2033 / TCP(sport=12346, dport=external_port)
2035 self.pg6.add_stream(p)
2036 self.pg_enable_capture(self.pg_interfaces)
2038 capture = self.pg0.get_capture(1)
2043 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2044 self.assertEqual(tcp.dport, local_port)
2045 self.assert_packet_checksums_valid(p)
2047 self.logger.error(ppp("Unexpected or invalid packet:", p))
2050 # from service VRF0 back to client VRF1
2052 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2053 / IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4)
2054 / TCP(sport=local_port, dport=12346)
2056 self.pg0.add_stream(p)
2057 self.pg_enable_capture(self.pg_interfaces)
2059 capture = self.pg6.get_capture(1)
2064 self.assertEqual(ip.src, self.pg0.local_ip4)
2065 self.assertEqual(tcp.sport, external_port)
2066 self.assert_packet_checksums_valid(p)
2068 self.logger.error(ppp("Unexpected or invalid packet:", p))
2071 def test_multiple_vrf_4(self):
2072 """Multiple VRF - client in VRF0, service in VRF1"""
2074 external_addr = "1.2.3.4"
2079 flags = self.config_flags.NAT_IS_INSIDE
2080 self.vapi.nat44_interface_add_del_feature(
2081 sw_if_index=self.pg0.sw_if_index, is_add=1
2083 self.vapi.nat44_interface_add_del_feature(
2084 sw_if_index=self.pg0.sw_if_index, is_add=1, flags=flags
2086 self.vapi.nat44_interface_add_del_feature(
2087 sw_if_index=self.pg5.sw_if_index, is_add=1
2089 self.vapi.nat44_interface_add_del_feature(
2090 sw_if_index=self.pg5.sw_if_index, is_add=1, flags=flags
2092 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2093 self.nat_add_static_mapping(
2094 self.pg5.remote_ip4,
2099 proto=IP_PROTOS.tcp,
2103 # from client VRF0 to service VRF1
2105 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2106 / IP(src=self.pg0.remote_ip4, dst=external_addr)
2107 / TCP(sport=12347, dport=external_port)
2109 self.pg0.add_stream(p)
2110 self.pg_enable_capture(self.pg_interfaces)
2112 capture = self.pg5.get_capture(1)
2117 self.assertEqual(ip.dst, self.pg5.remote_ip4)
2118 self.assertEqual(tcp.dport, local_port)
2119 self.assert_packet_checksums_valid(p)
2121 self.logger.error(ppp("Unexpected or invalid packet:", p))
2124 # from service VRF1 back to client VRF0
2126 Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac)
2127 / IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4)
2128 / TCP(sport=local_port, dport=12347)
2130 self.pg5.add_stream(p)
2131 self.pg_enable_capture(self.pg_interfaces)
2133 capture = self.pg0.get_capture(1)
2138 self.assertEqual(ip.src, external_addr)
2139 self.assertEqual(tcp.sport, external_port)
2140 self.assert_packet_checksums_valid(p)
2142 self.logger.error(ppp("Unexpected or invalid packet:", p))
2145 def test_multiple_vrf_5(self):
2146 """Multiple VRF - forwarding - no translation"""
2148 external_addr = "1.2.3.4"
2153 self.vapi.nat44_forwarding_enable_disable(enable=1)
2154 flags = self.config_flags.NAT_IS_INSIDE
2155 self.vapi.nat44_interface_add_del_feature(
2156 sw_if_index=self.pg0.sw_if_index, is_add=1
2158 self.vapi.nat44_interface_add_del_feature(
2159 sw_if_index=self.pg0.sw_if_index, is_add=1, flags=flags
2161 self.vapi.nat44_interface_add_del_feature(
2162 sw_if_index=self.pg5.sw_if_index, is_add=1
2164 self.vapi.nat44_interface_add_del_feature(
2165 sw_if_index=self.pg5.sw_if_index, is_add=1, flags=flags
2167 self.vapi.nat44_interface_add_del_feature(
2168 sw_if_index=self.pg6.sw_if_index, is_add=1
2170 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2171 self.nat_add_static_mapping(
2172 self.pg5.remote_ip4,
2177 proto=IP_PROTOS.tcp,
2180 self.nat_add_static_mapping(
2181 self.pg0.remote_ip4,
2182 external_sw_if_index=self.pg0.sw_if_index,
2183 local_port=local_port,
2185 external_port=external_port,
2186 proto=IP_PROTOS.tcp,
2190 # from client to server (both VRF1, no translation)
2192 Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac)
2193 / IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4)
2194 / TCP(sport=12348, dport=local_port)
2196 self.pg6.add_stream(p)
2197 self.pg_enable_capture(self.pg_interfaces)
2199 capture = self.pg5.get_capture(1)
2204 self.assertEqual(ip.dst, self.pg5.remote_ip4)
2205 self.assertEqual(tcp.dport, local_port)
2206 self.assert_packet_checksums_valid(p)
2208 self.logger.error(ppp("Unexpected or invalid packet:", p))
2211 # from server back to client (both VRF1, no translation)
2213 Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac)
2214 / IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4)
2215 / TCP(sport=local_port, dport=12348)
2217 self.pg5.add_stream(p)
2218 self.pg_enable_capture(self.pg_interfaces)
2220 capture = self.pg6.get_capture(1)
2225 self.assertEqual(ip.src, self.pg5.remote_ip4)
2226 self.assertEqual(tcp.sport, local_port)
2227 self.assert_packet_checksums_valid(p)
2229 self.logger.error(ppp("Unexpected or invalid packet:", p))
2232 # from client VRF1 to server VRF0 (no translation)
2234 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2235 / IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4)
2236 / TCP(sport=local_port, dport=12349)
2238 self.pg0.add_stream(p)
2239 self.pg_enable_capture(self.pg_interfaces)
2241 capture = self.pg6.get_capture(1)
2246 self.assertEqual(ip.src, self.pg0.remote_ip4)
2247 self.assertEqual(tcp.sport, local_port)
2248 self.assert_packet_checksums_valid(p)
2250 self.logger.error(ppp("Unexpected or invalid packet:", p))
2253 # from server VRF0 back to client VRF1 (no translation)
2255 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2256 / IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4)
2257 / TCP(sport=local_port, dport=12349)
2259 self.pg0.add_stream(p)
2260 self.pg_enable_capture(self.pg_interfaces)
2262 capture = self.pg6.get_capture(1)
2267 self.assertEqual(ip.src, self.pg0.remote_ip4)
2268 self.assertEqual(tcp.sport, local_port)
2269 self.assert_packet_checksums_valid(p)
2271 self.logger.error(ppp("Unexpected or invalid packet:", p))
2274 # from client VRF0 to server VRF1 (no translation)
2276 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2277 / IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4)
2278 / TCP(sport=12344, dport=local_port)
2280 self.pg0.add_stream(p)
2281 self.pg_enable_capture(self.pg_interfaces)
2283 capture = self.pg5.get_capture(1)
2288 self.assertEqual(ip.dst, self.pg5.remote_ip4)
2289 self.assertEqual(tcp.dport, local_port)
2290 self.assert_packet_checksums_valid(p)
2292 self.logger.error(ppp("Unexpected or invalid packet:", p))
2295 # from server VRF1 back to client VRF0 (no translation)
2297 Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac)
2298 / IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4)
2299 / TCP(sport=local_port, dport=12344)
2301 self.pg5.add_stream(p)
2302 self.pg_enable_capture(self.pg_interfaces)
2304 capture = self.pg0.get_capture(1)
2309 self.assertEqual(ip.src, self.pg5.remote_ip4)
2310 self.assertEqual(tcp.sport, local_port)
2311 self.assert_packet_checksums_valid(p)
2313 self.logger.error(ppp("Unexpected or invalid packet:", p))
2316 def test_outside_address_distribution(self):
2317 """NAT44ED outside address distribution based on source address"""
2323 nat_distribution = {}
2324 for i in range(1, addresses):
2326 nat_addresses.append(a)
2327 nat_distribution[a] = set()
2329 self.nat_add_inside_interface(self.pg0)
2330 self.nat_add_outside_interface(self.pg1)
2332 self.vapi.nat44_add_del_address_range(
2333 first_ip_address=nat_addresses[0],
2334 last_ip_address=nat_addresses[-1],
2340 self.pg0.generate_remote_hosts(x)
2344 info = self.create_packet_info(self.pg0, self.pg1)
2345 payload = self.info_to_payload(info)
2347 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2348 / IP(src=self.pg0.remote_hosts[i].ip4, dst=self.pg1.remote_ip4)
2349 / UDP(sport=7000 + i, dport=8000 + i)
2355 self.pg0.add_stream(pkts)
2356 self.pg_enable_capture(self.pg_interfaces)
2358 recvd = self.pg1.get_capture(len(pkts))
2359 for p_recvd in recvd:
2360 payload_info = self.payload_to_info(p_recvd[Raw])
2361 packet_index = payload_info.index
2362 info = self._packet_infos[packet_index]
2363 self.assertTrue(info is not None)
2364 self.assertEqual(packet_index, info.index)
2366 self.assertIn(p_recvd[IP].src, nat_distribution)
2367 nat_distribution[p_recvd[IP].src].add(p_sent[IP].src)
2369 var = variance(map(len, nat_distribution.values()), x / addresses)
2370 self.assertLess(var, 0.33, msg="Bad outside address distribution")
2372 def test_dynamic_edge_ports(self):
2373 """NAT44ED dynamic translation test: edge ports"""
2375 worker_count = self.vpp_worker_count or 1
2377 port_per_thread = (65536 - port_offset) // worker_count
2378 port_count = port_per_thread * worker_count
2380 # worker thread edge ports
2381 thread_edge_ports = {0, port_offset - 1, 65535}
2382 for i in range(0, worker_count):
2383 port_thread_offset = (port_per_thread * i) + port_offset
2384 for port_range_offset in [0, port_per_thread - 1]:
2385 port = port_thread_offset + port_range_offset
2386 thread_edge_ports.add(port)
2387 thread_drop_ports = set(
2389 lambda x: x not in range(port_offset, port_offset + port_count),
2397 self.nat_add_address(self.nat_addr)
2400 self.configure_ip4_interface(in_if, hosts=worker_count)
2401 self.configure_ip4_interface(out_if)
2403 self.nat_add_inside_interface(in_if)
2404 self.nat_add_outside_interface(out_if)
2407 tc1 = self.statistics["/nat44-ed/in2out/slowpath/tcp"]
2408 uc1 = self.statistics["/nat44-ed/in2out/slowpath/udp"]
2409 ic1 = self.statistics["/nat44-ed/in2out/slowpath/icmp"]
2410 dc1 = self.statistics["/nat44-ed/in2out/slowpath/drops"]
2412 pkt_count = worker_count * len(thread_edge_ports)
2414 i2o_pkts = [[] for x in range(0, worker_count)]
2415 for i in range(0, worker_count):
2416 remote_host = in_if.remote_hosts[i]
2417 for port in thread_edge_ports:
2419 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
2420 / IP(src=remote_host.ip4, dst=out_if.remote_ip4)
2421 / TCP(sport=port, dport=port)
2423 i2o_pkts[i].append(p)
2426 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
2427 / IP(src=remote_host.ip4, dst=out_if.remote_ip4)
2428 / UDP(sport=port, dport=port)
2430 i2o_pkts[i].append(p)
2433 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
2434 / IP(src=remote_host.ip4, dst=out_if.remote_ip4)
2435 / ICMP(id=port, seq=port, type="echo-request")
2437 i2o_pkts[i].append(p)
2439 for i in range(0, worker_count):
2440 if len(i2o_pkts[i]) > 0:
2441 in_if.add_stream(i2o_pkts[i], worker=i)
2443 self.pg_enable_capture(self.pg_interfaces)
2445 capture = out_if.get_capture(pkt_count * 3)
2446 for packet in capture:
2447 self.assert_packet_checksums_valid(packet)
2448 if packet.haslayer(TCP):
2449 self.assert_in_range(
2452 port_offset + port_count,
2455 elif packet.haslayer(UDP):
2456 self.assert_in_range(
2459 port_offset + port_count,
2462 elif packet.haslayer(ICMP):
2463 self.assert_in_range(
2466 port_offset + port_count,
2471 ppp("Unexpected or invalid packet (outside network):", packet)
2474 if_idx = in_if.sw_if_index
2475 tc2 = self.statistics["/nat44-ed/in2out/slowpath/tcp"]
2476 uc2 = self.statistics["/nat44-ed/in2out/slowpath/udp"]
2477 ic2 = self.statistics["/nat44-ed/in2out/slowpath/icmp"]
2478 dc2 = self.statistics["/nat44-ed/in2out/slowpath/drops"]
2480 self.assertEqual(tc2[:, if_idx].sum() - tc1[:, if_idx].sum(), pkt_count)
2481 self.assertEqual(uc2[:, if_idx].sum() - uc1[:, if_idx].sum(), pkt_count)
2482 self.assertEqual(ic2[:, if_idx].sum() - ic1[:, if_idx].sum(), pkt_count)
2483 self.assertEqual(dc2[:, if_idx].sum() - dc1[:, if_idx].sum(), 0)
2486 tc1 = self.statistics["/nat44-ed/out2in/fastpath/tcp"]
2487 uc1 = self.statistics["/nat44-ed/out2in/fastpath/udp"]
2488 ic1 = self.statistics["/nat44-ed/out2in/fastpath/icmp"]
2489 dc1 = self.statistics["/nat44-ed/out2in/fastpath/drops"]
2490 dc3 = self.statistics["/nat44-ed/out2in/slowpath/drops"]
2492 # replies to unchanged thread ports should pass on each worker,
2493 # excluding packets outside dynamic port range
2494 drop_count = worker_count * len(thread_drop_ports)
2495 pass_count = worker_count * len(thread_edge_ports) - drop_count
2497 o2i_pkts = [[] for x in range(0, worker_count)]
2498 for i in range(0, worker_count):
2499 for port in thread_edge_ports:
2501 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
2502 / IP(src=out_if.remote_ip4, dst=self.nat_addr)
2503 / TCP(sport=port, dport=port)
2505 o2i_pkts[i].append(p)
2508 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
2509 / IP(src=out_if.remote_ip4, dst=self.nat_addr)
2510 / UDP(sport=port, dport=port)
2512 o2i_pkts[i].append(p)
2515 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
2516 / IP(src=out_if.remote_ip4, dst=self.nat_addr)
2517 / ICMP(id=port, seq=port, type="echo-reply")
2519 o2i_pkts[i].append(p)
2521 for i in range(0, worker_count):
2522 if len(o2i_pkts[i]) > 0:
2523 out_if.add_stream(o2i_pkts[i], worker=i)
2525 self.pg_enable_capture(self.pg_interfaces)
2527 capture = in_if.get_capture(pass_count * 3)
2528 for packet in capture:
2529 self.assert_packet_checksums_valid(packet)
2530 if packet.haslayer(TCP):
2531 self.assertIn(packet[TCP].dport, thread_edge_ports, "dst TCP port")
2532 self.assertEqual(packet[TCP].dport, packet[TCP].sport, "TCP ports")
2533 elif packet.haslayer(UDP):
2534 self.assertIn(packet[UDP].dport, thread_edge_ports, "dst UDP port")
2535 self.assertEqual(packet[UDP].dport, packet[UDP].sport, "UDP ports")
2536 elif packet.haslayer(ICMP):
2537 self.assertIn(packet[ICMP].id, thread_edge_ports, "ICMP id")
2538 self.assertEqual(packet[ICMP].id, packet[ICMP].seq, "ICMP id & seq")
2541 ppp("Unexpected or invalid packet (inside network):", packet)
2544 if_idx = out_if.sw_if_index
2545 tc2 = self.statistics["/nat44-ed/out2in/fastpath/tcp"]
2546 uc2 = self.statistics["/nat44-ed/out2in/fastpath/udp"]
2547 ic2 = self.statistics["/nat44-ed/out2in/fastpath/icmp"]
2548 dc2 = self.statistics["/nat44-ed/out2in/fastpath/drops"]
2549 dc4 = self.statistics["/nat44-ed/out2in/slowpath/drops"]
2551 self.assertEqual(tc2[:, if_idx].sum() - tc1[:, if_idx].sum(), pass_count)
2552 self.assertEqual(uc2[:, if_idx].sum() - uc1[:, if_idx].sum(), pass_count)
2553 self.assertEqual(ic2[:, if_idx].sum() - ic1[:, if_idx].sum(), pass_count)
2554 self.assertEqual(dc2[:, if_idx].sum() - dc1[:, if_idx].sum(), 0)
2556 dc4[:, if_idx].sum() - dc3[:, if_idx].sum(), drop_count * 3
2563 def test_delete_interface(self):
2564 """NAT44ED delete nat interface"""
2566 self.nat_add_address(self.nat_addr)
2568 interfaces = self.create_loopback_interfaces(4)
2569 self.nat_add_outside_interface(interfaces[0])
2570 self.nat_add_inside_interface(interfaces[1])
2571 self.nat_add_outside_interface(interfaces[2])
2572 self.nat_add_inside_interface(interfaces[2])
2573 self.vapi.nat44_ed_add_del_output_interface(
2574 sw_if_index=interfaces[3].sw_if_index, is_add=1
2577 nat_sw_if_indices = [
2579 for i in self.vapi.nat44_interface_dump()
2580 + list(self.vapi.vpp.details_iter(self.vapi.nat44_ed_output_interface_get))
2582 self.assertEqual(len(nat_sw_if_indices), len(interfaces))
2585 for i in interfaces:
2586 # delete nat-enabled interface
2587 self.assertIn(i.sw_if_index, nat_sw_if_indices)
2588 i.remove_vpp_config()
2590 # create interface with the same index
2591 lo = VppLoInterface(self)
2592 loopbacks.append(lo)
2593 self.assertEqual(lo.sw_if_index, i.sw_if_index)
2595 # check interface is not nat-enabled
2596 nat_sw_if_indices = [
2598 for i in self.vapi.nat44_interface_dump()
2600 self.vapi.vpp.details_iter(self.vapi.nat44_ed_output_interface_get)
2603 self.assertNotIn(lo.sw_if_index, nat_sw_if_indices)
2606 i.remove_vpp_config()
2609 @tag_fixme_ubuntu2204
2610 class TestNAT44EDMW(TestNAT44ED):
2611 """NAT44ED MW Test Case"""
2613 vpp_worker_count = 4
2616 def test_dynamic(self):
2617 """NAT44ED dynamic translation test"""
2619 tcp_port_offset = 20
2620 udp_port_offset = 20
2623 self.nat_add_address(self.nat_addr)
2624 self.nat_add_inside_interface(self.pg0)
2625 self.nat_add_outside_interface(self.pg1)
2628 tc1 = self.statistics["/nat44-ed/in2out/slowpath/tcp"]
2629 uc1 = self.statistics["/nat44-ed/in2out/slowpath/udp"]
2630 ic1 = self.statistics["/nat44-ed/in2out/slowpath/icmp"]
2631 dc1 = self.statistics["/nat44-ed/in2out/slowpath/drops"]
2633 i2o_pkts = [[] for x in range(0, self.vpp_worker_count)]
2635 for i in range(pkt_count):
2637 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2638 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
2639 / TCP(sport=tcp_port_offset + i, dport=20)
2641 i2o_pkts[p[TCP].sport % self.vpp_worker_count].append(p)
2644 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2645 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
2646 / UDP(sport=udp_port_offset + i, dport=20)
2648 i2o_pkts[p[UDP].sport % self.vpp_worker_count].append(p)
2651 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2652 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
2653 / ICMP(id=icmp_id_offset + i, type="echo-request")
2655 i2o_pkts[p[ICMP].id % self.vpp_worker_count].append(p)
2657 for i in range(0, self.vpp_worker_count):
2658 if len(i2o_pkts[i]) > 0:
2659 self.pg0.add_stream(i2o_pkts[i], worker=i)
2661 self.pg_enable_capture(self.pg_interfaces)
2663 capture = self.pg1.get_capture(pkt_count * 3, timeout=5)
2665 if_idx = self.pg0.sw_if_index
2666 tc2 = self.statistics["/nat44-ed/in2out/slowpath/tcp"]
2667 uc2 = self.statistics["/nat44-ed/in2out/slowpath/udp"]
2668 ic2 = self.statistics["/nat44-ed/in2out/slowpath/icmp"]
2669 dc2 = self.statistics["/nat44-ed/in2out/slowpath/drops"]
2671 self.assertEqual(tc2[:, if_idx].sum() - tc1[:, if_idx].sum(), pkt_count)
2672 self.assertEqual(uc2[:, if_idx].sum() - uc1[:, if_idx].sum(), pkt_count)
2673 self.assertEqual(ic2[:, if_idx].sum() - ic1[:, if_idx].sum(), pkt_count)
2674 self.assertEqual(dc2[:, if_idx].sum() - dc1[:, if_idx].sum(), 0)
2676 self.logger.info(self.vapi.cli("show trace"))
2679 tc1 = self.statistics["/nat44-ed/out2in/fastpath/tcp"]
2680 uc1 = self.statistics["/nat44-ed/out2in/fastpath/udp"]
2681 ic1 = self.statistics["/nat44-ed/out2in/fastpath/icmp"]
2682 dc1 = self.statistics["/nat44-ed/out2in/fastpath/drops"]
2684 recvd_tcp_ports = set()
2685 recvd_udp_ports = set()
2686 recvd_icmp_ids = set()
2690 recvd_tcp_ports.add(p[TCP].sport)
2692 recvd_udp_ports.add(p[UDP].sport)
2694 recvd_icmp_ids.add(p[ICMP].id)
2696 recvd_tcp_ports = list(recvd_tcp_ports)
2697 recvd_udp_ports = list(recvd_udp_ports)
2698 recvd_icmp_ids = list(recvd_icmp_ids)
2700 o2i_pkts = [[] for x in range(0, self.vpp_worker_count)]
2701 for i in range(pkt_count):
2703 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2704 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
2705 / TCP(dport=choice(recvd_tcp_ports), sport=20)
2707 o2i_pkts[p[TCP].dport % self.vpp_worker_count].append(p)
2710 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2711 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
2712 / UDP(dport=choice(recvd_udp_ports), sport=20)
2714 o2i_pkts[p[UDP].dport % self.vpp_worker_count].append(p)
2717 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2718 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
2719 / ICMP(id=choice(recvd_icmp_ids), type="echo-reply")
2721 o2i_pkts[p[ICMP].id % self.vpp_worker_count].append(p)
2723 for i in range(0, self.vpp_worker_count):
2724 if len(o2i_pkts[i]) > 0:
2725 self.pg1.add_stream(o2i_pkts[i], worker=i)
2727 self.pg_enable_capture(self.pg_interfaces)
2729 capture = self.pg0.get_capture(pkt_count * 3)
2730 for packet in capture:
2732 self.assert_packet_checksums_valid(packet)
2733 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2734 if packet.haslayer(TCP):
2735 self.assert_in_range(
2738 tcp_port_offset + pkt_count,
2741 elif packet.haslayer(UDP):
2742 self.assert_in_range(
2745 udp_port_offset + pkt_count,
2749 self.assert_in_range(
2752 icmp_id_offset + pkt_count,
2757 ppp("Unexpected or invalid packet (inside network):", packet)
2761 if_idx = self.pg1.sw_if_index
2762 tc2 = self.statistics["/nat44-ed/out2in/fastpath/tcp"]
2763 uc2 = self.statistics["/nat44-ed/out2in/fastpath/udp"]
2764 ic2 = self.statistics["/nat44-ed/out2in/fastpath/icmp"]
2765 dc2 = self.statistics["/nat44-ed/out2in/fastpath/drops"]
2767 self.assertEqual(tc2[:, if_idx].sum() - tc1[:, if_idx].sum(), pkt_count)
2768 self.assertEqual(uc2[:, if_idx].sum() - uc1[:, if_idx].sum(), pkt_count)
2769 self.assertEqual(ic2[:, if_idx].sum() - ic1[:, if_idx].sum(), pkt_count)
2770 self.assertEqual(dc2[:, if_idx].sum() - dc1[:, if_idx].sum(), 0)
2772 sc = self.statistics["/nat44-ed/total-sessions"]
2775 len(recvd_tcp_ports) + len(recvd_udp_ports) + len(recvd_icmp_ids),
2778 def test_frag_in_order(self):
2779 """NAT44ED translate fragments arriving in order"""
2781 self.nat_add_address(self.nat_addr)
2782 self.nat_add_inside_interface(self.pg0)
2783 self.nat_add_outside_interface(self.pg1)
2785 self.frag_in_order(proto=IP_PROTOS.tcp, ignore_port=True)
2786 self.frag_in_order(proto=IP_PROTOS.udp, ignore_port=True)
2787 self.frag_in_order(proto=IP_PROTOS.icmp, ignore_port=True)
2789 def test_frag_in_order_do_not_translate(self):
2790 """NAT44ED don't translate fragments arriving in order"""
2792 self.nat_add_address(self.nat_addr)
2793 self.nat_add_inside_interface(self.pg0)
2794 self.nat_add_outside_interface(self.pg1)
2795 self.vapi.nat44_forwarding_enable_disable(enable=True)
2797 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
2799 def test_frag_out_of_order(self):
2800 """NAT44ED translate fragments arriving out of order"""
2802 self.nat_add_address(self.nat_addr)
2803 self.nat_add_inside_interface(self.pg0)
2804 self.nat_add_outside_interface(self.pg1)
2806 self.frag_out_of_order(proto=IP_PROTOS.tcp, ignore_port=True)
2807 self.frag_out_of_order(proto=IP_PROTOS.udp, ignore_port=True)
2808 self.frag_out_of_order(proto=IP_PROTOS.icmp, ignore_port=True)
2810 def test_frag_in_order_in_plus_out(self):
2811 """NAT44ED in+out interface fragments in order"""
2813 in_port = self.random_port()
2814 out_port = self.random_port()
2816 self.nat_add_address(self.nat_addr)
2817 self.nat_add_inside_interface(self.pg0)
2818 self.nat_add_outside_interface(self.pg0)
2819 self.nat_add_inside_interface(self.pg1)
2820 self.nat_add_outside_interface(self.pg1)
2822 # add static mappings for server
2823 self.nat_add_static_mapping(
2824 self.server_addr, self.nat_addr, in_port, out_port, proto=IP_PROTOS.tcp
2826 self.nat_add_static_mapping(
2827 self.server_addr, self.nat_addr, in_port, out_port, proto=IP_PROTOS.udp
2829 self.nat_add_static_mapping(
2830 self.server_addr, self.nat_addr, proto=IP_PROTOS.icmp
2833 # run tests for each protocol
2834 self.frag_in_order_in_plus_out(
2835 self.server_addr, self.nat_addr, in_port, out_port, IP_PROTOS.tcp
2837 self.frag_in_order_in_plus_out(
2838 self.server_addr, self.nat_addr, in_port, out_port, IP_PROTOS.udp
2840 self.frag_in_order_in_plus_out(
2841 self.server_addr, self.nat_addr, in_port, out_port, IP_PROTOS.icmp
2844 def test_frag_out_of_order_in_plus_out(self):
2845 """NAT44ED in+out interface fragments out of order"""
2847 in_port = self.random_port()
2848 out_port = self.random_port()
2850 self.nat_add_address(self.nat_addr)
2851 self.nat_add_inside_interface(self.pg0)
2852 self.nat_add_outside_interface(self.pg0)
2853 self.nat_add_inside_interface(self.pg1)
2854 self.nat_add_outside_interface(self.pg1)
2856 # add static mappings for server
2857 self.nat_add_static_mapping(
2858 self.server_addr, self.nat_addr, in_port, out_port, proto=IP_PROTOS.tcp
2860 self.nat_add_static_mapping(
2861 self.server_addr, self.nat_addr, in_port, out_port, proto=IP_PROTOS.udp
2863 self.nat_add_static_mapping(
2864 self.server_addr, self.nat_addr, proto=IP_PROTOS.icmp
2867 # run tests for each protocol
2868 self.frag_out_of_order_in_plus_out(
2869 self.server_addr, self.nat_addr, in_port, out_port, IP_PROTOS.tcp
2871 self.frag_out_of_order_in_plus_out(
2872 self.server_addr, self.nat_addr, in_port, out_port, IP_PROTOS.udp
2874 self.frag_out_of_order_in_plus_out(
2875 self.server_addr, self.nat_addr, in_port, out_port, IP_PROTOS.icmp
2878 def test_reass_hairpinning(self):
2879 """NAT44ED fragments hairpinning"""
2881 server_addr = self.pg0.remote_hosts[1].ip4
2883 host_in_port = self.random_port()
2884 server_in_port = self.random_port()
2885 server_out_port = self.random_port()
2887 self.nat_add_address(self.nat_addr)
2888 self.nat_add_inside_interface(self.pg0)
2889 self.nat_add_outside_interface(self.pg1)
2891 # add static mapping for server
2892 self.nat_add_static_mapping(
2897 proto=IP_PROTOS.tcp,
2899 self.nat_add_static_mapping(
2904 proto=IP_PROTOS.udp,
2906 self.nat_add_static_mapping(server_addr, self.nat_addr)
2908 self.reass_hairpinning(
2913 proto=IP_PROTOS.tcp,
2916 self.reass_hairpinning(
2921 proto=IP_PROTOS.udp,
2924 self.reass_hairpinning(
2929 proto=IP_PROTOS.icmp,
2933 def test_session_limit_per_vrf(self):
2934 """NAT44ED per vrf session limit"""
2937 inside_vrf10 = self.pg2
2942 # 2 interfaces pg0, pg1 (vrf10, limit 1 tcp session)
2943 # non existing vrf_id makes process core dump
2944 self.vapi.nat44_set_session_limit(session_limit=limit, vrf_id=10)
2946 self.nat_add_inside_interface(inside)
2947 self.nat_add_inside_interface(inside_vrf10)
2948 self.nat_add_outside_interface(outside)
2951 self.nat_add_interface_address(outside)
2953 # BUG: causing core dump - when bad vrf_id is specified
2954 # self.nat_add_address(outside.local_ip4, vrf_id=20)
2956 stream = self.create_tcp_stream(inside_vrf10, outside, limit * 2)
2957 inside_vrf10.add_stream(stream)
2959 self.pg_enable_capture(self.pg_interfaces)
2962 capture = outside.get_capture(limit)
2964 stream = self.create_tcp_stream(inside, outside, limit * 2)
2965 inside.add_stream(stream)
2967 self.pg_enable_capture(self.pg_interfaces)
2970 capture = outside.get_capture(len(stream))
2972 def test_show_max_translations(self):
2973 """NAT44ED API test - max translations per thread"""
2974 config = self.vapi.nat44_show_running_config()
2975 self.assertEqual(self.max_sessions, config.sessions)
2977 def test_lru_cleanup(self):
2978 """NAT44ED LRU cleanup algorithm"""
2980 self.nat_add_address(self.nat_addr)
2981 self.nat_add_inside_interface(self.pg0)
2982 self.nat_add_outside_interface(self.pg1)
2984 self.vapi.nat_set_timeouts(
2985 udp=1, tcp_established=7440, tcp_transitory=30, icmp=1
2988 tcp_port_out = self.init_tcp_session(self.pg0, self.pg1, 2000, 80)
2990 for i in range(0, self.max_sessions - 1):
2992 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2993 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64)
2994 / UDP(sport=7000 + i, dport=80)
2998 self.pg0.add_stream(pkts)
2999 self.pg_enable_capture(self.pg_interfaces)
3001 self.pg1.get_capture(len(pkts))
3002 self.virtual_sleep(1.5, "wait for timeouts")
3005 for i in range(0, self.max_sessions - 1):
3007 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3008 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64)
3009 / ICMP(id=8000 + i, type="echo-request")
3013 self.pg0.add_stream(pkts)
3014 self.pg_enable_capture(self.pg_interfaces)
3016 self.pg1.get_capture(len(pkts))
3018 def test_session_rst_timeout(self):
3019 """NAT44ED session RST timeouts"""
3021 self.nat_add_address(self.nat_addr)
3022 self.nat_add_inside_interface(self.pg0)
3023 self.nat_add_outside_interface(self.pg1)
3025 self.vapi.nat_set_timeouts(
3026 udp=300, tcp_established=7440, tcp_transitory=5, icmp=60
3029 self.init_tcp_session(
3030 self.pg0, self.pg1, self.tcp_port_in, self.tcp_external_port
3033 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3034 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3035 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="R")
3037 self.send_and_expect(self.pg0, p, self.pg1)
3039 self.virtual_sleep(6)
3041 # The session is already closed
3043 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3044 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3045 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="P")
3047 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
3049 # The session can be re-opened
3051 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3052 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3053 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="S")
3055 self.send_and_expect(self.pg0, p, self.pg1)
3057 def test_session_rst_established_timeout(self):
3058 """NAT44ED session RST timeouts"""
3060 self.nat_add_address(self.nat_addr)
3061 self.nat_add_inside_interface(self.pg0)
3062 self.nat_add_outside_interface(self.pg1)
3064 self.vapi.nat_set_timeouts(
3065 udp=300, tcp_established=7440, tcp_transitory=5, icmp=60
3068 self.init_tcp_session(
3069 self.pg0, self.pg1, self.tcp_port_in, self.tcp_external_port
3072 # Wait at least the transitory time, the session is in established
3073 # state anyway. RST followed by a data packet should move it to
3075 self.virtual_sleep(6)
3077 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3078 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3079 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="R")
3081 self.send_and_expect(self.pg0, p, self.pg1)
3084 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3085 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3086 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="P")
3088 self.send_and_expect(self.pg0, p, self.pg1)
3090 # State is transitory, session should be closed after 6 seconds
3091 self.virtual_sleep(6)
3094 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3095 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3096 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="P")
3098 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
3100 def test_dynamic_out_of_ports(self):
3101 """NAT44ED dynamic translation test: out of ports"""
3103 self.nat_add_inside_interface(self.pg0)
3104 self.nat_add_outside_interface(self.pg1)
3106 # in2out and no NAT addresses added
3107 pkts = self.create_stream_in(self.pg0, self.pg1)
3109 self.send_and_assert_no_replies(
3113 stats_diff=self.no_diff
3116 "/err/nat44-ed-in2out-slowpath/out of ports": len(pkts),
3118 self.pg0.sw_if_index: {
3119 "/nat44-ed/in2out/slowpath/drops": len(pkts),
3124 # in2out after NAT addresses added
3125 self.nat_add_address(self.nat_addr)
3127 tcpn, udpn, icmpn = (
3128 sum(x) for x in zip(*((TCP in p, UDP in p, ICMP in p) for p in pkts))
3131 self.send_and_expect(
3136 stats_diff=self.no_diff
3139 "/err/nat44-ed-in2out-slowpath/out of ports": 0,
3141 self.pg0.sw_if_index: {
3142 "/nat44-ed/in2out/slowpath/drops": 0,
3143 "/nat44-ed/in2out/slowpath/tcp": tcpn,
3144 "/nat44-ed/in2out/slowpath/udp": udpn,
3145 "/nat44-ed/in2out/slowpath/icmp": icmpn,
3150 def test_unknown_proto(self):
3151 """NAT44ED translate packet with unknown protocol"""
3153 self.nat_add_address(self.nat_addr)
3154 self.nat_add_inside_interface(self.pg0)
3155 self.nat_add_outside_interface(self.pg1)
3159 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3160 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3161 / TCP(sport=self.tcp_port_in, dport=20)
3163 self.pg0.add_stream(p)
3164 self.pg_enable_capture(self.pg_interfaces)
3166 p = self.pg1.get_capture(1)
3169 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3170 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3172 / IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4)
3173 / TCP(sport=1234, dport=1234)
3175 self.pg0.add_stream(p)
3176 self.pg_enable_capture(self.pg_interfaces)
3178 p = self.pg1.get_capture(1)
3181 self.assertEqual(packet[IP].src, self.nat_addr)
3182 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3183 self.assertEqual(packet.haslayer(GRE), 1)
3184 self.assert_packet_checksums_valid(packet)
3186 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3191 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
3192 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3194 / IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4)
3195 / TCP(sport=1234, dport=1234)
3197 self.pg1.add_stream(p)
3198 self.pg_enable_capture(self.pg_interfaces)
3200 p = self.pg0.get_capture(1)
3203 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3204 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3205 self.assertEqual(packet.haslayer(GRE), 1)
3206 self.assert_packet_checksums_valid(packet)
3208 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3211 def test_hairpinning_unknown_proto(self):
3212 """NAT44ED translate packet with unknown protocol - hairpinning"""
3213 host = self.pg0.remote_hosts[0]
3214 server = self.pg0.remote_hosts[1]
3216 server_out_port = 8765
3217 server_nat_ip = "10.0.0.11"
3219 self.nat_add_address(self.nat_addr)
3220 self.nat_add_inside_interface(self.pg0)
3221 self.nat_add_outside_interface(self.pg1)
3223 # add static mapping for server
3224 self.nat_add_static_mapping(server.ip4, server_nat_ip)
3228 Ether(src=host.mac, dst=self.pg0.local_mac)
3229 / IP(src=host.ip4, dst=server_nat_ip)
3230 / TCP(sport=host_in_port, dport=server_out_port)
3232 self.pg0.add_stream(p)
3233 self.pg_enable_capture(self.pg_interfaces)
3235 self.pg0.get_capture(1)
3238 Ether(dst=self.pg0.local_mac, src=host.mac)
3239 / IP(src=host.ip4, dst=server_nat_ip)
3241 / IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4)
3242 / TCP(sport=1234, dport=1234)
3244 self.pg0.add_stream(p)
3245 self.pg_enable_capture(self.pg_interfaces)
3247 p = self.pg0.get_capture(1)
3250 self.assertEqual(packet[IP].src, self.nat_addr)
3251 self.assertEqual(packet[IP].dst, server.ip4)
3252 self.assertEqual(packet.haslayer(GRE), 1)
3253 self.assert_packet_checksums_valid(packet)
3255 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3260 Ether(dst=self.pg0.local_mac, src=server.mac)
3261 / IP(src=server.ip4, dst=self.nat_addr)
3263 / IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4)
3264 / TCP(sport=1234, dport=1234)
3266 self.pg0.add_stream(p)
3267 self.pg_enable_capture(self.pg_interfaces)
3269 p = self.pg0.get_capture(1)
3272 self.assertEqual(packet[IP].src, server_nat_ip)
3273 self.assertEqual(packet[IP].dst, host.ip4)
3274 self.assertEqual(packet.haslayer(GRE), 1)
3275 self.assert_packet_checksums_valid(packet)
3277 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3280 def test_output_feature_and_service(self):
3281 """NAT44ED interface output feature and services"""
3282 external_addr = "1.2.3.4"
3286 self.vapi.nat44_forwarding_enable_disable(enable=1)
3287 self.nat_add_address(self.nat_addr)
3288 flags = self.config_flags.NAT_IS_ADDR_ONLY
3289 self.vapi.nat44_add_del_identity_mapping(
3290 ip_address=self.pg1.remote_ip4,
3291 sw_if_index=0xFFFFFFFF,
3295 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
3296 self.nat_add_static_mapping(
3297 self.pg0.remote_ip4,
3301 proto=IP_PROTOS.tcp,
3305 self.nat_add_inside_interface(self.pg0)
3306 self.nat_add_outside_interface(self.pg0)
3307 self.vapi.nat44_ed_add_del_output_interface(
3308 sw_if_index=self.pg1.sw_if_index, is_add=1
3311 # from client to service
3313 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3314 / IP(src=self.pg1.remote_ip4, dst=external_addr)
3315 / TCP(sport=12345, dport=external_port)
3317 self.pg1.add_stream(p)
3318 self.pg_enable_capture(self.pg_interfaces)
3320 capture = self.pg0.get_capture(1)
3325 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3326 self.assertEqual(tcp.dport, local_port)
3327 self.assert_packet_checksums_valid(p)
3329 self.logger.error(ppp("Unexpected or invalid packet:", p))
3332 # from service back to client
3334 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3335 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3336 / TCP(sport=local_port, dport=12345)
3338 self.pg0.add_stream(p)
3339 self.pg_enable_capture(self.pg_interfaces)
3341 capture = self.pg1.get_capture(1)
3346 self.assertEqual(ip.src, external_addr)
3347 self.assertEqual(tcp.sport, external_port)
3348 self.assert_packet_checksums_valid(p)
3350 self.logger.error(ppp("Unexpected or invalid packet:", p))
3353 # from local network host to external network
3354 pkts = self.create_stream_in(self.pg0, self.pg1)
3355 self.pg0.add_stream(pkts)
3356 self.pg_enable_capture(self.pg_interfaces)
3358 capture = self.pg1.get_capture(len(pkts))
3359 self.verify_capture_out(capture, ignore_port=True)
3360 pkts = self.create_stream_in(self.pg0, self.pg1)
3361 self.pg0.add_stream(pkts)
3362 self.pg_enable_capture(self.pg_interfaces)
3364 capture = self.pg1.get_capture(len(pkts))
3365 self.verify_capture_out(capture, ignore_port=True)
3367 # from external network back to local network host
3368 pkts = self.create_stream_out(self.pg1)
3369 self.pg1.add_stream(pkts)
3370 self.pg_enable_capture(self.pg_interfaces)
3372 capture = self.pg0.get_capture(len(pkts))
3373 self.verify_capture_in(capture, self.pg0)
3375 def test_output_feature_and_service3(self):
3376 """NAT44ED interface output feature and DST NAT"""
3377 external_addr = "1.2.3.4"
3381 self.vapi.nat44_forwarding_enable_disable(enable=1)
3382 self.nat_add_address(self.nat_addr)
3383 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
3384 self.nat_add_static_mapping(
3385 self.pg1.remote_ip4,
3389 proto=IP_PROTOS.tcp,
3393 self.nat_add_inside_interface(self.pg0)
3394 self.nat_add_outside_interface(self.pg0)
3395 self.vapi.nat44_ed_add_del_output_interface(
3396 sw_if_index=self.pg1.sw_if_index, is_add=1
3400 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3401 / IP(src=self.pg0.remote_ip4, dst=external_addr)
3402 / TCP(sport=12345, dport=external_port)
3404 self.pg0.add_stream(p)
3405 self.pg_enable_capture(self.pg_interfaces)
3407 capture = self.pg1.get_capture(1)
3412 self.assertEqual(ip.src, self.pg0.remote_ip4)
3413 self.assertEqual(tcp.sport, 12345)
3414 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3415 self.assertEqual(tcp.dport, local_port)
3416 self.assert_packet_checksums_valid(p)
3418 self.logger.error(ppp("Unexpected or invalid packet:", p))
3422 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3423 / IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4)
3424 / TCP(sport=local_port, dport=12345)
3426 self.pg1.add_stream(p)
3427 self.pg_enable_capture(self.pg_interfaces)
3429 capture = self.pg0.get_capture(1)
3434 self.assertEqual(ip.src, external_addr)
3435 self.assertEqual(tcp.sport, external_port)
3436 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3437 self.assertEqual(tcp.dport, 12345)
3438 self.assert_packet_checksums_valid(p)
3440 self.logger.error(ppp("Unexpected or invalid packet:", p))
3443 def test_self_twice_nat_lb_negative(self):
3444 """NAT44ED Self Twice NAT local service load balancing (negative test)"""
3445 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True, client_id=2)
3447 def test_self_twice_nat_negative(self):
3448 """NAT44ED Self Twice NAT (negative test)"""
3449 self.twice_nat_common(self_twice_nat=True)
3451 def test_static_lb_multi_clients(self):
3452 """NAT44ED local service load balancing - multiple clients"""
3454 external_addr = self.nat_addr
3457 server1 = self.pg0.remote_hosts[0]
3458 server2 = self.pg0.remote_hosts[1]
3459 server3 = self.pg0.remote_hosts[2]
3462 {"addr": server1.ip4, "port": local_port, "probability": 90, "vrf_id": 0},
3463 {"addr": server2.ip4, "port": local_port, "probability": 10, "vrf_id": 0},
3466 flags = self.config_flags.NAT_IS_INSIDE
3467 self.vapi.nat44_interface_add_del_feature(
3468 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
3470 self.vapi.nat44_interface_add_del_feature(
3471 sw_if_index=self.pg1.sw_if_index, is_add=1
3474 self.nat_add_address(self.nat_addr)
3475 self.vapi.nat44_add_del_lb_static_mapping(
3477 external_addr=external_addr,
3478 external_port=external_port,
3479 protocol=IP_PROTOS.tcp,
3480 local_num=len(locals),
3486 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
3488 for client in clients:
3490 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3491 / IP(src=client, dst=self.nat_addr)
3492 / TCP(sport=12345, dport=external_port)
3495 self.pg1.add_stream(pkts)
3496 self.pg_enable_capture(self.pg_interfaces)
3498 capture = self.pg0.get_capture(len(pkts))
3500 if p[IP].dst == server1.ip4:
3504 self.assertGreaterEqual(server1_n, server2_n)
3507 "addr": server3.ip4,
3514 self.vapi.nat44_lb_static_mapping_add_del_local(
3516 external_addr=external_addr,
3517 external_port=external_port,
3519 protocol=IP_PROTOS.tcp,
3524 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
3526 for client in clients:
3528 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3529 / IP(src=client, dst=self.nat_addr)
3530 / TCP(sport=12346, dport=external_port)
3533 self.assertGreater(len(pkts), 0)
3534 self.pg1.add_stream(pkts)
3535 self.pg_enable_capture(self.pg_interfaces)
3537 capture = self.pg0.get_capture(len(pkts))
3539 if p[IP].dst == server1.ip4:
3541 elif p[IP].dst == server2.ip4:
3545 self.assertGreater(server1_n, 0)
3546 self.assertGreater(server2_n, 0)
3547 self.assertGreater(server3_n, 0)
3550 "addr": server2.ip4,
3556 # remove one back-end
3557 self.vapi.nat44_lb_static_mapping_add_del_local(
3559 external_addr=external_addr,
3560 external_port=external_port,
3562 protocol=IP_PROTOS.tcp,
3567 self.pg1.add_stream(pkts)
3568 self.pg_enable_capture(self.pg_interfaces)
3570 capture = self.pg0.get_capture(len(pkts))
3572 if p[IP].dst == server1.ip4:
3574 elif p[IP].dst == server2.ip4:
3578 self.assertGreater(server1_n, 0)
3579 self.assertEqual(server2_n, 0)
3580 self.assertGreater(server3_n, 0)
3582 # put zzz in front of syslog test name so that it runs as a last test
3583 # setting syslog sender cannot be undone and if it is set, it messes
3584 # with self.send_and_assert_no_replies functionality
3585 def test_zzz_syslog_sess(self):
3586 """NAT44ED Test syslog session creation and deletion"""
3587 self.vapi.syslog_set_filter(self.syslog_severity.SYSLOG_API_SEVERITY_INFO)
3588 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
3590 self.nat_add_address(self.nat_addr)
3591 self.nat_add_inside_interface(self.pg0)
3592 self.nat_add_outside_interface(self.pg1)
3595 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3596 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3597 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port)
3599 self.pg0.add_stream(p)
3600 self.pg_enable_capture(self.pg_interfaces)
3602 capture = self.pg1.get_capture(1)
3603 self.tcp_port_out = capture[0][TCP].sport
3604 capture = self.pg3.get_capture(1)
3605 self.verify_syslog_sess(capture[0][Raw].load, "SADD")
3607 self.pg_enable_capture(self.pg_interfaces)
3609 self.nat_add_address(self.nat_addr, is_add=0)
3610 capture = self.pg3.get_capture(1)
3611 self.verify_syslog_sess(capture[0][Raw].load, "SDEL")
3613 # put zzz in front of syslog test name so that it runs as a last test
3614 # setting syslog sender cannot be undone and if it is set, it messes
3615 # with self.send_and_assert_no_replies functionality
3616 def test_zzz_syslog_sess_reopen(self):
3617 """Syslog events for session reopen"""
3618 self.vapi.syslog_set_filter(self.syslog_severity.SYSLOG_API_SEVERITY_INFO)
3619 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
3621 self.nat_add_address(self.nat_addr)
3622 self.nat_add_inside_interface(self.pg0)
3623 self.nat_add_outside_interface(self.pg1)
3627 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3628 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3629 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port)
3631 capture = self.send_and_expect(self.pg0, p, self.pg1)[0]
3632 self.tcp_port_out = capture[0][TCP].sport
3633 capture = self.pg3.get_capture(1)
3634 self.verify_syslog_sess(capture[0][Raw].load, "SADD")
3638 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
3639 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3640 / TCP(sport=self.tcp_external_port, dport=self.tcp_port_out, flags="SA")
3642 self.send_and_expect(self.pg1, p, self.pg0)
3645 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3646 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3647 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="A")
3649 self.send_and_expect(self.pg0, p, self.pg1)
3653 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3654 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3655 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="F")
3657 self.send_and_expect(self.pg0, p, self.pg1)
3661 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
3662 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3663 / TCP(sport=self.tcp_external_port, dport=self.tcp_port_out, flags="F")
3665 self.send_and_expect(self.pg1, p, self.pg0)
3667 self.init_tcp_session(
3668 self.pg0, self.pg1, self.tcp_port_in, self.tcp_external_port
3671 # 2 records should be produced - first one del & add
3672 capture = self.pg3.get_capture(2)
3673 self.verify_syslog_sess(capture[0][Raw].load, "SDEL")
3674 self.verify_syslog_sess(capture[1][Raw].load, "SADD")
3676 def test_twice_nat_interface_addr(self):
3677 """NAT44ED Acquire twice NAT addresses from interface"""
3678 flags = self.config_flags.NAT_IS_TWICE_NAT
3679 self.vapi.nat44_add_del_interface_addr(
3680 sw_if_index=self.pg11.sw_if_index, flags=flags, is_add=1
3683 # no address in NAT pool
3684 adresses = self.vapi.nat44_address_dump()
3685 self.assertEqual(0, len(adresses))
3687 # configure interface address and check NAT address pool
3688 self.pg11.config_ip4()
3689 adresses = self.vapi.nat44_address_dump()
3690 self.assertEqual(1, len(adresses))
3691 self.assertEqual(str(adresses[0].ip_address), self.pg11.local_ip4)
3692 self.assertEqual(adresses[0].flags, flags)
3694 # remove interface address and check NAT address pool
3695 self.pg11.unconfig_ip4()
3696 adresses = self.vapi.nat44_address_dump()
3697 self.assertEqual(0, len(adresses))
3699 def test_output_feature_stateful_acl(self):
3700 """NAT44ED output feature works with stateful ACL"""
3702 self.nat_add_address(self.nat_addr)
3703 self.vapi.nat44_ed_add_del_output_interface(
3704 sw_if_index=self.pg1.sw_if_index, is_add=1
3707 # First ensure that the NAT is working sans ACL
3709 # send packets out2in, no sessions yet so packets should drop
3710 pkts_out2in = self.create_stream_out(self.pg1)
3711 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
3713 # send packets into inside intf, ensure received via outside intf
3714 pkts_in2out = self.create_stream_in(self.pg0, self.pg1)
3715 capture = self.send_and_expect(
3716 self.pg0, pkts_in2out, self.pg1, len(pkts_in2out)
3718 self.verify_capture_out(capture, ignore_port=True)
3720 # send out2in again, with sessions created it should work now
3721 pkts_out2in = self.create_stream_out(self.pg1)
3722 capture = self.send_and_expect(
3723 self.pg1, pkts_out2in, self.pg0, len(pkts_out2in)
3725 self.verify_capture_in(capture, self.pg0)
3727 # Create an ACL blocking everything
3728 out2in_deny_rule = AclRule(is_permit=0)
3729 out2in_acl = VppAcl(self, rules=[out2in_deny_rule])
3730 out2in_acl.add_vpp_config()
3732 # create an ACL to permit/reflect everything
3733 in2out_reflect_rule = AclRule(is_permit=2)
3734 in2out_acl = VppAcl(self, rules=[in2out_reflect_rule])
3735 in2out_acl.add_vpp_config()
3737 # apply as input acl on interface and confirm it blocks everything
3738 acl_if = VppAclInterface(
3739 self, sw_if_index=self.pg1.sw_if_index, n_input=1, acls=[out2in_acl]
3741 acl_if.add_vpp_config()
3742 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
3745 acl_if.acls = [out2in_acl, in2out_acl]
3746 acl_if.add_vpp_config()
3747 # send in2out to generate ACL state (NAT state was created earlier)
3748 capture = self.send_and_expect(
3749 self.pg0, pkts_in2out, self.pg1, len(pkts_in2out)
3751 self.verify_capture_out(capture, ignore_port=True)
3753 # send out2in again. ACL state exists so it should work now.
3754 # TCP packets with the syn flag set also need the ack flag
3755 for p in pkts_out2in:
3756 if p.haslayer(TCP) and p[TCP].flags & 0x02:
3757 p[TCP].flags |= 0x10
3758 capture = self.send_and_expect(
3759 self.pg1, pkts_out2in, self.pg0, len(pkts_out2in)
3761 self.verify_capture_in(capture, self.pg0)
3762 self.logger.info(self.vapi.cli("show trace"))
3764 def test_tcp_close(self):
3765 """NAT44ED Close TCP session from inside network - output feature"""
3766 config = self.vapi.nat44_show_running_config()
3767 old_timeouts = config.timeouts
3769 self.vapi.nat_set_timeouts(
3770 udp=old_timeouts.udp,
3771 tcp_established=old_timeouts.tcp_established,
3772 icmp=old_timeouts.icmp,
3773 tcp_transitory=new_transitory,
3776 self.vapi.nat44_forwarding_enable_disable(enable=1)
3777 self.nat_add_address(self.pg1.local_ip4)
3778 twice_nat_addr = "10.0.1.3"
3779 service_ip = "192.168.16.150"
3780 self.nat_add_address(twice_nat_addr, twice_nat=1)
3782 flags = self.config_flags.NAT_IS_INSIDE
3783 self.vapi.nat44_interface_add_del_feature(
3784 sw_if_index=self.pg0.sw_if_index, is_add=1
3786 self.vapi.nat44_interface_add_del_feature(
3787 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
3789 self.vapi.nat44_ed_add_del_output_interface(
3790 is_add=1, sw_if_index=self.pg1.sw_if_index
3794 self.config_flags.NAT_IS_OUT2IN_ONLY | self.config_flags.NAT_IS_TWICE_NAT
3796 self.nat_add_static_mapping(
3797 self.pg0.remote_ip4, service_ip, 80, 80, proto=IP_PROTOS.tcp, flags=flags
3799 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3800 start_sessnum = len(sessions)
3802 # SYN packet out->in
3804 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3805 / IP(src=self.pg1.remote_ip4, dst=service_ip)
3806 / TCP(sport=33898, dport=80, flags="S")
3808 capture = self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
3810 tcp_port = p[TCP].sport
3812 # SYN + ACK packet in->out
3814 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3815 / IP(src=self.pg0.remote_ip4, dst=twice_nat_addr)
3816 / TCP(sport=80, dport=tcp_port, flags="SA")
3818 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
3820 # ACK packet out->in
3822 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3823 / IP(src=self.pg1.remote_ip4, dst=service_ip)
3824 / TCP(sport=33898, dport=80, flags="A")
3826 self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
3828 # FIN packet in -> out
3830 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3831 / IP(src=self.pg0.remote_ip4, dst=twice_nat_addr)
3832 / TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300)
3834 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
3836 # FIN+ACK packet out -> in
3838 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3839 / IP(src=self.pg1.remote_ip4, dst=service_ip)
3840 / TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101)
3842 self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
3844 # ACK packet in -> out
3846 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3847 / IP(src=self.pg0.remote_ip4, dst=twice_nat_addr)
3848 / TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301)
3850 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
3852 # session now in transitory timeout, but traffic still flows
3853 # try FIN packet out->in
3855 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3856 / IP(src=self.pg1.remote_ip4, dst=service_ip)
3857 / TCP(sport=33898, dport=80, flags="F")
3859 self.pg1.add_stream(p)
3860 self.pg_enable_capture(self.pg_interfaces)
3863 self.virtual_sleep(new_transitory, "wait for transitory timeout")
3864 self.pg0.get_capture(1)
3866 # session should still exist
3867 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3868 self.assertEqual(len(sessions) - start_sessnum, 1)
3870 # send FIN+ACK packet out -> in - will cause session to be wiped
3871 # but won't create a new session
3873 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3874 / IP(src=self.pg1.remote_ip4, dst=service_ip)
3875 / TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101)
3877 self.send_and_assert_no_replies(self.pg1, p)
3878 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3879 self.assertEqual(len(sessions) - start_sessnum, 0)
3881 def test_tcp_session_close_in(self):
3882 """NAT44ED Close TCP session from inside network"""
3884 in_port = self.tcp_port_in
3886 ext_port = self.tcp_external_port
3888 self.nat_add_address(self.nat_addr)
3889 self.nat_add_inside_interface(self.pg0)
3890 self.nat_add_outside_interface(self.pg1)
3891 self.nat_add_static_mapping(
3892 self.pg0.remote_ip4,
3896 proto=IP_PROTOS.tcp,
3897 flags=self.config_flags.NAT_IS_TWICE_NAT,
3900 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3901 session_n = len(sessions)
3903 self.vapi.nat_set_timeouts(
3904 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
3907 self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3909 # FIN packet in -> out
3911 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3912 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3913 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=100, ack=300)
3915 self.send_and_expect(self.pg0, p, self.pg1)
3918 # ACK packet out -> in
3920 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3921 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3922 / TCP(sport=ext_port, dport=out_port, flags="A", seq=300, ack=101)
3926 # FIN packet out -> in
3928 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3929 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3930 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=101)
3934 self.send_and_expect(self.pg1, pkts, self.pg0)
3936 # ACK packet in -> out
3938 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3939 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3940 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
3942 self.send_and_expect(self.pg0, p, self.pg1)
3944 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3945 self.assertEqual(len(sessions) - session_n, 1)
3947 # retransmit FIN packet out -> in
3949 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3950 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3951 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=101)
3954 self.send_and_expect(self.pg1, p, self.pg0)
3956 # retransmit ACK packet in -> out
3958 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3959 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3960 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
3962 self.send_and_expect(self.pg0, p, self.pg1)
3964 self.virtual_sleep(3)
3965 # retransmit ACK packet in -> out - this will cause session to be wiped
3967 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3968 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3969 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
3971 self.send_and_assert_no_replies(self.pg0, p)
3972 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3973 self.assertEqual(len(sessions) - session_n, 0)
3975 def test_tcp_session_close_out(self):
3976 """NAT44ED Close TCP session from outside network"""
3978 in_port = self.tcp_port_in
3980 ext_port = self.tcp_external_port
3982 self.nat_add_address(self.nat_addr)
3983 self.nat_add_inside_interface(self.pg0)
3984 self.nat_add_outside_interface(self.pg1)
3985 self.nat_add_static_mapping(
3986 self.pg0.remote_ip4,
3990 proto=IP_PROTOS.tcp,
3991 flags=self.config_flags.NAT_IS_TWICE_NAT,
3994 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3995 session_n = len(sessions)
3997 self.vapi.nat_set_timeouts(
3998 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
4001 _ = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
4003 # FIN packet out -> in
4005 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4006 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4007 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=100, ack=300)
4009 self.pg1.add_stream(p)
4010 self.pg_enable_capture(self.pg_interfaces)
4012 self.pg0.get_capture(1)
4014 # FIN+ACK packet in -> out
4016 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4017 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4018 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=300, ack=101)
4021 self.pg0.add_stream(p)
4022 self.pg_enable_capture(self.pg_interfaces)
4024 self.pg1.get_capture(1)
4026 # ACK packet out -> in
4028 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4029 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4030 / TCP(sport=ext_port, dport=out_port, flags="A", seq=101, ack=301)
4032 self.pg1.add_stream(p)
4033 self.pg_enable_capture(self.pg_interfaces)
4035 self.pg0.get_capture(1)
4037 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4038 self.assertEqual(len(sessions) - session_n, 1)
4040 # retransmit FIN packet out -> in
4042 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4043 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4044 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=101)
4046 self.send_and_expect(self.pg1, p, self.pg0)
4048 # retransmit ACK packet in -> out
4050 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4051 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4052 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4054 self.send_and_expect(self.pg0, p, self.pg1)
4056 self.virtual_sleep(3)
4057 # retransmit ACK packet in -> out - this will cause session to be wiped
4059 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4060 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4061 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4063 self.send_and_assert_no_replies(self.pg0, p)
4064 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4065 self.assertEqual(len(sessions) - session_n, 0)
4067 def test_tcp_session_close_simultaneous(self):
4068 """Simultaneous TCP close from both sides"""
4070 in_port = self.tcp_port_in
4073 self.nat_add_address(self.nat_addr)
4074 self.nat_add_inside_interface(self.pg0)
4075 self.nat_add_outside_interface(self.pg1)
4076 self.nat_add_static_mapping(
4077 self.pg0.remote_ip4,
4081 proto=IP_PROTOS.tcp,
4082 flags=self.config_flags.NAT_IS_TWICE_NAT,
4085 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4086 session_n = len(sessions)
4088 self.vapi.nat_set_timeouts(
4089 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
4092 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
4094 # FIN packet in -> out
4096 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4097 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4098 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=100, ack=300)
4100 self.send_and_expect(self.pg0, p, self.pg1)
4102 # FIN packet out -> in
4104 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4105 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4106 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=100)
4108 self.send_and_expect(self.pg1, p, self.pg0)
4110 # ACK packet in -> out
4112 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4113 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4114 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4116 self.send_and_expect(self.pg0, p, self.pg1)
4118 # ACK packet out -> in
4120 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4121 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4122 / TCP(sport=ext_port, dport=out_port, flags="A", seq=301, ack=101)
4124 self.send_and_expect(self.pg1, p, self.pg0)
4126 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4127 self.assertEqual(len(sessions) - session_n, 1)
4129 # retransmit FIN packet out -> in
4131 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4132 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4133 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=101)
4135 self.send_and_expect(self.pg1, p, self.pg0)
4137 # retransmit ACK packet in -> out
4139 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4140 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4141 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4143 self.send_and_expect(self.pg0, p, self.pg1)
4145 self.virtual_sleep(3)
4146 # retransmit ACK packet in -> out - this will cause session to be wiped
4148 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4149 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4150 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4152 self.pg_send(self.pg0, p)
4153 self.send_and_assert_no_replies(self.pg0, p)
4154 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4155 self.assertEqual(len(sessions) - session_n, 0)
4157 def test_tcp_session_half_reopen_inside(self):
4158 """TCP session in FIN/FIN state not reopened by in2out SYN only"""
4159 in_port = self.tcp_port_in
4162 self.nat_add_address(self.nat_addr)
4163 self.nat_add_inside_interface(self.pg0)
4164 self.nat_add_outside_interface(self.pg1)
4165 self.nat_add_static_mapping(
4166 self.pg0.remote_ip4,
4170 proto=IP_PROTOS.tcp,
4171 flags=self.config_flags.NAT_IS_TWICE_NAT,
4174 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4175 session_n = len(sessions)
4177 self.vapi.nat_set_timeouts(
4178 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
4181 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
4183 # FIN packet in -> out
4185 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4186 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4187 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=100, ack=300)
4189 self.send_and_expect(self.pg0, p, self.pg1)
4191 # FIN packet out -> in
4193 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4194 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4195 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=100)
4197 self.send_and_expect(self.pg1, p, self.pg0)
4199 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4200 self.assertEqual(len(sessions) - session_n, 1)
4202 # send SYN packet in -> out
4204 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4205 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4206 / TCP(sport=in_port, dport=ext_port, flags="S", seq=101, ack=301)
4208 self.send_and_expect(self.pg0, p, self.pg1)
4210 self.virtual_sleep(3)
4211 # send ACK packet in -> out - session should be wiped
4213 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4214 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4215 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4217 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
4218 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4219 self.assertEqual(len(sessions) - session_n, 0)
4221 def test_tcp_session_half_reopen_outside(self):
4222 """TCP session in FIN/FIN state not reopened by out2in SYN only"""
4223 in_port = self.tcp_port_in
4226 self.nat_add_address(self.nat_addr)
4227 self.nat_add_inside_interface(self.pg0)
4228 self.nat_add_outside_interface(self.pg1)
4229 self.nat_add_static_mapping(
4230 self.pg0.remote_ip4,
4234 proto=IP_PROTOS.tcp,
4235 flags=self.config_flags.NAT_IS_TWICE_NAT,
4238 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4239 session_n = len(sessions)
4241 self.vapi.nat_set_timeouts(
4242 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
4245 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
4247 # FIN packet in -> out
4249 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4250 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4251 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=100, ack=300)
4253 self.send_and_expect(self.pg0, p, self.pg1)
4255 # FIN packet out -> in
4257 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4258 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4259 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=100)
4261 self.send_and_expect(self.pg1, p, self.pg0)
4263 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4264 self.assertEqual(len(sessions) - session_n, 1)
4266 # send SYN packet out -> in
4268 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4269 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4270 / TCP(sport=ext_port, dport=out_port, flags="S", seq=300, ack=101)
4272 self.send_and_expect(self.pg1, p, self.pg0)
4274 self.virtual_sleep(3)
4275 # send ACK packet in -> out - session should be wiped
4277 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4278 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4279 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4281 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
4282 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4283 self.assertEqual(len(sessions) - session_n, 0)
4285 def test_tcp_session_reopen(self):
4286 """TCP session in FIN/FIN state reopened by SYN from both sides"""
4287 in_port = self.tcp_port_in
4290 self.nat_add_address(self.nat_addr)
4291 self.nat_add_inside_interface(self.pg0)
4292 self.nat_add_outside_interface(self.pg1)
4293 self.nat_add_static_mapping(
4294 self.pg0.remote_ip4,
4298 proto=IP_PROTOS.tcp,
4299 flags=self.config_flags.NAT_IS_TWICE_NAT,
4302 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4303 session_n = len(sessions)
4305 self.vapi.nat_set_timeouts(
4306 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
4309 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
4311 # FIN packet in -> out
4313 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4314 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4315 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=100, ack=300)
4317 self.send_and_expect(self.pg0, p, self.pg1)
4319 # FIN packet out -> in
4321 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4322 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4323 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=100)
4325 self.send_and_expect(self.pg1, p, self.pg0)
4327 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4328 self.assertEqual(len(sessions) - session_n, 1)
4330 # send SYN packet out -> in
4332 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4333 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4334 / TCP(sport=ext_port, dport=out_port, flags="S", seq=300, ack=101)
4336 self.send_and_expect(self.pg1, p, self.pg0)
4338 # send SYN packet in -> out
4340 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4341 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4342 / TCP(sport=in_port, dport=ext_port, flags="SA", seq=101, ack=301)
4344 self.send_and_expect(self.pg0, p, self.pg1)
4346 # send ACK packet out -> in
4348 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4349 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4350 / TCP(sport=ext_port, dport=out_port, flags="A", seq=300, ack=101)
4352 self.send_and_expect(self.pg1, p, self.pg0)
4354 self.virtual_sleep(3)
4355 # send ACK packet in -> out - should be forwarded and session alive
4357 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4358 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4359 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4361 self.send_and_expect(self.pg0, p, self.pg1)
4362 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4363 self.assertEqual(len(sessions) - session_n, 1)
4365 def test_dynamic_vrf(self):
4366 """NAT44ED dynamic translation test: different VRF"""
4371 self.nat_add_address(self.nat_addr, vrf_id=vrf_id_in)
4374 self.configure_ip4_interface(self.pg7, table_id=vrf_id_in)
4375 self.configure_ip4_interface(self.pg8, table_id=vrf_id_out)
4377 self.nat_add_inside_interface(self.pg7)
4378 self.nat_add_outside_interface(self.pg8)
4380 # just basic stuff nothing special
4381 pkts = self.create_stream_in(self.pg7, self.pg8)
4382 self.pg7.add_stream(pkts)
4383 self.pg_enable_capture(self.pg_interfaces)
4385 capture = self.pg8.get_capture(len(pkts))
4386 self.verify_capture_out(capture, ignore_port=True)
4388 pkts = self.create_stream_out(self.pg8)
4389 self.pg8.add_stream(pkts)
4390 self.pg_enable_capture(self.pg_interfaces)
4392 capture = self.pg7.get_capture(len(pkts))
4393 self.verify_capture_in(capture, self.pg7)
4399 self.vapi.ip_table_add_del(is_add=0, table={"table_id": vrf_id_in})
4400 self.vapi.ip_table_add_del(is_add=0, table={"table_id": vrf_id_out})
4402 def test_dynamic_output_feature_vrf(self):
4403 """NAT44ED dynamic translation test: output-feature, VRF"""
4405 # other then default (0)
4408 self.nat_add_address(self.nat_addr)
4409 self.vapi.nat44_ed_add_del_output_interface(
4410 sw_if_index=self.pg8.sw_if_index, is_add=1
4413 self.configure_ip4_interface(self.pg7, table_id=new_vrf_id)
4414 self.configure_ip4_interface(self.pg8, table_id=new_vrf_id)
4417 tcpn = self.statistics["/nat44-ed/in2out/slowpath/tcp"]
4418 udpn = self.statistics["/nat44-ed/in2out/slowpath/udp"]
4419 icmpn = self.statistics["/nat44-ed/in2out/slowpath/icmp"]
4420 drops = self.statistics["/nat44-ed/in2out/slowpath/drops"]
4422 pkts = self.create_stream_in(self.pg7, self.pg8)
4423 self.pg7.add_stream(pkts)
4424 self.pg_enable_capture(self.pg_interfaces)
4426 capture = self.pg8.get_capture(len(pkts))
4427 self.verify_capture_out(capture, ignore_port=True)
4429 if_idx = self.pg8.sw_if_index
4430 cnt = self.statistics["/nat44-ed/in2out/slowpath/tcp"]
4431 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
4432 cnt = self.statistics["/nat44-ed/in2out/slowpath/udp"]
4433 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
4434 cnt = self.statistics["/nat44-ed/in2out/slowpath/icmp"]
4435 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
4436 cnt = self.statistics["/nat44-ed/in2out/slowpath/drops"]
4437 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
4440 tcpn = self.statistics["/nat44-ed/out2in/fastpath/tcp"]
4441 udpn = self.statistics["/nat44-ed/out2in/fastpath/udp"]
4442 icmpn = self.statistics["/nat44-ed/out2in/fastpath/icmp"]
4443 drops = self.statistics["/nat44-ed/out2in/fastpath/drops"]
4445 pkts = self.create_stream_out(self.pg8)
4446 self.pg8.add_stream(pkts)
4447 self.pg_enable_capture(self.pg_interfaces)
4449 capture = self.pg7.get_capture(len(pkts))
4450 self.verify_capture_in(capture, self.pg7)
4452 if_idx = self.pg8.sw_if_index
4453 cnt = self.statistics["/nat44-ed/out2in/fastpath/tcp"]
4454 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
4455 cnt = self.statistics["/nat44-ed/out2in/fastpath/udp"]
4456 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
4457 cnt = self.statistics["/nat44-ed/out2in/fastpath/icmp"]
4458 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
4459 cnt = self.statistics["/nat44-ed/out2in/fastpath/drops"]
4460 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
4462 sessions = self.statistics["/nat44-ed/total-sessions"]
4463 self.assertEqual(sessions[:, 0].sum(), 3)
4469 self.vapi.ip_table_add_del(is_add=0, table={"table_id": new_vrf_id})
4471 def test_next_src_nat(self):
4472 """NAT44ED On way back forward packet to nat44-in2out node."""
4474 twice_nat_addr = "10.0.1.3"
4477 post_twice_nat_port = 0
4479 self.vapi.nat44_forwarding_enable_disable(enable=1)
4480 self.nat_add_address(twice_nat_addr, twice_nat=1)
4482 self.config_flags.NAT_IS_OUT2IN_ONLY
4483 | self.config_flags.NAT_IS_SELF_TWICE_NAT
4485 self.nat_add_static_mapping(
4486 self.pg6.remote_ip4,
4487 self.pg1.remote_ip4,
4490 proto=IP_PROTOS.tcp,
4494 self.vapi.nat44_interface_add_del_feature(
4495 sw_if_index=self.pg6.sw_if_index, is_add=1
4499 Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac)
4500 / IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4)
4501 / TCP(sport=12345, dport=external_port)
4503 self.pg6.add_stream(p)
4504 self.pg_enable_capture(self.pg_interfaces)
4506 capture = self.pg6.get_capture(1)
4511 self.assertEqual(ip.src, twice_nat_addr)
4512 self.assertNotEqual(tcp.sport, 12345)
4513 post_twice_nat_port = tcp.sport
4514 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4515 self.assertEqual(tcp.dport, local_port)
4516 self.assert_packet_checksums_valid(p)
4518 self.logger.error(ppp("Unexpected or invalid packet:", p))
4522 Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac)
4523 / IP(src=self.pg6.remote_ip4, dst=twice_nat_addr)
4524 / TCP(sport=local_port, dport=post_twice_nat_port)
4526 self.pg6.add_stream(p)
4527 self.pg_enable_capture(self.pg_interfaces)
4529 capture = self.pg6.get_capture(1)
4534 self.assertEqual(ip.src, self.pg1.remote_ip4)
4535 self.assertEqual(tcp.sport, external_port)
4536 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4537 self.assertEqual(tcp.dport, 12345)
4538 self.assert_packet_checksums_valid(p)
4540 self.logger.error(ppp("Unexpected or invalid packet:", p))
4543 def test_one_armed_nat44_static(self):
4544 """NAT44ED One armed NAT and 1:1 NAPT asymmetrical rule"""
4546 remote_host = self.pg4.remote_hosts[0]
4547 local_host = self.pg4.remote_hosts[1]
4552 self.vapi.nat44_forwarding_enable_disable(enable=1)
4553 self.nat_add_address(self.nat_addr, twice_nat=1)
4555 self.config_flags.NAT_IS_OUT2IN_ONLY | self.config_flags.NAT_IS_TWICE_NAT
4557 self.nat_add_static_mapping(
4562 proto=IP_PROTOS.tcp,
4565 flags = self.config_flags.NAT_IS_INSIDE
4566 self.vapi.nat44_interface_add_del_feature(
4567 sw_if_index=self.pg4.sw_if_index, is_add=1
4569 self.vapi.nat44_interface_add_del_feature(
4570 sw_if_index=self.pg4.sw_if_index, flags=flags, is_add=1
4573 # from client to service
4575 Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac)
4576 / IP(src=remote_host.ip4, dst=self.nat_addr)
4577 / TCP(sport=12345, dport=external_port)
4579 self.pg4.add_stream(p)
4580 self.pg_enable_capture(self.pg_interfaces)
4582 capture = self.pg4.get_capture(1)
4587 self.assertEqual(ip.dst, local_host.ip4)
4588 self.assertEqual(ip.src, self.nat_addr)
4589 self.assertEqual(tcp.dport, local_port)
4590 self.assertNotEqual(tcp.sport, 12345)
4591 eh_port_in = tcp.sport
4592 self.assert_packet_checksums_valid(p)
4594 self.logger.error(ppp("Unexpected or invalid packet:", p))
4597 # from service back to client
4599 Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac)
4600 / IP(src=local_host.ip4, dst=self.nat_addr)
4601 / TCP(sport=local_port, dport=eh_port_in)
4603 self.pg4.add_stream(p)
4604 self.pg_enable_capture(self.pg_interfaces)
4606 capture = self.pg4.get_capture(1)
4611 self.assertEqual(ip.src, self.nat_addr)
4612 self.assertEqual(ip.dst, remote_host.ip4)
4613 self.assertEqual(tcp.sport, external_port)
4614 self.assertEqual(tcp.dport, 12345)
4615 self.assert_packet_checksums_valid(p)
4617 self.logger.error(ppp("Unexpected or invalid packet:", p))
4620 def test_icmp_error_fwd_outbound(self):
4621 """NAT44ED ICMP error outbound with forwarding enabled"""
4623 # Ensure that an outbound ICMP error message is properly associated
4624 # with the inbound forward bypass session it is related to.
4627 self.nat_add_address(self.nat_addr)
4628 self.nat_add_inside_interface(self.pg0)
4629 self.nat_add_outside_interface(self.pg1)
4631 # enable forwarding and initiate connection out2in
4632 self.vapi.nat44_forwarding_enable_disable(enable=1)
4634 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4635 / IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4)
4636 / UDP(sport=21, dport=20)
4640 self.pg1.add_stream(p1)
4641 self.pg_enable_capture(self.pg_interfaces)
4643 capture = self.pg0.get_capture(1)[0]
4645 self.logger.info(self.vapi.cli("show nat44 sessions"))
4647 # reply with ICMP error message in2out
4648 # We cannot reliably retrieve forward bypass sessions via the API.
4649 # session dumps for a user will only look on the worker that the
4650 # user is supposed to be mapped to in2out. The forward bypass session
4651 # is not necessarily created on that worker.
4653 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4654 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4655 / ICMP(type="dest-unreach", code="port-unreachable")
4659 self.pg0.add_stream(p2)
4660 self.pg_enable_capture(self.pg_interfaces)
4662 capture = self.pg1.get_capture(1)[0]
4664 self.logger.info(self.vapi.cli("show nat44 sessions"))
4666 self.logger.info(ppp("p1 packet:", p1))
4667 self.logger.info(ppp("p2 packet:", p2))
4668 self.logger.info(ppp("capture packet:", capture))
4670 def test_tcp_session_open_retransmit1(self):
4671 """NAT44ED Open TCP session with SYN,ACK retransmit 1
4673 The client does not receive the [SYN,ACK] or the
4674 ACK from the client is lost. Therefore, the [SYN, ACK]
4675 is retransmitted by the server.
4678 in_port = self.tcp_port_in
4679 ext_port = self.tcp_external_port
4682 self.nat_add_address(self.nat_addr)
4683 self.nat_add_inside_interface(self.pg0)
4684 self.nat_add_outside_interface(self.pg1)
4686 self.vapi.nat_set_timeouts(
4687 udp=300, tcp_established=7440, tcp_transitory=5, icmp=60
4689 # SYN packet in->out
4691 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4692 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4693 / TCP(sport=in_port, dport=ext_port, flags="S")
4695 p = self.send_and_expect(self.pg0, p, self.pg1)[0]
4696 out_port = p[TCP].sport
4698 # SYN + ACK packet out->in
4700 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4701 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4702 / TCP(sport=ext_port, dport=out_port, flags="SA")
4704 self.send_and_expect(self.pg1, p, self.pg0)
4706 # ACK in->out does not arrive
4708 # resent SYN + ACK packet out->in
4710 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4711 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4712 / TCP(sport=ext_port, dport=out_port, flags="SA")
4714 self.send_and_expect(self.pg1, p, self.pg0)
4716 # ACK packet in->out
4718 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4719 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4720 / TCP(sport=in_port, dport=ext_port, flags="A")
4722 self.send_and_expect(self.pg0, p, self.pg1)
4724 # Verify that the data can be transmitted after the transitory time
4725 self.virtual_sleep(6)
4728 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4729 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4730 / TCP(sport=in_port, dport=ext_port, flags="PA")
4733 self.send_and_expect(self.pg0, p, self.pg1)
4735 def test_tcp_session_open_retransmit2(self):
4736 """NAT44ED Open TCP session with SYN,ACK retransmit 2
4738 The ACK is lost to the server after the TCP session is opened.
4739 Data is sent by the client, then the [SYN,ACK] is
4740 retransmitted by the server.
4743 in_port = self.tcp_port_in
4744 ext_port = self.tcp_external_port
4747 self.nat_add_address(self.nat_addr)
4748 self.nat_add_inside_interface(self.pg0)
4749 self.nat_add_outside_interface(self.pg1)
4751 self.vapi.nat_set_timeouts(
4752 udp=300, tcp_established=7440, tcp_transitory=5, icmp=60
4754 # SYN packet in->out
4756 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4757 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4758 / TCP(sport=in_port, dport=ext_port, flags="S")
4760 p = self.send_and_expect(self.pg0, p, self.pg1)[0]
4761 out_port = p[TCP].sport
4763 # SYN + ACK packet out->in
4765 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4766 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4767 / TCP(sport=ext_port, dport=out_port, flags="SA")
4769 self.send_and_expect(self.pg1, p, self.pg0)
4771 # ACK packet in->out -- not received by the server
4773 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4774 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4775 / TCP(sport=in_port, dport=ext_port, flags="A")
4777 self.send_and_expect(self.pg0, p, self.pg1)
4779 # PUSH + ACK packet in->out
4781 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4782 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4783 / TCP(sport=in_port, dport=ext_port, flags="PA")
4786 self.send_and_expect(self.pg0, p, self.pg1)
4788 # resent SYN + ACK packet out->in
4790 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4791 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4792 / TCP(sport=ext_port, dport=out_port, flags="SA")
4794 self.send_and_expect(self.pg1, p, self.pg0)
4796 # resent ACK packet in->out
4798 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4799 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4800 / TCP(sport=in_port, dport=ext_port, flags="A")
4802 self.send_and_expect(self.pg0, p, self.pg1)
4804 # resent PUSH + ACK packet in->out
4806 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4807 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4808 / TCP(sport=in_port, dport=ext_port, flags="PA")
4811 self.send_and_expect(self.pg0, p, self.pg1)
4813 # ACK packet out->in
4815 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4816 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4817 / TCP(sport=ext_port, dport=out_port, flags="A")
4819 self.send_and_expect(self.pg1, p, self.pg0)
4821 # Verify that the data can be transmitted after the transitory time
4822 self.virtual_sleep(6)
4825 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4826 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4827 / TCP(sport=in_port, dport=ext_port, flags="PA")
4830 self.send_and_expect(self.pg0, p, self.pg1)
4832 def test_dynamic_ports_exhausted(self):
4833 """NAT44ED dynamic translation test: address ports exhaused"""
4835 sessions_per_batch = 128
4836 n_available_ports = 65536 - 1024
4837 n_sessions = n_available_ports + 2 * sessions_per_batch
4839 # set high enough session limit for ports to be exhausted
4840 self.plugin_disable()
4841 self.plugin_enable(max_sessions=n_sessions)
4843 self.nat_add_inside_interface(self.pg0)
4844 self.nat_add_outside_interface(self.pg1)
4846 # set timeouts to high for sessions to reallistically expire
4847 config = self.vapi.nat44_show_running_config()
4848 old_timeouts = config.timeouts
4849 self.vapi.nat_set_timeouts(
4851 tcp_established=old_timeouts.tcp_established,
4852 tcp_transitory=old_timeouts.tcp_transitory,
4853 icmp=old_timeouts.icmp,
4856 # in2out after NAT addresses added
4857 self.nat_add_address(self.nat_addr)
4859 for i in range(n_sessions // sessions_per_batch):
4860 pkts = self.create_udp_stream(
4864 base_port=i * sessions_per_batch + 100,
4867 self.pg0.add_stream(pkts)
4870 err = self.statistics.get_err_counter(
4871 "/err/nat44-ed-in2out-slowpath/out of ports"
4873 if err > sessions_per_batch:
4876 # Check for ports to be used no more than once
4878 sessions = self.vapi.cli("show nat44 sessions")
4880 f" *o2i flow: match: saddr {self.pg1.remote_ip4} sport [0-9]+ daddr {self.nat_addr} dport ([0-9]+) proto UDP.*"
4882 for line in sessions.splitlines():
4885 port = int(m.groups()[0])
4886 self.assertNotIn(port, ports)
4889 self.assertGreaterEqual(err, sessions_per_batch)
4892 if __name__ == "__main__":
4893 unittest.main(testRunner=VppTestRunner)