5 from random import randint, choice
8 from framework import VppTestCase, VppTestRunner
9 from scapy.data import IP_PROTOS
10 from scapy.layers.inet import IP, TCP, UDP, ICMP, GRE
11 from scapy.layers.inet import IPerror, TCPerror
12 from scapy.layers.l2 import Ether
13 from scapy.packet import Raw
14 from syslog_rfc5424_parser import SyslogMessage, ParseError
15 from syslog_rfc5424_parser.constants import SyslogSeverity
16 from util import ppp, pr, ip4_range
17 from vpp_acl import AclRule, VppAcl, VppAclInterface
18 from vpp_ip_route import VppIpRoute, VppRoutePath
19 from vpp_papi import VppEnum
20 from util import StatsDiff
23 class TestNAT44ED(VppTestCase):
24 """NAT44ED Test Case"""
26 nat_addr = "10.0.10.3"
37 tcp_external_port = 80
50 def plugin_enable(self):
51 self.vapi.nat44_ed_plugin_enable_disable(sessions=self.max_sessions, enable=1)
53 def plugin_disable(self):
54 self.vapi.nat44_ed_plugin_enable_disable(enable=0)
57 def config_flags(self):
58 return VppEnum.vl_api_nat_config_flags_t
61 def nat44_config_flags(self):
62 return VppEnum.vl_api_nat44_config_flags_t
65 def syslog_severity(self):
66 return VppEnum.vl_api_syslog_severity_t
69 def server_addr(self):
70 return self.pg1.remote_hosts[0].ip4
74 return randint(1024, 65535)
77 def proto2layer(proto):
78 if proto == IP_PROTOS.tcp:
80 elif proto == IP_PROTOS.udp:
82 elif proto == IP_PROTOS.icmp:
85 raise Exception("Unsupported protocol")
88 def create_and_add_ip4_table(cls, i, table_id=0):
89 cls.vapi.ip_table_add_del(is_add=1, table={"table_id": table_id})
90 i.set_table_ip4(table_id)
93 def configure_ip4_interface(cls, i, hosts=0, table_id=None):
95 cls.create_and_add_ip4_table(i, table_id)
102 i.generate_remote_hosts(hosts)
103 i.configure_ipv4_neighbors()
106 def nat_add_interface_address(cls, i):
107 cls.vapi.nat44_add_del_interface_addr(sw_if_index=i.sw_if_index, is_add=1)
109 def nat_add_inside_interface(self, i):
110 self.vapi.nat44_interface_add_del_feature(
111 flags=self.config_flags.NAT_IS_INSIDE, sw_if_index=i.sw_if_index, is_add=1
114 def nat_add_outside_interface(self, i):
115 self.vapi.nat44_interface_add_del_feature(
116 flags=self.config_flags.NAT_IS_OUTSIDE, sw_if_index=i.sw_if_index, is_add=1
119 def nat_add_address(self, address, twice_nat=0, vrf_id=0xFFFFFFFF, is_add=1):
120 flags = self.config_flags.NAT_IS_TWICE_NAT if twice_nat else 0
121 self.vapi.nat44_add_del_address_range(
122 first_ip_address=address,
123 last_ip_address=address,
129 def nat_add_static_mapping(
132 external_ip="0.0.0.0",
137 external_sw_if_index=0xFFFFFFFF,
143 if not (local_port and external_port):
144 flags |= self.config_flags.NAT_IS_ADDR_ONLY
146 self.vapi.nat44_add_del_static_mapping(
148 local_ip_address=local_ip,
149 external_ip_address=external_ip,
150 external_sw_if_index=external_sw_if_index,
151 local_port=local_port,
152 external_port=external_port,
163 cls.create_pg_interfaces(range(12))
164 cls.interfaces = list(cls.pg_interfaces[:4])
166 cls.create_and_add_ip4_table(cls.pg2, 10)
168 for i in cls.interfaces:
169 cls.configure_ip4_interface(i, hosts=3)
171 # test specific (test-multiple-vrf)
172 cls.vapi.ip_table_add_del(is_add=1, table={"table_id": 1})
174 # test specific (test-one-armed-nat44-static)
175 cls.pg4.generate_remote_hosts(2)
177 cls.vapi.sw_interface_add_del_address(
178 sw_if_index=cls.pg4.sw_if_index, prefix="10.0.0.1/24"
181 cls.pg4.resolve_arp()
182 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
183 cls.pg4.resolve_arp()
185 # test specific interface (pg5)
186 cls.pg5._local_ip4 = "10.1.1.1"
187 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
188 cls.pg5.set_table_ip4(1)
191 cls.pg5.resolve_arp()
193 # test specific interface (pg6)
194 cls.pg6._local_ip4 = "10.1.2.1"
195 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
196 cls.pg6.set_table_ip4(1)
199 cls.pg6.resolve_arp()
208 [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=0)],
218 [VppRoutePath(cls.pg1.local_ip4, cls.pg1.sw_if_index)],
227 [VppRoutePath("0.0.0.0", cls.pg5.sw_if_index)],
237 [VppRoutePath("0.0.0.0", cls.pg6.sw_if_index)],
247 [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=1)],
256 cls.no_diff = StatsDiff(
259 "/nat44-ed/in2out/fastpath/tcp": 0,
260 "/nat44-ed/in2out/fastpath/udp": 0,
261 "/nat44-ed/in2out/fastpath/icmp": 0,
262 "/nat44-ed/in2out/fastpath/drops": 0,
263 "/nat44-ed/in2out/slowpath/tcp": 0,
264 "/nat44-ed/in2out/slowpath/udp": 0,
265 "/nat44-ed/in2out/slowpath/icmp": 0,
266 "/nat44-ed/in2out/slowpath/drops": 0,
267 "/nat44-ed/in2out/fastpath/tcp": 0,
268 "/nat44-ed/in2out/fastpath/udp": 0,
269 "/nat44-ed/in2out/fastpath/icmp": 0,
270 "/nat44-ed/in2out/fastpath/drops": 0,
271 "/nat44-ed/in2out/slowpath/tcp": 0,
272 "/nat44-ed/in2out/slowpath/udp": 0,
273 "/nat44-ed/in2out/slowpath/icmp": 0,
274 "/nat44-ed/in2out/slowpath/drops": 0,
276 for pg in cls.pg_interfaces
280 def get_err_counter(self, path):
281 return self.statistics.get_err_counter(path)
283 def reass_hairpinning(
292 layer = self.proto2layer(proto)
294 if proto == IP_PROTOS.tcp:
295 data = b"A" * 4 + b"B" * 16 + b"C" * 3
297 data = b"A" * 16 + b"B" * 16 + b"C" * 3
299 # send packet from host to server
300 pkts = self.create_stream_frag(
301 self.pg0, self.nat_addr, host_in_port, server_out_port, data, proto
303 self.pg0.add_stream(pkts)
304 self.pg_enable_capture(self.pg_interfaces)
306 frags = self.pg0.get_capture(len(pkts))
307 p = self.reass_frags_and_verify(frags, self.nat_addr, server_addr)
308 if proto != IP_PROTOS.icmp:
310 self.assertNotEqual(p[layer].sport, host_in_port)
311 self.assertEqual(p[layer].dport, server_in_port)
314 self.assertNotEqual(p[layer].id, host_in_port)
315 self.assertEqual(data, p[Raw].load)
317 def frag_out_of_order(
318 self, proto=IP_PROTOS.tcp, dont_translate=False, ignore_port=False
320 layer = self.proto2layer(proto)
322 if proto == IP_PROTOS.tcp:
323 data = b"A" * 4 + b"B" * 16 + b"C" * 3
325 data = b"A" * 16 + b"B" * 16 + b"C" * 3
326 self.port_in = self.random_port()
330 pkts = self.create_stream_frag(
331 self.pg0, self.pg1.remote_ip4, self.port_in, 20, data, proto
334 self.pg0.add_stream(pkts)
335 self.pg_enable_capture(self.pg_interfaces)
337 frags = self.pg1.get_capture(len(pkts))
338 if not dont_translate:
339 p = self.reass_frags_and_verify(
340 frags, self.nat_addr, self.pg1.remote_ip4
343 p = self.reass_frags_and_verify(
344 frags, self.pg0.remote_ip4, self.pg1.remote_ip4
346 if proto != IP_PROTOS.icmp:
347 if not dont_translate:
348 self.assertEqual(p[layer].dport, 20)
350 self.assertNotEqual(p[layer].sport, self.port_in)
352 self.assertEqual(p[layer].sport, self.port_in)
355 if not dont_translate:
356 self.assertNotEqual(p[layer].id, self.port_in)
358 self.assertEqual(p[layer].id, self.port_in)
359 self.assertEqual(data, p[Raw].load)
362 if not dont_translate:
363 dst_addr = self.nat_addr
365 dst_addr = self.pg0.remote_ip4
366 if proto != IP_PROTOS.icmp:
368 dport = p[layer].sport
372 pkts = self.create_stream_frag(
373 self.pg1, dst_addr, sport, dport, data, proto, echo_reply=True
376 self.pg1.add_stream(pkts)
377 self.pg_enable_capture(self.pg_interfaces)
378 self.logger.info(self.vapi.cli("show trace"))
380 frags = self.pg0.get_capture(len(pkts))
381 p = self.reass_frags_and_verify(
382 frags, self.pg1.remote_ip4, self.pg0.remote_ip4
384 if proto != IP_PROTOS.icmp:
385 self.assertEqual(p[layer].sport, 20)
386 self.assertEqual(p[layer].dport, self.port_in)
388 self.assertEqual(p[layer].id, self.port_in)
389 self.assertEqual(data, p[Raw].load)
391 def reass_frags_and_verify(self, frags, src, dst):
394 self.assertEqual(p[IP].src, src)
395 self.assertEqual(p[IP].dst, dst)
396 self.assert_ip_checksum_valid(p)
397 buffer.seek(p[IP].frag * 8)
398 buffer.write(bytes(p[IP].payload))
399 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst, proto=frags[0][IP].proto)
400 if ip.proto == IP_PROTOS.tcp:
401 p = ip / TCP(buffer.getvalue())
402 self.logger.debug(ppp("Reassembled:", p))
403 self.assert_tcp_checksum_valid(p)
404 elif ip.proto == IP_PROTOS.udp:
405 p = ip / UDP(buffer.getvalue()[:8]) / Raw(buffer.getvalue()[8:])
406 elif ip.proto == IP_PROTOS.icmp:
407 p = ip / ICMP(buffer.getvalue())
411 self, proto=IP_PROTOS.tcp, dont_translate=False, ignore_port=False
413 layer = self.proto2layer(proto)
415 if proto == IP_PROTOS.tcp:
416 data = b"A" * 4 + b"B" * 16 + b"C" * 3
418 data = b"A" * 16 + b"B" * 16 + b"C" * 3
419 self.port_in = self.random_port()
422 pkts = self.create_stream_frag(
423 self.pg0, self.pg1.remote_ip4, self.port_in, 20, data, proto
425 self.pg0.add_stream(pkts)
426 self.pg_enable_capture(self.pg_interfaces)
428 frags = self.pg1.get_capture(len(pkts))
429 if not dont_translate:
430 p = self.reass_frags_and_verify(frags, self.nat_addr, self.pg1.remote_ip4)
432 p = self.reass_frags_and_verify(
433 frags, self.pg0.remote_ip4, self.pg1.remote_ip4
435 if proto != IP_PROTOS.icmp:
436 if not dont_translate:
437 self.assertEqual(p[layer].dport, 20)
439 self.assertNotEqual(p[layer].sport, self.port_in)
441 self.assertEqual(p[layer].sport, self.port_in)
444 if not dont_translate:
445 self.assertNotEqual(p[layer].id, self.port_in)
447 self.assertEqual(p[layer].id, self.port_in)
448 self.assertEqual(data, p[Raw].load)
451 if not dont_translate:
452 dst_addr = self.nat_addr
454 dst_addr = self.pg0.remote_ip4
455 if proto != IP_PROTOS.icmp:
457 dport = p[layer].sport
461 pkts = self.create_stream_frag(
462 self.pg1, dst_addr, sport, dport, data, proto, echo_reply=True
464 self.pg1.add_stream(pkts)
465 self.pg_enable_capture(self.pg_interfaces)
467 frags = self.pg0.get_capture(len(pkts))
468 p = self.reass_frags_and_verify(frags, self.pg1.remote_ip4, self.pg0.remote_ip4)
469 if proto != IP_PROTOS.icmp:
470 self.assertEqual(p[layer].sport, 20)
471 self.assertEqual(p[layer].dport, self.port_in)
473 self.assertEqual(p[layer].id, self.port_in)
474 self.assertEqual(data, p[Raw].load)
476 def verify_capture_out(
477 self, capture, nat_ip=None, same_port=False, dst_ip=None, ignore_port=False
480 nat_ip = self.nat_addr
481 for packet in capture:
483 self.assert_packet_checksums_valid(packet)
484 self.assertEqual(packet[IP].src, nat_ip)
485 if dst_ip is not None:
486 self.assertEqual(packet[IP].dst, dst_ip)
487 if packet.haslayer(TCP):
490 self.assertEqual(packet[TCP].sport, self.tcp_port_in)
492 self.assertNotEqual(packet[TCP].sport, self.tcp_port_in)
493 self.tcp_port_out = packet[TCP].sport
494 self.assert_packet_checksums_valid(packet)
495 elif packet.haslayer(UDP):
498 self.assertEqual(packet[UDP].sport, self.udp_port_in)
500 self.assertNotEqual(packet[UDP].sport, self.udp_port_in)
501 self.udp_port_out = packet[UDP].sport
505 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
507 self.assertNotEqual(packet[ICMP].id, self.icmp_id_in)
508 self.icmp_id_out = packet[ICMP].id
509 self.assert_packet_checksums_valid(packet)
512 ppp("Unexpected or invalid packet (outside network):", packet)
516 def verify_capture_in(self, capture, in_if):
517 for packet in capture:
519 self.assert_packet_checksums_valid(packet)
520 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
521 if packet.haslayer(TCP):
522 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
523 elif packet.haslayer(UDP):
524 self.assertEqual(packet[UDP].dport, self.udp_port_in)
526 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
529 ppp("Unexpected or invalid packet (inside network):", packet)
533 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
535 dst_ip = out_if.remote_ip4
540 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
541 / IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl)
542 / TCP(sport=self.tcp_port_in, dport=20)
548 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
549 / IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl)
550 / UDP(sport=self.udp_port_in, dport=20)
556 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
557 / IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl)
558 / ICMP(id=self.icmp_id_in, type="echo-request")
564 def create_stream_out(self, out_if, dst_ip=None, ttl=64, use_inside_ports=False):
566 dst_ip = self.nat_addr
567 if not use_inside_ports:
568 tcp_port = self.tcp_port_out
569 udp_port = self.udp_port_out
570 icmp_id = self.icmp_id_out
572 tcp_port = self.tcp_port_in
573 udp_port = self.udp_port_in
574 icmp_id = self.icmp_id_in
578 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
579 / IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl)
580 / TCP(dport=tcp_port, sport=20)
586 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
587 / IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl)
588 / UDP(dport=udp_port, sport=20)
594 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
595 / IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl)
596 / ICMP(id=icmp_id, type="echo-reply")
602 def create_tcp_stream(self, in_if, out_if, count):
606 for i in range(count):
608 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
609 / IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=64)
610 / TCP(sport=port + i, dport=20)
616 def create_stream_frag(
617 self, src_if, dst, sport, dport, data, proto=IP_PROTOS.tcp, echo_reply=False
619 if proto == IP_PROTOS.tcp:
621 IP(src=src_if.remote_ip4, dst=dst)
622 / TCP(sport=sport, dport=dport)
625 p = p.__class__(scapy.compat.raw(p))
626 chksum = p[TCP].chksum
627 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
628 elif proto == IP_PROTOS.udp:
629 proto_header = UDP(sport=sport, dport=dport)
630 elif proto == IP_PROTOS.icmp:
632 proto_header = ICMP(id=sport, type="echo-request")
634 proto_header = ICMP(id=sport, type="echo-reply")
636 raise Exception("Unsupported protocol")
637 id = self.random_port()
639 if proto == IP_PROTOS.tcp:
642 raw = Raw(data[0:16])
644 Ether(src=src_if.remote_mac, dst=src_if.local_mac)
645 / IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id)
650 if proto == IP_PROTOS.tcp:
651 raw = Raw(data[4:20])
653 raw = Raw(data[16:32])
655 Ether(src=src_if.remote_mac, dst=src_if.local_mac)
656 / IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id, proto=proto)
660 if proto == IP_PROTOS.tcp:
665 Ether(src=src_if.remote_mac, dst=src_if.local_mac)
666 / IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto, id=id)
672 def frag_in_order_in_plus_out(
673 self, in_addr, out_addr, in_port, out_port, proto=IP_PROTOS.tcp
676 layer = self.proto2layer(proto)
678 if proto == IP_PROTOS.tcp:
679 data = b"A" * 4 + b"B" * 16 + b"C" * 3
681 data = b"A" * 16 + b"B" * 16 + b"C" * 3
682 port_in = self.random_port()
686 pkts = self.create_stream_frag(
687 self.pg0, out_addr, port_in, out_port, data, proto
689 self.pg0.add_stream(pkts)
690 self.pg_enable_capture(self.pg_interfaces)
692 frags = self.pg1.get_capture(len(pkts))
693 p = self.reass_frags_and_verify(frags, self.pg0.remote_ip4, in_addr)
694 if proto != IP_PROTOS.icmp:
695 self.assertEqual(p[layer].sport, port_in)
696 self.assertEqual(p[layer].dport, in_port)
698 self.assertEqual(p[layer].id, port_in)
699 self.assertEqual(data, p[Raw].load)
702 if proto != IP_PROTOS.icmp:
703 pkts = self.create_stream_frag(
704 self.pg1, self.pg0.remote_ip4, in_port, p[layer].sport, data, proto
707 pkts = self.create_stream_frag(
716 self.pg1.add_stream(pkts)
717 self.pg_enable_capture(self.pg_interfaces)
719 frags = self.pg0.get_capture(len(pkts))
720 p = self.reass_frags_and_verify(frags, out_addr, self.pg0.remote_ip4)
721 if proto != IP_PROTOS.icmp:
722 self.assertEqual(p[layer].sport, out_port)
723 self.assertEqual(p[layer].dport, port_in)
725 self.assertEqual(p[layer].id, port_in)
726 self.assertEqual(data, p[Raw].load)
728 def frag_out_of_order_in_plus_out(
729 self, in_addr, out_addr, in_port, out_port, proto=IP_PROTOS.tcp
732 layer = self.proto2layer(proto)
734 if proto == IP_PROTOS.tcp:
735 data = b"A" * 4 + b"B" * 16 + b"C" * 3
737 data = b"A" * 16 + b"B" * 16 + b"C" * 3
738 port_in = self.random_port()
742 pkts = self.create_stream_frag(
743 self.pg0, out_addr, port_in, out_port, data, proto
746 self.pg0.add_stream(pkts)
747 self.pg_enable_capture(self.pg_interfaces)
749 frags = self.pg1.get_capture(len(pkts))
750 p = self.reass_frags_and_verify(frags, self.pg0.remote_ip4, in_addr)
751 if proto != IP_PROTOS.icmp:
752 self.assertEqual(p[layer].dport, in_port)
753 self.assertEqual(p[layer].sport, port_in)
754 self.assertEqual(p[layer].dport, in_port)
756 self.assertEqual(p[layer].id, port_in)
757 self.assertEqual(data, p[Raw].load)
760 if proto != IP_PROTOS.icmp:
761 pkts = self.create_stream_frag(
762 self.pg1, self.pg0.remote_ip4, in_port, p[layer].sport, data, proto
765 pkts = self.create_stream_frag(
775 self.pg1.add_stream(pkts)
776 self.pg_enable_capture(self.pg_interfaces)
778 frags = self.pg0.get_capture(len(pkts))
779 p = self.reass_frags_and_verify(frags, out_addr, self.pg0.remote_ip4)
780 if proto != IP_PROTOS.icmp:
781 self.assertEqual(p[layer].sport, out_port)
782 self.assertEqual(p[layer].dport, port_in)
784 self.assertEqual(p[layer].id, port_in)
785 self.assertEqual(data, p[Raw].load)
787 def init_tcp_session(self, in_if, out_if, in_port, ext_port):
790 Ether(src=in_if.remote_mac, dst=in_if.local_mac)
791 / IP(src=in_if.remote_ip4, dst=out_if.remote_ip4)
792 / TCP(sport=in_port, dport=ext_port, flags="S")
795 self.pg_enable_capture(self.pg_interfaces)
797 capture = out_if.get_capture(1)
799 out_port = p[TCP].sport
801 # SYN + ACK packet out->in
803 Ether(src=out_if.remote_mac, dst=out_if.local_mac)
804 / IP(src=out_if.remote_ip4, dst=self.nat_addr)
805 / TCP(sport=ext_port, dport=out_port, flags="SA")
808 self.pg_enable_capture(self.pg_interfaces)
814 Ether(src=in_if.remote_mac, dst=in_if.local_mac)
815 / IP(src=in_if.remote_ip4, dst=out_if.remote_ip4)
816 / TCP(sport=in_port, dport=ext_port, flags="A")
819 self.pg_enable_capture(self.pg_interfaces)
821 out_if.get_capture(1)
825 def twice_nat_common(
826 self, self_twice_nat=False, same_pg=False, lb=False, client_id=None
828 twice_nat_addr = "10.0.1.3"
836 port_in1 = port_in + 1
837 port_in2 = port_in + 2
842 server1 = self.pg0.remote_hosts[0]
843 server2 = self.pg0.remote_hosts[1]
855 eh_translate = (not self_twice_nat) or (not lb and same_pg) or client_id == 1
857 self.nat_add_address(self.nat_addr)
858 self.nat_add_address(twice_nat_addr, twice_nat=1)
862 flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
864 flags |= self.config_flags.NAT_IS_TWICE_NAT
867 self.nat_add_static_mapping(
877 {"addr": server1.ip4, "port": port_in1, "probability": 50, "vrf_id": 0},
878 {"addr": server2.ip4, "port": port_in2, "probability": 50, "vrf_id": 0},
880 out_addr = self.nat_addr
882 self.vapi.nat44_add_del_lb_static_mapping(
885 external_addr=out_addr,
886 external_port=port_out,
887 protocol=IP_PROTOS.tcp,
888 local_num=len(locals),
891 self.nat_add_inside_interface(pg0)
892 self.nat_add_outside_interface(pg1)
898 assert client_id is not None
900 client = self.pg0.remote_hosts[0]
902 client = self.pg0.remote_hosts[1]
904 client = pg1.remote_hosts[0]
906 Ether(src=pg1.remote_mac, dst=pg1.local_mac)
907 / IP(src=client.ip4, dst=self.nat_addr)
908 / TCP(sport=eh_port_out, dport=port_out)
911 self.pg_enable_capture(self.pg_interfaces)
913 capture = pg0.get_capture(1)
919 if ip.dst == server1.ip4:
925 self.assertEqual(ip.dst, server.ip4)
927 self.assertIn(tcp.dport, [port_in1, port_in2])
929 self.assertEqual(tcp.dport, port_in)
931 self.assertEqual(ip.src, twice_nat_addr)
932 self.assertNotEqual(tcp.sport, eh_port_out)
934 self.assertEqual(ip.src, client.ip4)
935 self.assertEqual(tcp.sport, eh_port_out)
937 eh_port_in = tcp.sport
938 saved_port_in = tcp.dport
939 self.assert_packet_checksums_valid(p)
941 self.logger.error(ppp("Unexpected or invalid packet:", p))
945 Ether(src=server.mac, dst=pg0.local_mac)
946 / IP(src=server.ip4, dst=eh_addr_in)
947 / TCP(sport=saved_port_in, dport=eh_port_in)
950 self.pg_enable_capture(self.pg_interfaces)
952 capture = pg1.get_capture(1)
957 self.assertEqual(ip.dst, client.ip4)
958 self.assertEqual(ip.src, self.nat_addr)
959 self.assertEqual(tcp.dport, eh_port_out)
960 self.assertEqual(tcp.sport, port_out)
961 self.assert_packet_checksums_valid(p)
963 self.logger.error(ppp("Unexpected or invalid packet:", p))
967 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
968 self.assertEqual(len(sessions), 1)
969 self.assertTrue(sessions[0].flags & self.config_flags.NAT_IS_EXT_HOST_VALID)
970 self.assertTrue(sessions[0].flags & self.config_flags.NAT_IS_TWICE_NAT)
971 self.logger.info(self.vapi.cli("show nat44 sessions"))
972 self.vapi.nat44_del_session(
973 address=sessions[0].inside_ip_address,
974 port=sessions[0].inside_port,
975 protocol=sessions[0].protocol,
977 self.config_flags.NAT_IS_INSIDE
978 | self.config_flags.NAT_IS_EXT_HOST_VALID
980 ext_host_address=sessions[0].ext_host_nat_address,
981 ext_host_port=sessions[0].ext_host_nat_port,
983 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
984 self.assertEqual(len(sessions), 0)
986 def verify_syslog_sess(self, data, msgid, is_ip6=False):
987 message = data.decode("utf-8")
989 message = SyslogMessage.parse(message)
990 except ParseError as e:
994 self.assertEqual(message.severity, SyslogSeverity.info)
995 self.assertEqual(message.appname, "NAT")
996 self.assertEqual(message.msgid, msgid)
997 sd_params = message.sd.get("nsess")
998 self.assertTrue(sd_params is not None)
1000 self.assertEqual(sd_params.get("IATYP"), "IPv6")
1001 self.assertEqual(sd_params.get("ISADDR"), self.pg0.remote_ip6)
1003 self.assertEqual(sd_params.get("IATYP"), "IPv4")
1004 self.assertEqual(sd_params.get("ISADDR"), self.pg0.remote_ip4)
1005 self.assertTrue(sd_params.get("SSUBIX") is not None)
1006 self.assertEqual(sd_params.get("ISPORT"), "%d" % self.tcp_port_in)
1007 self.assertEqual(sd_params.get("XATYP"), "IPv4")
1008 self.assertEqual(sd_params.get("XSADDR"), self.nat_addr)
1009 self.assertEqual(sd_params.get("XSPORT"), "%d" % self.tcp_port_out)
1010 self.assertEqual(sd_params.get("PROTO"), "%d" % IP_PROTOS.tcp)
1011 self.assertEqual(sd_params.get("SVLAN"), "0")
1012 self.assertEqual(sd_params.get("XDADDR"), self.pg1.remote_ip4)
1013 self.assertEqual(sd_params.get("XDPORT"), "%d" % self.tcp_external_port)
1015 def test_icmp_error(self):
1016 """NAT44ED test ICMP error message with inner header"""
1020 self.nat_add_address(self.nat_addr)
1021 self.nat_add_inside_interface(self.pg0)
1022 self.nat_add_outside_interface(self.pg1)
1024 # in2out (initiate connection)
1026 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1027 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1028 / UDP(sport=21, dport=20)
1030 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1031 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1032 / TCP(sport=21, dport=20, flags="S")
1034 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1035 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1036 / ICMP(type="echo-request", id=7777)
1040 capture = self.send_and_expect(self.pg0, p1, self.pg1)
1042 # out2in (send error message)
1044 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1045 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1046 / ICMP(type="dest-unreach", code="port-unreachable")
1051 capture = self.send_and_expect(self.pg1, p2, self.pg0)
1055 assert c[IP].dst == self.pg0.remote_ip4
1056 assert c[IPerror].src == self.pg0.remote_ip4
1057 except AssertionError as a:
1058 raise AssertionError(f"Packet {pr(c)} not translated properly") from a
1060 def test_icmp_echo_reply_trailer(self):
1061 """ICMP echo reply with ethernet trailer"""
1063 self.nat_add_address(self.nat_addr)
1064 self.nat_add_inside_interface(self.pg0)
1065 self.nat_add_outside_interface(self.pg1)
1069 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1070 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1071 / ICMP(type=8, id=0xABCD, seq=0)
1074 self.pg0.add_stream(p1)
1075 self.pg_enable_capture(self.pg_interfaces)
1077 c = self.pg1.get_capture(1)[0]
1079 self.logger.debug(self.vapi.cli("show trace"))
1083 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1084 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr, id=0xEE59)
1085 / ICMP(type=0, id=c[ICMP].id, seq=0)
1088 # force checksum calculation
1089 p2 = p2.__class__(bytes(p2))
1091 self.logger.debug(ppp("Packet before modification:", p2))
1093 # hex representation of vss monitoring ethernet trailer
1094 # this seems to be just added to end of packet without modifying
1095 # IP or ICMP lengths / checksums
1096 p2 = p2 / Raw("\x00\x00\x52\x54\x00\x46\xab\x04\x84\x18")
1097 # change it so that IP/ICMP is unaffected
1100 self.logger.debug(ppp("Packet with added trailer:", p2))
1102 self.pg1.add_stream(p2)
1103 self.pg_enable_capture(self.pg_interfaces)
1106 self.pg0.get_capture(1)
1108 def test_users_dump(self):
1109 """NAT44ED API test - nat44_user_dump"""
1111 self.nat_add_address(self.nat_addr)
1112 self.nat_add_inside_interface(self.pg0)
1113 self.nat_add_outside_interface(self.pg1)
1115 self.vapi.nat44_forwarding_enable_disable(enable=1)
1117 local_ip = self.pg0.remote_ip4
1118 external_ip = self.nat_addr
1119 self.nat_add_static_mapping(local_ip, external_ip)
1121 users = self.vapi.nat44_user_dump()
1122 self.assertEqual(len(users), 0)
1124 # in2out - static mapping match
1126 pkts = self.create_stream_out(self.pg1)
1127 self.pg1.add_stream(pkts)
1128 self.pg_enable_capture(self.pg_interfaces)
1130 capture = self.pg0.get_capture(len(pkts))
1131 self.verify_capture_in(capture, self.pg0)
1133 pkts = self.create_stream_in(self.pg0, self.pg1)
1134 self.pg0.add_stream(pkts)
1135 self.pg_enable_capture(self.pg_interfaces)
1137 capture = self.pg1.get_capture(len(pkts))
1138 self.verify_capture_out(capture, same_port=True)
1140 users = self.vapi.nat44_user_dump()
1141 self.assertEqual(len(users), 1)
1142 static_user = users[0]
1143 self.assertEqual(static_user.nstaticsessions, 3)
1144 self.assertEqual(static_user.nsessions, 0)
1146 # in2out - no static mapping match (forwarding test)
1148 host0 = self.pg0.remote_hosts[0]
1149 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1151 pkts = self.create_stream_out(
1152 self.pg1, dst_ip=self.pg0.remote_ip4, use_inside_ports=True
1154 self.pg1.add_stream(pkts)
1155 self.pg_enable_capture(self.pg_interfaces)
1157 capture = self.pg0.get_capture(len(pkts))
1158 self.verify_capture_in(capture, self.pg0)
1160 pkts = self.create_stream_in(self.pg0, self.pg1)
1161 self.pg0.add_stream(pkts)
1162 self.pg_enable_capture(self.pg_interfaces)
1164 capture = self.pg1.get_capture(len(pkts))
1165 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4, same_port=True)
1167 self.pg0.remote_hosts[0] = host0
1169 users = self.vapi.nat44_user_dump()
1170 self.assertEqual(len(users), 2)
1171 if str(users[0].ip_address) == self.pg0.remote_hosts[0].ip4:
1172 non_static_user = users[1]
1173 static_user = users[0]
1175 non_static_user = users[0]
1176 static_user = users[1]
1177 self.assertEqual(static_user.nstaticsessions, 3)
1178 self.assertEqual(static_user.nsessions, 0)
1179 self.assertEqual(non_static_user.nstaticsessions, 0)
1180 self.assertEqual(non_static_user.nsessions, 3)
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 def test_frag_out_of_order_do_not_translate(self):
1196 """NAT44ED don't translate fragments arriving out of order"""
1197 self.nat_add_inside_interface(self.pg0)
1198 self.nat_add_outside_interface(self.pg1)
1199 self.vapi.nat44_forwarding_enable_disable(enable=True)
1200 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
1202 def test_forwarding(self):
1203 """NAT44ED forwarding test"""
1205 self.nat_add_inside_interface(self.pg0)
1206 self.nat_add_outside_interface(self.pg1)
1207 self.vapi.nat44_forwarding_enable_disable(enable=1)
1209 real_ip = self.pg0.remote_ip4
1210 alias_ip = self.nat_addr
1211 flags = self.config_flags.NAT_IS_ADDR_ONLY
1212 self.vapi.nat44_add_del_static_mapping(
1214 local_ip_address=real_ip,
1215 external_ip_address=alias_ip,
1216 external_sw_if_index=0xFFFFFFFF,
1221 # in2out - static mapping match
1223 pkts = self.create_stream_out(self.pg1)
1224 self.pg1.add_stream(pkts)
1225 self.pg_enable_capture(self.pg_interfaces)
1227 capture = self.pg0.get_capture(len(pkts))
1228 self.verify_capture_in(capture, self.pg0)
1230 pkts = self.create_stream_in(self.pg0, self.pg1)
1231 self.pg0.add_stream(pkts)
1232 self.pg_enable_capture(self.pg_interfaces)
1234 capture = self.pg1.get_capture(len(pkts))
1235 self.verify_capture_out(capture, same_port=True)
1237 # in2out - no static mapping match
1239 host0 = self.pg0.remote_hosts[0]
1240 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1242 pkts = self.create_stream_out(
1243 self.pg1, dst_ip=self.pg0.remote_ip4, use_inside_ports=True
1245 self.pg1.add_stream(pkts)
1246 self.pg_enable_capture(self.pg_interfaces)
1248 capture = self.pg0.get_capture(len(pkts))
1249 self.verify_capture_in(capture, self.pg0)
1251 pkts = self.create_stream_in(self.pg0, self.pg1)
1252 self.pg0.add_stream(pkts)
1253 self.pg_enable_capture(self.pg_interfaces)
1255 capture = self.pg1.get_capture(len(pkts))
1256 self.verify_capture_out(
1257 capture, nat_ip=self.pg0.remote_ip4, same_port=True
1260 self.pg0.remote_hosts[0] = host0
1262 user = self.pg0.remote_hosts[1]
1263 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
1264 self.assertEqual(len(sessions), 3)
1265 self.assertTrue(sessions[0].flags & self.config_flags.NAT_IS_EXT_HOST_VALID)
1266 self.vapi.nat44_del_session(
1267 address=sessions[0].inside_ip_address,
1268 port=sessions[0].inside_port,
1269 protocol=sessions[0].protocol,
1271 self.config_flags.NAT_IS_INSIDE
1272 | self.config_flags.NAT_IS_EXT_HOST_VALID
1274 ext_host_address=sessions[0].ext_host_address,
1275 ext_host_port=sessions[0].ext_host_port,
1277 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
1278 self.assertEqual(len(sessions), 2)
1281 self.vapi.nat44_forwarding_enable_disable(enable=0)
1282 flags = self.config_flags.NAT_IS_ADDR_ONLY
1283 self.vapi.nat44_add_del_static_mapping(
1285 local_ip_address=real_ip,
1286 external_ip_address=alias_ip,
1287 external_sw_if_index=0xFFFFFFFF,
1291 def test_output_feature_and_service2(self):
1292 """NAT44ED interface output feature and service host direct access"""
1293 self.vapi.nat44_forwarding_enable_disable(enable=1)
1294 self.nat_add_address(self.nat_addr)
1296 self.vapi.nat44_ed_add_del_output_interface(
1297 sw_if_index=self.pg1.sw_if_index, is_add=1
1300 # session initiated from service host - translate
1301 pkts = self.create_stream_in(self.pg0, self.pg1)
1302 self.pg0.add_stream(pkts)
1303 self.pg_enable_capture(self.pg_interfaces)
1305 capture = self.pg1.get_capture(len(pkts))
1306 self.verify_capture_out(capture, ignore_port=True)
1308 pkts = self.create_stream_out(self.pg1)
1309 self.pg1.add_stream(pkts)
1310 self.pg_enable_capture(self.pg_interfaces)
1312 capture = self.pg0.get_capture(len(pkts))
1313 self.verify_capture_in(capture, self.pg0)
1315 # session initiated from remote host - do not translate
1316 tcp_port_in = self.tcp_port_in
1317 udp_port_in = self.udp_port_in
1318 icmp_id_in = self.icmp_id_in
1320 self.tcp_port_in = 60303
1321 self.udp_port_in = 60304
1322 self.icmp_id_in = 60305
1325 pkts = self.create_stream_out(
1326 self.pg1, self.pg0.remote_ip4, use_inside_ports=True
1328 self.pg1.add_stream(pkts)
1329 self.pg_enable_capture(self.pg_interfaces)
1331 capture = self.pg0.get_capture(len(pkts))
1332 self.verify_capture_in(capture, self.pg0)
1334 pkts = self.create_stream_in(self.pg0, self.pg1)
1335 self.pg0.add_stream(pkts)
1336 self.pg_enable_capture(self.pg_interfaces)
1338 capture = self.pg1.get_capture(len(pkts))
1339 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4, same_port=True)
1341 self.tcp_port_in = tcp_port_in
1342 self.udp_port_in = udp_port_in
1343 self.icmp_id_in = icmp_id_in
1345 def test_twice_nat(self):
1346 """NAT44ED Twice NAT"""
1347 self.twice_nat_common()
1349 def test_self_twice_nat_positive(self):
1350 """NAT44ED Self Twice NAT (positive test)"""
1351 self.twice_nat_common(self_twice_nat=True, same_pg=True)
1353 def test_self_twice_nat_lb_positive(self):
1354 """NAT44ED Self Twice NAT local service load balancing (positive test)"""
1355 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True, client_id=1)
1357 def test_twice_nat_lb(self):
1358 """NAT44ED Twice NAT local service load balancing"""
1359 self.twice_nat_common(lb=True)
1361 def test_output_feature(self):
1362 """NAT44ED interface output feature (in2out postrouting)"""
1363 self.vapi.nat44_forwarding_enable_disable(enable=1)
1364 self.nat_add_address(self.nat_addr)
1366 self.nat_add_outside_interface(self.pg0)
1367 self.vapi.nat44_ed_add_del_output_interface(
1368 sw_if_index=self.pg1.sw_if_index, is_add=1
1372 pkts = self.create_stream_in(self.pg0, self.pg1)
1373 self.pg0.add_stream(pkts)
1374 self.pg_enable_capture(self.pg_interfaces)
1376 capture = self.pg1.get_capture(len(pkts))
1377 self.verify_capture_out(capture, ignore_port=True)
1378 self.logger.debug(self.vapi.cli("show trace"))
1381 pkts = self.create_stream_out(self.pg1)
1382 self.pg1.add_stream(pkts)
1383 self.pg_enable_capture(self.pg_interfaces)
1385 capture = self.pg0.get_capture(len(pkts))
1386 self.verify_capture_in(capture, self.pg0)
1387 self.logger.debug(self.vapi.cli("show trace"))
1390 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
1391 self.pg0.add_stream(pkts)
1392 self.pg_enable_capture(self.pg_interfaces)
1394 capture = self.pg1.get_capture(len(pkts))
1395 self.verify_capture_out(capture, ignore_port=True)
1396 self.logger.debug(self.vapi.cli("show trace"))
1399 pkts = self.create_stream_out(self.pg1, ttl=2)
1400 self.pg1.add_stream(pkts)
1401 self.pg_enable_capture(self.pg_interfaces)
1403 capture = self.pg0.get_capture(len(pkts))
1404 self.verify_capture_in(capture, self.pg0)
1405 self.logger.debug(self.vapi.cli("show trace"))
1408 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1409 capture = self.send_and_expect_some(self.pg0, pkts, self.pg0)
1411 self.assertIn(ICMP, p)
1412 self.assertEqual(p[ICMP].type, 11) # 11 == time-exceeded
1414 def test_static_with_port_out2(self):
1415 """NAT44ED 1:1 NAPT asymmetrical rule"""
1420 self.vapi.nat44_forwarding_enable_disable(enable=1)
1421 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1422 self.nat_add_static_mapping(
1423 self.pg0.remote_ip4,
1427 proto=IP_PROTOS.tcp,
1431 self.nat_add_inside_interface(self.pg0)
1432 self.nat_add_outside_interface(self.pg1)
1434 # from client to service
1436 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1437 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1438 / TCP(sport=12345, dport=external_port)
1440 self.pg1.add_stream(p)
1441 self.pg_enable_capture(self.pg_interfaces)
1443 capture = self.pg0.get_capture(1)
1448 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1449 self.assertEqual(tcp.dport, local_port)
1450 self.assert_packet_checksums_valid(p)
1452 self.logger.error(ppp("Unexpected or invalid packet:", p))
1457 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
1458 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1462 self.pg0.add_stream(p)
1463 self.pg_enable_capture(self.pg_interfaces)
1465 capture = self.pg1.get_capture(1)
1468 self.assertEqual(p[IP].src, self.nat_addr)
1470 self.assertEqual(inner.dst, self.nat_addr)
1471 self.assertEqual(inner[TCPerror].dport, external_port)
1473 self.logger.error(ppp("Unexpected or invalid packet:", p))
1476 # from service back to client
1478 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1479 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1480 / TCP(sport=local_port, dport=12345)
1482 self.pg0.add_stream(p)
1483 self.pg_enable_capture(self.pg_interfaces)
1485 capture = self.pg1.get_capture(1)
1490 self.assertEqual(ip.src, self.nat_addr)
1491 self.assertEqual(tcp.sport, external_port)
1492 self.assert_packet_checksums_valid(p)
1494 self.logger.error(ppp("Unexpected or invalid packet:", p))
1499 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1500 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1504 self.pg1.add_stream(p)
1505 self.pg_enable_capture(self.pg_interfaces)
1507 capture = self.pg0.get_capture(1)
1510 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
1512 self.assertEqual(inner.src, self.pg0.remote_ip4)
1513 self.assertEqual(inner[TCPerror].sport, local_port)
1515 self.logger.error(ppp("Unexpected or invalid packet:", p))
1518 # from client to server (no translation)
1520 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1521 / IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4)
1522 / TCP(sport=12346, dport=local_port)
1524 self.pg1.add_stream(p)
1525 self.pg_enable_capture(self.pg_interfaces)
1527 capture = self.pg0.get_capture(1)
1532 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1533 self.assertEqual(tcp.dport, local_port)
1534 self.assert_packet_checksums_valid(p)
1536 self.logger.error(ppp("Unexpected or invalid packet:", p))
1539 # from service back to client (no translation)
1541 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
1542 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
1543 / TCP(sport=local_port, dport=12346)
1545 self.pg0.add_stream(p)
1546 self.pg_enable_capture(self.pg_interfaces)
1548 capture = self.pg1.get_capture(1)
1553 self.assertEqual(ip.src, self.pg0.remote_ip4)
1554 self.assertEqual(tcp.sport, local_port)
1555 self.assert_packet_checksums_valid(p)
1557 self.logger.error(ppp("Unexpected or invalid packet:", p))
1560 def test_static_lb(self):
1561 """NAT44ED local service load balancing"""
1562 external_addr_n = self.nat_addr
1565 server1 = self.pg0.remote_hosts[0]
1566 server2 = self.pg0.remote_hosts[1]
1569 {"addr": server1.ip4, "port": local_port, "probability": 70, "vrf_id": 0},
1570 {"addr": server2.ip4, "port": local_port, "probability": 30, "vrf_id": 0},
1573 self.nat_add_address(self.nat_addr)
1574 self.vapi.nat44_add_del_lb_static_mapping(
1576 external_addr=external_addr_n,
1577 external_port=external_port,
1578 protocol=IP_PROTOS.tcp,
1579 local_num=len(locals),
1582 flags = self.config_flags.NAT_IS_INSIDE
1583 self.vapi.nat44_interface_add_del_feature(
1584 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1586 self.vapi.nat44_interface_add_del_feature(
1587 sw_if_index=self.pg1.sw_if_index, is_add=1
1590 # from client to service
1592 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1593 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1594 / TCP(sport=12345, dport=external_port)
1596 self.pg1.add_stream(p)
1597 self.pg_enable_capture(self.pg_interfaces)
1599 capture = self.pg0.get_capture(1)
1605 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1606 if ip.dst == server1.ip4:
1610 self.assertEqual(tcp.dport, local_port)
1611 self.assert_packet_checksums_valid(p)
1613 self.logger.error(ppp("Unexpected or invalid packet:", p))
1616 # from service back to client
1618 Ether(src=server.mac, dst=self.pg0.local_mac)
1619 / IP(src=server.ip4, dst=self.pg1.remote_ip4)
1620 / TCP(sport=local_port, dport=12345)
1622 self.pg0.add_stream(p)
1623 self.pg_enable_capture(self.pg_interfaces)
1625 capture = self.pg1.get_capture(1)
1630 self.assertEqual(ip.src, self.nat_addr)
1631 self.assertEqual(tcp.sport, external_port)
1632 self.assert_packet_checksums_valid(p)
1634 self.logger.error(ppp("Unexpected or invalid packet:", p))
1637 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
1638 self.assertEqual(len(sessions), 1)
1639 self.assertTrue(sessions[0].flags & self.config_flags.NAT_IS_EXT_HOST_VALID)
1640 self.vapi.nat44_del_session(
1641 address=sessions[0].inside_ip_address,
1642 port=sessions[0].inside_port,
1643 protocol=sessions[0].protocol,
1645 self.config_flags.NAT_IS_INSIDE
1646 | self.config_flags.NAT_IS_EXT_HOST_VALID
1648 ext_host_address=sessions[0].ext_host_address,
1649 ext_host_port=sessions[0].ext_host_port,
1651 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
1652 self.assertEqual(len(sessions), 0)
1654 def test_static_lb_2(self):
1655 """NAT44ED local service load balancing (asymmetrical rule)"""
1656 external_addr = self.nat_addr
1659 server1 = self.pg0.remote_hosts[0]
1660 server2 = self.pg0.remote_hosts[1]
1663 {"addr": server1.ip4, "port": local_port, "probability": 70, "vrf_id": 0},
1664 {"addr": server2.ip4, "port": local_port, "probability": 30, "vrf_id": 0},
1667 self.vapi.nat44_forwarding_enable_disable(enable=1)
1668 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1669 self.vapi.nat44_add_del_lb_static_mapping(
1672 external_addr=external_addr,
1673 external_port=external_port,
1674 protocol=IP_PROTOS.tcp,
1675 local_num=len(locals),
1678 flags = self.config_flags.NAT_IS_INSIDE
1679 self.vapi.nat44_interface_add_del_feature(
1680 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1682 self.vapi.nat44_interface_add_del_feature(
1683 sw_if_index=self.pg1.sw_if_index, is_add=1
1686 # from client to service
1688 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1689 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1690 / TCP(sport=12345, dport=external_port)
1692 self.pg1.add_stream(p)
1693 self.pg_enable_capture(self.pg_interfaces)
1695 capture = self.pg0.get_capture(1)
1701 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1702 if ip.dst == server1.ip4:
1706 self.assertEqual(tcp.dport, local_port)
1707 self.assert_packet_checksums_valid(p)
1709 self.logger.error(ppp("Unexpected or invalid packet:", p))
1712 # from service back to client
1714 Ether(src=server.mac, dst=self.pg0.local_mac)
1715 / IP(src=server.ip4, dst=self.pg1.remote_ip4)
1716 / TCP(sport=local_port, dport=12345)
1718 self.pg0.add_stream(p)
1719 self.pg_enable_capture(self.pg_interfaces)
1721 capture = self.pg1.get_capture(1)
1726 self.assertEqual(ip.src, self.nat_addr)
1727 self.assertEqual(tcp.sport, external_port)
1728 self.assert_packet_checksums_valid(p)
1730 self.logger.error(ppp("Unexpected or invalid packet:", p))
1733 # from client to server (no translation)
1735 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1736 / IP(src=self.pg1.remote_ip4, dst=server1.ip4)
1737 / TCP(sport=12346, dport=local_port)
1739 self.pg1.add_stream(p)
1740 self.pg_enable_capture(self.pg_interfaces)
1742 capture = self.pg0.get_capture(1)
1748 self.assertEqual(ip.dst, server1.ip4)
1749 self.assertEqual(tcp.dport, local_port)
1750 self.assert_packet_checksums_valid(p)
1752 self.logger.error(ppp("Unexpected or invalid packet:", p))
1755 # from service back to client (no translation)
1757 Ether(src=server1.mac, dst=self.pg0.local_mac)
1758 / IP(src=server1.ip4, dst=self.pg1.remote_ip4)
1759 / TCP(sport=local_port, dport=12346)
1761 self.pg0.add_stream(p)
1762 self.pg_enable_capture(self.pg_interfaces)
1764 capture = self.pg1.get_capture(1)
1769 self.assertEqual(ip.src, server1.ip4)
1770 self.assertEqual(tcp.sport, local_port)
1771 self.assert_packet_checksums_valid(p)
1773 self.logger.error(ppp("Unexpected or invalid packet:", p))
1776 def test_lb_affinity(self):
1777 """NAT44ED local service load balancing affinity"""
1778 external_addr = self.nat_addr
1781 server1 = self.pg0.remote_hosts[0]
1782 server2 = self.pg0.remote_hosts[1]
1785 {"addr": server1.ip4, "port": local_port, "probability": 50, "vrf_id": 0},
1786 {"addr": server2.ip4, "port": local_port, "probability": 50, "vrf_id": 0},
1789 self.nat_add_address(self.nat_addr)
1790 self.vapi.nat44_add_del_lb_static_mapping(
1792 external_addr=external_addr,
1793 external_port=external_port,
1794 protocol=IP_PROTOS.tcp,
1796 local_num=len(locals),
1799 flags = self.config_flags.NAT_IS_INSIDE
1800 self.vapi.nat44_interface_add_del_feature(
1801 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
1803 self.vapi.nat44_interface_add_del_feature(
1804 sw_if_index=self.pg1.sw_if_index, is_add=1
1808 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1809 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1810 / TCP(sport=1025, dport=external_port)
1812 self.pg1.add_stream(p)
1813 self.pg_enable_capture(self.pg_interfaces)
1815 capture = self.pg0.get_capture(1)
1816 backend = capture[0][IP].dst
1818 sessions = self.vapi.nat44_user_session_dump(backend, 0)
1819 self.assertEqual(len(sessions), 1)
1820 self.assertTrue(sessions[0].flags & self.config_flags.NAT_IS_EXT_HOST_VALID)
1821 self.vapi.nat44_del_session(
1822 address=sessions[0].inside_ip_address,
1823 port=sessions[0].inside_port,
1824 protocol=sessions[0].protocol,
1826 self.config_flags.NAT_IS_INSIDE
1827 | self.config_flags.NAT_IS_EXT_HOST_VALID
1829 ext_host_address=sessions[0].ext_host_address,
1830 ext_host_port=sessions[0].ext_host_port,
1834 for port in range(1030, 1100):
1836 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
1837 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1838 / TCP(sport=port, dport=external_port)
1841 self.pg1.add_stream(pkts)
1842 self.pg_enable_capture(self.pg_interfaces)
1844 capture = self.pg0.get_capture(len(pkts))
1846 self.assertEqual(p[IP].dst, backend)
1848 def test_multiple_vrf_1(self):
1849 """Multiple VRF - both client & service in VRF1"""
1851 external_addr = "1.2.3.4"
1856 flags = self.config_flags.NAT_IS_INSIDE
1857 self.vapi.nat44_interface_add_del_feature(
1858 sw_if_index=self.pg5.sw_if_index, is_add=1
1860 self.vapi.nat44_interface_add_del_feature(
1861 sw_if_index=self.pg5.sw_if_index, is_add=1, flags=flags
1863 self.vapi.nat44_interface_add_del_feature(
1864 sw_if_index=self.pg6.sw_if_index, is_add=1
1866 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1867 self.nat_add_static_mapping(
1868 self.pg5.remote_ip4,
1873 proto=IP_PROTOS.tcp,
1878 Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac)
1879 / IP(src=self.pg6.remote_ip4, dst=external_addr)
1880 / TCP(sport=12345, dport=external_port)
1882 self.pg6.add_stream(p)
1883 self.pg_enable_capture(self.pg_interfaces)
1885 capture = self.pg5.get_capture(1)
1890 self.assertEqual(ip.dst, self.pg5.remote_ip4)
1891 self.assertEqual(tcp.dport, local_port)
1892 self.assert_packet_checksums_valid(p)
1894 self.logger.error(ppp("Unexpected or invalid packet:", p))
1898 Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac)
1899 / IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4)
1900 / TCP(sport=local_port, dport=12345)
1902 self.pg5.add_stream(p)
1903 self.pg_enable_capture(self.pg_interfaces)
1905 capture = self.pg6.get_capture(1)
1910 self.assertEqual(ip.src, external_addr)
1911 self.assertEqual(tcp.sport, external_port)
1912 self.assert_packet_checksums_valid(p)
1914 self.logger.error(ppp("Unexpected or invalid packet:", p))
1917 def test_multiple_vrf_2(self):
1918 """Multiple VRF - dynamic NAT from VRF1 to VRF0 (output-feature)"""
1920 external_addr = "1.2.3.4"
1925 self.nat_add_address(self.nat_addr)
1926 flags = self.config_flags.NAT_IS_INSIDE
1927 self.vapi.nat44_ed_add_del_output_interface(
1928 sw_if_index=self.pg1.sw_if_index, is_add=1
1930 self.vapi.nat44_interface_add_del_feature(
1931 sw_if_index=self.pg5.sw_if_index, is_add=1
1933 self.vapi.nat44_interface_add_del_feature(
1934 sw_if_index=self.pg5.sw_if_index, is_add=1, flags=flags
1936 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1937 self.nat_add_static_mapping(
1938 self.pg5.remote_ip4,
1943 proto=IP_PROTOS.tcp,
1948 Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac)
1949 / IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4)
1950 / TCP(sport=2345, dport=22)
1952 self.pg5.add_stream(p)
1953 self.pg_enable_capture(self.pg_interfaces)
1955 capture = self.pg1.get_capture(1)
1960 self.assertEqual(ip.src, self.nat_addr)
1961 self.assert_packet_checksums_valid(p)
1964 self.logger.error(ppp("Unexpected or invalid packet:", p))
1968 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
1969 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
1970 / TCP(sport=22, dport=port)
1972 self.pg1.add_stream(p)
1973 self.pg_enable_capture(self.pg_interfaces)
1975 capture = self.pg5.get_capture(1)
1980 self.assertEqual(ip.dst, self.pg5.remote_ip4)
1981 self.assertEqual(tcp.dport, 2345)
1982 self.assert_packet_checksums_valid(p)
1984 self.logger.error(ppp("Unexpected or invalid packet:", p))
1987 def test_multiple_vrf_3(self):
1988 """Multiple VRF - client in VRF1, service in VRF0"""
1990 external_addr = "1.2.3.4"
1995 flags = self.config_flags.NAT_IS_INSIDE
1996 self.vapi.nat44_interface_add_del_feature(
1997 sw_if_index=self.pg0.sw_if_index, is_add=1
1999 self.vapi.nat44_interface_add_del_feature(
2000 sw_if_index=self.pg0.sw_if_index, is_add=1, flags=flags
2002 self.vapi.nat44_interface_add_del_feature(
2003 sw_if_index=self.pg6.sw_if_index, is_add=1
2005 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2006 self.nat_add_static_mapping(
2007 self.pg0.remote_ip4,
2008 external_sw_if_index=self.pg0.sw_if_index,
2009 local_port=local_port,
2011 external_port=external_port,
2012 proto=IP_PROTOS.tcp,
2016 # from client VRF1 to service VRF0
2018 Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac)
2019 / IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4)
2020 / TCP(sport=12346, dport=external_port)
2022 self.pg6.add_stream(p)
2023 self.pg_enable_capture(self.pg_interfaces)
2025 capture = self.pg0.get_capture(1)
2030 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2031 self.assertEqual(tcp.dport, local_port)
2032 self.assert_packet_checksums_valid(p)
2034 self.logger.error(ppp("Unexpected or invalid packet:", p))
2037 # from service VRF0 back to client VRF1
2039 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2040 / IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4)
2041 / TCP(sport=local_port, dport=12346)
2043 self.pg0.add_stream(p)
2044 self.pg_enable_capture(self.pg_interfaces)
2046 capture = self.pg6.get_capture(1)
2051 self.assertEqual(ip.src, self.pg0.local_ip4)
2052 self.assertEqual(tcp.sport, external_port)
2053 self.assert_packet_checksums_valid(p)
2055 self.logger.error(ppp("Unexpected or invalid packet:", p))
2058 def test_multiple_vrf_4(self):
2059 """Multiple VRF - client in VRF0, service in VRF1"""
2061 external_addr = "1.2.3.4"
2066 flags = self.config_flags.NAT_IS_INSIDE
2067 self.vapi.nat44_interface_add_del_feature(
2068 sw_if_index=self.pg0.sw_if_index, is_add=1
2070 self.vapi.nat44_interface_add_del_feature(
2071 sw_if_index=self.pg0.sw_if_index, is_add=1, flags=flags
2073 self.vapi.nat44_interface_add_del_feature(
2074 sw_if_index=self.pg5.sw_if_index, is_add=1
2076 self.vapi.nat44_interface_add_del_feature(
2077 sw_if_index=self.pg5.sw_if_index, is_add=1, flags=flags
2079 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2080 self.nat_add_static_mapping(
2081 self.pg5.remote_ip4,
2086 proto=IP_PROTOS.tcp,
2090 # from client VRF0 to service VRF1
2092 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2093 / IP(src=self.pg0.remote_ip4, dst=external_addr)
2094 / TCP(sport=12347, dport=external_port)
2096 self.pg0.add_stream(p)
2097 self.pg_enable_capture(self.pg_interfaces)
2099 capture = self.pg5.get_capture(1)
2104 self.assertEqual(ip.dst, self.pg5.remote_ip4)
2105 self.assertEqual(tcp.dport, local_port)
2106 self.assert_packet_checksums_valid(p)
2108 self.logger.error(ppp("Unexpected or invalid packet:", p))
2111 # from service VRF1 back to client VRF0
2113 Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac)
2114 / IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4)
2115 / TCP(sport=local_port, dport=12347)
2117 self.pg5.add_stream(p)
2118 self.pg_enable_capture(self.pg_interfaces)
2120 capture = self.pg0.get_capture(1)
2125 self.assertEqual(ip.src, external_addr)
2126 self.assertEqual(tcp.sport, external_port)
2127 self.assert_packet_checksums_valid(p)
2129 self.logger.error(ppp("Unexpected or invalid packet:", p))
2132 def test_multiple_vrf_5(self):
2133 """Multiple VRF - forwarding - no translation"""
2135 external_addr = "1.2.3.4"
2140 self.vapi.nat44_forwarding_enable_disable(enable=1)
2141 flags = self.config_flags.NAT_IS_INSIDE
2142 self.vapi.nat44_interface_add_del_feature(
2143 sw_if_index=self.pg0.sw_if_index, is_add=1
2145 self.vapi.nat44_interface_add_del_feature(
2146 sw_if_index=self.pg0.sw_if_index, is_add=1, flags=flags
2148 self.vapi.nat44_interface_add_del_feature(
2149 sw_if_index=self.pg5.sw_if_index, is_add=1
2151 self.vapi.nat44_interface_add_del_feature(
2152 sw_if_index=self.pg5.sw_if_index, is_add=1, flags=flags
2154 self.vapi.nat44_interface_add_del_feature(
2155 sw_if_index=self.pg6.sw_if_index, is_add=1
2157 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2158 self.nat_add_static_mapping(
2159 self.pg5.remote_ip4,
2164 proto=IP_PROTOS.tcp,
2167 self.nat_add_static_mapping(
2168 self.pg0.remote_ip4,
2169 external_sw_if_index=self.pg0.sw_if_index,
2170 local_port=local_port,
2172 external_port=external_port,
2173 proto=IP_PROTOS.tcp,
2177 # from client to server (both VRF1, no translation)
2179 Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac)
2180 / IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4)
2181 / TCP(sport=12348, dport=local_port)
2183 self.pg6.add_stream(p)
2184 self.pg_enable_capture(self.pg_interfaces)
2186 capture = self.pg5.get_capture(1)
2191 self.assertEqual(ip.dst, self.pg5.remote_ip4)
2192 self.assertEqual(tcp.dport, local_port)
2193 self.assert_packet_checksums_valid(p)
2195 self.logger.error(ppp("Unexpected or invalid packet:", p))
2198 # from server back to client (both VRF1, no translation)
2200 Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac)
2201 / IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4)
2202 / TCP(sport=local_port, dport=12348)
2204 self.pg5.add_stream(p)
2205 self.pg_enable_capture(self.pg_interfaces)
2207 capture = self.pg6.get_capture(1)
2212 self.assertEqual(ip.src, self.pg5.remote_ip4)
2213 self.assertEqual(tcp.sport, local_port)
2214 self.assert_packet_checksums_valid(p)
2216 self.logger.error(ppp("Unexpected or invalid packet:", p))
2219 # from client VRF1 to server VRF0 (no translation)
2221 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2222 / IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4)
2223 / TCP(sport=local_port, dport=12349)
2225 self.pg0.add_stream(p)
2226 self.pg_enable_capture(self.pg_interfaces)
2228 capture = self.pg6.get_capture(1)
2233 self.assertEqual(ip.src, self.pg0.remote_ip4)
2234 self.assertEqual(tcp.sport, local_port)
2235 self.assert_packet_checksums_valid(p)
2237 self.logger.error(ppp("Unexpected or invalid packet:", p))
2240 # from server VRF0 back to client VRF1 (no translation)
2242 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2243 / IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4)
2244 / TCP(sport=local_port, dport=12349)
2246 self.pg0.add_stream(p)
2247 self.pg_enable_capture(self.pg_interfaces)
2249 capture = self.pg6.get_capture(1)
2254 self.assertEqual(ip.src, self.pg0.remote_ip4)
2255 self.assertEqual(tcp.sport, local_port)
2256 self.assert_packet_checksums_valid(p)
2258 self.logger.error(ppp("Unexpected or invalid packet:", p))
2261 # from client VRF0 to server VRF1 (no translation)
2263 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2264 / IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4)
2265 / TCP(sport=12344, dport=local_port)
2267 self.pg0.add_stream(p)
2268 self.pg_enable_capture(self.pg_interfaces)
2270 capture = self.pg5.get_capture(1)
2275 self.assertEqual(ip.dst, self.pg5.remote_ip4)
2276 self.assertEqual(tcp.dport, local_port)
2277 self.assert_packet_checksums_valid(p)
2279 self.logger.error(ppp("Unexpected or invalid packet:", p))
2282 # from server VRF1 back to client VRF0 (no translation)
2284 Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac)
2285 / IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4)
2286 / TCP(sport=local_port, dport=12344)
2288 self.pg5.add_stream(p)
2289 self.pg_enable_capture(self.pg_interfaces)
2291 capture = self.pg0.get_capture(1)
2296 self.assertEqual(ip.src, self.pg5.remote_ip4)
2297 self.assertEqual(tcp.sport, local_port)
2298 self.assert_packet_checksums_valid(p)
2300 self.logger.error(ppp("Unexpected or invalid packet:", p))
2303 def test_outside_address_distribution(self):
2304 """Outside address distribution based on source address"""
2309 for i in range(1, x):
2311 nat_addresses.append(a)
2313 self.nat_add_inside_interface(self.pg0)
2314 self.nat_add_outside_interface(self.pg1)
2316 self.vapi.nat44_add_del_address_range(
2317 first_ip_address=nat_addresses[0],
2318 last_ip_address=nat_addresses[-1],
2324 self.pg0.generate_remote_hosts(x)
2328 info = self.create_packet_info(self.pg0, self.pg1)
2329 payload = self.info_to_payload(info)
2331 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2332 / IP(src=self.pg0.remote_hosts[i].ip4, dst=self.pg1.remote_ip4)
2333 / UDP(sport=7000 + i, dport=8000 + i)
2339 self.pg0.add_stream(pkts)
2340 self.pg_enable_capture(self.pg_interfaces)
2342 recvd = self.pg1.get_capture(len(pkts))
2343 for p_recvd in recvd:
2344 payload_info = self.payload_to_info(p_recvd[Raw])
2345 packet_index = payload_info.index
2346 info = self._packet_infos[packet_index]
2347 self.assertTrue(info is not None)
2348 self.assertEqual(packet_index, info.index)
2350 packed = socket.inet_aton(p_sent[IP].src)
2351 numeric = struct.unpack("!L", packed)[0]
2352 numeric = socket.htonl(numeric)
2353 a = nat_addresses[(numeric - 1) % len(nat_addresses)]
2357 "Invalid packet (src IP %s translated to %s, but expected %s)"
2358 % (p_sent[IP].src, p_recvd[IP].src, a),
2361 def test_dynamic_edge_ports(self):
2362 """NAT44ED dynamic translation test: edge ports"""
2364 worker_count = self.vpp_worker_count or 1
2366 port_per_thread = (65536 - port_offset) // worker_count
2367 port_count = port_per_thread * worker_count
2369 # worker thread edge ports
2370 thread_edge_ports = {0, port_offset - 1, 65535}
2371 for i in range(0, worker_count):
2372 port_thread_offset = (port_per_thread * i) + port_offset
2373 for port_range_offset in [0, port_per_thread - 1]:
2374 port = port_thread_offset + port_range_offset
2375 thread_edge_ports.add(port)
2376 thread_drop_ports = set(
2378 lambda x: x not in range(port_offset, port_offset + port_count),
2386 self.nat_add_address(self.nat_addr)
2389 self.configure_ip4_interface(in_if, hosts=worker_count)
2390 self.configure_ip4_interface(out_if)
2392 self.nat_add_inside_interface(in_if)
2393 self.nat_add_outside_interface(out_if)
2396 tc1 = self.statistics["/nat44-ed/in2out/slowpath/tcp"]
2397 uc1 = self.statistics["/nat44-ed/in2out/slowpath/udp"]
2398 ic1 = self.statistics["/nat44-ed/in2out/slowpath/icmp"]
2399 dc1 = self.statistics["/nat44-ed/in2out/slowpath/drops"]
2401 pkt_count = worker_count * len(thread_edge_ports)
2403 i2o_pkts = [[] for x in range(0, worker_count)]
2404 for i in range(0, worker_count):
2405 remote_host = in_if.remote_hosts[i]
2406 for port in thread_edge_ports:
2408 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
2409 / IP(src=remote_host.ip4, dst=out_if.remote_ip4)
2410 / TCP(sport=port, dport=port)
2412 i2o_pkts[i].append(p)
2415 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
2416 / IP(src=remote_host.ip4, dst=out_if.remote_ip4)
2417 / UDP(sport=port, dport=port)
2419 i2o_pkts[i].append(p)
2422 Ether(dst=in_if.local_mac, src=in_if.remote_mac)
2423 / IP(src=remote_host.ip4, dst=out_if.remote_ip4)
2424 / ICMP(id=port, seq=port, type="echo-request")
2426 i2o_pkts[i].append(p)
2428 for i in range(0, worker_count):
2429 if len(i2o_pkts[i]) > 0:
2430 in_if.add_stream(i2o_pkts[i], worker=i)
2432 self.pg_enable_capture(self.pg_interfaces)
2434 capture = out_if.get_capture(pkt_count * 3)
2435 for packet in capture:
2436 self.assert_packet_checksums_valid(packet)
2437 if packet.haslayer(TCP):
2438 self.assert_in_range(
2441 port_offset + port_count,
2444 elif packet.haslayer(UDP):
2445 self.assert_in_range(
2448 port_offset + port_count,
2451 elif packet.haslayer(ICMP):
2452 self.assert_in_range(
2455 port_offset + port_count,
2460 ppp("Unexpected or invalid packet (outside network):", packet)
2463 if_idx = in_if.sw_if_index
2464 tc2 = self.statistics["/nat44-ed/in2out/slowpath/tcp"]
2465 uc2 = self.statistics["/nat44-ed/in2out/slowpath/udp"]
2466 ic2 = self.statistics["/nat44-ed/in2out/slowpath/icmp"]
2467 dc2 = self.statistics["/nat44-ed/in2out/slowpath/drops"]
2469 self.assertEqual(tc2[:, if_idx].sum() - tc1[:, if_idx].sum(), pkt_count)
2470 self.assertEqual(uc2[:, if_idx].sum() - uc1[:, if_idx].sum(), pkt_count)
2471 self.assertEqual(ic2[:, if_idx].sum() - ic1[:, if_idx].sum(), pkt_count)
2472 self.assertEqual(dc2[:, if_idx].sum() - dc1[:, if_idx].sum(), 0)
2475 tc1 = self.statistics["/nat44-ed/out2in/fastpath/tcp"]
2476 uc1 = self.statistics["/nat44-ed/out2in/fastpath/udp"]
2477 ic1 = self.statistics["/nat44-ed/out2in/fastpath/icmp"]
2478 dc1 = self.statistics["/nat44-ed/out2in/fastpath/drops"]
2479 dc3 = self.statistics["/nat44-ed/out2in/slowpath/drops"]
2481 # replies to unchanged thread ports should pass on each worker,
2482 # excluding packets outside dynamic port range
2483 drop_count = worker_count * len(thread_drop_ports)
2484 pass_count = worker_count * len(thread_edge_ports) - drop_count
2486 o2i_pkts = [[] for x in range(0, worker_count)]
2487 for i in range(0, worker_count):
2488 for port in thread_edge_ports:
2490 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
2491 / IP(src=out_if.remote_ip4, dst=self.nat_addr)
2492 / TCP(sport=port, dport=port)
2494 o2i_pkts[i].append(p)
2497 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
2498 / IP(src=out_if.remote_ip4, dst=self.nat_addr)
2499 / UDP(sport=port, dport=port)
2501 o2i_pkts[i].append(p)
2504 Ether(dst=out_if.local_mac, src=out_if.remote_mac)
2505 / IP(src=out_if.remote_ip4, dst=self.nat_addr)
2506 / ICMP(id=port, seq=port, type="echo-reply")
2508 o2i_pkts[i].append(p)
2510 for i in range(0, worker_count):
2511 if len(o2i_pkts[i]) > 0:
2512 out_if.add_stream(o2i_pkts[i], worker=i)
2514 self.pg_enable_capture(self.pg_interfaces)
2516 capture = in_if.get_capture(pass_count * 3)
2517 for packet in capture:
2518 self.assert_packet_checksums_valid(packet)
2519 if packet.haslayer(TCP):
2520 self.assertIn(packet[TCP].dport, thread_edge_ports, "dst TCP port")
2521 self.assertEqual(packet[TCP].dport, packet[TCP].sport, "TCP ports")
2522 elif packet.haslayer(UDP):
2523 self.assertIn(packet[UDP].dport, thread_edge_ports, "dst UDP port")
2524 self.assertEqual(packet[UDP].dport, packet[UDP].sport, "UDP ports")
2525 elif packet.haslayer(ICMP):
2526 self.assertIn(packet[ICMP].id, thread_edge_ports, "ICMP id")
2527 self.assertEqual(packet[ICMP].id, packet[ICMP].seq, "ICMP id & seq")
2530 ppp("Unexpected or invalid packet (inside network):", packet)
2533 if_idx = out_if.sw_if_index
2534 tc2 = self.statistics["/nat44-ed/out2in/fastpath/tcp"]
2535 uc2 = self.statistics["/nat44-ed/out2in/fastpath/udp"]
2536 ic2 = self.statistics["/nat44-ed/out2in/fastpath/icmp"]
2537 dc2 = self.statistics["/nat44-ed/out2in/fastpath/drops"]
2538 dc4 = self.statistics["/nat44-ed/out2in/slowpath/drops"]
2540 self.assertEqual(tc2[:, if_idx].sum() - tc1[:, if_idx].sum(), pass_count)
2541 self.assertEqual(uc2[:, if_idx].sum() - uc1[:, if_idx].sum(), pass_count)
2542 self.assertEqual(ic2[:, if_idx].sum() - ic1[:, if_idx].sum(), pass_count)
2543 self.assertEqual(dc2[:, if_idx].sum() - dc1[:, if_idx].sum(), 0)
2545 dc4[:, if_idx].sum() - dc3[:, if_idx].sum(), drop_count * 3
2553 class TestNAT44EDMW(TestNAT44ED):
2554 """NAT44ED MW Test Case"""
2556 vpp_worker_count = 4
2559 def test_dynamic(self):
2560 """NAT44ED dynamic translation test"""
2562 tcp_port_offset = 20
2563 udp_port_offset = 20
2566 self.nat_add_address(self.nat_addr)
2567 self.nat_add_inside_interface(self.pg0)
2568 self.nat_add_outside_interface(self.pg1)
2571 tc1 = self.statistics["/nat44-ed/in2out/slowpath/tcp"]
2572 uc1 = self.statistics["/nat44-ed/in2out/slowpath/udp"]
2573 ic1 = self.statistics["/nat44-ed/in2out/slowpath/icmp"]
2574 dc1 = self.statistics["/nat44-ed/in2out/slowpath/drops"]
2576 i2o_pkts = [[] for x in range(0, self.vpp_worker_count)]
2578 for i in range(pkt_count):
2580 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2581 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
2582 / TCP(sport=tcp_port_offset + i, dport=20)
2584 i2o_pkts[p[TCP].sport % self.vpp_worker_count].append(p)
2587 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2588 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
2589 / UDP(sport=udp_port_offset + i, dport=20)
2591 i2o_pkts[p[UDP].sport % self.vpp_worker_count].append(p)
2594 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2595 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
2596 / ICMP(id=icmp_id_offset + i, type="echo-request")
2598 i2o_pkts[p[ICMP].id % self.vpp_worker_count].append(p)
2600 for i in range(0, self.vpp_worker_count):
2601 if len(i2o_pkts[i]) > 0:
2602 self.pg0.add_stream(i2o_pkts[i], worker=i)
2604 self.pg_enable_capture(self.pg_interfaces)
2606 capture = self.pg1.get_capture(pkt_count * 3, timeout=5)
2608 if_idx = self.pg0.sw_if_index
2609 tc2 = self.statistics["/nat44-ed/in2out/slowpath/tcp"]
2610 uc2 = self.statistics["/nat44-ed/in2out/slowpath/udp"]
2611 ic2 = self.statistics["/nat44-ed/in2out/slowpath/icmp"]
2612 dc2 = self.statistics["/nat44-ed/in2out/slowpath/drops"]
2614 self.assertEqual(tc2[:, if_idx].sum() - tc1[:, if_idx].sum(), pkt_count)
2615 self.assertEqual(uc2[:, if_idx].sum() - uc1[:, if_idx].sum(), pkt_count)
2616 self.assertEqual(ic2[:, if_idx].sum() - ic1[:, if_idx].sum(), pkt_count)
2617 self.assertEqual(dc2[:, if_idx].sum() - dc1[:, if_idx].sum(), 0)
2619 self.logger.info(self.vapi.cli("show trace"))
2622 tc1 = self.statistics["/nat44-ed/out2in/fastpath/tcp"]
2623 uc1 = self.statistics["/nat44-ed/out2in/fastpath/udp"]
2624 ic1 = self.statistics["/nat44-ed/out2in/fastpath/icmp"]
2625 dc1 = self.statistics["/nat44-ed/out2in/fastpath/drops"]
2627 recvd_tcp_ports = set()
2628 recvd_udp_ports = set()
2629 recvd_icmp_ids = set()
2633 recvd_tcp_ports.add(p[TCP].sport)
2635 recvd_udp_ports.add(p[UDP].sport)
2637 recvd_icmp_ids.add(p[ICMP].id)
2639 recvd_tcp_ports = list(recvd_tcp_ports)
2640 recvd_udp_ports = list(recvd_udp_ports)
2641 recvd_icmp_ids = list(recvd_icmp_ids)
2643 o2i_pkts = [[] for x in range(0, self.vpp_worker_count)]
2644 for i in range(pkt_count):
2646 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2647 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
2648 / TCP(dport=choice(recvd_tcp_ports), sport=20)
2650 o2i_pkts[p[TCP].dport % self.vpp_worker_count].append(p)
2653 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2654 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
2655 / UDP(dport=choice(recvd_udp_ports), sport=20)
2657 o2i_pkts[p[UDP].dport % self.vpp_worker_count].append(p)
2660 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
2661 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
2662 / ICMP(id=choice(recvd_icmp_ids), type="echo-reply")
2664 o2i_pkts[p[ICMP].id % self.vpp_worker_count].append(p)
2666 for i in range(0, self.vpp_worker_count):
2667 if len(o2i_pkts[i]) > 0:
2668 self.pg1.add_stream(o2i_pkts[i], worker=i)
2670 self.pg_enable_capture(self.pg_interfaces)
2672 capture = self.pg0.get_capture(pkt_count * 3)
2673 for packet in capture:
2675 self.assert_packet_checksums_valid(packet)
2676 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2677 if packet.haslayer(TCP):
2678 self.assert_in_range(
2681 tcp_port_offset + pkt_count,
2684 elif packet.haslayer(UDP):
2685 self.assert_in_range(
2688 udp_port_offset + pkt_count,
2692 self.assert_in_range(
2695 icmp_id_offset + pkt_count,
2700 ppp("Unexpected or invalid packet (inside network):", packet)
2704 if_idx = self.pg1.sw_if_index
2705 tc2 = self.statistics["/nat44-ed/out2in/fastpath/tcp"]
2706 uc2 = self.statistics["/nat44-ed/out2in/fastpath/udp"]
2707 ic2 = self.statistics["/nat44-ed/out2in/fastpath/icmp"]
2708 dc2 = self.statistics["/nat44-ed/out2in/fastpath/drops"]
2710 self.assertEqual(tc2[:, if_idx].sum() - tc1[:, if_idx].sum(), pkt_count)
2711 self.assertEqual(uc2[:, if_idx].sum() - uc1[:, if_idx].sum(), pkt_count)
2712 self.assertEqual(ic2[:, if_idx].sum() - ic1[:, if_idx].sum(), pkt_count)
2713 self.assertEqual(dc2[:, if_idx].sum() - dc1[:, if_idx].sum(), 0)
2715 sc = self.statistics["/nat44-ed/total-sessions"]
2718 len(recvd_tcp_ports) + len(recvd_udp_ports) + len(recvd_icmp_ids),
2721 def test_frag_in_order(self):
2722 """NAT44ED translate fragments arriving in order"""
2724 self.nat_add_address(self.nat_addr)
2725 self.nat_add_inside_interface(self.pg0)
2726 self.nat_add_outside_interface(self.pg1)
2728 self.frag_in_order(proto=IP_PROTOS.tcp, ignore_port=True)
2729 self.frag_in_order(proto=IP_PROTOS.udp, ignore_port=True)
2730 self.frag_in_order(proto=IP_PROTOS.icmp, ignore_port=True)
2732 def test_frag_in_order_do_not_translate(self):
2733 """NAT44ED don't translate fragments arriving in order"""
2735 self.nat_add_address(self.nat_addr)
2736 self.nat_add_inside_interface(self.pg0)
2737 self.nat_add_outside_interface(self.pg1)
2738 self.vapi.nat44_forwarding_enable_disable(enable=True)
2740 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
2742 def test_frag_out_of_order(self):
2743 """NAT44ED translate fragments arriving out of order"""
2745 self.nat_add_address(self.nat_addr)
2746 self.nat_add_inside_interface(self.pg0)
2747 self.nat_add_outside_interface(self.pg1)
2749 self.frag_out_of_order(proto=IP_PROTOS.tcp, ignore_port=True)
2750 self.frag_out_of_order(proto=IP_PROTOS.udp, ignore_port=True)
2751 self.frag_out_of_order(proto=IP_PROTOS.icmp, ignore_port=True)
2753 def test_frag_in_order_in_plus_out(self):
2754 """NAT44ED in+out interface fragments in order"""
2756 in_port = self.random_port()
2757 out_port = self.random_port()
2759 self.nat_add_address(self.nat_addr)
2760 self.nat_add_inside_interface(self.pg0)
2761 self.nat_add_outside_interface(self.pg0)
2762 self.nat_add_inside_interface(self.pg1)
2763 self.nat_add_outside_interface(self.pg1)
2765 # add static mappings for server
2766 self.nat_add_static_mapping(
2767 self.server_addr, self.nat_addr, in_port, out_port, proto=IP_PROTOS.tcp
2769 self.nat_add_static_mapping(
2770 self.server_addr, self.nat_addr, in_port, out_port, proto=IP_PROTOS.udp
2772 self.nat_add_static_mapping(
2773 self.server_addr, self.nat_addr, proto=IP_PROTOS.icmp
2776 # run tests for each protocol
2777 self.frag_in_order_in_plus_out(
2778 self.server_addr, self.nat_addr, in_port, out_port, IP_PROTOS.tcp
2780 self.frag_in_order_in_plus_out(
2781 self.server_addr, self.nat_addr, in_port, out_port, IP_PROTOS.udp
2783 self.frag_in_order_in_plus_out(
2784 self.server_addr, self.nat_addr, in_port, out_port, IP_PROTOS.icmp
2787 def test_frag_out_of_order_in_plus_out(self):
2788 """NAT44ED in+out interface fragments out of order"""
2790 in_port = self.random_port()
2791 out_port = self.random_port()
2793 self.nat_add_address(self.nat_addr)
2794 self.nat_add_inside_interface(self.pg0)
2795 self.nat_add_outside_interface(self.pg0)
2796 self.nat_add_inside_interface(self.pg1)
2797 self.nat_add_outside_interface(self.pg1)
2799 # add static mappings for server
2800 self.nat_add_static_mapping(
2801 self.server_addr, self.nat_addr, in_port, out_port, proto=IP_PROTOS.tcp
2803 self.nat_add_static_mapping(
2804 self.server_addr, self.nat_addr, in_port, out_port, proto=IP_PROTOS.udp
2806 self.nat_add_static_mapping(
2807 self.server_addr, self.nat_addr, proto=IP_PROTOS.icmp
2810 # run tests for each protocol
2811 self.frag_out_of_order_in_plus_out(
2812 self.server_addr, self.nat_addr, in_port, out_port, IP_PROTOS.tcp
2814 self.frag_out_of_order_in_plus_out(
2815 self.server_addr, self.nat_addr, in_port, out_port, IP_PROTOS.udp
2817 self.frag_out_of_order_in_plus_out(
2818 self.server_addr, self.nat_addr, in_port, out_port, IP_PROTOS.icmp
2821 def test_reass_hairpinning(self):
2822 """NAT44ED fragments hairpinning"""
2824 server_addr = self.pg0.remote_hosts[1].ip4
2826 host_in_port = self.random_port()
2827 server_in_port = self.random_port()
2828 server_out_port = self.random_port()
2830 self.nat_add_address(self.nat_addr)
2831 self.nat_add_inside_interface(self.pg0)
2832 self.nat_add_outside_interface(self.pg1)
2834 # add static mapping for server
2835 self.nat_add_static_mapping(
2840 proto=IP_PROTOS.tcp,
2842 self.nat_add_static_mapping(
2847 proto=IP_PROTOS.udp,
2849 self.nat_add_static_mapping(server_addr, self.nat_addr)
2851 self.reass_hairpinning(
2856 proto=IP_PROTOS.tcp,
2859 self.reass_hairpinning(
2864 proto=IP_PROTOS.udp,
2867 self.reass_hairpinning(
2872 proto=IP_PROTOS.icmp,
2876 def test_session_limit_per_vrf(self):
2877 """NAT44ED per vrf session limit"""
2880 inside_vrf10 = self.pg2
2885 # 2 interfaces pg0, pg1 (vrf10, limit 1 tcp session)
2886 # non existing vrf_id makes process core dump
2887 self.vapi.nat44_set_session_limit(session_limit=limit, vrf_id=10)
2889 self.nat_add_inside_interface(inside)
2890 self.nat_add_inside_interface(inside_vrf10)
2891 self.nat_add_outside_interface(outside)
2894 self.nat_add_interface_address(outside)
2896 # BUG: causing core dump - when bad vrf_id is specified
2897 # self.nat_add_address(outside.local_ip4, vrf_id=20)
2899 stream = self.create_tcp_stream(inside_vrf10, outside, limit * 2)
2900 inside_vrf10.add_stream(stream)
2902 self.pg_enable_capture(self.pg_interfaces)
2905 capture = outside.get_capture(limit)
2907 stream = self.create_tcp_stream(inside, outside, limit * 2)
2908 inside.add_stream(stream)
2910 self.pg_enable_capture(self.pg_interfaces)
2913 capture = outside.get_capture(len(stream))
2915 def test_show_max_translations(self):
2916 """NAT44ED API test - max translations per thread"""
2917 config = self.vapi.nat44_show_running_config()
2918 self.assertEqual(self.max_sessions, config.sessions)
2920 def test_lru_cleanup(self):
2921 """NAT44ED LRU cleanup algorithm"""
2923 self.nat_add_address(self.nat_addr)
2924 self.nat_add_inside_interface(self.pg0)
2925 self.nat_add_outside_interface(self.pg1)
2927 self.vapi.nat_set_timeouts(
2928 udp=1, tcp_established=7440, tcp_transitory=30, icmp=1
2931 tcp_port_out = self.init_tcp_session(self.pg0, self.pg1, 2000, 80)
2933 for i in range(0, self.max_sessions - 1):
2935 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2936 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64)
2937 / UDP(sport=7000 + i, dport=80)
2941 self.pg0.add_stream(pkts)
2942 self.pg_enable_capture(self.pg_interfaces)
2944 self.pg1.get_capture(len(pkts))
2945 self.virtual_sleep(1.5, "wait for timeouts")
2948 for i in range(0, self.max_sessions - 1):
2950 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
2951 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64)
2952 / ICMP(id=8000 + i, type="echo-request")
2956 self.pg0.add_stream(pkts)
2957 self.pg_enable_capture(self.pg_interfaces)
2959 self.pg1.get_capture(len(pkts))
2961 def test_session_rst_timeout(self):
2962 """NAT44ED session RST timeouts"""
2964 self.nat_add_address(self.nat_addr)
2965 self.nat_add_inside_interface(self.pg0)
2966 self.nat_add_outside_interface(self.pg1)
2968 self.vapi.nat_set_timeouts(
2969 udp=300, tcp_established=7440, tcp_transitory=5, icmp=60
2972 self.init_tcp_session(
2973 self.pg0, self.pg1, self.tcp_port_in, self.tcp_external_port
2976 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2977 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
2978 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="R")
2980 self.send_and_expect(self.pg0, p, self.pg1)
2982 self.virtual_sleep(6)
2984 # The session is already closed
2986 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2987 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
2988 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="P")
2990 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
2992 # The session can be re-opened
2994 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
2995 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
2996 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="S")
2998 self.send_and_expect(self.pg0, p, self.pg1)
3000 def test_session_rst_established_timeout(self):
3001 """NAT44ED session RST timeouts"""
3003 self.nat_add_address(self.nat_addr)
3004 self.nat_add_inside_interface(self.pg0)
3005 self.nat_add_outside_interface(self.pg1)
3007 self.vapi.nat_set_timeouts(
3008 udp=300, tcp_established=7440, tcp_transitory=5, icmp=60
3011 self.init_tcp_session(
3012 self.pg0, self.pg1, self.tcp_port_in, self.tcp_external_port
3015 # Wait at least the transitory time, the session is in established
3016 # state anyway. RST followed by a data packet should move it to
3018 self.virtual_sleep(6)
3020 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3021 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3022 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="R")
3024 self.send_and_expect(self.pg0, p, self.pg1)
3027 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3028 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3029 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="P")
3031 self.send_and_expect(self.pg0, p, self.pg1)
3033 # State is transitory, session should be closed after 6 seconds
3034 self.virtual_sleep(6)
3037 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3038 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3039 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="P")
3041 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
3043 def test_dynamic_out_of_ports(self):
3044 """NAT44ED dynamic translation test: out of ports"""
3046 self.nat_add_inside_interface(self.pg0)
3047 self.nat_add_outside_interface(self.pg1)
3049 # in2out and no NAT addresses added
3050 pkts = self.create_stream_in(self.pg0, self.pg1)
3052 self.send_and_assert_no_replies(
3056 stats_diff=self.no_diff
3059 "/err/nat44-ed-in2out-slowpath/out of ports": len(pkts),
3061 self.pg0.sw_if_index: {
3062 "/nat44-ed/in2out/slowpath/drops": len(pkts),
3067 # in2out after NAT addresses added
3068 self.nat_add_address(self.nat_addr)
3070 tcpn, udpn, icmpn = (
3071 sum(x) for x in zip(*((TCP in p, UDP in p, ICMP in p) for p in pkts))
3074 self.send_and_expect(
3079 stats_diff=self.no_diff
3082 "/err/nat44-ed-in2out-slowpath/out of ports": 0,
3084 self.pg0.sw_if_index: {
3085 "/nat44-ed/in2out/slowpath/drops": 0,
3086 "/nat44-ed/in2out/slowpath/tcp": tcpn,
3087 "/nat44-ed/in2out/slowpath/udp": udpn,
3088 "/nat44-ed/in2out/slowpath/icmp": icmpn,
3093 def test_unknown_proto(self):
3094 """NAT44ED translate packet with unknown protocol"""
3096 self.nat_add_address(self.nat_addr)
3097 self.nat_add_inside_interface(self.pg0)
3098 self.nat_add_outside_interface(self.pg1)
3102 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3103 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3104 / TCP(sport=self.tcp_port_in, dport=20)
3106 self.pg0.add_stream(p)
3107 self.pg_enable_capture(self.pg_interfaces)
3109 p = self.pg1.get_capture(1)
3112 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3113 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3115 / IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4)
3116 / TCP(sport=1234, dport=1234)
3118 self.pg0.add_stream(p)
3119 self.pg_enable_capture(self.pg_interfaces)
3121 p = self.pg1.get_capture(1)
3124 self.assertEqual(packet[IP].src, self.nat_addr)
3125 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
3126 self.assertEqual(packet.haslayer(GRE), 1)
3127 self.assert_packet_checksums_valid(packet)
3129 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3134 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
3135 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3137 / IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4)
3138 / TCP(sport=1234, dport=1234)
3140 self.pg1.add_stream(p)
3141 self.pg_enable_capture(self.pg_interfaces)
3143 p = self.pg0.get_capture(1)
3146 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
3147 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
3148 self.assertEqual(packet.haslayer(GRE), 1)
3149 self.assert_packet_checksums_valid(packet)
3151 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3154 def test_hairpinning_unknown_proto(self):
3155 """NAT44ED translate packet with unknown protocol - hairpinning"""
3156 host = self.pg0.remote_hosts[0]
3157 server = self.pg0.remote_hosts[1]
3159 server_out_port = 8765
3160 server_nat_ip = "10.0.0.11"
3162 self.nat_add_address(self.nat_addr)
3163 self.nat_add_inside_interface(self.pg0)
3164 self.nat_add_outside_interface(self.pg1)
3166 # add static mapping for server
3167 self.nat_add_static_mapping(server.ip4, server_nat_ip)
3171 Ether(src=host.mac, dst=self.pg0.local_mac)
3172 / IP(src=host.ip4, dst=server_nat_ip)
3173 / TCP(sport=host_in_port, dport=server_out_port)
3175 self.pg0.add_stream(p)
3176 self.pg_enable_capture(self.pg_interfaces)
3178 self.pg0.get_capture(1)
3181 Ether(dst=self.pg0.local_mac, src=host.mac)
3182 / IP(src=host.ip4, dst=server_nat_ip)
3184 / IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4)
3185 / TCP(sport=1234, dport=1234)
3187 self.pg0.add_stream(p)
3188 self.pg_enable_capture(self.pg_interfaces)
3190 p = self.pg0.get_capture(1)
3193 self.assertEqual(packet[IP].src, self.nat_addr)
3194 self.assertEqual(packet[IP].dst, server.ip4)
3195 self.assertEqual(packet.haslayer(GRE), 1)
3196 self.assert_packet_checksums_valid(packet)
3198 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3203 Ether(dst=self.pg0.local_mac, src=server.mac)
3204 / IP(src=server.ip4, dst=self.nat_addr)
3206 / IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4)
3207 / TCP(sport=1234, dport=1234)
3209 self.pg0.add_stream(p)
3210 self.pg_enable_capture(self.pg_interfaces)
3212 p = self.pg0.get_capture(1)
3215 self.assertEqual(packet[IP].src, server_nat_ip)
3216 self.assertEqual(packet[IP].dst, host.ip4)
3217 self.assertEqual(packet.haslayer(GRE), 1)
3218 self.assert_packet_checksums_valid(packet)
3220 self.logger.error(ppp("Unexpected or invalid packet:", packet))
3223 def test_output_feature_and_service(self):
3224 """NAT44ED interface output feature and services"""
3225 external_addr = "1.2.3.4"
3229 self.vapi.nat44_forwarding_enable_disable(enable=1)
3230 self.nat_add_address(self.nat_addr)
3231 flags = self.config_flags.NAT_IS_ADDR_ONLY
3232 self.vapi.nat44_add_del_identity_mapping(
3233 ip_address=self.pg1.remote_ip4,
3234 sw_if_index=0xFFFFFFFF,
3238 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
3239 self.nat_add_static_mapping(
3240 self.pg0.remote_ip4,
3244 proto=IP_PROTOS.tcp,
3248 self.nat_add_inside_interface(self.pg0)
3249 self.nat_add_outside_interface(self.pg0)
3250 self.vapi.nat44_ed_add_del_output_interface(
3251 sw_if_index=self.pg1.sw_if_index, is_add=1
3254 # from client to service
3256 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3257 / IP(src=self.pg1.remote_ip4, dst=external_addr)
3258 / TCP(sport=12345, dport=external_port)
3260 self.pg1.add_stream(p)
3261 self.pg_enable_capture(self.pg_interfaces)
3263 capture = self.pg0.get_capture(1)
3268 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3269 self.assertEqual(tcp.dport, local_port)
3270 self.assert_packet_checksums_valid(p)
3272 self.logger.error(ppp("Unexpected or invalid packet:", p))
3275 # from service back to client
3277 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3278 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3279 / TCP(sport=local_port, dport=12345)
3281 self.pg0.add_stream(p)
3282 self.pg_enable_capture(self.pg_interfaces)
3284 capture = self.pg1.get_capture(1)
3289 self.assertEqual(ip.src, external_addr)
3290 self.assertEqual(tcp.sport, external_port)
3291 self.assert_packet_checksums_valid(p)
3293 self.logger.error(ppp("Unexpected or invalid packet:", p))
3296 # from local network host to external network
3297 pkts = self.create_stream_in(self.pg0, self.pg1)
3298 self.pg0.add_stream(pkts)
3299 self.pg_enable_capture(self.pg_interfaces)
3301 capture = self.pg1.get_capture(len(pkts))
3302 self.verify_capture_out(capture, ignore_port=True)
3303 pkts = self.create_stream_in(self.pg0, self.pg1)
3304 self.pg0.add_stream(pkts)
3305 self.pg_enable_capture(self.pg_interfaces)
3307 capture = self.pg1.get_capture(len(pkts))
3308 self.verify_capture_out(capture, ignore_port=True)
3310 # from external network back to local network host
3311 pkts = self.create_stream_out(self.pg1)
3312 self.pg1.add_stream(pkts)
3313 self.pg_enable_capture(self.pg_interfaces)
3315 capture = self.pg0.get_capture(len(pkts))
3316 self.verify_capture_in(capture, self.pg0)
3318 def test_output_feature_and_service3(self):
3319 """NAT44ED interface output feature and DST NAT"""
3320 external_addr = "1.2.3.4"
3324 self.vapi.nat44_forwarding_enable_disable(enable=1)
3325 self.nat_add_address(self.nat_addr)
3326 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
3327 self.nat_add_static_mapping(
3328 self.pg1.remote_ip4,
3332 proto=IP_PROTOS.tcp,
3336 self.nat_add_inside_interface(self.pg0)
3337 self.nat_add_outside_interface(self.pg0)
3338 self.vapi.nat44_ed_add_del_output_interface(
3339 sw_if_index=self.pg1.sw_if_index, is_add=1
3343 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3344 / IP(src=self.pg0.remote_ip4, dst=external_addr)
3345 / TCP(sport=12345, dport=external_port)
3347 self.pg0.add_stream(p)
3348 self.pg_enable_capture(self.pg_interfaces)
3350 capture = self.pg1.get_capture(1)
3355 self.assertEqual(ip.src, self.pg0.remote_ip4)
3356 self.assertEqual(tcp.sport, 12345)
3357 self.assertEqual(ip.dst, self.pg1.remote_ip4)
3358 self.assertEqual(tcp.dport, local_port)
3359 self.assert_packet_checksums_valid(p)
3361 self.logger.error(ppp("Unexpected or invalid packet:", p))
3365 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3366 / IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4)
3367 / TCP(sport=local_port, dport=12345)
3369 self.pg1.add_stream(p)
3370 self.pg_enable_capture(self.pg_interfaces)
3372 capture = self.pg0.get_capture(1)
3377 self.assertEqual(ip.src, external_addr)
3378 self.assertEqual(tcp.sport, external_port)
3379 self.assertEqual(ip.dst, self.pg0.remote_ip4)
3380 self.assertEqual(tcp.dport, 12345)
3381 self.assert_packet_checksums_valid(p)
3383 self.logger.error(ppp("Unexpected or invalid packet:", p))
3386 def test_self_twice_nat_lb_negative(self):
3387 """NAT44ED Self Twice NAT local service load balancing (negative test)"""
3388 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True, client_id=2)
3390 def test_self_twice_nat_negative(self):
3391 """NAT44ED Self Twice NAT (negative test)"""
3392 self.twice_nat_common(self_twice_nat=True)
3394 def test_static_lb_multi_clients(self):
3395 """NAT44ED local service load balancing - multiple clients"""
3397 external_addr = self.nat_addr
3400 server1 = self.pg0.remote_hosts[0]
3401 server2 = self.pg0.remote_hosts[1]
3402 server3 = self.pg0.remote_hosts[2]
3405 {"addr": server1.ip4, "port": local_port, "probability": 90, "vrf_id": 0},
3406 {"addr": server2.ip4, "port": local_port, "probability": 10, "vrf_id": 0},
3409 flags = self.config_flags.NAT_IS_INSIDE
3410 self.vapi.nat44_interface_add_del_feature(
3411 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
3413 self.vapi.nat44_interface_add_del_feature(
3414 sw_if_index=self.pg1.sw_if_index, is_add=1
3417 self.nat_add_address(self.nat_addr)
3418 self.vapi.nat44_add_del_lb_static_mapping(
3420 external_addr=external_addr,
3421 external_port=external_port,
3422 protocol=IP_PROTOS.tcp,
3423 local_num=len(locals),
3429 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
3431 for client in clients:
3433 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3434 / IP(src=client, dst=self.nat_addr)
3435 / TCP(sport=12345, dport=external_port)
3438 self.pg1.add_stream(pkts)
3439 self.pg_enable_capture(self.pg_interfaces)
3441 capture = self.pg0.get_capture(len(pkts))
3443 if p[IP].dst == server1.ip4:
3447 self.assertGreaterEqual(server1_n, server2_n)
3450 "addr": server3.ip4,
3457 self.vapi.nat44_lb_static_mapping_add_del_local(
3459 external_addr=external_addr,
3460 external_port=external_port,
3462 protocol=IP_PROTOS.tcp,
3467 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
3469 for client in clients:
3471 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3472 / IP(src=client, dst=self.nat_addr)
3473 / TCP(sport=12346, dport=external_port)
3476 self.assertGreater(len(pkts), 0)
3477 self.pg1.add_stream(pkts)
3478 self.pg_enable_capture(self.pg_interfaces)
3480 capture = self.pg0.get_capture(len(pkts))
3482 if p[IP].dst == server1.ip4:
3484 elif p[IP].dst == server2.ip4:
3488 self.assertGreater(server1_n, 0)
3489 self.assertGreater(server2_n, 0)
3490 self.assertGreater(server3_n, 0)
3493 "addr": server2.ip4,
3499 # remove one back-end
3500 self.vapi.nat44_lb_static_mapping_add_del_local(
3502 external_addr=external_addr,
3503 external_port=external_port,
3505 protocol=IP_PROTOS.tcp,
3510 self.pg1.add_stream(pkts)
3511 self.pg_enable_capture(self.pg_interfaces)
3513 capture = self.pg0.get_capture(len(pkts))
3515 if p[IP].dst == server1.ip4:
3517 elif p[IP].dst == server2.ip4:
3521 self.assertGreater(server1_n, 0)
3522 self.assertEqual(server2_n, 0)
3523 self.assertGreater(server3_n, 0)
3525 # put zzz in front of syslog test name so that it runs as a last test
3526 # setting syslog sender cannot be undone and if it is set, it messes
3527 # with self.send_and_assert_no_replies functionality
3528 def test_zzz_syslog_sess(self):
3529 """NAT44ED Test syslog session creation and deletion"""
3530 self.vapi.syslog_set_filter(self.syslog_severity.SYSLOG_API_SEVERITY_INFO)
3531 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
3533 self.nat_add_address(self.nat_addr)
3534 self.nat_add_inside_interface(self.pg0)
3535 self.nat_add_outside_interface(self.pg1)
3538 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3539 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3540 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port)
3542 self.pg0.add_stream(p)
3543 self.pg_enable_capture(self.pg_interfaces)
3545 capture = self.pg1.get_capture(1)
3546 self.tcp_port_out = capture[0][TCP].sport
3547 capture = self.pg3.get_capture(1)
3548 self.verify_syslog_sess(capture[0][Raw].load, "SADD")
3550 self.pg_enable_capture(self.pg_interfaces)
3552 self.nat_add_address(self.nat_addr, is_add=0)
3553 capture = self.pg3.get_capture(1)
3554 self.verify_syslog_sess(capture[0][Raw].load, "SDEL")
3556 # put zzz in front of syslog test name so that it runs as a last test
3557 # setting syslog sender cannot be undone and if it is set, it messes
3558 # with self.send_and_assert_no_replies functionality
3559 def test_zzz_syslog_sess_reopen(self):
3560 """Syslog events for session reopen"""
3561 self.vapi.syslog_set_filter(self.syslog_severity.SYSLOG_API_SEVERITY_INFO)
3562 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
3564 self.nat_add_address(self.nat_addr)
3565 self.nat_add_inside_interface(self.pg0)
3566 self.nat_add_outside_interface(self.pg1)
3570 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3571 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3572 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port)
3574 capture = self.send_and_expect(self.pg0, p, self.pg1)[0]
3575 self.tcp_port_out = capture[0][TCP].sport
3576 capture = self.pg3.get_capture(1)
3577 self.verify_syslog_sess(capture[0][Raw].load, "SADD")
3581 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
3582 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3583 / TCP(sport=self.tcp_external_port, dport=self.tcp_port_out, flags="SA")
3585 self.send_and_expect(self.pg1, p, self.pg0)
3588 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3589 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3590 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="A")
3592 self.send_and_expect(self.pg0, p, self.pg1)
3596 Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
3597 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3598 / TCP(sport=self.tcp_port_in, dport=self.tcp_external_port, flags="F")
3600 self.send_and_expect(self.pg0, p, self.pg1)
3604 Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
3605 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3606 / TCP(sport=self.tcp_external_port, dport=self.tcp_port_out, flags="F")
3608 self.send_and_expect(self.pg1, p, self.pg0)
3610 self.init_tcp_session(
3611 self.pg0, self.pg1, self.tcp_port_in, self.tcp_external_port
3614 # 2 records should be produced - first one del & add
3615 capture = self.pg3.get_capture(2)
3616 self.verify_syslog_sess(capture[0][Raw].load, "SDEL")
3617 self.verify_syslog_sess(capture[1][Raw].load, "SADD")
3619 def test_twice_nat_interface_addr(self):
3620 """NAT44ED Acquire twice NAT addresses from interface"""
3621 flags = self.config_flags.NAT_IS_TWICE_NAT
3622 self.vapi.nat44_add_del_interface_addr(
3623 sw_if_index=self.pg11.sw_if_index, flags=flags, is_add=1
3626 # no address in NAT pool
3627 adresses = self.vapi.nat44_address_dump()
3628 self.assertEqual(0, len(adresses))
3630 # configure interface address and check NAT address pool
3631 self.pg11.config_ip4()
3632 adresses = self.vapi.nat44_address_dump()
3633 self.assertEqual(1, len(adresses))
3634 self.assertEqual(str(adresses[0].ip_address), self.pg11.local_ip4)
3635 self.assertEqual(adresses[0].flags, flags)
3637 # remove interface address and check NAT address pool
3638 self.pg11.unconfig_ip4()
3639 adresses = self.vapi.nat44_address_dump()
3640 self.assertEqual(0, len(adresses))
3642 def test_output_feature_stateful_acl(self):
3643 """NAT44ED output feature works with stateful ACL"""
3645 self.nat_add_address(self.nat_addr)
3646 self.vapi.nat44_ed_add_del_output_interface(
3647 sw_if_index=self.pg1.sw_if_index, is_add=1
3650 # First ensure that the NAT is working sans ACL
3652 # send packets out2in, no sessions yet so packets should drop
3653 pkts_out2in = self.create_stream_out(self.pg1)
3654 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
3656 # send packets into inside intf, ensure received via outside intf
3657 pkts_in2out = self.create_stream_in(self.pg0, self.pg1)
3658 capture = self.send_and_expect(
3659 self.pg0, pkts_in2out, self.pg1, len(pkts_in2out)
3661 self.verify_capture_out(capture, ignore_port=True)
3663 # send out2in again, with sessions created it should work now
3664 pkts_out2in = self.create_stream_out(self.pg1)
3665 capture = self.send_and_expect(
3666 self.pg1, pkts_out2in, self.pg0, len(pkts_out2in)
3668 self.verify_capture_in(capture, self.pg0)
3670 # Create an ACL blocking everything
3671 out2in_deny_rule = AclRule(is_permit=0)
3672 out2in_acl = VppAcl(self, rules=[out2in_deny_rule])
3673 out2in_acl.add_vpp_config()
3675 # create an ACL to permit/reflect everything
3676 in2out_reflect_rule = AclRule(is_permit=2)
3677 in2out_acl = VppAcl(self, rules=[in2out_reflect_rule])
3678 in2out_acl.add_vpp_config()
3680 # apply as input acl on interface and confirm it blocks everything
3681 acl_if = VppAclInterface(
3682 self, sw_if_index=self.pg1.sw_if_index, n_input=1, acls=[out2in_acl]
3684 acl_if.add_vpp_config()
3685 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
3688 acl_if.acls = [out2in_acl, in2out_acl]
3689 acl_if.add_vpp_config()
3690 # send in2out to generate ACL state (NAT state was created earlier)
3691 capture = self.send_and_expect(
3692 self.pg0, pkts_in2out, self.pg1, len(pkts_in2out)
3694 self.verify_capture_out(capture, ignore_port=True)
3696 # send out2in again. ACL state exists so it should work now.
3697 # TCP packets with the syn flag set also need the ack flag
3698 for p in pkts_out2in:
3699 if p.haslayer(TCP) and p[TCP].flags & 0x02:
3700 p[TCP].flags |= 0x10
3701 capture = self.send_and_expect(
3702 self.pg1, pkts_out2in, self.pg0, len(pkts_out2in)
3704 self.verify_capture_in(capture, self.pg0)
3705 self.logger.info(self.vapi.cli("show trace"))
3707 def test_tcp_close(self):
3708 """NAT44ED Close TCP session from inside network - output feature"""
3709 config = self.vapi.nat44_show_running_config()
3710 old_timeouts = config.timeouts
3712 self.vapi.nat_set_timeouts(
3713 udp=old_timeouts.udp,
3714 tcp_established=old_timeouts.tcp_established,
3715 icmp=old_timeouts.icmp,
3716 tcp_transitory=new_transitory,
3719 self.vapi.nat44_forwarding_enable_disable(enable=1)
3720 self.nat_add_address(self.pg1.local_ip4)
3721 twice_nat_addr = "10.0.1.3"
3722 service_ip = "192.168.16.150"
3723 self.nat_add_address(twice_nat_addr, twice_nat=1)
3725 flags = self.config_flags.NAT_IS_INSIDE
3726 self.vapi.nat44_interface_add_del_feature(
3727 sw_if_index=self.pg0.sw_if_index, is_add=1
3729 self.vapi.nat44_interface_add_del_feature(
3730 sw_if_index=self.pg0.sw_if_index, flags=flags, is_add=1
3732 self.vapi.nat44_ed_add_del_output_interface(
3733 is_add=1, sw_if_index=self.pg1.sw_if_index
3737 self.config_flags.NAT_IS_OUT2IN_ONLY | self.config_flags.NAT_IS_TWICE_NAT
3739 self.nat_add_static_mapping(
3740 self.pg0.remote_ip4, service_ip, 80, 80, proto=IP_PROTOS.tcp, flags=flags
3742 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3743 start_sessnum = len(sessions)
3745 # SYN packet out->in
3747 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3748 / IP(src=self.pg1.remote_ip4, dst=service_ip)
3749 / TCP(sport=33898, dport=80, flags="S")
3751 capture = self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
3753 tcp_port = p[TCP].sport
3755 # SYN + ACK packet in->out
3757 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3758 / IP(src=self.pg0.remote_ip4, dst=twice_nat_addr)
3759 / TCP(sport=80, dport=tcp_port, flags="SA")
3761 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
3763 # ACK packet out->in
3765 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3766 / IP(src=self.pg1.remote_ip4, dst=service_ip)
3767 / TCP(sport=33898, dport=80, flags="A")
3769 self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
3771 # FIN packet in -> out
3773 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3774 / IP(src=self.pg0.remote_ip4, dst=twice_nat_addr)
3775 / TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300)
3777 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
3779 # FIN+ACK packet out -> in
3781 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3782 / IP(src=self.pg1.remote_ip4, dst=service_ip)
3783 / TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101)
3785 self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
3787 # ACK packet in -> out
3789 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3790 / IP(src=self.pg0.remote_ip4, dst=twice_nat_addr)
3791 / TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301)
3793 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
3795 # session now in transitory timeout, but traffic still flows
3796 # try FIN packet out->in
3798 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3799 / IP(src=self.pg1.remote_ip4, dst=service_ip)
3800 / TCP(sport=33898, dport=80, flags="F")
3802 self.pg1.add_stream(p)
3803 self.pg_enable_capture(self.pg_interfaces)
3806 self.virtual_sleep(new_transitory, "wait for transitory timeout")
3807 self.pg0.get_capture(1)
3809 # session should still exist
3810 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3811 self.assertEqual(len(sessions) - start_sessnum, 1)
3813 # send FIN+ACK packet out -> in - will cause session to be wiped
3814 # but won't create a new session
3816 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3817 / IP(src=self.pg1.remote_ip4, dst=service_ip)
3818 / TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101)
3820 self.send_and_assert_no_replies(self.pg1, p)
3821 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3822 self.assertEqual(len(sessions) - start_sessnum, 0)
3824 def test_tcp_session_close_in(self):
3825 """NAT44ED Close TCP session from inside network"""
3827 in_port = self.tcp_port_in
3829 ext_port = self.tcp_external_port
3831 self.nat_add_address(self.nat_addr)
3832 self.nat_add_inside_interface(self.pg0)
3833 self.nat_add_outside_interface(self.pg1)
3834 self.nat_add_static_mapping(
3835 self.pg0.remote_ip4,
3839 proto=IP_PROTOS.tcp,
3840 flags=self.config_flags.NAT_IS_TWICE_NAT,
3843 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3844 session_n = len(sessions)
3846 self.vapi.nat_set_timeouts(
3847 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
3850 self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3852 # FIN packet in -> out
3854 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3855 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3856 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=100, ack=300)
3858 self.send_and_expect(self.pg0, p, self.pg1)
3861 # ACK packet out -> in
3863 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3864 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3865 / TCP(sport=ext_port, dport=out_port, flags="A", seq=300, ack=101)
3869 # FIN packet out -> in
3871 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3872 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3873 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=101)
3877 self.send_and_expect(self.pg1, pkts, self.pg0)
3879 # ACK packet in -> out
3881 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3882 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3883 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
3885 self.send_and_expect(self.pg0, p, self.pg1)
3887 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3888 self.assertEqual(len(sessions) - session_n, 1)
3890 # retransmit FIN packet out -> in
3892 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3893 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3894 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=101)
3897 self.send_and_expect(self.pg1, p, self.pg0)
3899 # retransmit ACK packet in -> out
3901 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3902 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3903 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
3905 self.send_and_expect(self.pg0, p, self.pg1)
3907 self.virtual_sleep(3)
3908 # retransmit ACK packet in -> out - this will cause session to be wiped
3910 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3911 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3912 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
3914 self.send_and_assert_no_replies(self.pg0, p)
3915 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3916 self.assertEqual(len(sessions) - session_n, 0)
3918 def test_tcp_session_close_out(self):
3919 """NAT44ED Close TCP session from outside network"""
3921 in_port = self.tcp_port_in
3923 ext_port = self.tcp_external_port
3925 self.nat_add_address(self.nat_addr)
3926 self.nat_add_inside_interface(self.pg0)
3927 self.nat_add_outside_interface(self.pg1)
3928 self.nat_add_static_mapping(
3929 self.pg0.remote_ip4,
3933 proto=IP_PROTOS.tcp,
3934 flags=self.config_flags.NAT_IS_TWICE_NAT,
3937 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3938 session_n = len(sessions)
3940 self.vapi.nat_set_timeouts(
3941 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
3944 _ = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3946 # FIN packet out -> in
3948 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3949 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3950 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=100, ack=300)
3952 self.pg1.add_stream(p)
3953 self.pg_enable_capture(self.pg_interfaces)
3955 self.pg0.get_capture(1)
3957 # FIN+ACK packet in -> out
3959 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3960 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3961 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=300, ack=101)
3964 self.pg0.add_stream(p)
3965 self.pg_enable_capture(self.pg_interfaces)
3967 self.pg1.get_capture(1)
3969 # ACK packet out -> in
3971 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3972 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3973 / TCP(sport=ext_port, dport=out_port, flags="A", seq=101, ack=301)
3975 self.pg1.add_stream(p)
3976 self.pg_enable_capture(self.pg_interfaces)
3978 self.pg0.get_capture(1)
3980 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3981 self.assertEqual(len(sessions) - session_n, 1)
3983 # retransmit FIN packet out -> in
3985 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
3986 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
3987 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=101)
3989 self.send_and_expect(self.pg1, p, self.pg0)
3991 # retransmit ACK packet in -> out
3993 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
3994 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
3995 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
3997 self.send_and_expect(self.pg0, p, self.pg1)
3999 self.virtual_sleep(3)
4000 # retransmit ACK packet in -> out - this will cause session to be wiped
4002 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4003 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4004 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4006 self.send_and_assert_no_replies(self.pg0, p)
4007 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4008 self.assertEqual(len(sessions) - session_n, 0)
4010 def test_tcp_session_close_simultaneous(self):
4011 """Simultaneous TCP close from both sides"""
4013 in_port = self.tcp_port_in
4016 self.nat_add_address(self.nat_addr)
4017 self.nat_add_inside_interface(self.pg0)
4018 self.nat_add_outside_interface(self.pg1)
4019 self.nat_add_static_mapping(
4020 self.pg0.remote_ip4,
4024 proto=IP_PROTOS.tcp,
4025 flags=self.config_flags.NAT_IS_TWICE_NAT,
4028 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4029 session_n = len(sessions)
4031 self.vapi.nat_set_timeouts(
4032 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
4035 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
4037 # FIN packet in -> out
4039 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4040 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4041 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=100, ack=300)
4043 self.send_and_expect(self.pg0, p, self.pg1)
4045 # FIN packet out -> in
4047 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4048 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4049 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=100)
4051 self.send_and_expect(self.pg1, p, self.pg0)
4053 # ACK packet in -> out
4055 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4056 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4057 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4059 self.send_and_expect(self.pg0, p, self.pg1)
4061 # ACK packet out -> in
4063 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4064 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4065 / TCP(sport=ext_port, dport=out_port, flags="A", seq=301, ack=101)
4067 self.send_and_expect(self.pg1, p, self.pg0)
4069 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4070 self.assertEqual(len(sessions) - session_n, 1)
4072 # retransmit FIN packet out -> in
4074 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4075 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4076 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=101)
4078 self.send_and_expect(self.pg1, p, self.pg0)
4080 # retransmit ACK packet in -> out
4082 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4083 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4084 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4086 self.send_and_expect(self.pg0, p, self.pg1)
4088 self.virtual_sleep(3)
4089 # retransmit ACK packet in -> out - this will cause session to be wiped
4091 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4092 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4093 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4095 self.pg_send(self.pg0, p)
4096 self.send_and_assert_no_replies(self.pg0, p)
4097 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4098 self.assertEqual(len(sessions) - session_n, 0)
4100 def test_tcp_session_half_reopen_inside(self):
4101 """TCP session in FIN/FIN state not reopened by in2out SYN only"""
4102 in_port = self.tcp_port_in
4105 self.nat_add_address(self.nat_addr)
4106 self.nat_add_inside_interface(self.pg0)
4107 self.nat_add_outside_interface(self.pg1)
4108 self.nat_add_static_mapping(
4109 self.pg0.remote_ip4,
4113 proto=IP_PROTOS.tcp,
4114 flags=self.config_flags.NAT_IS_TWICE_NAT,
4117 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4118 session_n = len(sessions)
4120 self.vapi.nat_set_timeouts(
4121 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
4124 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
4126 # FIN packet in -> out
4128 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4129 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4130 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=100, ack=300)
4132 self.send_and_expect(self.pg0, p, self.pg1)
4134 # FIN packet out -> in
4136 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4137 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4138 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=100)
4140 self.send_and_expect(self.pg1, p, self.pg0)
4142 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4143 self.assertEqual(len(sessions) - session_n, 1)
4145 # send SYN packet in -> out
4147 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4148 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4149 / TCP(sport=in_port, dport=ext_port, flags="S", seq=101, ack=301)
4151 self.send_and_expect(self.pg0, p, self.pg1)
4153 self.virtual_sleep(3)
4154 # send ACK packet in -> out - session should be wiped
4156 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4157 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4158 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4160 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
4161 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4162 self.assertEqual(len(sessions) - session_n, 0)
4164 def test_tcp_session_half_reopen_outside(self):
4165 """TCP session in FIN/FIN state not reopened by out2in SYN only"""
4166 in_port = self.tcp_port_in
4169 self.nat_add_address(self.nat_addr)
4170 self.nat_add_inside_interface(self.pg0)
4171 self.nat_add_outside_interface(self.pg1)
4172 self.nat_add_static_mapping(
4173 self.pg0.remote_ip4,
4177 proto=IP_PROTOS.tcp,
4178 flags=self.config_flags.NAT_IS_TWICE_NAT,
4181 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4182 session_n = len(sessions)
4184 self.vapi.nat_set_timeouts(
4185 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
4188 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
4190 # FIN packet in -> out
4192 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4193 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4194 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=100, ack=300)
4196 self.send_and_expect(self.pg0, p, self.pg1)
4198 # FIN packet out -> in
4200 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4201 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4202 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=100)
4204 self.send_and_expect(self.pg1, p, self.pg0)
4206 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4207 self.assertEqual(len(sessions) - session_n, 1)
4209 # send SYN packet out -> in
4211 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4212 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4213 / TCP(sport=ext_port, dport=out_port, flags="S", seq=300, ack=101)
4215 self.send_and_expect(self.pg1, p, self.pg0)
4217 self.virtual_sleep(3)
4218 # send ACK packet in -> out - session should be wiped
4220 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4221 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4222 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4224 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
4225 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4226 self.assertEqual(len(sessions) - session_n, 0)
4228 def test_tcp_session_reopen(self):
4229 """TCP session in FIN/FIN state reopened by SYN from both sides"""
4230 in_port = self.tcp_port_in
4233 self.nat_add_address(self.nat_addr)
4234 self.nat_add_inside_interface(self.pg0)
4235 self.nat_add_outside_interface(self.pg1)
4236 self.nat_add_static_mapping(
4237 self.pg0.remote_ip4,
4241 proto=IP_PROTOS.tcp,
4242 flags=self.config_flags.NAT_IS_TWICE_NAT,
4245 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4246 session_n = len(sessions)
4248 self.vapi.nat_set_timeouts(
4249 udp=300, tcp_established=7440, tcp_transitory=2, icmp=5
4252 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
4254 # FIN packet in -> out
4256 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4257 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4258 / TCP(sport=in_port, dport=ext_port, flags="FA", seq=100, ack=300)
4260 self.send_and_expect(self.pg0, p, self.pg1)
4262 # FIN packet out -> in
4264 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4265 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4266 / TCP(sport=ext_port, dport=out_port, flags="FA", seq=300, ack=100)
4268 self.send_and_expect(self.pg1, p, self.pg0)
4270 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4271 self.assertEqual(len(sessions) - session_n, 1)
4273 # send SYN packet out -> in
4275 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4276 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4277 / TCP(sport=ext_port, dport=out_port, flags="S", seq=300, ack=101)
4279 self.send_and_expect(self.pg1, p, self.pg0)
4281 # send SYN packet in -> out
4283 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4284 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4285 / TCP(sport=in_port, dport=ext_port, flags="SA", seq=101, ack=301)
4287 self.send_and_expect(self.pg0, p, self.pg1)
4289 # send ACK packet out -> in
4291 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4292 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4293 / TCP(sport=ext_port, dport=out_port, flags="A", seq=300, ack=101)
4295 self.send_and_expect(self.pg1, p, self.pg0)
4297 self.virtual_sleep(3)
4298 # send ACK packet in -> out - should be forwarded and session alive
4300 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4301 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4302 / TCP(sport=in_port, dport=ext_port, flags="A", seq=101, ack=301)
4304 self.send_and_expect(self.pg0, p, self.pg1)
4305 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
4306 self.assertEqual(len(sessions) - session_n, 1)
4308 def test_dynamic_vrf(self):
4309 """NAT44ED dynamic translation test: different VRF"""
4314 self.nat_add_address(self.nat_addr, vrf_id=vrf_id_in)
4317 self.configure_ip4_interface(self.pg7, table_id=vrf_id_in)
4318 self.configure_ip4_interface(self.pg8, table_id=vrf_id_out)
4320 self.nat_add_inside_interface(self.pg7)
4321 self.nat_add_outside_interface(self.pg8)
4323 # just basic stuff nothing special
4324 pkts = self.create_stream_in(self.pg7, self.pg8)
4325 self.pg7.add_stream(pkts)
4326 self.pg_enable_capture(self.pg_interfaces)
4328 capture = self.pg8.get_capture(len(pkts))
4329 self.verify_capture_out(capture, ignore_port=True)
4331 pkts = self.create_stream_out(self.pg8)
4332 self.pg8.add_stream(pkts)
4333 self.pg_enable_capture(self.pg_interfaces)
4335 capture = self.pg7.get_capture(len(pkts))
4336 self.verify_capture_in(capture, self.pg7)
4342 self.vapi.ip_table_add_del(is_add=0, table={"table_id": vrf_id_in})
4343 self.vapi.ip_table_add_del(is_add=0, table={"table_id": vrf_id_out})
4345 def test_dynamic_output_feature_vrf(self):
4346 """NAT44ED dynamic translation test: output-feature, VRF"""
4348 # other then default (0)
4351 self.nat_add_address(self.nat_addr)
4352 self.vapi.nat44_ed_add_del_output_interface(
4353 sw_if_index=self.pg8.sw_if_index, is_add=1
4356 self.configure_ip4_interface(self.pg7, table_id=new_vrf_id)
4357 self.configure_ip4_interface(self.pg8, table_id=new_vrf_id)
4360 tcpn = self.statistics["/nat44-ed/in2out/slowpath/tcp"]
4361 udpn = self.statistics["/nat44-ed/in2out/slowpath/udp"]
4362 icmpn = self.statistics["/nat44-ed/in2out/slowpath/icmp"]
4363 drops = self.statistics["/nat44-ed/in2out/slowpath/drops"]
4365 pkts = self.create_stream_in(self.pg7, self.pg8)
4366 self.pg7.add_stream(pkts)
4367 self.pg_enable_capture(self.pg_interfaces)
4369 capture = self.pg8.get_capture(len(pkts))
4370 self.verify_capture_out(capture, ignore_port=True)
4372 if_idx = self.pg8.sw_if_index
4373 cnt = self.statistics["/nat44-ed/in2out/slowpath/tcp"]
4374 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
4375 cnt = self.statistics["/nat44-ed/in2out/slowpath/udp"]
4376 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
4377 cnt = self.statistics["/nat44-ed/in2out/slowpath/icmp"]
4378 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
4379 cnt = self.statistics["/nat44-ed/in2out/slowpath/drops"]
4380 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
4383 tcpn = self.statistics["/nat44-ed/out2in/fastpath/tcp"]
4384 udpn = self.statistics["/nat44-ed/out2in/fastpath/udp"]
4385 icmpn = self.statistics["/nat44-ed/out2in/fastpath/icmp"]
4386 drops = self.statistics["/nat44-ed/out2in/fastpath/drops"]
4388 pkts = self.create_stream_out(self.pg8)
4389 self.pg8.add_stream(pkts)
4390 self.pg_enable_capture(self.pg_interfaces)
4392 capture = self.pg7.get_capture(len(pkts))
4393 self.verify_capture_in(capture, self.pg7)
4395 if_idx = self.pg8.sw_if_index
4396 cnt = self.statistics["/nat44-ed/out2in/fastpath/tcp"]
4397 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
4398 cnt = self.statistics["/nat44-ed/out2in/fastpath/udp"]
4399 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
4400 cnt = self.statistics["/nat44-ed/out2in/fastpath/icmp"]
4401 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
4402 cnt = self.statistics["/nat44-ed/out2in/fastpath/drops"]
4403 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
4405 sessions = self.statistics["/nat44-ed/total-sessions"]
4406 self.assertEqual(sessions[:, 0].sum(), 3)
4412 self.vapi.ip_table_add_del(is_add=0, table={"table_id": new_vrf_id})
4414 def test_next_src_nat(self):
4415 """NAT44ED On way back forward packet to nat44-in2out node."""
4417 twice_nat_addr = "10.0.1.3"
4420 post_twice_nat_port = 0
4422 self.vapi.nat44_forwarding_enable_disable(enable=1)
4423 self.nat_add_address(twice_nat_addr, twice_nat=1)
4425 self.config_flags.NAT_IS_OUT2IN_ONLY
4426 | self.config_flags.NAT_IS_SELF_TWICE_NAT
4428 self.nat_add_static_mapping(
4429 self.pg6.remote_ip4,
4430 self.pg1.remote_ip4,
4433 proto=IP_PROTOS.tcp,
4437 self.vapi.nat44_interface_add_del_feature(
4438 sw_if_index=self.pg6.sw_if_index, is_add=1
4442 Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac)
4443 / IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4)
4444 / TCP(sport=12345, dport=external_port)
4446 self.pg6.add_stream(p)
4447 self.pg_enable_capture(self.pg_interfaces)
4449 capture = self.pg6.get_capture(1)
4454 self.assertEqual(ip.src, twice_nat_addr)
4455 self.assertNotEqual(tcp.sport, 12345)
4456 post_twice_nat_port = tcp.sport
4457 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4458 self.assertEqual(tcp.dport, local_port)
4459 self.assert_packet_checksums_valid(p)
4461 self.logger.error(ppp("Unexpected or invalid packet:", p))
4465 Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac)
4466 / IP(src=self.pg6.remote_ip4, dst=twice_nat_addr)
4467 / TCP(sport=local_port, dport=post_twice_nat_port)
4469 self.pg6.add_stream(p)
4470 self.pg_enable_capture(self.pg_interfaces)
4472 capture = self.pg6.get_capture(1)
4477 self.assertEqual(ip.src, self.pg1.remote_ip4)
4478 self.assertEqual(tcp.sport, external_port)
4479 self.assertEqual(ip.dst, self.pg6.remote_ip4)
4480 self.assertEqual(tcp.dport, 12345)
4481 self.assert_packet_checksums_valid(p)
4483 self.logger.error(ppp("Unexpected or invalid packet:", p))
4486 def test_one_armed_nat44_static(self):
4487 """NAT44ED One armed NAT and 1:1 NAPT asymmetrical rule"""
4489 remote_host = self.pg4.remote_hosts[0]
4490 local_host = self.pg4.remote_hosts[1]
4495 self.vapi.nat44_forwarding_enable_disable(enable=1)
4496 self.nat_add_address(self.nat_addr, twice_nat=1)
4498 self.config_flags.NAT_IS_OUT2IN_ONLY | self.config_flags.NAT_IS_TWICE_NAT
4500 self.nat_add_static_mapping(
4505 proto=IP_PROTOS.tcp,
4508 flags = self.config_flags.NAT_IS_INSIDE
4509 self.vapi.nat44_interface_add_del_feature(
4510 sw_if_index=self.pg4.sw_if_index, is_add=1
4512 self.vapi.nat44_interface_add_del_feature(
4513 sw_if_index=self.pg4.sw_if_index, flags=flags, is_add=1
4516 # from client to service
4518 Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac)
4519 / IP(src=remote_host.ip4, dst=self.nat_addr)
4520 / TCP(sport=12345, dport=external_port)
4522 self.pg4.add_stream(p)
4523 self.pg_enable_capture(self.pg_interfaces)
4525 capture = self.pg4.get_capture(1)
4530 self.assertEqual(ip.dst, local_host.ip4)
4531 self.assertEqual(ip.src, self.nat_addr)
4532 self.assertEqual(tcp.dport, local_port)
4533 self.assertNotEqual(tcp.sport, 12345)
4534 eh_port_in = tcp.sport
4535 self.assert_packet_checksums_valid(p)
4537 self.logger.error(ppp("Unexpected or invalid packet:", p))
4540 # from service back to client
4542 Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac)
4543 / IP(src=local_host.ip4, dst=self.nat_addr)
4544 / TCP(sport=local_port, dport=eh_port_in)
4546 self.pg4.add_stream(p)
4547 self.pg_enable_capture(self.pg_interfaces)
4549 capture = self.pg4.get_capture(1)
4554 self.assertEqual(ip.src, self.nat_addr)
4555 self.assertEqual(ip.dst, remote_host.ip4)
4556 self.assertEqual(tcp.sport, external_port)
4557 self.assertEqual(tcp.dport, 12345)
4558 self.assert_packet_checksums_valid(p)
4560 self.logger.error(ppp("Unexpected or invalid packet:", p))
4563 def test_icmp_error_fwd_outbound(self):
4564 """NAT44ED ICMP error outbound with forwarding enabled"""
4566 # Ensure that an outbound ICMP error message is properly associated
4567 # with the inbound forward bypass session it is related to.
4570 self.nat_add_address(self.nat_addr)
4571 self.nat_add_inside_interface(self.pg0)
4572 self.nat_add_outside_interface(self.pg1)
4574 # enable forwarding and initiate connection out2in
4575 self.vapi.nat44_forwarding_enable_disable(enable=1)
4577 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4578 / IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4)
4579 / UDP(sport=21, dport=20)
4583 self.pg1.add_stream(p1)
4584 self.pg_enable_capture(self.pg_interfaces)
4586 capture = self.pg0.get_capture(1)[0]
4588 self.logger.info(self.vapi.cli("show nat44 sessions"))
4590 # reply with ICMP error message in2out
4591 # We cannot reliably retrieve forward bypass sessions via the API.
4592 # session dumps for a user will only look on the worker that the
4593 # user is supposed to be mapped to in2out. The forward bypass session
4594 # is not necessarily created on that worker.
4596 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4597 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4598 / ICMP(type="dest-unreach", code="port-unreachable")
4602 self.pg0.add_stream(p2)
4603 self.pg_enable_capture(self.pg_interfaces)
4605 capture = self.pg1.get_capture(1)[0]
4607 self.logger.info(self.vapi.cli("show nat44 sessions"))
4609 self.logger.info(ppp("p1 packet:", p1))
4610 self.logger.info(ppp("p2 packet:", p2))
4611 self.logger.info(ppp("capture packet:", capture))
4613 def test_tcp_session_open_retransmit1(self):
4614 """NAT44ED Open TCP session with SYN,ACK retransmit 1
4616 The client does not receive the [SYN,ACK] or the
4617 ACK from the client is lost. Therefore, the [SYN, ACK]
4618 is retransmitted by the server.
4621 in_port = self.tcp_port_in
4622 ext_port = self.tcp_external_port
4625 self.nat_add_address(self.nat_addr)
4626 self.nat_add_inside_interface(self.pg0)
4627 self.nat_add_outside_interface(self.pg1)
4629 self.vapi.nat_set_timeouts(
4630 udp=300, tcp_established=7440, tcp_transitory=5, icmp=60
4632 # SYN packet in->out
4634 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4635 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4636 / TCP(sport=in_port, dport=ext_port, flags="S")
4638 p = self.send_and_expect(self.pg0, p, self.pg1)[0]
4639 out_port = p[TCP].sport
4641 # SYN + ACK packet out->in
4643 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4644 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4645 / TCP(sport=ext_port, dport=out_port, flags="SA")
4647 self.send_and_expect(self.pg1, p, self.pg0)
4649 # ACK in->out does not arrive
4651 # resent SYN + ACK packet out->in
4653 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4654 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4655 / TCP(sport=ext_port, dport=out_port, flags="SA")
4657 self.send_and_expect(self.pg1, p, self.pg0)
4659 # ACK packet in->out
4661 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4662 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4663 / TCP(sport=in_port, dport=ext_port, flags="A")
4665 self.send_and_expect(self.pg0, p, self.pg1)
4667 # Verify that the data can be transmitted after the transitory time
4668 self.virtual_sleep(6)
4671 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4672 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4673 / TCP(sport=in_port, dport=ext_port, flags="PA")
4676 self.send_and_expect(self.pg0, p, self.pg1)
4678 def test_tcp_session_open_retransmit2(self):
4679 """NAT44ED Open TCP session with SYN,ACK retransmit 2
4681 The ACK is lost to the server after the TCP session is opened.
4682 Data is sent by the client, then the [SYN,ACK] is
4683 retransmitted by the server.
4686 in_port = self.tcp_port_in
4687 ext_port = self.tcp_external_port
4690 self.nat_add_address(self.nat_addr)
4691 self.nat_add_inside_interface(self.pg0)
4692 self.nat_add_outside_interface(self.pg1)
4694 self.vapi.nat_set_timeouts(
4695 udp=300, tcp_established=7440, tcp_transitory=5, icmp=60
4697 # SYN packet in->out
4699 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4700 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4701 / TCP(sport=in_port, dport=ext_port, flags="S")
4703 p = self.send_and_expect(self.pg0, p, self.pg1)[0]
4704 out_port = p[TCP].sport
4706 # SYN + ACK packet out->in
4708 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4709 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4710 / TCP(sport=ext_port, dport=out_port, flags="SA")
4712 self.send_and_expect(self.pg1, p, self.pg0)
4714 # ACK packet in->out -- not received by the server
4716 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4717 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4718 / TCP(sport=in_port, dport=ext_port, flags="A")
4720 self.send_and_expect(self.pg0, p, self.pg1)
4722 # PUSH + ACK packet in->out
4724 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4725 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4726 / TCP(sport=in_port, dport=ext_port, flags="PA")
4729 self.send_and_expect(self.pg0, p, self.pg1)
4731 # resent SYN + ACK packet out->in
4733 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4734 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4735 / TCP(sport=ext_port, dport=out_port, flags="SA")
4737 self.send_and_expect(self.pg1, p, self.pg0)
4739 # resent ACK packet in->out
4741 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4742 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4743 / TCP(sport=in_port, dport=ext_port, flags="A")
4745 self.send_and_expect(self.pg0, p, self.pg1)
4747 # resent PUSH + ACK packet in->out
4749 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4750 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4751 / TCP(sport=in_port, dport=ext_port, flags="PA")
4754 self.send_and_expect(self.pg0, p, self.pg1)
4756 # ACK packet out->in
4758 Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
4759 / IP(src=self.pg1.remote_ip4, dst=self.nat_addr)
4760 / TCP(sport=ext_port, dport=out_port, flags="A")
4762 self.send_and_expect(self.pg1, p, self.pg0)
4764 # Verify that the data can be transmitted after the transitory time
4765 self.virtual_sleep(6)
4768 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
4769 / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4)
4770 / TCP(sport=in_port, dport=ext_port, flags="PA")
4773 self.send_and_expect(self.pg0, p, self.pg1)
4776 if __name__ == "__main__":
4777 unittest.main(testRunner=VppTestRunner)