5 from random import randint, choice
9 from framework import VppTestCase, VppLoInterface
10 from asfframework import VppTestRunner, tag_fixme_ubuntu2204, is_distro_ubuntu2204
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 5 tcp sessions)
2943 self.vapi.nat44_set_session_limit(session_limit=limit, vrf_id=10)
2945 # expect error when bad is specified
2946 with self.vapi.assert_negative_api_retval():
2947 self.vapi.nat44_set_session_limit(session_limit=limit, vrf_id=20)
2949 self.nat_add_inside_interface(inside)
2950 self.nat_add_inside_interface(inside_vrf10)
2951 self.nat_add_outside_interface(outside)
2954 self.nat_add_interface_address(outside)
2956 # BUG: causing core dump - when bad vrf_id is specified
2957 # self.nat_add_address(outside.local_ip4, vrf_id=20)
2959 stream = self.create_tcp_stream(inside_vrf10, outside, limit * 2)
2960 inside_vrf10.add_stream(stream)
2962 self.pg_enable_capture(self.pg_interfaces)
2965 capture = outside.get_capture(limit)
2967 stream = self.create_tcp_stream(inside, outside, limit * 2)
2968 inside.add_stream(stream)
2970 self.pg_enable_capture(self.pg_interfaces)
2973 capture = outside.get_capture(len(stream))
2975 def test_show_max_translations(self):
2976 """NAT44ED API test - max translations per thread"""
2977 config = self.vapi.nat44_show_running_config()
2978 self.assertEqual(self.max_sessions, config.sessions)
2980 def test_lru_cleanup(self):
2981 """NAT44ED LRU cleanup algorithm"""
2983 self.nat_add_address(self.nat_addr)
2984 self.nat_add_inside_interface(self.pg0)
2985 self.nat_add_outside_interface(self.pg1)
2987 self.vapi.nat_set_timeouts(
2988 udp=1, tcp_established=7440, tcp_transitory=30, icmp=1
2991 tcp_port_out = self.init_tcp_session(self.pg0, self.pg1, 2000, 80)
2993 for i in range(0, self.max_sessions - 1):
2995 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2996 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64)
2997 / UDP(sport=7000 + i, dport=80)
3001 self.pg0.add_stream(pkts)
3002 self.pg_enable_capture(self.pg_interfaces)
3004 self.pg1.get_capture(len(pkts))
3005 self.virtual_sleep(1.5, "wait for timeouts")
3008 for i in range(0, self.max_sessions - 1):
3010 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3011 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64)
3012 / ICMP(id=8000 + i, type="echo-request")
3016 self.pg0.add_stream(pkts)
3017 self.pg_enable_capture(self.pg_interfaces)
3019 self.pg1.get_capture(len(pkts))
3021 def test_session_rst_timeout(self):
3022 """NAT44ED session RST timeouts"""
3024 self.nat_add_address(self.nat_addr)
3025 self.nat_add_inside_interface(self.pg0)
3026 self.nat_add_outside_interface(self.pg1)
3028 self.vapi.nat_set_timeouts(
3029 udp=300, tcp_established=7440, tcp_transitory=5, icmp=60
3032 self.init_tcp_session(
3033 self.pg0, self.pg1, self.tcp_port_in, self.tcp_external_port
3036 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3037 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3038 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="R")
3040 self.send_and_expect(self.pg0, p, self.pg1)
3042 self.virtual_sleep(6)
3044 # The session is already closed
3046 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3047 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3048 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="P")
3050 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
3052 # The session can be re-opened
3054 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3055 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3056 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="S")
3058 self.send_and_expect(self.pg0, p, self.pg1)
3060 def test_session_rst_established_timeout(self):
3061 """NAT44ED session RST timeouts"""
3063 self.nat_add_address(self.nat_addr)
3064 self.nat_add_inside_interface(self.pg0)
3065 self.nat_add_outside_interface(self.pg1)
3067 self.vapi.nat_set_timeouts(
3068 udp=300, tcp_established=7440, tcp_transitory=5, icmp=60
3071 self.init_tcp_session(
3072 self.pg0, self.pg1, self.tcp_port_in, self.tcp_external_port
3075 # Wait at least the transitory time, the session is in established
3076 # state anyway. RST followed by a data packet should move it to
3078 self.virtual_sleep(6)
3080 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3081 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3082 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="R")
3084 self.send_and_expect(self.pg0, p, self.pg1)
3087 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3088 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3089 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="P")
3091 self.send_and_expect(self.pg0, p, self.pg1)
3093 # State is transitory, session should be closed after 6 seconds
3094 self.virtual_sleep(6)
3097 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3098 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3099 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="P")
3101 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
3103 def test_dynamic_out_of_ports(self):
3104 """NAT44ED dynamic translation test: out of ports"""
3106 self.nat_add_inside_interface(self.pg0)
3107 self.nat_add_outside_interface(self.pg1)
3109 # in2out and no NAT addresses added
3110 pkts = self.create_stream_in(self.pg0, self.pg1)
3112 self.send_and_assert_no_replies(
3116 stats_diff=self.no_diff
3119 "/err/nat44-ed-in2out-slowpath/out of ports": len(pkts),
3121 self.pg0.sw_if_index: {
3122 "/nat44-ed/in2out/slowpath/drops": len(pkts),
3127 # in2out after NAT addresses added
3128 self.nat_add_address(self.nat_addr)
3130 tcpn, udpn, icmpn = (
3131 sum(x) for x in zip(*((TCP in p, UDP in p, ICMP in p) for p in pkts))
3134 self.send_and_expect(
3139 stats_diff=self.no_diff
3142 "/err/nat44-ed-in2out-slowpath/out of ports": 0,
3144 self.pg0.sw_if_index: {
3145 "/nat44-ed/in2out/slowpath/drops": 0,
3146 "/nat44-ed/in2out/slowpath/tcp": tcpn,
3147 "/nat44-ed/in2out/slowpath/udp": udpn,
3148 "/nat44-ed/in2out/slowpath/icmp": icmpn,
3153 def test_unknown_proto(self):
3154 """NAT44ED translate packet with unknown protocol"""
3156 self.nat_add_address(self.nat_addr)
3157 self.nat_add_inside_interface(self.pg0)
3158 self.nat_add_outside_interface(self.pg1)
3162 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3163 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3164 / TCP(sport=self.tcp_port_in, dport=20)
3166 self.pg0.add_stream(p)
3167 self.pg_enable_capture(self.pg_interfaces)
3169 p = self.pg1.get_capture(1)
3172 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3173 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3175 / IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4)
3176 / TCP(sport=1234, dport=1234)
3178 self.pg0.add_stream(p)
3179 self.pg_enable_capture(self.pg_interfaces)
3181 p = self.pg1.get_capture(1)
3184 self.assertEqual(packet[IP].src, self.nat_addr)
3185 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3186 self.assertEqual(packet.haslayer(GRE), 1)
3187 self.assert_packet_checksums_valid(packet)
3189 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3194 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
3195 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3197 / IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4)
3198 / TCP(sport=1234, dport=1234)
3200 self.pg1.add_stream(p)
3201 self.pg_enable_capture(self.pg_interfaces)
3203 p = self.pg0.get_capture(1)
3206 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3207 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3208 self.assertEqual(packet.haslayer(GRE), 1)
3209 self.assert_packet_checksums_valid(packet)
3211 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3214 def test_hairpinning_unknown_proto(self):
3215 """NAT44ED translate packet with unknown protocol - hairpinning"""
3216 host = self.pg0.remote_hosts[0]
3217 server = self.pg0.remote_hosts[1]
3219 server_out_port = 8765
3220 server_nat_ip = "10.0.0.11"
3222 self.nat_add_address(self.nat_addr)
3223 self.nat_add_inside_interface(self.pg0)
3224 self.nat_add_outside_interface(self.pg1)
3226 # add static mapping for server
3227 self.nat_add_static_mapping(server.ip4, server_nat_ip)
3231 Ether(src=host.mac, dst=self.pg0.local_mac)
3232 / IP(src=host.ip4, dst=server_nat_ip)
3233 / TCP(sport=host_in_port, dport=server_out_port)
3235 self.pg0.add_stream(p)
3236 self.pg_enable_capture(self.pg_interfaces)
3238 self.pg0.get_capture(1)
3241 Ether(dst=self.pg0.local_mac, src=host.mac)
3242 / IP(src=host.ip4, dst=server_nat_ip)
3244 / IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4)
3245 / TCP(sport=1234, dport=1234)
3247 self.pg0.add_stream(p)
3248 self.pg_enable_capture(self.pg_interfaces)
3250 p = self.pg0.get_capture(1)
3253 self.assertEqual(packet[IP].src, self.nat_addr)
3254 self.assertEqual(packet[IP].dst, server.ip4)
3255 self.assertEqual(packet.haslayer(GRE), 1)
3256 self.assert_packet_checksums_valid(packet)
3258 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3263 Ether(dst=self.pg0.local_mac, src=server.mac)
3264 / IP(src=server.ip4, dst=self.nat_addr)
3266 / IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4)
3267 / TCP(sport=1234, dport=1234)
3269 self.pg0.add_stream(p)
3270 self.pg_enable_capture(self.pg_interfaces)
3272 p = self.pg0.get_capture(1)
3275 self.assertEqual(packet[IP].src, server_nat_ip)
3276 self.assertEqual(packet[IP].dst, host.ip4)
3277 self.assertEqual(packet.haslayer(GRE), 1)
3278 self.assert_packet_checksums_valid(packet)
3280 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3283 def test_output_feature_and_service(self):
3284 """NAT44ED interface output feature and services"""
3285 external_addr = "1.2.3.4"
3289 self.vapi.nat44_forwarding_enable_disable(enable=1)
3290 self.nat_add_address(self.nat_addr)
3291 flags = self.config_flags.NAT_IS_ADDR_ONLY
3292 self.vapi.nat44_add_del_identity_mapping(
3293 ip_address=self.pg1.remote_ip4,
3294 sw_if_index=0xFFFFFFFF,
3298 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
3299 self.nat_add_static_mapping(
3300 self.pg0.remote_ip4,
3304 proto=IP_PROTOS.tcp,
3308 self.nat_add_inside_interface(self.pg0)
3309 self.nat_add_outside_interface(self.pg0)
3310 self.vapi.nat44_ed_add_del_output_interface(
3311 sw_if_index=self.pg1.sw_if_index, is_add=1
3314 # from client to service
3316 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3317 / IP(src=self.pg1.remote_ip4, dst=external_addr)
3318 / TCP(sport=12345, dport=external_port)
3320 self.pg1.add_stream(p)
3321 self.pg_enable_capture(self.pg_interfaces)
3323 capture = self.pg0.get_capture(1)
3328 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3329 self.assertEqual(tcp.dport, local_port)
3330 self.assert_packet_checksums_valid(p)
3332 self.logger.error(ppp("Unexpected or invalid packet:", p))
3335 # from service back to client
3337 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3338 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3339 / TCP(sport=local_port, dport=12345)
3341 self.pg0.add_stream(p)
3342 self.pg_enable_capture(self.pg_interfaces)
3344 capture = self.pg1.get_capture(1)
3349 self.assertEqual(ip.src, external_addr)
3350 self.assertEqual(tcp.sport, external_port)
3351 self.assert_packet_checksums_valid(p)
3353 self.logger.error(ppp("Unexpected or invalid packet:", p))
3356 # from local network host to external network
3357 pkts = self.create_stream_in(self.pg0, self.pg1)
3358 self.pg0.add_stream(pkts)
3359 self.pg_enable_capture(self.pg_interfaces)
3361 capture = self.pg1.get_capture(len(pkts))
3362 self.verify_capture_out(capture, ignore_port=True)
3363 pkts = self.create_stream_in(self.pg0, self.pg1)
3364 self.pg0.add_stream(pkts)
3365 self.pg_enable_capture(self.pg_interfaces)
3367 capture = self.pg1.get_capture(len(pkts))
3368 self.verify_capture_out(capture, ignore_port=True)
3370 # from external network back to local network host
3371 pkts = self.create_stream_out(self.pg1)
3372 self.pg1.add_stream(pkts)
3373 self.pg_enable_capture(self.pg_interfaces)
3375 capture = self.pg0.get_capture(len(pkts))
3376 self.verify_capture_in(capture, self.pg0)
3378 def test_output_feature_and_service3(self):
3379 """NAT44ED interface output feature and DST NAT"""
3380 external_addr = "1.2.3.4"
3384 self.vapi.nat44_forwarding_enable_disable(enable=1)
3385 self.nat_add_address(self.nat_addr)
3386 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
3387 self.nat_add_static_mapping(
3388 self.pg1.remote_ip4,
3392 proto=IP_PROTOS.tcp,
3396 self.nat_add_inside_interface(self.pg0)
3397 self.nat_add_outside_interface(self.pg0)
3398 self.vapi.nat44_ed_add_del_output_interface(
3399 sw_if_index=self.pg1.sw_if_index, is_add=1
3403 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3404 / IP(src=self.pg0.remote_ip4, dst=external_addr)
3405 / TCP(sport=12345, dport=external_port)
3407 self.pg0.add_stream(p)
3408 self.pg_enable_capture(self.pg_interfaces)
3410 capture = self.pg1.get_capture(1)
3415 self.assertEqual(ip.src, self.pg0.remote_ip4)
3416 self.assertEqual(tcp.sport, 12345)
3417 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3418 self.assertEqual(tcp.dport, local_port)
3419 self.assert_packet_checksums_valid(p)
3421 self.logger.error(ppp("Unexpected or invalid packet:", p))
3425 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3426 / IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4)
3427 / TCP(sport=local_port, dport=12345)
3429 self.pg1.add_stream(p)
3430 self.pg_enable_capture(self.pg_interfaces)
3432 capture = self.pg0.get_capture(1)
3437 self.assertEqual(ip.src, external_addr)
3438 self.assertEqual(tcp.sport, external_port)
3439 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3440 self.assertEqual(tcp.dport, 12345)
3441 self.assert_packet_checksums_valid(p)
3443 self.logger.error(ppp("Unexpected or invalid packet:", p))
3446 def test_self_twice_nat_lb_negative(self):
3447 """NAT44ED Self Twice NAT local service load balancing (negative test)"""
3448 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True, client_id=2)
3450 def test_self_twice_nat_negative(self):
3451 """NAT44ED Self Twice NAT (negative test)"""
3452 self.twice_nat_common(self_twice_nat=True)
3454 def test_static_lb_multi_clients(self):
3455 """NAT44ED local service load balancing - multiple clients"""
3457 external_addr = self.nat_addr
3460 server1 = self.pg0.remote_hosts[0]
3461 server2 = self.pg0.remote_hosts[1]
3462 server3 = self.pg0.remote_hosts[2]
3465 {"addr": server1.ip4, "port": local_port, "probability": 90, "vrf_id": 0},
3466 {"addr": server2.ip4, "port": local_port, "probability": 10, "vrf_id": 0},
3469 flags = self.config_flags.NAT_IS_INSIDE
3470 self.vapi.nat44_interface_add_del_feature(
3471 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
3473 self.vapi.nat44_interface_add_del_feature(
3474 sw_if_index=self.pg1.sw_if_index, is_add=1
3477 self.nat_add_address(self.nat_addr)
3478 self.vapi.nat44_add_del_lb_static_mapping(
3480 external_addr=external_addr,
3481 external_port=external_port,
3482 protocol=IP_PROTOS.tcp,
3483 local_num=len(locals),
3489 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
3491 for client in clients:
3493 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3494 / IP(src=client, dst=self.nat_addr)
3495 / TCP(sport=12345, dport=external_port)
3498 self.pg1.add_stream(pkts)
3499 self.pg_enable_capture(self.pg_interfaces)
3501 capture = self.pg0.get_capture(len(pkts))
3503 if p[IP].dst == server1.ip4:
3507 self.assertGreaterEqual(server1_n, server2_n)
3510 "addr": server3.ip4,
3517 self.vapi.nat44_lb_static_mapping_add_del_local(
3519 external_addr=external_addr,
3520 external_port=external_port,
3522 protocol=IP_PROTOS.tcp,
3527 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
3529 for client in clients:
3531 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3532 / IP(src=client, dst=self.nat_addr)
3533 / TCP(sport=12346, dport=external_port)
3536 self.assertGreater(len(pkts), 0)
3537 self.pg1.add_stream(pkts)
3538 self.pg_enable_capture(self.pg_interfaces)
3540 capture = self.pg0.get_capture(len(pkts))
3542 if p[IP].dst == server1.ip4:
3544 elif p[IP].dst == server2.ip4:
3548 self.assertGreater(server1_n, 0)
3549 self.assertGreater(server2_n, 0)
3550 self.assertGreater(server3_n, 0)
3553 "addr": server2.ip4,
3559 # remove one back-end
3560 self.vapi.nat44_lb_static_mapping_add_del_local(
3562 external_addr=external_addr,
3563 external_port=external_port,
3565 protocol=IP_PROTOS.tcp,
3570 self.pg1.add_stream(pkts)
3571 self.pg_enable_capture(self.pg_interfaces)
3573 capture = self.pg0.get_capture(len(pkts))
3575 if p[IP].dst == server1.ip4:
3577 elif p[IP].dst == server2.ip4:
3581 self.assertGreater(server1_n, 0)
3582 self.assertEqual(server2_n, 0)
3583 self.assertGreater(server3_n, 0)
3585 # put zzz in front of syslog test name so that it runs as a last test
3586 # setting syslog sender cannot be undone and if it is set, it messes
3587 # with self.send_and_assert_no_replies functionality
3588 def test_zzz_syslog_sess(self):
3589 """NAT44ED Test syslog session creation and deletion"""
3590 self.vapi.syslog_set_filter(self.syslog_severity.SYSLOG_API_SEVERITY_INFO)
3591 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
3593 self.nat_add_address(self.nat_addr)
3594 self.nat_add_inside_interface(self.pg0)
3595 self.nat_add_outside_interface(self.pg1)
3598 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3599 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3600 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port)
3602 self.pg0.add_stream(p)
3603 self.pg_enable_capture(self.pg_interfaces)
3605 capture = self.pg1.get_capture(1)
3606 self.tcp_port_out = capture[0][TCP].sport
3607 capture = self.pg3.get_capture(1)
3608 self.verify_syslog_sess(capture[0][Raw].load, "SADD")
3610 self.pg_enable_capture(self.pg_interfaces)
3612 self.nat_add_address(self.nat_addr, is_add=0)
3613 capture = self.pg3.get_capture(1)
3614 self.verify_syslog_sess(capture[0][Raw].load, "SDEL")
3616 # put zzz in front of syslog test name so that it runs as a last test
3617 # setting syslog sender cannot be undone and if it is set, it messes
3618 # with self.send_and_assert_no_replies functionality
3619 def test_zzz_syslog_sess_reopen(self):
3620 """Syslog events for session reopen"""
3621 self.vapi.syslog_set_filter(self.syslog_severity.SYSLOG_API_SEVERITY_INFO)
3622 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
3624 self.nat_add_address(self.nat_addr)
3625 self.nat_add_inside_interface(self.pg0)
3626 self.nat_add_outside_interface(self.pg1)
3630 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3631 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3632 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port)
3634 capture = self.send_and_expect(self.pg0, p, self.pg1)[0]
3635 self.tcp_port_out = capture[0][TCP].sport
3636 capture = self.pg3.get_capture(1)
3637 self.verify_syslog_sess(capture[0][Raw].load, "SADD")
3641 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
3642 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3643 / TCP(sport=self.tcp_external_port, dport=self.tcp_port_out, flags="SA")
3645 self.send_and_expect(self.pg1, p, self.pg0)
3648 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3649 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3650 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="A")
3652 self.send_and_expect(self.pg0, p, self.pg1)
3656 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3657 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3658 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="F")
3660 self.send_and_expect(self.pg0, p, self.pg1)
3664 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
3665 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3666 / TCP(sport=self.tcp_external_port, dport=self.tcp_port_out, flags="F")
3668 self.send_and_expect(self.pg1, p, self.pg0)
3670 self.init_tcp_session(
3671 self.pg0, self.pg1, self.tcp_port_in, self.tcp_external_port
3674 # 2 records should be produced - first one del & add
3675 capture = self.pg3.get_capture(2)
3676 self.verify_syslog_sess(capture[0][Raw].load, "SDEL")
3677 self.verify_syslog_sess(capture[1][Raw].load, "SADD")
3679 def test_twice_nat_interface_addr(self):
3680 """NAT44ED Acquire twice NAT addresses from interface"""
3681 flags = self.config_flags.NAT_IS_TWICE_NAT
3682 self.vapi.nat44_add_del_interface_addr(
3683 sw_if_index=self.pg11.sw_if_index, flags=flags, is_add=1
3686 # no address in NAT pool
3687 adresses = self.vapi.nat44_address_dump()
3688 self.assertEqual(0, len(adresses))
3690 # configure interface address and check NAT address pool
3691 self.pg11.config_ip4()
3692 adresses = self.vapi.nat44_address_dump()
3693 self.assertEqual(1, len(adresses))
3694 self.assertEqual(str(adresses[0].ip_address), self.pg11.local_ip4)
3695 self.assertEqual(adresses[0].flags, flags)
3697 # remove interface address and check NAT address pool
3698 self.pg11.unconfig_ip4()
3699 adresses = self.vapi.nat44_address_dump()
3700 self.assertEqual(0, len(adresses))
3702 def test_output_feature_stateful_acl(self):
3703 """NAT44ED output feature works with stateful ACL"""
3705 self.nat_add_address(self.nat_addr)
3706 self.vapi.nat44_ed_add_del_output_interface(
3707 sw_if_index=self.pg1.sw_if_index, is_add=1
3710 # First ensure that the NAT is working sans ACL
3712 # send packets out2in, no sessions yet so packets should drop
3713 pkts_out2in = self.create_stream_out(self.pg1)
3714 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
3716 # send packets into inside intf, ensure received via outside intf
3717 pkts_in2out = self.create_stream_in(self.pg0, self.pg1)
3718 capture = self.send_and_expect(
3719 self.pg0, pkts_in2out, self.pg1, len(pkts_in2out)
3721 self.verify_capture_out(capture, ignore_port=True)
3723 # send out2in again, with sessions created it should work now
3724 pkts_out2in = self.create_stream_out(self.pg1)
3725 capture = self.send_and_expect(
3726 self.pg1, pkts_out2in, self.pg0, len(pkts_out2in)
3728 self.verify_capture_in(capture, self.pg0)
3730 # Create an ACL blocking everything
3731 out2in_deny_rule = AclRule(is_permit=0)
3732 out2in_acl = VppAcl(self, rules=[out2in_deny_rule])
3733 out2in_acl.add_vpp_config()
3735 # create an ACL to permit/reflect everything
3736 in2out_reflect_rule = AclRule(is_permit=2)
3737 in2out_acl = VppAcl(self, rules=[in2out_reflect_rule])
3738 in2out_acl.add_vpp_config()
3740 # apply as input acl on interface and confirm it blocks everything
3741 acl_if = VppAclInterface(
3742 self, sw_if_index=self.pg1.sw_if_index, n_input=1, acls=[out2in_acl]
3744 acl_if.add_vpp_config()
3745 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
3748 acl_if.acls = [out2in_acl, in2out_acl]
3749 acl_if.add_vpp_config()
3750 # send in2out to generate ACL state (NAT state was created earlier)
3751 capture = self.send_and_expect(
3752 self.pg0, pkts_in2out, self.pg1, len(pkts_in2out)
3754 self.verify_capture_out(capture, ignore_port=True)
3756 # send out2in again. ACL state exists so it should work now.
3757 # TCP packets with the syn flag set also need the ack flag
3758 for p in pkts_out2in:
3759 if p.haslayer(TCP) and p[TCP].flags & 0x02:
3760 p[TCP].flags |= 0x10
3761 capture = self.send_and_expect(
3762 self.pg1, pkts_out2in, self.pg0, len(pkts_out2in)
3764 self.verify_capture_in(capture, self.pg0)
3765 self.logger.info(self.vapi.cli("show trace"))
3767 def test_tcp_close(self):
3768 """NAT44ED Close TCP session from inside network - output feature"""
3769 config = self.vapi.nat44_show_running_config()
3770 old_timeouts = config.timeouts
3772 self.vapi.nat_set_timeouts(
3773 udp=old_timeouts.udp,
3774 tcp_established=old_timeouts.tcp_established,
3775 icmp=old_timeouts.icmp,
3776 tcp_transitory=new_transitory,
3779 self.vapi.nat44_forwarding_enable_disable(enable=1)
3780 self.nat_add_address(self.pg1.local_ip4)
3781 twice_nat_addr = "10.0.1.3"
3782 service_ip = "192.168.16.150"
3783 self.nat_add_address(twice_nat_addr, twice_nat=1)
3785 flags = self.config_flags.NAT_IS_INSIDE
3786 self.vapi.nat44_interface_add_del_feature(
3787 sw_if_index=self.pg0.sw_if_index, is_add=1
3789 self.vapi.nat44_interface_add_del_feature(
3790 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
3792 self.vapi.nat44_ed_add_del_output_interface(
3793 is_add=1, sw_if_index=self.pg1.sw_if_index
3797 self.config_flags.NAT_IS_OUT2IN_ONLY | self.config_flags.NAT_IS_TWICE_NAT
3799 self.nat_add_static_mapping(
3800 self.pg0.remote_ip4, service_ip, 80, 80, proto=IP_PROTOS.tcp, flags=flags
3802 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3803 start_sessnum = len(sessions)
3805 # SYN packet out->in
3807 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3808 / IP(src=self.pg1.remote_ip4, dst=service_ip)
3809 / TCP(sport=33898, dport=80, flags="S")
3811 capture = self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
3813 tcp_port = p[TCP].sport
3815 # SYN + ACK packet in->out
3817 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3818 / IP(src=self.pg0.remote_ip4, dst=twice_nat_addr)
3819 / TCP(sport=80, dport=tcp_port, flags="SA")
3821 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
3823 # ACK packet out->in
3825 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3826 / IP(src=self.pg1.remote_ip4, dst=service_ip)
3827 / TCP(sport=33898, dport=80, flags="A")
3829 self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
3831 # FIN packet in -> out
3833 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3834 / IP(src=self.pg0.remote_ip4, dst=twice_nat_addr)
3835 / TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300)
3837 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
3839 # FIN+ACK packet out -> in
3841 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3842 / IP(src=self.pg1.remote_ip4, dst=service_ip)
3843 / TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101)
3845 self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
3847 # ACK packet in -> out
3849 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3850 / IP(src=self.pg0.remote_ip4, dst=twice_nat_addr)
3851 / TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301)
3853 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
3855 # session now in transitory timeout, but traffic still flows
3856 # try FIN packet out->in
3858 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3859 / IP(src=self.pg1.remote_ip4, dst=service_ip)
3860 / TCP(sport=33898, dport=80, flags="F")
3862 self.pg1.add_stream(p)
3863 self.pg_enable_capture(self.pg_interfaces)
3866 self.virtual_sleep(new_transitory, "wait for transitory timeout")
3867 self.pg0.get_capture(1)
3869 # session should still exist
3870 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3871 self.assertEqual(len(sessions) - start_sessnum, 1)
3873 # send FIN+ACK packet out -> in - will cause session to be wiped
3874 # but won't create a new session
3876 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3877 / IP(src=self.pg1.remote_ip4, dst=service_ip)
3878 / TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101)
3880 self.send_and_assert_no_replies(self.pg1, p)
3881 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3882 self.assertEqual(len(sessions) - start_sessnum, 0)
3884 def test_tcp_session_close_in(self):
3885 """NAT44ED Close TCP session from inside network"""
3887 in_port = self.tcp_port_in
3889 ext_port = self.tcp_external_port
3891 self.nat_add_address(self.nat_addr)
3892 self.nat_add_inside_interface(self.pg0)
3893 self.nat_add_outside_interface(self.pg1)
3894 self.nat_add_static_mapping(
3895 self.pg0.remote_ip4,
3899 proto=IP_PROTOS.tcp,
3900 flags=self.config_flags.NAT_IS_TWICE_NAT,
3903 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3904 session_n = len(sessions)
3906 self.vapi.nat_set_timeouts(
3907 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
3910 self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3912 # FIN packet in -> out
3914 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3915 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3916 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=100, ack=300)
3918 self.send_and_expect(self.pg0, p, self.pg1)
3921 # ACK packet out -> in
3923 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3924 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3925 / TCP(sport=ext_port, dport=out_port, flags="A", seq=300, ack=101)
3929 # FIN packet out -> in
3931 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3932 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3933 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=101)
3937 self.send_and_expect(self.pg1, pkts, self.pg0)
3939 # ACK packet in -> out
3941 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3942 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3943 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
3945 self.send_and_expect(self.pg0, p, self.pg1)
3947 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3948 self.assertEqual(len(sessions) - session_n, 1)
3950 # retransmit FIN packet out -> in
3952 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3953 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3954 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=101)
3957 self.send_and_expect(self.pg1, p, self.pg0)
3959 # retransmit ACK packet in -> out
3961 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3962 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3963 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
3965 self.send_and_expect(self.pg0, p, self.pg1)
3967 self.virtual_sleep(3)
3968 # retransmit ACK packet in -> out - this will cause session to be wiped
3970 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3971 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3972 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
3974 self.send_and_assert_no_replies(self.pg0, p)
3975 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3976 self.assertEqual(len(sessions) - session_n, 0)
3978 def test_tcp_session_close_out(self):
3979 """NAT44ED Close TCP session from outside network"""
3981 in_port = self.tcp_port_in
3983 ext_port = self.tcp_external_port
3985 self.nat_add_address(self.nat_addr)
3986 self.nat_add_inside_interface(self.pg0)
3987 self.nat_add_outside_interface(self.pg1)
3988 self.nat_add_static_mapping(
3989 self.pg0.remote_ip4,
3993 proto=IP_PROTOS.tcp,
3994 flags=self.config_flags.NAT_IS_TWICE_NAT,
3997 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3998 session_n = len(sessions)
4000 self.vapi.nat_set_timeouts(
4001 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
4004 _ = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
4006 # FIN packet out -> in
4008 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4009 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4010 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=100, ack=300)
4012 self.pg1.add_stream(p)
4013 self.pg_enable_capture(self.pg_interfaces)
4015 self.pg0.get_capture(1)
4017 # FIN+ACK packet in -> out
4019 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4020 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4021 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=300, ack=101)
4024 self.pg0.add_stream(p)
4025 self.pg_enable_capture(self.pg_interfaces)
4027 self.pg1.get_capture(1)
4029 # ACK packet out -> in
4031 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4032 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4033 / TCP(sport=ext_port, dport=out_port, flags="A", seq=101, ack=301)
4035 self.pg1.add_stream(p)
4036 self.pg_enable_capture(self.pg_interfaces)
4038 self.pg0.get_capture(1)
4040 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4041 self.assertEqual(len(sessions) - session_n, 1)
4043 # retransmit FIN packet out -> in
4045 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4046 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4047 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=101)
4049 self.send_and_expect(self.pg1, p, self.pg0)
4051 # retransmit ACK packet in -> out
4053 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4054 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4055 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4057 self.send_and_expect(self.pg0, p, self.pg1)
4059 self.virtual_sleep(3)
4060 # retransmit ACK packet in -> out - this will cause session to be wiped
4062 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4063 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4064 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4066 self.send_and_assert_no_replies(self.pg0, p)
4067 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4068 self.assertEqual(len(sessions) - session_n, 0)
4070 def test_tcp_session_close_simultaneous(self):
4071 """Simultaneous TCP close from both sides"""
4073 in_port = self.tcp_port_in
4076 self.nat_add_address(self.nat_addr)
4077 self.nat_add_inside_interface(self.pg0)
4078 self.nat_add_outside_interface(self.pg1)
4079 self.nat_add_static_mapping(
4080 self.pg0.remote_ip4,
4084 proto=IP_PROTOS.tcp,
4085 flags=self.config_flags.NAT_IS_TWICE_NAT,
4088 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4089 session_n = len(sessions)
4091 self.vapi.nat_set_timeouts(
4092 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
4095 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
4097 # FIN packet in -> out
4099 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4100 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4101 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=100, ack=300)
4103 self.send_and_expect(self.pg0, p, self.pg1)
4105 # FIN packet out -> in
4107 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4108 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4109 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=100)
4111 self.send_and_expect(self.pg1, p, self.pg0)
4113 # ACK packet in -> out
4115 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4116 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4117 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4119 self.send_and_expect(self.pg0, p, self.pg1)
4121 # ACK packet out -> in
4123 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4124 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4125 / TCP(sport=ext_port, dport=out_port, flags="A", seq=301, ack=101)
4127 self.send_and_expect(self.pg1, p, self.pg0)
4129 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4130 self.assertEqual(len(sessions) - session_n, 1)
4132 # retransmit FIN packet out -> in
4134 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4135 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4136 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=101)
4138 self.send_and_expect(self.pg1, p, self.pg0)
4140 # retransmit ACK packet in -> out
4142 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4143 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4144 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4146 self.send_and_expect(self.pg0, p, self.pg1)
4148 self.virtual_sleep(3)
4149 # retransmit ACK packet in -> out - this will cause session to be wiped
4151 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4152 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4153 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4155 self.pg_send(self.pg0, p)
4156 self.send_and_assert_no_replies(self.pg0, p)
4157 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4158 self.assertEqual(len(sessions) - session_n, 0)
4160 def test_tcp_session_half_reopen_inside(self):
4161 """TCP session in FIN/FIN state not reopened by in2out SYN only"""
4162 in_port = self.tcp_port_in
4165 self.nat_add_address(self.nat_addr)
4166 self.nat_add_inside_interface(self.pg0)
4167 self.nat_add_outside_interface(self.pg1)
4168 self.nat_add_static_mapping(
4169 self.pg0.remote_ip4,
4173 proto=IP_PROTOS.tcp,
4174 flags=self.config_flags.NAT_IS_TWICE_NAT,
4177 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4178 session_n = len(sessions)
4180 self.vapi.nat_set_timeouts(
4181 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
4184 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
4186 # FIN packet in -> out
4188 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4189 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4190 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=100, ack=300)
4192 self.send_and_expect(self.pg0, p, self.pg1)
4194 # FIN packet out -> in
4196 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4197 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4198 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=100)
4200 self.send_and_expect(self.pg1, p, self.pg0)
4202 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4203 self.assertEqual(len(sessions) - session_n, 1)
4205 # send SYN packet in -> out
4207 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4208 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4209 / TCP(sport=in_port, dport=ext_port, flags="S", seq=101, ack=301)
4211 self.send_and_expect(self.pg0, p, self.pg1)
4213 self.virtual_sleep(3)
4214 # send ACK packet in -> out - session should be wiped
4216 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4217 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4218 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4220 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
4221 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4222 self.assertEqual(len(sessions) - session_n, 0)
4224 def test_tcp_session_half_reopen_outside(self):
4225 """TCP session in FIN/FIN state not reopened by out2in SYN only"""
4226 in_port = self.tcp_port_in
4229 self.nat_add_address(self.nat_addr)
4230 self.nat_add_inside_interface(self.pg0)
4231 self.nat_add_outside_interface(self.pg1)
4232 self.nat_add_static_mapping(
4233 self.pg0.remote_ip4,
4237 proto=IP_PROTOS.tcp,
4238 flags=self.config_flags.NAT_IS_TWICE_NAT,
4241 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4242 session_n = len(sessions)
4244 self.vapi.nat_set_timeouts(
4245 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
4248 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
4250 # FIN packet in -> out
4252 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4253 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4254 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=100, ack=300)
4256 self.send_and_expect(self.pg0, p, self.pg1)
4258 # FIN packet out -> in
4260 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4261 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4262 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=100)
4264 self.send_and_expect(self.pg1, p, self.pg0)
4266 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4267 self.assertEqual(len(sessions) - session_n, 1)
4269 # send SYN packet out -> in
4271 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4272 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4273 / TCP(sport=ext_port, dport=out_port, flags="S", seq=300, ack=101)
4275 self.send_and_expect(self.pg1, p, self.pg0)
4277 self.virtual_sleep(3)
4278 # send ACK packet in -> out - session should be wiped
4280 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4281 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4282 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4284 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
4285 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4286 self.assertEqual(len(sessions) - session_n, 0)
4288 def test_tcp_session_reopen(self):
4289 """TCP session in FIN/FIN state reopened by SYN from both sides"""
4290 in_port = self.tcp_port_in
4293 self.nat_add_address(self.nat_addr)
4294 self.nat_add_inside_interface(self.pg0)
4295 self.nat_add_outside_interface(self.pg1)
4296 self.nat_add_static_mapping(
4297 self.pg0.remote_ip4,
4301 proto=IP_PROTOS.tcp,
4302 flags=self.config_flags.NAT_IS_TWICE_NAT,
4305 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4306 session_n = len(sessions)
4308 self.vapi.nat_set_timeouts(
4309 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
4312 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
4314 # FIN packet in -> out
4316 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4317 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4318 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=100, ack=300)
4320 self.send_and_expect(self.pg0, p, self.pg1)
4322 # FIN packet out -> in
4324 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4325 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4326 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=100)
4328 self.send_and_expect(self.pg1, p, self.pg0)
4330 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4331 self.assertEqual(len(sessions) - session_n, 1)
4333 # send SYN packet out -> in
4335 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4336 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4337 / TCP(sport=ext_port, dport=out_port, flags="S", seq=300, ack=101)
4339 self.send_and_expect(self.pg1, p, self.pg0)
4341 # send SYN packet in -> out
4343 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4344 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4345 / TCP(sport=in_port, dport=ext_port, flags="SA", seq=101, ack=301)
4347 self.send_and_expect(self.pg0, p, self.pg1)
4349 # send ACK packet out -> in
4351 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4352 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4353 / TCP(sport=ext_port, dport=out_port, flags="A", seq=300, ack=101)
4355 self.send_and_expect(self.pg1, p, self.pg0)
4357 self.virtual_sleep(3)
4358 # send ACK packet in -> out - should be forwarded and session alive
4360 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4361 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4362 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4364 self.send_and_expect(self.pg0, p, self.pg1)
4365 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4366 self.assertEqual(len(sessions) - session_n, 1)
4368 def test_dynamic_vrf(self):
4369 """NAT44ED dynamic translation test: different VRF"""
4374 self.nat_add_address(self.nat_addr, vrf_id=vrf_id_in)
4377 self.configure_ip4_interface(self.pg7, table_id=vrf_id_in)
4378 self.configure_ip4_interface(self.pg8, table_id=vrf_id_out)
4380 self.nat_add_inside_interface(self.pg7)
4381 self.nat_add_outside_interface(self.pg8)
4383 # just basic stuff nothing special
4384 pkts = self.create_stream_in(self.pg7, self.pg8)
4385 self.pg7.add_stream(pkts)
4386 self.pg_enable_capture(self.pg_interfaces)
4388 capture = self.pg8.get_capture(len(pkts))
4389 self.verify_capture_out(capture, ignore_port=True)
4391 pkts = self.create_stream_out(self.pg8)
4392 self.pg8.add_stream(pkts)
4393 self.pg_enable_capture(self.pg_interfaces)
4395 capture = self.pg7.get_capture(len(pkts))
4396 self.verify_capture_in(capture, self.pg7)
4402 self.vapi.ip_table_add_del(is_add=0, table={"table_id": vrf_id_in})
4403 self.vapi.ip_table_add_del(is_add=0, table={"table_id": vrf_id_out})
4405 def test_dynamic_output_feature_vrf(self):
4406 """NAT44ED dynamic translation test: output-feature, VRF"""
4408 # other then default (0)
4411 self.nat_add_address(self.nat_addr)
4412 self.vapi.nat44_ed_add_del_output_interface(
4413 sw_if_index=self.pg8.sw_if_index, is_add=1
4416 self.configure_ip4_interface(self.pg7, table_id=new_vrf_id)
4417 self.configure_ip4_interface(self.pg8, table_id=new_vrf_id)
4420 tcpn = self.statistics["/nat44-ed/in2out/slowpath/tcp"]
4421 udpn = self.statistics["/nat44-ed/in2out/slowpath/udp"]
4422 icmpn = self.statistics["/nat44-ed/in2out/slowpath/icmp"]
4423 drops = self.statistics["/nat44-ed/in2out/slowpath/drops"]
4425 pkts = self.create_stream_in(self.pg7, self.pg8)
4426 self.pg7.add_stream(pkts)
4427 self.pg_enable_capture(self.pg_interfaces)
4429 capture = self.pg8.get_capture(len(pkts))
4430 self.verify_capture_out(capture, ignore_port=True)
4432 if_idx = self.pg8.sw_if_index
4433 cnt = self.statistics["/nat44-ed/in2out/slowpath/tcp"]
4434 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
4435 cnt = self.statistics["/nat44-ed/in2out/slowpath/udp"]
4436 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
4437 cnt = self.statistics["/nat44-ed/in2out/slowpath/icmp"]
4438 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
4439 cnt = self.statistics["/nat44-ed/in2out/slowpath/drops"]
4440 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
4443 tcpn = self.statistics["/nat44-ed/out2in/fastpath/tcp"]
4444 udpn = self.statistics["/nat44-ed/out2in/fastpath/udp"]
4445 icmpn = self.statistics["/nat44-ed/out2in/fastpath/icmp"]
4446 drops = self.statistics["/nat44-ed/out2in/fastpath/drops"]
4448 pkts = self.create_stream_out(self.pg8)
4449 self.pg8.add_stream(pkts)
4450 self.pg_enable_capture(self.pg_interfaces)
4452 capture = self.pg7.get_capture(len(pkts))
4453 self.verify_capture_in(capture, self.pg7)
4455 if_idx = self.pg8.sw_if_index
4456 cnt = self.statistics["/nat44-ed/out2in/fastpath/tcp"]
4457 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
4458 cnt = self.statistics["/nat44-ed/out2in/fastpath/udp"]
4459 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
4460 cnt = self.statistics["/nat44-ed/out2in/fastpath/icmp"]
4461 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
4462 cnt = self.statistics["/nat44-ed/out2in/fastpath/drops"]
4463 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
4465 sessions = self.statistics["/nat44-ed/total-sessions"]
4466 self.assertEqual(sessions[:, 0].sum(), 3)
4472 self.vapi.ip_table_add_del(is_add=0, table={"table_id": new_vrf_id})
4474 def test_next_src_nat(self):
4475 """NAT44ED On way back forward packet to nat44-in2out node."""
4477 twice_nat_addr = "10.0.1.3"
4480 post_twice_nat_port = 0
4482 self.vapi.nat44_forwarding_enable_disable(enable=1)
4483 self.nat_add_address(twice_nat_addr, twice_nat=1)
4485 self.config_flags.NAT_IS_OUT2IN_ONLY
4486 | self.config_flags.NAT_IS_SELF_TWICE_NAT
4488 self.nat_add_static_mapping(
4489 self.pg6.remote_ip4,
4490 self.pg1.remote_ip4,
4493 proto=IP_PROTOS.tcp,
4497 self.vapi.nat44_interface_add_del_feature(
4498 sw_if_index=self.pg6.sw_if_index, is_add=1
4502 Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac)
4503 / IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4)
4504 / TCP(sport=12345, dport=external_port)
4506 self.pg6.add_stream(p)
4507 self.pg_enable_capture(self.pg_interfaces)
4509 capture = self.pg6.get_capture(1)
4514 self.assertEqual(ip.src, twice_nat_addr)
4515 self.assertNotEqual(tcp.sport, 12345)
4516 post_twice_nat_port = tcp.sport
4517 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4518 self.assertEqual(tcp.dport, local_port)
4519 self.assert_packet_checksums_valid(p)
4521 self.logger.error(ppp("Unexpected or invalid packet:", p))
4525 Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac)
4526 / IP(src=self.pg6.remote_ip4, dst=twice_nat_addr)
4527 / TCP(sport=local_port, dport=post_twice_nat_port)
4529 self.pg6.add_stream(p)
4530 self.pg_enable_capture(self.pg_interfaces)
4532 capture = self.pg6.get_capture(1)
4537 self.assertEqual(ip.src, self.pg1.remote_ip4)
4538 self.assertEqual(tcp.sport, external_port)
4539 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4540 self.assertEqual(tcp.dport, 12345)
4541 self.assert_packet_checksums_valid(p)
4543 self.logger.error(ppp("Unexpected or invalid packet:", p))
4546 def test_one_armed_nat44_static(self):
4547 """NAT44ED One armed NAT and 1:1 NAPT asymmetrical rule"""
4549 remote_host = self.pg4.remote_hosts[0]
4550 local_host = self.pg4.remote_hosts[1]
4555 self.vapi.nat44_forwarding_enable_disable(enable=1)
4556 self.nat_add_address(self.nat_addr, twice_nat=1)
4558 self.config_flags.NAT_IS_OUT2IN_ONLY | self.config_flags.NAT_IS_TWICE_NAT
4560 self.nat_add_static_mapping(
4565 proto=IP_PROTOS.tcp,
4568 flags = self.config_flags.NAT_IS_INSIDE
4569 self.vapi.nat44_interface_add_del_feature(
4570 sw_if_index=self.pg4.sw_if_index, is_add=1
4572 self.vapi.nat44_interface_add_del_feature(
4573 sw_if_index=self.pg4.sw_if_index, flags=flags, is_add=1
4576 # from client to service
4578 Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac)
4579 / IP(src=remote_host.ip4, dst=self.nat_addr)
4580 / TCP(sport=12345, dport=external_port)
4582 self.pg4.add_stream(p)
4583 self.pg_enable_capture(self.pg_interfaces)
4585 capture = self.pg4.get_capture(1)
4590 self.assertEqual(ip.dst, local_host.ip4)
4591 self.assertEqual(ip.src, self.nat_addr)
4592 self.assertEqual(tcp.dport, local_port)
4593 self.assertNotEqual(tcp.sport, 12345)
4594 eh_port_in = tcp.sport
4595 self.assert_packet_checksums_valid(p)
4597 self.logger.error(ppp("Unexpected or invalid packet:", p))
4600 # from service back to client
4602 Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac)
4603 / IP(src=local_host.ip4, dst=self.nat_addr)
4604 / TCP(sport=local_port, dport=eh_port_in)
4606 self.pg4.add_stream(p)
4607 self.pg_enable_capture(self.pg_interfaces)
4609 capture = self.pg4.get_capture(1)
4614 self.assertEqual(ip.src, self.nat_addr)
4615 self.assertEqual(ip.dst, remote_host.ip4)
4616 self.assertEqual(tcp.sport, external_port)
4617 self.assertEqual(tcp.dport, 12345)
4618 self.assert_packet_checksums_valid(p)
4620 self.logger.error(ppp("Unexpected or invalid packet:", p))
4623 def test_icmp_error_fwd_outbound(self):
4624 """NAT44ED ICMP error outbound with forwarding enabled"""
4626 # Ensure that an outbound ICMP error message is properly associated
4627 # with the inbound forward bypass session it is related to.
4630 self.nat_add_address(self.nat_addr)
4631 self.nat_add_inside_interface(self.pg0)
4632 self.nat_add_outside_interface(self.pg1)
4634 # enable forwarding and initiate connection out2in
4635 self.vapi.nat44_forwarding_enable_disable(enable=1)
4637 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4638 / IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4)
4639 / UDP(sport=21, dport=20)
4643 self.pg1.add_stream(p1)
4644 self.pg_enable_capture(self.pg_interfaces)
4646 capture = self.pg0.get_capture(1)[0]
4648 self.logger.info(self.vapi.cli("show nat44 sessions"))
4650 # reply with ICMP error message in2out
4651 # We cannot reliably retrieve forward bypass sessions via the API.
4652 # session dumps for a user will only look on the worker that the
4653 # user is supposed to be mapped to in2out. The forward bypass session
4654 # is not necessarily created on that worker.
4656 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4657 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4658 / ICMP(type="dest-unreach", code="port-unreachable")
4662 self.pg0.add_stream(p2)
4663 self.pg_enable_capture(self.pg_interfaces)
4665 capture = self.pg1.get_capture(1)[0]
4667 self.logger.info(self.vapi.cli("show nat44 sessions"))
4669 self.logger.info(ppp("p1 packet:", p1))
4670 self.logger.info(ppp("p2 packet:", p2))
4671 self.logger.info(ppp("capture packet:", capture))
4673 def test_tcp_session_open_retransmit1(self):
4674 """NAT44ED Open TCP session with SYN,ACK retransmit 1
4676 The client does not receive the [SYN,ACK] or the
4677 ACK from the client is lost. Therefore, the [SYN, ACK]
4678 is retransmitted by the server.
4681 in_port = self.tcp_port_in
4682 ext_port = self.tcp_external_port
4685 self.nat_add_address(self.nat_addr)
4686 self.nat_add_inside_interface(self.pg0)
4687 self.nat_add_outside_interface(self.pg1)
4689 self.vapi.nat_set_timeouts(
4690 udp=300, tcp_established=7440, tcp_transitory=5, icmp=60
4692 # SYN packet in->out
4694 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4695 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4696 / TCP(sport=in_port, dport=ext_port, flags="S")
4698 p = self.send_and_expect(self.pg0, p, self.pg1)[0]
4699 out_port = p[TCP].sport
4701 # SYN + ACK packet out->in
4703 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4704 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4705 / TCP(sport=ext_port, dport=out_port, flags="SA")
4707 self.send_and_expect(self.pg1, p, self.pg0)
4709 # ACK in->out does not arrive
4711 # resent SYN + ACK packet out->in
4713 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4714 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4715 / TCP(sport=ext_port, dport=out_port, flags="SA")
4717 self.send_and_expect(self.pg1, p, self.pg0)
4719 # ACK packet in->out
4721 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4722 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4723 / TCP(sport=in_port, dport=ext_port, flags="A")
4725 self.send_and_expect(self.pg0, p, self.pg1)
4727 # Verify that the data can be transmitted after the transitory time
4728 self.virtual_sleep(6)
4731 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4732 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4733 / TCP(sport=in_port, dport=ext_port, flags="PA")
4736 self.send_and_expect(self.pg0, p, self.pg1)
4738 def test_tcp_session_open_retransmit2(self):
4739 """NAT44ED Open TCP session with SYN,ACK retransmit 2
4741 The ACK is lost to the server after the TCP session is opened.
4742 Data is sent by the client, then the [SYN,ACK] is
4743 retransmitted by the server.
4746 in_port = self.tcp_port_in
4747 ext_port = self.tcp_external_port
4750 self.nat_add_address(self.nat_addr)
4751 self.nat_add_inside_interface(self.pg0)
4752 self.nat_add_outside_interface(self.pg1)
4754 self.vapi.nat_set_timeouts(
4755 udp=300, tcp_established=7440, tcp_transitory=5, icmp=60
4757 # SYN packet in->out
4759 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4760 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4761 / TCP(sport=in_port, dport=ext_port, flags="S")
4763 p = self.send_and_expect(self.pg0, p, self.pg1)[0]
4764 out_port = p[TCP].sport
4766 # SYN + ACK packet out->in
4768 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4769 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4770 / TCP(sport=ext_port, dport=out_port, flags="SA")
4772 self.send_and_expect(self.pg1, p, self.pg0)
4774 # ACK packet in->out -- not received by the server
4776 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4777 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4778 / TCP(sport=in_port, dport=ext_port, flags="A")
4780 self.send_and_expect(self.pg0, p, self.pg1)
4782 # PUSH + ACK packet in->out
4784 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4785 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4786 / TCP(sport=in_port, dport=ext_port, flags="PA")
4789 self.send_and_expect(self.pg0, p, self.pg1)
4791 # resent SYN + ACK packet out->in
4793 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4794 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4795 / TCP(sport=ext_port, dport=out_port, flags="SA")
4797 self.send_and_expect(self.pg1, p, self.pg0)
4799 # resent ACK packet in->out
4801 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4802 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4803 / TCP(sport=in_port, dport=ext_port, flags="A")
4805 self.send_and_expect(self.pg0, p, self.pg1)
4807 # resent PUSH + ACK packet in->out
4809 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4810 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4811 / TCP(sport=in_port, dport=ext_port, flags="PA")
4814 self.send_and_expect(self.pg0, p, self.pg1)
4816 # ACK packet out->in
4818 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4819 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4820 / TCP(sport=ext_port, dport=out_port, flags="A")
4822 self.send_and_expect(self.pg1, p, self.pg0)
4824 # Verify that the data can be transmitted after the transitory time
4825 self.virtual_sleep(6)
4828 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4829 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4830 / TCP(sport=in_port, dport=ext_port, flags="PA")
4833 self.send_and_expect(self.pg0, p, self.pg1)
4835 def test_dynamic_ports_exhausted(self):
4836 """NAT44ED dynamic translation test: address ports exhaused"""
4838 sessions_per_batch = 128
4839 n_available_ports = 65536 - 1024
4840 n_sessions = n_available_ports + 2 * sessions_per_batch
4842 # set high enough session limit for ports to be exhausted
4843 self.plugin_disable()
4844 self.plugin_enable(max_sessions=n_sessions)
4846 self.nat_add_inside_interface(self.pg0)
4847 self.nat_add_outside_interface(self.pg1)
4849 # set timeouts to high for sessions to reallistically expire
4850 config = self.vapi.nat44_show_running_config()
4851 old_timeouts = config.timeouts
4852 self.vapi.nat_set_timeouts(
4854 tcp_established=old_timeouts.tcp_established,
4855 tcp_transitory=old_timeouts.tcp_transitory,
4856 icmp=old_timeouts.icmp,
4859 # in2out after NAT addresses added
4860 self.nat_add_address(self.nat_addr)
4862 for i in range(n_sessions // sessions_per_batch):
4863 pkts = self.create_udp_stream(
4867 base_port=i * sessions_per_batch + 100,
4870 self.pg0.add_stream(pkts)
4873 err = self.statistics.get_err_counter(
4874 "/err/nat44-ed-in2out-slowpath/out of ports"
4876 if err > sessions_per_batch:
4879 # Check for ports to be used no more than once
4881 sessions = self.vapi.cli("show nat44 sessions")
4883 f" *o2i flow: match: saddr {self.pg1.remote_ip4} sport [0-9]+ daddr {self.nat_addr} dport ([0-9]+) proto UDP.*"
4885 for line in sessions.splitlines():
4888 port = int(m.groups()[0])
4889 self.assertNotIn(port, ports)
4892 self.assertGreaterEqual(err, sessions_per_batch)
4895 if __name__ == "__main__":
4896 unittest.main(testRunner=VppTestRunner)