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(
52 sessions=self.max_sessions, enable=1)
54 def plugin_disable(self):
55 self.vapi.nat44_ed_plugin_enable_disable(enable=0)
58 def config_flags(self):
59 return VppEnum.vl_api_nat_config_flags_t
62 def nat44_config_flags(self):
63 return VppEnum.vl_api_nat44_config_flags_t
66 def syslog_severity(self):
67 return VppEnum.vl_api_syslog_severity_t
70 def server_addr(self):
71 return self.pg1.remote_hosts[0].ip4
75 return randint(1025, 65535)
78 def proto2layer(proto):
79 if proto == IP_PROTOS.tcp:
81 elif proto == IP_PROTOS.udp:
83 elif proto == IP_PROTOS.icmp:
86 raise Exception("Unsupported protocol")
89 def create_and_add_ip4_table(cls, i, table_id=0):
90 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': table_id})
91 i.set_table_ip4(table_id)
94 def configure_ip4_interface(cls, i, hosts=0, table_id=None):
96 cls.create_and_add_ip4_table(i, table_id)
103 i.generate_remote_hosts(hosts)
104 i.configure_ipv4_neighbors()
107 def nat_add_interface_address(cls, i):
108 cls.vapi.nat44_add_del_interface_addr(
109 sw_if_index=i.sw_if_index, is_add=1)
111 def nat_add_inside_interface(self, i):
112 self.vapi.nat44_interface_add_del_feature(
113 flags=self.config_flags.NAT_IS_INSIDE,
114 sw_if_index=i.sw_if_index, is_add=1)
116 def nat_add_outside_interface(self, i):
117 self.vapi.nat44_interface_add_del_feature(
118 flags=self.config_flags.NAT_IS_OUTSIDE,
119 sw_if_index=i.sw_if_index, is_add=1)
121 def nat_add_address(self, address, twice_nat=0,
122 vrf_id=0xFFFFFFFF, is_add=1):
123 flags = self.config_flags.NAT_IS_TWICE_NAT if twice_nat else 0
124 self.vapi.nat44_add_del_address_range(first_ip_address=address,
125 last_ip_address=address,
130 def nat_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
131 local_port=0, external_port=0, vrf_id=0,
132 is_add=1, external_sw_if_index=0xFFFFFFFF,
133 proto=0, tag="", flags=0):
135 if not (local_port and external_port):
136 flags |= self.config_flags.NAT_IS_ADDR_ONLY
138 self.vapi.nat44_add_del_static_mapping(
140 local_ip_address=local_ip,
141 external_ip_address=external_ip,
142 external_sw_if_index=external_sw_if_index,
143 local_port=local_port,
144 external_port=external_port,
145 vrf_id=vrf_id, protocol=proto,
153 cls.create_pg_interfaces(range(12))
154 cls.interfaces = list(cls.pg_interfaces[:4])
156 cls.create_and_add_ip4_table(cls.pg2, 10)
158 for i in cls.interfaces:
159 cls.configure_ip4_interface(i, hosts=3)
161 # test specific (test-multiple-vrf)
162 cls.vapi.ip_table_add_del(is_add=1, table={'table_id': 1})
164 # test specific (test-one-armed-nat44-static)
165 cls.pg4.generate_remote_hosts(2)
167 cls.vapi.sw_interface_add_del_address(
168 sw_if_index=cls.pg4.sw_if_index,
169 prefix="10.0.0.1/24")
171 cls.pg4.resolve_arp()
172 cls.pg4._remote_hosts[1]._ip4 = cls.pg4._remote_hosts[0]._ip4
173 cls.pg4.resolve_arp()
175 # test specific interface (pg5)
176 cls.pg5._local_ip4 = "10.1.1.1"
177 cls.pg5._remote_hosts[0]._ip4 = "10.1.1.2"
178 cls.pg5.set_table_ip4(1)
181 cls.pg5.resolve_arp()
183 # test specific interface (pg6)
184 cls.pg6._local_ip4 = "10.1.2.1"
185 cls.pg6._remote_hosts[0]._ip4 = "10.1.2.2"
186 cls.pg6.set_table_ip4(1)
189 cls.pg6.resolve_arp()
193 rl.append(VppIpRoute(cls, "0.0.0.0", 0,
194 [VppRoutePath("0.0.0.0", 0xffffffff,
196 register=False, table_id=1))
197 rl.append(VppIpRoute(cls, "0.0.0.0", 0,
198 [VppRoutePath(cls.pg1.local_ip4,
199 cls.pg1.sw_if_index)],
201 rl.append(VppIpRoute(cls, cls.pg5.remote_ip4, 32,
202 [VppRoutePath("0.0.0.0",
203 cls.pg5.sw_if_index)],
204 register=False, table_id=1))
205 rl.append(VppIpRoute(cls, cls.pg6.remote_ip4, 32,
206 [VppRoutePath("0.0.0.0",
207 cls.pg6.sw_if_index)],
208 register=False, table_id=1))
209 rl.append(VppIpRoute(cls, cls.pg6.remote_ip4, 16,
210 [VppRoutePath("0.0.0.0", 0xffffffff,
212 register=False, table_id=0))
217 cls.no_diff = StatsDiff({
219 '/nat44-ed/in2out/fastpath/tcp': 0,
220 '/nat44-ed/in2out/fastpath/udp': 0,
221 '/nat44-ed/in2out/fastpath/icmp': 0,
222 '/nat44-ed/in2out/fastpath/drops': 0,
223 '/nat44-ed/in2out/slowpath/tcp': 0,
224 '/nat44-ed/in2out/slowpath/udp': 0,
225 '/nat44-ed/in2out/slowpath/icmp': 0,
226 '/nat44-ed/in2out/slowpath/drops': 0,
227 '/nat44-ed/in2out/fastpath/tcp': 0,
228 '/nat44-ed/in2out/fastpath/udp': 0,
229 '/nat44-ed/in2out/fastpath/icmp': 0,
230 '/nat44-ed/in2out/fastpath/drops': 0,
231 '/nat44-ed/in2out/slowpath/tcp': 0,
232 '/nat44-ed/in2out/slowpath/udp': 0,
233 '/nat44-ed/in2out/slowpath/icmp': 0,
234 '/nat44-ed/in2out/slowpath/drops': 0,
236 for pg in cls.pg_interfaces
239 def get_err_counter(self, path):
240 return self.statistics.get_err_counter(path)
242 def reass_hairpinning(self, server_addr, server_in_port, server_out_port,
243 host_in_port, proto=IP_PROTOS.tcp,
245 layer = self.proto2layer(proto)
247 if proto == IP_PROTOS.tcp:
248 data = b"A" * 4 + b"B" * 16 + b"C" * 3
250 data = b"A" * 16 + b"B" * 16 + b"C" * 3
252 # send packet from host to server
253 pkts = self.create_stream_frag(self.pg0,
259 self.pg0.add_stream(pkts)
260 self.pg_enable_capture(self.pg_interfaces)
262 frags = self.pg0.get_capture(len(pkts))
263 p = self.reass_frags_and_verify(frags,
266 if proto != IP_PROTOS.icmp:
268 self.assertNotEqual(p[layer].sport, host_in_port)
269 self.assertEqual(p[layer].dport, server_in_port)
272 self.assertNotEqual(p[layer].id, host_in_port)
273 self.assertEqual(data, p[Raw].load)
275 def frag_out_of_order(self, proto=IP_PROTOS.tcp, dont_translate=False,
277 layer = self.proto2layer(proto)
279 if proto == IP_PROTOS.tcp:
280 data = b"A" * 4 + b"B" * 16 + b"C" * 3
282 data = b"A" * 16 + b"B" * 16 + b"C" * 3
283 self.port_in = self.random_port()
287 pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
288 self.port_in, 20, data, proto)
290 self.pg0.add_stream(pkts)
291 self.pg_enable_capture(self.pg_interfaces)
293 frags = self.pg1.get_capture(len(pkts))
294 if not dont_translate:
295 p = self.reass_frags_and_verify(frags,
299 p = self.reass_frags_and_verify(frags,
302 if proto != IP_PROTOS.icmp:
303 if not dont_translate:
304 self.assertEqual(p[layer].dport, 20)
306 self.assertNotEqual(p[layer].sport, self.port_in)
308 self.assertEqual(p[layer].sport, self.port_in)
311 if not dont_translate:
312 self.assertNotEqual(p[layer].id, self.port_in)
314 self.assertEqual(p[layer].id, self.port_in)
315 self.assertEqual(data, p[Raw].load)
318 if not dont_translate:
319 dst_addr = self.nat_addr
321 dst_addr = self.pg0.remote_ip4
322 if proto != IP_PROTOS.icmp:
324 dport = p[layer].sport
328 pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport,
329 data, proto, echo_reply=True)
331 self.pg1.add_stream(pkts)
332 self.pg_enable_capture(self.pg_interfaces)
333 self.logger.info(self.vapi.cli("show trace"))
335 frags = self.pg0.get_capture(len(pkts))
336 p = self.reass_frags_and_verify(frags,
339 if proto != IP_PROTOS.icmp:
340 self.assertEqual(p[layer].sport, 20)
341 self.assertEqual(p[layer].dport, self.port_in)
343 self.assertEqual(p[layer].id, self.port_in)
344 self.assertEqual(data, p[Raw].load)
346 def reass_frags_and_verify(self, frags, src, dst):
349 self.assertEqual(p[IP].src, src)
350 self.assertEqual(p[IP].dst, dst)
351 self.assert_ip_checksum_valid(p)
352 buffer.seek(p[IP].frag * 8)
353 buffer.write(bytes(p[IP].payload))
354 ip = IP(src=frags[0][IP].src, dst=frags[0][IP].dst,
355 proto=frags[0][IP].proto)
356 if ip.proto == IP_PROTOS.tcp:
357 p = (ip / TCP(buffer.getvalue()))
358 self.logger.debug(ppp("Reassembled:", p))
359 self.assert_tcp_checksum_valid(p)
360 elif ip.proto == IP_PROTOS.udp:
361 p = (ip / UDP(buffer.getvalue()[:8]) /
362 Raw(buffer.getvalue()[8:]))
363 elif ip.proto == IP_PROTOS.icmp:
364 p = (ip / ICMP(buffer.getvalue()))
367 def frag_in_order(self, proto=IP_PROTOS.tcp, dont_translate=False,
369 layer = self.proto2layer(proto)
371 if proto == IP_PROTOS.tcp:
372 data = b"A" * 4 + b"B" * 16 + b"C" * 3
374 data = b"A" * 16 + b"B" * 16 + b"C" * 3
375 self.port_in = self.random_port()
378 pkts = self.create_stream_frag(self.pg0, self.pg1.remote_ip4,
379 self.port_in, 20, data, proto)
380 self.pg0.add_stream(pkts)
381 self.pg_enable_capture(self.pg_interfaces)
383 frags = self.pg1.get_capture(len(pkts))
384 if not dont_translate:
385 p = self.reass_frags_and_verify(frags,
389 p = self.reass_frags_and_verify(frags,
392 if proto != IP_PROTOS.icmp:
393 if not dont_translate:
394 self.assertEqual(p[layer].dport, 20)
396 self.assertNotEqual(p[layer].sport, self.port_in)
398 self.assertEqual(p[layer].sport, self.port_in)
401 if not dont_translate:
402 self.assertNotEqual(p[layer].id, self.port_in)
404 self.assertEqual(p[layer].id, self.port_in)
405 self.assertEqual(data, p[Raw].load)
408 if not dont_translate:
409 dst_addr = self.nat_addr
411 dst_addr = self.pg0.remote_ip4
412 if proto != IP_PROTOS.icmp:
414 dport = p[layer].sport
418 pkts = self.create_stream_frag(self.pg1, dst_addr, sport, dport, data,
419 proto, echo_reply=True)
420 self.pg1.add_stream(pkts)
421 self.pg_enable_capture(self.pg_interfaces)
423 frags = self.pg0.get_capture(len(pkts))
424 p = self.reass_frags_and_verify(frags,
427 if proto != IP_PROTOS.icmp:
428 self.assertEqual(p[layer].sport, 20)
429 self.assertEqual(p[layer].dport, self.port_in)
431 self.assertEqual(p[layer].id, self.port_in)
432 self.assertEqual(data, p[Raw].load)
434 def verify_capture_out(self, capture, nat_ip=None, same_port=False,
435 dst_ip=None, ignore_port=False):
437 nat_ip = self.nat_addr
438 for packet in capture:
440 self.assert_packet_checksums_valid(packet)
441 self.assertEqual(packet[IP].src, nat_ip)
442 if dst_ip is not None:
443 self.assertEqual(packet[IP].dst, dst_ip)
444 if packet.haslayer(TCP):
448 packet[TCP].sport, self.tcp_port_in)
451 packet[TCP].sport, self.tcp_port_in)
452 self.tcp_port_out = packet[TCP].sport
453 self.assert_packet_checksums_valid(packet)
454 elif packet.haslayer(UDP):
458 packet[UDP].sport, self.udp_port_in)
461 packet[UDP].sport, self.udp_port_in)
462 self.udp_port_out = packet[UDP].sport
467 packet[ICMP].id, self.icmp_id_in)
470 packet[ICMP].id, self.icmp_id_in)
471 self.icmp_id_out = packet[ICMP].id
472 self.assert_packet_checksums_valid(packet)
474 self.logger.error(ppp("Unexpected or invalid packet "
475 "(outside network):", packet))
478 def verify_capture_in(self, capture, in_if):
479 for packet in capture:
481 self.assert_packet_checksums_valid(packet)
482 self.assertEqual(packet[IP].dst, in_if.remote_ip4)
483 if packet.haslayer(TCP):
484 self.assertEqual(packet[TCP].dport, self.tcp_port_in)
485 elif packet.haslayer(UDP):
486 self.assertEqual(packet[UDP].dport, self.udp_port_in)
488 self.assertEqual(packet[ICMP].id, self.icmp_id_in)
490 self.logger.error(ppp("Unexpected or invalid packet "
491 "(inside network):", packet))
494 def create_stream_in(self, in_if, out_if, dst_ip=None, ttl=64):
496 dst_ip = out_if.remote_ip4
500 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
501 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
502 TCP(sport=self.tcp_port_in, dport=20))
506 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
507 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
508 UDP(sport=self.udp_port_in, dport=20))
512 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
513 IP(src=in_if.remote_ip4, dst=dst_ip, ttl=ttl) /
514 ICMP(id=self.icmp_id_in, type='echo-request'))
519 def create_stream_out(self, out_if, dst_ip=None, ttl=64,
520 use_inside_ports=False):
522 dst_ip = self.nat_addr
523 if not use_inside_ports:
524 tcp_port = self.tcp_port_out
525 udp_port = self.udp_port_out
526 icmp_id = self.icmp_id_out
528 tcp_port = self.tcp_port_in
529 udp_port = self.udp_port_in
530 icmp_id = self.icmp_id_in
533 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
534 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
535 TCP(dport=tcp_port, sport=20))
539 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
540 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
541 UDP(dport=udp_port, sport=20))
545 p = (Ether(dst=out_if.local_mac, src=out_if.remote_mac) /
546 IP(src=out_if.remote_ip4, dst=dst_ip, ttl=ttl) /
547 ICMP(id=icmp_id, type='echo-reply'))
552 def create_tcp_stream(self, in_if, out_if, count):
556 for i in range(count):
557 p = (Ether(dst=in_if.local_mac, src=in_if.remote_mac) /
558 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4, ttl=64) /
559 TCP(sport=port + i, dport=20))
564 def create_stream_frag(self, src_if, dst, sport, dport, data,
565 proto=IP_PROTOS.tcp, echo_reply=False):
566 if proto == IP_PROTOS.tcp:
567 p = (IP(src=src_if.remote_ip4, dst=dst) /
568 TCP(sport=sport, dport=dport) /
570 p = p.__class__(scapy.compat.raw(p))
571 chksum = p[TCP].chksum
572 proto_header = TCP(sport=sport, dport=dport, chksum=chksum)
573 elif proto == IP_PROTOS.udp:
574 proto_header = UDP(sport=sport, dport=dport)
575 elif proto == IP_PROTOS.icmp:
577 proto_header = ICMP(id=sport, type='echo-request')
579 proto_header = ICMP(id=sport, type='echo-reply')
581 raise Exception("Unsupported protocol")
582 id = self.random_port()
584 if proto == IP_PROTOS.tcp:
587 raw = Raw(data[0:16])
588 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
589 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=0, id=id) /
593 if proto == IP_PROTOS.tcp:
594 raw = Raw(data[4:20])
596 raw = Raw(data[16:32])
597 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
598 IP(src=src_if.remote_ip4, dst=dst, flags="MF", frag=3, id=id,
602 if proto == IP_PROTOS.tcp:
606 p = (Ether(src=src_if.remote_mac, dst=src_if.local_mac) /
607 IP(src=src_if.remote_ip4, dst=dst, frag=5, proto=proto,
613 def frag_in_order_in_plus_out(self, in_addr, out_addr, in_port, out_port,
614 proto=IP_PROTOS.tcp):
616 layer = self.proto2layer(proto)
618 if proto == IP_PROTOS.tcp:
619 data = b"A" * 4 + b"B" * 16 + b"C" * 3
621 data = b"A" * 16 + b"B" * 16 + b"C" * 3
622 port_in = self.random_port()
626 pkts = self.create_stream_frag(self.pg0, out_addr,
629 self.pg0.add_stream(pkts)
630 self.pg_enable_capture(self.pg_interfaces)
632 frags = self.pg1.get_capture(len(pkts))
633 p = self.reass_frags_and_verify(frags,
636 if proto != IP_PROTOS.icmp:
637 self.assertEqual(p[layer].sport, port_in)
638 self.assertEqual(p[layer].dport, in_port)
640 self.assertEqual(p[layer].id, port_in)
641 self.assertEqual(data, p[Raw].load)
644 if proto != IP_PROTOS.icmp:
645 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
647 p[layer].sport, data, proto)
649 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
650 p[layer].id, 0, data, proto,
652 self.pg1.add_stream(pkts)
653 self.pg_enable_capture(self.pg_interfaces)
655 frags = self.pg0.get_capture(len(pkts))
656 p = self.reass_frags_and_verify(frags,
659 if proto != IP_PROTOS.icmp:
660 self.assertEqual(p[layer].sport, out_port)
661 self.assertEqual(p[layer].dport, port_in)
663 self.assertEqual(p[layer].id, port_in)
664 self.assertEqual(data, p[Raw].load)
666 def frag_out_of_order_in_plus_out(self, in_addr, out_addr, in_port,
667 out_port, proto=IP_PROTOS.tcp):
669 layer = self.proto2layer(proto)
671 if proto == IP_PROTOS.tcp:
672 data = b"A" * 4 + b"B" * 16 + b"C" * 3
674 data = b"A" * 16 + b"B" * 16 + b"C" * 3
675 port_in = self.random_port()
679 pkts = self.create_stream_frag(self.pg0, out_addr,
683 self.pg0.add_stream(pkts)
684 self.pg_enable_capture(self.pg_interfaces)
686 frags = self.pg1.get_capture(len(pkts))
687 p = self.reass_frags_and_verify(frags,
690 if proto != IP_PROTOS.icmp:
691 self.assertEqual(p[layer].dport, in_port)
692 self.assertEqual(p[layer].sport, port_in)
693 self.assertEqual(p[layer].dport, in_port)
695 self.assertEqual(p[layer].id, port_in)
696 self.assertEqual(data, p[Raw].load)
699 if proto != IP_PROTOS.icmp:
700 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
702 p[layer].sport, data, proto)
704 pkts = self.create_stream_frag(self.pg1, self.pg0.remote_ip4,
705 p[layer].id, 0, data, proto,
708 self.pg1.add_stream(pkts)
709 self.pg_enable_capture(self.pg_interfaces)
711 frags = self.pg0.get_capture(len(pkts))
712 p = self.reass_frags_and_verify(frags,
715 if proto != IP_PROTOS.icmp:
716 self.assertEqual(p[layer].sport, out_port)
717 self.assertEqual(p[layer].dport, port_in)
719 self.assertEqual(p[layer].id, port_in)
720 self.assertEqual(data, p[Raw].load)
722 def init_tcp_session(self, in_if, out_if, in_port, ext_port):
724 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
725 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
726 TCP(sport=in_port, dport=ext_port, flags="S"))
728 self.pg_enable_capture(self.pg_interfaces)
730 capture = out_if.get_capture(1)
732 out_port = p[TCP].sport
734 # SYN + ACK packet out->in
735 p = (Ether(src=out_if.remote_mac, dst=out_if.local_mac) /
736 IP(src=out_if.remote_ip4, dst=self.nat_addr) /
737 TCP(sport=ext_port, dport=out_port, flags="SA"))
739 self.pg_enable_capture(self.pg_interfaces)
744 p = (Ether(src=in_if.remote_mac, dst=in_if.local_mac) /
745 IP(src=in_if.remote_ip4, dst=out_if.remote_ip4) /
746 TCP(sport=in_port, dport=ext_port, flags="A"))
748 self.pg_enable_capture(self.pg_interfaces)
750 out_if.get_capture(1)
754 def twice_nat_common(self, self_twice_nat=False, same_pg=False, lb=False,
756 twice_nat_addr = '10.0.1.3'
764 port_in1 = port_in + 1
765 port_in2 = port_in + 2
770 server1 = self.pg0.remote_hosts[0]
771 server2 = self.pg0.remote_hosts[1]
783 eh_translate = ((not self_twice_nat) or (not lb and same_pg) or
786 self.nat_add_address(self.nat_addr)
787 self.nat_add_address(twice_nat_addr, twice_nat=1)
791 flags |= self.config_flags.NAT_IS_SELF_TWICE_NAT
793 flags |= self.config_flags.NAT_IS_TWICE_NAT
796 self.nat_add_static_mapping(pg0.remote_ip4, self.nat_addr,
801 locals = [{'addr': server1.ip4,
805 {'addr': server2.ip4,
809 out_addr = self.nat_addr
811 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
812 external_addr=out_addr,
813 external_port=port_out,
814 protocol=IP_PROTOS.tcp,
815 local_num=len(locals),
817 self.nat_add_inside_interface(pg0)
818 self.nat_add_outside_interface(pg1)
824 assert client_id is not None
826 client = self.pg0.remote_hosts[0]
828 client = self.pg0.remote_hosts[1]
830 client = pg1.remote_hosts[0]
831 p = (Ether(src=pg1.remote_mac, dst=pg1.local_mac) /
832 IP(src=client.ip4, dst=self.nat_addr) /
833 TCP(sport=eh_port_out, dport=port_out))
835 self.pg_enable_capture(self.pg_interfaces)
837 capture = pg0.get_capture(1)
843 if ip.dst == server1.ip4:
849 self.assertEqual(ip.dst, server.ip4)
851 self.assertIn(tcp.dport, [port_in1, port_in2])
853 self.assertEqual(tcp.dport, port_in)
855 self.assertEqual(ip.src, twice_nat_addr)
856 self.assertNotEqual(tcp.sport, eh_port_out)
858 self.assertEqual(ip.src, client.ip4)
859 self.assertEqual(tcp.sport, eh_port_out)
861 eh_port_in = tcp.sport
862 saved_port_in = tcp.dport
863 self.assert_packet_checksums_valid(p)
865 self.logger.error(ppp("Unexpected or invalid packet:", p))
868 p = (Ether(src=server.mac, dst=pg0.local_mac) /
869 IP(src=server.ip4, dst=eh_addr_in) /
870 TCP(sport=saved_port_in, dport=eh_port_in))
872 self.pg_enable_capture(self.pg_interfaces)
874 capture = pg1.get_capture(1)
879 self.assertEqual(ip.dst, client.ip4)
880 self.assertEqual(ip.src, self.nat_addr)
881 self.assertEqual(tcp.dport, eh_port_out)
882 self.assertEqual(tcp.sport, port_out)
883 self.assert_packet_checksums_valid(p)
885 self.logger.error(ppp("Unexpected or invalid packet:", p))
889 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
890 self.assertEqual(len(sessions), 1)
891 self.assertTrue(sessions[0].flags &
892 self.config_flags.NAT_IS_EXT_HOST_VALID)
893 self.assertTrue(sessions[0].flags &
894 self.config_flags.NAT_IS_TWICE_NAT)
895 self.logger.info(self.vapi.cli("show nat44 sessions"))
896 self.vapi.nat44_del_session(
897 address=sessions[0].inside_ip_address,
898 port=sessions[0].inside_port,
899 protocol=sessions[0].protocol,
900 flags=(self.config_flags.NAT_IS_INSIDE |
901 self.config_flags.NAT_IS_EXT_HOST_VALID),
902 ext_host_address=sessions[0].ext_host_nat_address,
903 ext_host_port=sessions[0].ext_host_nat_port)
904 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
905 self.assertEqual(len(sessions), 0)
907 def verify_syslog_sess(self, data, msgid, is_ip6=False):
908 message = data.decode('utf-8')
910 message = SyslogMessage.parse(message)
911 except ParseError as e:
915 self.assertEqual(message.severity, SyslogSeverity.info)
916 self.assertEqual(message.appname, 'NAT')
917 self.assertEqual(message.msgid, msgid)
918 sd_params = message.sd.get('nsess')
919 self.assertTrue(sd_params is not None)
921 self.assertEqual(sd_params.get('IATYP'), 'IPv6')
922 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip6)
924 self.assertEqual(sd_params.get('IATYP'), 'IPv4')
925 self.assertEqual(sd_params.get('ISADDR'), self.pg0.remote_ip4)
926 self.assertTrue(sd_params.get('SSUBIX') is not None)
927 self.assertEqual(sd_params.get('ISPORT'), "%d" % self.tcp_port_in)
928 self.assertEqual(sd_params.get('XATYP'), 'IPv4')
929 self.assertEqual(sd_params.get('XSADDR'), self.nat_addr)
930 self.assertEqual(sd_params.get('XSPORT'), "%d" % self.tcp_port_out)
931 self.assertEqual(sd_params.get('PROTO'), "%d" % IP_PROTOS.tcp)
932 self.assertEqual(sd_params.get('SVLAN'), '0')
933 self.assertEqual(sd_params.get('XDADDR'), self.pg1.remote_ip4)
934 self.assertEqual(sd_params.get('XDPORT'),
935 "%d" % self.tcp_external_port)
937 def test_icmp_error(self):
938 """ NAT44ED test ICMP error message with inner header"""
942 self.nat_add_address(self.nat_addr)
943 self.nat_add_inside_interface(self.pg0)
944 self.nat_add_outside_interface(self.pg1)
946 # in2out (initiate connection)
947 p1 = [Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
948 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
949 UDP(sport=21, dport=20) / payload,
950 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
951 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
952 TCP(sport=21, dport=20, flags="S") / payload,
953 Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
954 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
955 ICMP(type='echo-request', id=7777) / payload,
958 capture = self.send_and_expect(self.pg0, p1, self.pg1)
960 # out2in (send error message)
961 p2 = [Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
962 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
963 ICMP(type='dest-unreach', code='port-unreachable') /
967 capture = self.send_and_expect(self.pg1, p2, self.pg0)
971 assert c[IP].dst == self.pg0.remote_ip4
972 assert c[IPerror].src == self.pg0.remote_ip4
973 except AssertionError as a:
974 raise AssertionError(
975 f"Packet {pr(c)} not translated properly") from a
977 def test_icmp_echo_reply_trailer(self):
978 """ ICMP echo reply with ethernet trailer"""
980 self.nat_add_address(self.nat_addr)
981 self.nat_add_inside_interface(self.pg0)
982 self.nat_add_outside_interface(self.pg1)
985 p1 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
986 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
987 ICMP(type=8, id=0xabcd, seq=0))
989 self.pg0.add_stream(p1)
990 self.pg_enable_capture(self.pg_interfaces)
992 c = self.pg1.get_capture(1)[0]
994 self.logger.debug(self.vapi.cli("show trace"))
997 p2 = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
998 IP(src=self.pg1.remote_ip4, dst=self.nat_addr, id=0xee59) /
999 ICMP(type=0, id=c[ICMP].id, seq=0))
1001 # force checksum calculation
1002 p2 = p2.__class__(bytes(p2))
1004 self.logger.debug(ppp("Packet before modification:", p2))
1006 # hex representation of vss monitoring ethernet trailer
1007 # this seems to be just added to end of packet without modifying
1008 # IP or ICMP lengths / checksums
1009 p2 = p2 / Raw("\x00\x00\x52\x54\x00\x46\xab\x04\x84\x18")
1010 # change it so that IP/ICMP is unaffected
1013 self.logger.debug(ppp("Packet with added trailer:", p2))
1015 self.pg1.add_stream(p2)
1016 self.pg_enable_capture(self.pg_interfaces)
1019 self.pg0.get_capture(1)
1021 def test_users_dump(self):
1022 """ NAT44ED API test - nat44_user_dump """
1024 self.nat_add_address(self.nat_addr)
1025 self.nat_add_inside_interface(self.pg0)
1026 self.nat_add_outside_interface(self.pg1)
1028 self.vapi.nat44_forwarding_enable_disable(enable=1)
1030 local_ip = self.pg0.remote_ip4
1031 external_ip = self.nat_addr
1032 self.nat_add_static_mapping(local_ip, external_ip)
1034 users = self.vapi.nat44_user_dump()
1035 self.assertEqual(len(users), 0)
1037 # in2out - static mapping match
1039 pkts = self.create_stream_out(self.pg1)
1040 self.pg1.add_stream(pkts)
1041 self.pg_enable_capture(self.pg_interfaces)
1043 capture = self.pg0.get_capture(len(pkts))
1044 self.verify_capture_in(capture, self.pg0)
1046 pkts = self.create_stream_in(self.pg0, self.pg1)
1047 self.pg0.add_stream(pkts)
1048 self.pg_enable_capture(self.pg_interfaces)
1050 capture = self.pg1.get_capture(len(pkts))
1051 self.verify_capture_out(capture, same_port=True)
1053 users = self.vapi.nat44_user_dump()
1054 self.assertEqual(len(users), 1)
1055 static_user = users[0]
1056 self.assertEqual(static_user.nstaticsessions, 3)
1057 self.assertEqual(static_user.nsessions, 0)
1059 # in2out - no static mapping match (forwarding test)
1061 host0 = self.pg0.remote_hosts[0]
1062 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1064 pkts = self.create_stream_out(self.pg1,
1065 dst_ip=self.pg0.remote_ip4,
1066 use_inside_ports=True)
1067 self.pg1.add_stream(pkts)
1068 self.pg_enable_capture(self.pg_interfaces)
1070 capture = self.pg0.get_capture(len(pkts))
1071 self.verify_capture_in(capture, self.pg0)
1073 pkts = self.create_stream_in(self.pg0, self.pg1)
1074 self.pg0.add_stream(pkts)
1075 self.pg_enable_capture(self.pg_interfaces)
1077 capture = self.pg1.get_capture(len(pkts))
1078 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1081 self.pg0.remote_hosts[0] = host0
1083 users = self.vapi.nat44_user_dump()
1084 self.assertEqual(len(users), 2)
1085 if str(users[0].ip_address) == self.pg0.remote_hosts[0].ip4:
1086 non_static_user = users[1]
1087 static_user = users[0]
1089 non_static_user = users[0]
1090 static_user = users[1]
1091 self.assertEqual(static_user.nstaticsessions, 3)
1092 self.assertEqual(static_user.nsessions, 0)
1093 self.assertEqual(non_static_user.nstaticsessions, 0)
1094 self.assertEqual(non_static_user.nsessions, 3)
1096 users = self.vapi.nat44_user_dump()
1097 self.assertEqual(len(users), 2)
1098 if str(users[0].ip_address) == self.pg0.remote_hosts[0].ip4:
1099 non_static_user = users[1]
1100 static_user = users[0]
1102 non_static_user = users[0]
1103 static_user = users[1]
1104 self.assertEqual(static_user.nstaticsessions, 3)
1105 self.assertEqual(static_user.nsessions, 0)
1106 self.assertEqual(non_static_user.nstaticsessions, 0)
1107 self.assertEqual(non_static_user.nsessions, 3)
1109 def test_frag_out_of_order_do_not_translate(self):
1110 """ NAT44ED don't translate fragments arriving out of order """
1111 self.nat_add_inside_interface(self.pg0)
1112 self.nat_add_outside_interface(self.pg1)
1113 self.vapi.nat44_forwarding_enable_disable(enable=True)
1114 self.frag_out_of_order(proto=IP_PROTOS.tcp, dont_translate=True)
1116 def test_forwarding(self):
1117 """ NAT44ED forwarding test """
1119 self.nat_add_inside_interface(self.pg0)
1120 self.nat_add_outside_interface(self.pg1)
1121 self.vapi.nat44_forwarding_enable_disable(enable=1)
1123 real_ip = self.pg0.remote_ip4
1124 alias_ip = self.nat_addr
1125 flags = self.config_flags.NAT_IS_ADDR_ONLY
1126 self.vapi.nat44_add_del_static_mapping(is_add=1,
1127 local_ip_address=real_ip,
1128 external_ip_address=alias_ip,
1129 external_sw_if_index=0xFFFFFFFF,
1133 # in2out - static mapping match
1135 pkts = self.create_stream_out(self.pg1)
1136 self.pg1.add_stream(pkts)
1137 self.pg_enable_capture(self.pg_interfaces)
1139 capture = self.pg0.get_capture(len(pkts))
1140 self.verify_capture_in(capture, self.pg0)
1142 pkts = self.create_stream_in(self.pg0, self.pg1)
1143 self.pg0.add_stream(pkts)
1144 self.pg_enable_capture(self.pg_interfaces)
1146 capture = self.pg1.get_capture(len(pkts))
1147 self.verify_capture_out(capture, same_port=True)
1149 # in2out - no static mapping match
1151 host0 = self.pg0.remote_hosts[0]
1152 self.pg0.remote_hosts[0] = self.pg0.remote_hosts[1]
1154 pkts = self.create_stream_out(self.pg1,
1155 dst_ip=self.pg0.remote_ip4,
1156 use_inside_ports=True)
1157 self.pg1.add_stream(pkts)
1158 self.pg_enable_capture(self.pg_interfaces)
1160 capture = self.pg0.get_capture(len(pkts))
1161 self.verify_capture_in(capture, self.pg0)
1163 pkts = self.create_stream_in(self.pg0, self.pg1)
1164 self.pg0.add_stream(pkts)
1165 self.pg_enable_capture(self.pg_interfaces)
1167 capture = self.pg1.get_capture(len(pkts))
1168 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1171 self.pg0.remote_hosts[0] = host0
1173 user = self.pg0.remote_hosts[1]
1174 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
1175 self.assertEqual(len(sessions), 3)
1176 self.assertTrue(sessions[0].flags &
1177 self.config_flags.NAT_IS_EXT_HOST_VALID)
1178 self.vapi.nat44_del_session(
1179 address=sessions[0].inside_ip_address,
1180 port=sessions[0].inside_port,
1181 protocol=sessions[0].protocol,
1182 flags=(self.config_flags.NAT_IS_INSIDE |
1183 self.config_flags.NAT_IS_EXT_HOST_VALID),
1184 ext_host_address=sessions[0].ext_host_address,
1185 ext_host_port=sessions[0].ext_host_port)
1186 sessions = self.vapi.nat44_user_session_dump(user.ip4, 0)
1187 self.assertEqual(len(sessions), 2)
1190 self.vapi.nat44_forwarding_enable_disable(enable=0)
1191 flags = self.config_flags.NAT_IS_ADDR_ONLY
1192 self.vapi.nat44_add_del_static_mapping(
1194 local_ip_address=real_ip,
1195 external_ip_address=alias_ip,
1196 external_sw_if_index=0xFFFFFFFF,
1199 def test_output_feature_and_service2(self):
1200 """ NAT44ED interface output feature and service host direct access """
1201 self.vapi.nat44_forwarding_enable_disable(enable=1)
1202 self.nat_add_address(self.nat_addr)
1204 self.vapi.nat44_ed_add_del_output_interface(
1205 sw_if_index=self.pg1.sw_if_index,
1208 # session initiated from service host - translate
1209 pkts = self.create_stream_in(self.pg0, self.pg1)
1210 self.pg0.add_stream(pkts)
1211 self.pg_enable_capture(self.pg_interfaces)
1213 capture = self.pg1.get_capture(len(pkts))
1214 self.verify_capture_out(capture, ignore_port=True)
1216 pkts = self.create_stream_out(self.pg1)
1217 self.pg1.add_stream(pkts)
1218 self.pg_enable_capture(self.pg_interfaces)
1220 capture = self.pg0.get_capture(len(pkts))
1221 self.verify_capture_in(capture, self.pg0)
1223 # session initiated from remote host - do not translate
1224 tcp_port_in = self.tcp_port_in
1225 udp_port_in = self.udp_port_in
1226 icmp_id_in = self.icmp_id_in
1228 self.tcp_port_in = 60303
1229 self.udp_port_in = 60304
1230 self.icmp_id_in = 60305
1233 pkts = self.create_stream_out(self.pg1,
1234 self.pg0.remote_ip4,
1235 use_inside_ports=True)
1236 self.pg1.add_stream(pkts)
1237 self.pg_enable_capture(self.pg_interfaces)
1239 capture = self.pg0.get_capture(len(pkts))
1240 self.verify_capture_in(capture, self.pg0)
1242 pkts = self.create_stream_in(self.pg0, self.pg1)
1243 self.pg0.add_stream(pkts)
1244 self.pg_enable_capture(self.pg_interfaces)
1246 capture = self.pg1.get_capture(len(pkts))
1247 self.verify_capture_out(capture, nat_ip=self.pg0.remote_ip4,
1250 self.tcp_port_in = tcp_port_in
1251 self.udp_port_in = udp_port_in
1252 self.icmp_id_in = icmp_id_in
1254 def test_twice_nat(self):
1255 """ NAT44ED Twice NAT """
1256 self.twice_nat_common()
1258 def test_self_twice_nat_positive(self):
1259 """ NAT44ED Self Twice NAT (positive test) """
1260 self.twice_nat_common(self_twice_nat=True, same_pg=True)
1262 def test_self_twice_nat_lb_positive(self):
1263 """ NAT44ED Self Twice NAT local service load balancing (positive test)
1265 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
1268 def test_twice_nat_lb(self):
1269 """ NAT44ED Twice NAT local service load balancing """
1270 self.twice_nat_common(lb=True)
1272 def test_output_feature(self):
1273 """ NAT44ED interface output feature (in2out postrouting) """
1274 self.vapi.nat44_forwarding_enable_disable(enable=1)
1275 self.nat_add_address(self.nat_addr)
1277 self.nat_add_outside_interface(self.pg0)
1278 self.vapi.nat44_ed_add_del_output_interface(
1279 sw_if_index=self.pg1.sw_if_index,
1283 pkts = self.create_stream_in(self.pg0, self.pg1)
1284 self.pg0.add_stream(pkts)
1285 self.pg_enable_capture(self.pg_interfaces)
1287 capture = self.pg1.get_capture(len(pkts))
1288 self.verify_capture_out(capture, ignore_port=True)
1289 self.logger.debug(self.vapi.cli("show trace"))
1292 pkts = self.create_stream_out(self.pg1)
1293 self.pg1.add_stream(pkts)
1294 self.pg_enable_capture(self.pg_interfaces)
1296 capture = self.pg0.get_capture(len(pkts))
1297 self.verify_capture_in(capture, self.pg0)
1298 self.logger.debug(self.vapi.cli("show trace"))
1301 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=2)
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)
1307 self.logger.debug(self.vapi.cli("show trace"))
1310 pkts = self.create_stream_out(self.pg1, ttl=2)
1311 self.pg1.add_stream(pkts)
1312 self.pg_enable_capture(self.pg_interfaces)
1314 capture = self.pg0.get_capture(len(pkts))
1315 self.verify_capture_in(capture, self.pg0)
1316 self.logger.debug(self.vapi.cli("show trace"))
1319 pkts = self.create_stream_in(self.pg0, self.pg1, ttl=1)
1320 capture = self.send_and_expect_some(self.pg0, pkts, self.pg0)
1322 self.assertIn(ICMP, p)
1323 self.assertEqual(p[ICMP].type, 11) # 11 == time-exceeded
1325 def test_static_with_port_out2(self):
1326 """ NAT44ED 1:1 NAPT asymmetrical rule """
1331 self.vapi.nat44_forwarding_enable_disable(enable=1)
1332 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1333 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
1334 local_port, external_port,
1335 proto=IP_PROTOS.tcp, flags=flags)
1337 self.nat_add_inside_interface(self.pg0)
1338 self.nat_add_outside_interface(self.pg1)
1340 # from client to service
1341 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1342 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1343 TCP(sport=12345, dport=external_port))
1344 self.pg1.add_stream(p)
1345 self.pg_enable_capture(self.pg_interfaces)
1347 capture = self.pg0.get_capture(1)
1352 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1353 self.assertEqual(tcp.dport, local_port)
1354 self.assert_packet_checksums_valid(p)
1356 self.logger.error(ppp("Unexpected or invalid packet:", p))
1360 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1361 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1362 ICMP(type=11) / capture[0][IP])
1363 self.pg0.add_stream(p)
1364 self.pg_enable_capture(self.pg_interfaces)
1366 capture = self.pg1.get_capture(1)
1369 self.assertEqual(p[IP].src, self.nat_addr)
1371 self.assertEqual(inner.dst, self.nat_addr)
1372 self.assertEqual(inner[TCPerror].dport, external_port)
1374 self.logger.error(ppp("Unexpected or invalid packet:", p))
1377 # from service back to client
1378 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1379 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1380 TCP(sport=local_port, dport=12345))
1381 self.pg0.add_stream(p)
1382 self.pg_enable_capture(self.pg_interfaces)
1384 capture = self.pg1.get_capture(1)
1389 self.assertEqual(ip.src, self.nat_addr)
1390 self.assertEqual(tcp.sport, external_port)
1391 self.assert_packet_checksums_valid(p)
1393 self.logger.error(ppp("Unexpected or invalid packet:", p))
1397 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1398 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1399 ICMP(type=11) / capture[0][IP])
1400 self.pg1.add_stream(p)
1401 self.pg_enable_capture(self.pg_interfaces)
1403 capture = self.pg0.get_capture(1)
1406 self.assertEqual(p[IP].dst, self.pg0.remote_ip4)
1408 self.assertEqual(inner.src, self.pg0.remote_ip4)
1409 self.assertEqual(inner[TCPerror].sport, local_port)
1411 self.logger.error(ppp("Unexpected or invalid packet:", p))
1414 # from client to server (no translation)
1415 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1416 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
1417 TCP(sport=12346, dport=local_port))
1418 self.pg1.add_stream(p)
1419 self.pg_enable_capture(self.pg_interfaces)
1421 capture = self.pg0.get_capture(1)
1426 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1427 self.assertEqual(tcp.dport, local_port)
1428 self.assert_packet_checksums_valid(p)
1430 self.logger.error(ppp("Unexpected or invalid packet:", p))
1433 # from service back to client (no translation)
1434 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1435 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1436 TCP(sport=local_port, dport=12346))
1437 self.pg0.add_stream(p)
1438 self.pg_enable_capture(self.pg_interfaces)
1440 capture = self.pg1.get_capture(1)
1445 self.assertEqual(ip.src, self.pg0.remote_ip4)
1446 self.assertEqual(tcp.sport, local_port)
1447 self.assert_packet_checksums_valid(p)
1449 self.logger.error(ppp("Unexpected or invalid packet:", p))
1452 def test_static_lb(self):
1453 """ NAT44ED local service load balancing """
1454 external_addr_n = self.nat_addr
1457 server1 = self.pg0.remote_hosts[0]
1458 server2 = self.pg0.remote_hosts[1]
1460 locals = [{'addr': server1.ip4,
1464 {'addr': server2.ip4,
1469 self.nat_add_address(self.nat_addr)
1470 self.vapi.nat44_add_del_lb_static_mapping(
1472 external_addr=external_addr_n,
1473 external_port=external_port,
1474 protocol=IP_PROTOS.tcp,
1475 local_num=len(locals),
1477 flags = self.config_flags.NAT_IS_INSIDE
1478 self.vapi.nat44_interface_add_del_feature(
1479 sw_if_index=self.pg0.sw_if_index,
1480 flags=flags, is_add=1)
1481 self.vapi.nat44_interface_add_del_feature(
1482 sw_if_index=self.pg1.sw_if_index,
1485 # from client to service
1486 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1487 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1488 TCP(sport=12345, dport=external_port))
1489 self.pg1.add_stream(p)
1490 self.pg_enable_capture(self.pg_interfaces)
1492 capture = self.pg0.get_capture(1)
1498 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1499 if ip.dst == server1.ip4:
1503 self.assertEqual(tcp.dport, local_port)
1504 self.assert_packet_checksums_valid(p)
1506 self.logger.error(ppp("Unexpected or invalid packet:", p))
1509 # from service back to client
1510 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1511 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1512 TCP(sport=local_port, dport=12345))
1513 self.pg0.add_stream(p)
1514 self.pg_enable_capture(self.pg_interfaces)
1516 capture = self.pg1.get_capture(1)
1521 self.assertEqual(ip.src, self.nat_addr)
1522 self.assertEqual(tcp.sport, external_port)
1523 self.assert_packet_checksums_valid(p)
1525 self.logger.error(ppp("Unexpected or invalid packet:", p))
1528 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
1529 self.assertEqual(len(sessions), 1)
1530 self.assertTrue(sessions[0].flags &
1531 self.config_flags.NAT_IS_EXT_HOST_VALID)
1532 self.vapi.nat44_del_session(
1533 address=sessions[0].inside_ip_address,
1534 port=sessions[0].inside_port,
1535 protocol=sessions[0].protocol,
1536 flags=(self.config_flags.NAT_IS_INSIDE |
1537 self.config_flags.NAT_IS_EXT_HOST_VALID),
1538 ext_host_address=sessions[0].ext_host_address,
1539 ext_host_port=sessions[0].ext_host_port)
1540 sessions = self.vapi.nat44_user_session_dump(server.ip4, 0)
1541 self.assertEqual(len(sessions), 0)
1543 def test_static_lb_2(self):
1544 """ NAT44ED local service load balancing (asymmetrical rule) """
1545 external_addr = self.nat_addr
1548 server1 = self.pg0.remote_hosts[0]
1549 server2 = self.pg0.remote_hosts[1]
1551 locals = [{'addr': server1.ip4,
1555 {'addr': server2.ip4,
1560 self.vapi.nat44_forwarding_enable_disable(enable=1)
1561 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1562 self.vapi.nat44_add_del_lb_static_mapping(is_add=1, flags=flags,
1563 external_addr=external_addr,
1564 external_port=external_port,
1565 protocol=IP_PROTOS.tcp,
1566 local_num=len(locals),
1568 flags = self.config_flags.NAT_IS_INSIDE
1569 self.vapi.nat44_interface_add_del_feature(
1570 sw_if_index=self.pg0.sw_if_index,
1571 flags=flags, is_add=1)
1572 self.vapi.nat44_interface_add_del_feature(
1573 sw_if_index=self.pg1.sw_if_index,
1576 # from client to service
1577 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1578 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1579 TCP(sport=12345, dport=external_port))
1580 self.pg1.add_stream(p)
1581 self.pg_enable_capture(self.pg_interfaces)
1583 capture = self.pg0.get_capture(1)
1589 self.assertIn(ip.dst, [server1.ip4, server2.ip4])
1590 if ip.dst == server1.ip4:
1594 self.assertEqual(tcp.dport, local_port)
1595 self.assert_packet_checksums_valid(p)
1597 self.logger.error(ppp("Unexpected or invalid packet:", p))
1600 # from service back to client
1601 p = (Ether(src=server.mac, dst=self.pg0.local_mac) /
1602 IP(src=server.ip4, dst=self.pg1.remote_ip4) /
1603 TCP(sport=local_port, dport=12345))
1604 self.pg0.add_stream(p)
1605 self.pg_enable_capture(self.pg_interfaces)
1607 capture = self.pg1.get_capture(1)
1612 self.assertEqual(ip.src, self.nat_addr)
1613 self.assertEqual(tcp.sport, external_port)
1614 self.assert_packet_checksums_valid(p)
1616 self.logger.error(ppp("Unexpected or invalid packet:", p))
1619 # from client to server (no translation)
1620 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1621 IP(src=self.pg1.remote_ip4, dst=server1.ip4) /
1622 TCP(sport=12346, dport=local_port))
1623 self.pg1.add_stream(p)
1624 self.pg_enable_capture(self.pg_interfaces)
1626 capture = self.pg0.get_capture(1)
1632 self.assertEqual(ip.dst, server1.ip4)
1633 self.assertEqual(tcp.dport, local_port)
1634 self.assert_packet_checksums_valid(p)
1636 self.logger.error(ppp("Unexpected or invalid packet:", p))
1639 # from service back to client (no translation)
1640 p = (Ether(src=server1.mac, dst=self.pg0.local_mac) /
1641 IP(src=server1.ip4, dst=self.pg1.remote_ip4) /
1642 TCP(sport=local_port, dport=12346))
1643 self.pg0.add_stream(p)
1644 self.pg_enable_capture(self.pg_interfaces)
1646 capture = self.pg1.get_capture(1)
1651 self.assertEqual(ip.src, server1.ip4)
1652 self.assertEqual(tcp.sport, local_port)
1653 self.assert_packet_checksums_valid(p)
1655 self.logger.error(ppp("Unexpected or invalid packet:", p))
1658 def test_lb_affinity(self):
1659 """ NAT44ED local service load balancing affinity """
1660 external_addr = self.nat_addr
1663 server1 = self.pg0.remote_hosts[0]
1664 server2 = self.pg0.remote_hosts[1]
1666 locals = [{'addr': server1.ip4,
1670 {'addr': server2.ip4,
1675 self.nat_add_address(self.nat_addr)
1676 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
1677 external_addr=external_addr,
1678 external_port=external_port,
1679 protocol=IP_PROTOS.tcp,
1681 local_num=len(locals),
1683 flags = self.config_flags.NAT_IS_INSIDE
1684 self.vapi.nat44_interface_add_del_feature(
1685 sw_if_index=self.pg0.sw_if_index,
1686 flags=flags, is_add=1)
1687 self.vapi.nat44_interface_add_del_feature(
1688 sw_if_index=self.pg1.sw_if_index,
1691 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1692 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1693 TCP(sport=1025, dport=external_port))
1694 self.pg1.add_stream(p)
1695 self.pg_enable_capture(self.pg_interfaces)
1697 capture = self.pg0.get_capture(1)
1698 backend = capture[0][IP].dst
1700 sessions = self.vapi.nat44_user_session_dump(backend, 0)
1701 self.assertEqual(len(sessions), 1)
1702 self.assertTrue(sessions[0].flags &
1703 self.config_flags.NAT_IS_EXT_HOST_VALID)
1704 self.vapi.nat44_del_session(
1705 address=sessions[0].inside_ip_address,
1706 port=sessions[0].inside_port,
1707 protocol=sessions[0].protocol,
1708 flags=(self.config_flags.NAT_IS_INSIDE |
1709 self.config_flags.NAT_IS_EXT_HOST_VALID),
1710 ext_host_address=sessions[0].ext_host_address,
1711 ext_host_port=sessions[0].ext_host_port)
1714 for port in range(1030, 1100):
1715 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1716 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1717 TCP(sport=port, dport=external_port))
1719 self.pg1.add_stream(pkts)
1720 self.pg_enable_capture(self.pg_interfaces)
1722 capture = self.pg0.get_capture(len(pkts))
1724 self.assertEqual(p[IP].dst, backend)
1726 def test_multiple_vrf_1(self):
1727 """ Multiple VRF - both client & service in VRF1 """
1729 external_addr = '1.2.3.4'
1734 flags = self.config_flags.NAT_IS_INSIDE
1735 self.vapi.nat44_interface_add_del_feature(
1736 sw_if_index=self.pg5.sw_if_index,
1738 self.vapi.nat44_interface_add_del_feature(
1739 sw_if_index=self.pg5.sw_if_index,
1740 is_add=1, flags=flags)
1741 self.vapi.nat44_interface_add_del_feature(
1742 sw_if_index=self.pg6.sw_if_index,
1744 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1745 self.nat_add_static_mapping(self.pg5.remote_ip4, external_addr,
1746 local_port, external_port, vrf_id=1,
1747 proto=IP_PROTOS.tcp, flags=flags)
1749 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
1750 IP(src=self.pg6.remote_ip4, dst=external_addr) /
1751 TCP(sport=12345, dport=external_port))
1752 self.pg6.add_stream(p)
1753 self.pg_enable_capture(self.pg_interfaces)
1755 capture = self.pg5.get_capture(1)
1760 self.assertEqual(ip.dst, self.pg5.remote_ip4)
1761 self.assertEqual(tcp.dport, local_port)
1762 self.assert_packet_checksums_valid(p)
1764 self.logger.error(ppp("Unexpected or invalid packet:", p))
1767 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
1768 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
1769 TCP(sport=local_port, dport=12345))
1770 self.pg5.add_stream(p)
1771 self.pg_enable_capture(self.pg_interfaces)
1773 capture = self.pg6.get_capture(1)
1778 self.assertEqual(ip.src, external_addr)
1779 self.assertEqual(tcp.sport, external_port)
1780 self.assert_packet_checksums_valid(p)
1782 self.logger.error(ppp("Unexpected or invalid packet:", p))
1785 def test_multiple_vrf_2(self):
1786 """ Multiple VRF - dynamic NAT from VRF1 to VRF0 (output-feature) """
1788 external_addr = '1.2.3.4'
1793 self.nat_add_address(self.nat_addr)
1794 flags = self.config_flags.NAT_IS_INSIDE
1795 self.vapi.nat44_ed_add_del_output_interface(
1796 sw_if_index=self.pg1.sw_if_index,
1798 self.vapi.nat44_interface_add_del_feature(
1799 sw_if_index=self.pg5.sw_if_index,
1801 self.vapi.nat44_interface_add_del_feature(
1802 sw_if_index=self.pg5.sw_if_index,
1803 is_add=1, flags=flags)
1804 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1805 self.nat_add_static_mapping(self.pg5.remote_ip4, external_addr,
1806 local_port, external_port, vrf_id=1,
1807 proto=IP_PROTOS.tcp, flags=flags)
1809 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
1810 IP(src=self.pg5.remote_ip4, dst=self.pg1.remote_ip4) /
1811 TCP(sport=2345, dport=22))
1812 self.pg5.add_stream(p)
1813 self.pg_enable_capture(self.pg_interfaces)
1815 capture = self.pg1.get_capture(1)
1820 self.assertEqual(ip.src, self.nat_addr)
1821 self.assert_packet_checksums_valid(p)
1824 self.logger.error(ppp("Unexpected or invalid packet:", p))
1827 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
1828 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
1829 TCP(sport=22, dport=port))
1830 self.pg1.add_stream(p)
1831 self.pg_enable_capture(self.pg_interfaces)
1833 capture = self.pg5.get_capture(1)
1838 self.assertEqual(ip.dst, self.pg5.remote_ip4)
1839 self.assertEqual(tcp.dport, 2345)
1840 self.assert_packet_checksums_valid(p)
1842 self.logger.error(ppp("Unexpected or invalid packet:", p))
1845 def test_multiple_vrf_3(self):
1846 """ Multiple VRF - client in VRF1, service in VRF0 """
1848 external_addr = '1.2.3.4'
1853 flags = self.config_flags.NAT_IS_INSIDE
1854 self.vapi.nat44_interface_add_del_feature(
1855 sw_if_index=self.pg0.sw_if_index,
1857 self.vapi.nat44_interface_add_del_feature(
1858 sw_if_index=self.pg0.sw_if_index,
1859 is_add=1, flags=flags)
1860 self.vapi.nat44_interface_add_del_feature(
1861 sw_if_index=self.pg6.sw_if_index,
1863 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1864 self.nat_add_static_mapping(
1865 self.pg0.remote_ip4,
1866 external_sw_if_index=self.pg0.sw_if_index,
1867 local_port=local_port,
1869 external_port=external_port,
1870 proto=IP_PROTOS.tcp,
1874 # from client VRF1 to service VRF0
1875 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
1876 IP(src=self.pg6.remote_ip4, dst=self.pg0.local_ip4) /
1877 TCP(sport=12346, dport=external_port))
1878 self.pg6.add_stream(p)
1879 self.pg_enable_capture(self.pg_interfaces)
1881 capture = self.pg0.get_capture(1)
1886 self.assertEqual(ip.dst, self.pg0.remote_ip4)
1887 self.assertEqual(tcp.dport, local_port)
1888 self.assert_packet_checksums_valid(p)
1890 self.logger.error(ppp("Unexpected or invalid packet:", p))
1893 # from service VRF0 back to client VRF1
1894 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1895 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
1896 TCP(sport=local_port, dport=12346))
1897 self.pg0.add_stream(p)
1898 self.pg_enable_capture(self.pg_interfaces)
1900 capture = self.pg6.get_capture(1)
1905 self.assertEqual(ip.src, self.pg0.local_ip4)
1906 self.assertEqual(tcp.sport, external_port)
1907 self.assert_packet_checksums_valid(p)
1909 self.logger.error(ppp("Unexpected or invalid packet:", p))
1912 def test_multiple_vrf_4(self):
1913 """ Multiple VRF - client in VRF0, service in VRF1 """
1915 external_addr = '1.2.3.4'
1920 flags = self.config_flags.NAT_IS_INSIDE
1921 self.vapi.nat44_interface_add_del_feature(
1922 sw_if_index=self.pg0.sw_if_index,
1924 self.vapi.nat44_interface_add_del_feature(
1925 sw_if_index=self.pg0.sw_if_index,
1926 is_add=1, flags=flags)
1927 self.vapi.nat44_interface_add_del_feature(
1928 sw_if_index=self.pg5.sw_if_index,
1930 self.vapi.nat44_interface_add_del_feature(
1931 sw_if_index=self.pg5.sw_if_index,
1932 is_add=1, flags=flags)
1933 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
1934 self.nat_add_static_mapping(self.pg5.remote_ip4, external_addr,
1935 local_port, external_port, vrf_id=1,
1936 proto=IP_PROTOS.tcp, flags=flags)
1938 # from client VRF0 to service VRF1
1939 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
1940 IP(src=self.pg0.remote_ip4, dst=external_addr) /
1941 TCP(sport=12347, dport=external_port))
1942 self.pg0.add_stream(p)
1943 self.pg_enable_capture(self.pg_interfaces)
1945 capture = self.pg5.get_capture(1)
1950 self.assertEqual(ip.dst, self.pg5.remote_ip4)
1951 self.assertEqual(tcp.dport, local_port)
1952 self.assert_packet_checksums_valid(p)
1954 self.logger.error(ppp("Unexpected or invalid packet:", p))
1957 # from service VRF1 back to client VRF0
1958 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
1959 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
1960 TCP(sport=local_port, dport=12347))
1961 self.pg5.add_stream(p)
1962 self.pg_enable_capture(self.pg_interfaces)
1964 capture = self.pg0.get_capture(1)
1969 self.assertEqual(ip.src, external_addr)
1970 self.assertEqual(tcp.sport, external_port)
1971 self.assert_packet_checksums_valid(p)
1973 self.logger.error(ppp("Unexpected or invalid packet:", p))
1976 def test_multiple_vrf_5(self):
1977 """ Multiple VRF - forwarding - no translation """
1979 external_addr = '1.2.3.4'
1984 self.vapi.nat44_forwarding_enable_disable(enable=1)
1985 flags = self.config_flags.NAT_IS_INSIDE
1986 self.vapi.nat44_interface_add_del_feature(
1987 sw_if_index=self.pg0.sw_if_index,
1989 self.vapi.nat44_interface_add_del_feature(
1990 sw_if_index=self.pg0.sw_if_index,
1991 is_add=1, flags=flags)
1992 self.vapi.nat44_interface_add_del_feature(
1993 sw_if_index=self.pg5.sw_if_index,
1995 self.vapi.nat44_interface_add_del_feature(
1996 sw_if_index=self.pg5.sw_if_index,
1997 is_add=1, flags=flags)
1998 self.vapi.nat44_interface_add_del_feature(
1999 sw_if_index=self.pg6.sw_if_index,
2001 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2002 self.nat_add_static_mapping(self.pg5.remote_ip4, external_addr,
2003 local_port, external_port, vrf_id=1,
2004 proto=IP_PROTOS.tcp, flags=flags)
2005 self.nat_add_static_mapping(
2006 self.pg0.remote_ip4,
2007 external_sw_if_index=self.pg0.sw_if_index,
2008 local_port=local_port,
2010 external_port=external_port,
2011 proto=IP_PROTOS.tcp,
2015 # from client to server (both VRF1, no translation)
2016 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
2017 IP(src=self.pg6.remote_ip4, dst=self.pg5.remote_ip4) /
2018 TCP(sport=12348, dport=local_port))
2019 self.pg6.add_stream(p)
2020 self.pg_enable_capture(self.pg_interfaces)
2022 capture = self.pg5.get_capture(1)
2027 self.assertEqual(ip.dst, self.pg5.remote_ip4)
2028 self.assertEqual(tcp.dport, local_port)
2029 self.assert_packet_checksums_valid(p)
2031 self.logger.error(ppp("Unexpected or invalid packet:", p))
2034 # from server back to client (both VRF1, no translation)
2035 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
2036 IP(src=self.pg5.remote_ip4, dst=self.pg6.remote_ip4) /
2037 TCP(sport=local_port, dport=12348))
2038 self.pg5.add_stream(p)
2039 self.pg_enable_capture(self.pg_interfaces)
2041 capture = self.pg6.get_capture(1)
2046 self.assertEqual(ip.src, self.pg5.remote_ip4)
2047 self.assertEqual(tcp.sport, local_port)
2048 self.assert_packet_checksums_valid(p)
2050 self.logger.error(ppp("Unexpected or invalid packet:", p))
2053 # from client VRF1 to server VRF0 (no translation)
2054 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2055 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
2056 TCP(sport=local_port, dport=12349))
2057 self.pg0.add_stream(p)
2058 self.pg_enable_capture(self.pg_interfaces)
2060 capture = self.pg6.get_capture(1)
2065 self.assertEqual(ip.src, self.pg0.remote_ip4)
2066 self.assertEqual(tcp.sport, local_port)
2067 self.assert_packet_checksums_valid(p)
2069 self.logger.error(ppp("Unexpected or invalid packet:", p))
2072 # from server VRF0 back to client VRF1 (no translation)
2073 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2074 IP(src=self.pg0.remote_ip4, dst=self.pg6.remote_ip4) /
2075 TCP(sport=local_port, dport=12349))
2076 self.pg0.add_stream(p)
2077 self.pg_enable_capture(self.pg_interfaces)
2079 capture = self.pg6.get_capture(1)
2084 self.assertEqual(ip.src, self.pg0.remote_ip4)
2085 self.assertEqual(tcp.sport, local_port)
2086 self.assert_packet_checksums_valid(p)
2088 self.logger.error(ppp("Unexpected or invalid packet:", p))
2091 # from client VRF0 to server VRF1 (no translation)
2092 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2093 IP(src=self.pg0.remote_ip4, dst=self.pg5.remote_ip4) /
2094 TCP(sport=12344, dport=local_port))
2095 self.pg0.add_stream(p)
2096 self.pg_enable_capture(self.pg_interfaces)
2098 capture = self.pg5.get_capture(1)
2103 self.assertEqual(ip.dst, self.pg5.remote_ip4)
2104 self.assertEqual(tcp.dport, local_port)
2105 self.assert_packet_checksums_valid(p)
2107 self.logger.error(ppp("Unexpected or invalid packet:", p))
2110 # from server VRF1 back to client VRF0 (no translation)
2111 p = (Ether(src=self.pg5.remote_mac, dst=self.pg5.local_mac) /
2112 IP(src=self.pg5.remote_ip4, dst=self.pg0.remote_ip4) /
2113 TCP(sport=local_port, dport=12344))
2114 self.pg5.add_stream(p)
2115 self.pg_enable_capture(self.pg_interfaces)
2117 capture = self.pg0.get_capture(1)
2122 self.assertEqual(ip.src, self.pg5.remote_ip4)
2123 self.assertEqual(tcp.sport, local_port)
2124 self.assert_packet_checksums_valid(p)
2126 self.logger.error(ppp("Unexpected or invalid packet:", p))
2129 def test_outside_address_distribution(self):
2130 """ Outside address distribution based on source address """
2135 for i in range(1, x):
2137 nat_addresses.append(a)
2139 self.nat_add_inside_interface(self.pg0)
2140 self.nat_add_outside_interface(self.pg1)
2142 self.vapi.nat44_add_del_address_range(
2143 first_ip_address=nat_addresses[0],
2144 last_ip_address=nat_addresses[-1],
2145 vrf_id=0xFFFFFFFF, is_add=1, flags=0)
2147 self.pg0.generate_remote_hosts(x)
2151 info = self.create_packet_info(self.pg0, self.pg1)
2152 payload = self.info_to_payload(info)
2153 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2154 IP(src=self.pg0.remote_hosts[i].ip4,
2155 dst=self.pg1.remote_ip4) /
2156 UDP(sport=7000+i, dport=8000+i) /
2161 self.pg0.add_stream(pkts)
2162 self.pg_enable_capture(self.pg_interfaces)
2164 recvd = self.pg1.get_capture(len(pkts))
2165 for p_recvd in recvd:
2166 payload_info = self.payload_to_info(p_recvd[Raw])
2167 packet_index = payload_info.index
2168 info = self._packet_infos[packet_index]
2169 self.assertTrue(info is not None)
2170 self.assertEqual(packet_index, info.index)
2172 packed = socket.inet_aton(p_sent[IP].src)
2173 numeric = struct.unpack("!L", packed)[0]
2174 numeric = socket.htonl(numeric)
2175 a = nat_addresses[(numeric-1) % len(nat_addresses)]
2178 "Invalid packet (src IP %s translated to %s, but expected %s)"
2179 % (p_sent[IP].src, p_recvd[IP].src, a))
2182 class TestNAT44EDMW(TestNAT44ED):
2183 """ NAT44ED MW Test Case """
2184 vpp_worker_count = 4
2187 def test_dynamic(self):
2188 """ NAT44ED dynamic translation test """
2190 tcp_port_offset = 20
2191 udp_port_offset = 20
2194 self.nat_add_address(self.nat_addr)
2195 self.nat_add_inside_interface(self.pg0)
2196 self.nat_add_outside_interface(self.pg1)
2199 tc1 = self.statistics['/nat44-ed/in2out/slowpath/tcp']
2200 uc1 = self.statistics['/nat44-ed/in2out/slowpath/udp']
2201 ic1 = self.statistics['/nat44-ed/in2out/slowpath/icmp']
2202 dc1 = self.statistics['/nat44-ed/in2out/slowpath/drops']
2204 i2o_pkts = [[] for x in range(0, self.vpp_worker_count)]
2206 for i in range(pkt_count):
2207 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2208 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2209 TCP(sport=tcp_port_offset + i, dport=20))
2210 i2o_pkts[p[TCP].sport % self.vpp_worker_count].append(p)
2212 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2213 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2214 UDP(sport=udp_port_offset + i, dport=20))
2215 i2o_pkts[p[UDP].sport % self.vpp_worker_count].append(p)
2217 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2218 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2219 ICMP(id=icmp_id_offset + i, type='echo-request'))
2220 i2o_pkts[p[ICMP].id % self.vpp_worker_count].append(p)
2222 for i in range(0, self.vpp_worker_count):
2223 if len(i2o_pkts[i]) > 0:
2224 self.pg0.add_stream(i2o_pkts[i], worker=i)
2226 self.pg_enable_capture(self.pg_interfaces)
2228 capture = self.pg1.get_capture(pkt_count * 3, timeout=5)
2230 if_idx = self.pg0.sw_if_index
2231 tc2 = self.statistics['/nat44-ed/in2out/slowpath/tcp']
2232 uc2 = self.statistics['/nat44-ed/in2out/slowpath/udp']
2233 ic2 = self.statistics['/nat44-ed/in2out/slowpath/icmp']
2234 dc2 = self.statistics['/nat44-ed/in2out/slowpath/drops']
2237 tc2[:, if_idx].sum() - tc1[:, if_idx].sum(), pkt_count)
2239 uc2[:, if_idx].sum() - uc1[:, if_idx].sum(), pkt_count)
2241 ic2[:, if_idx].sum() - ic1[:, if_idx].sum(), pkt_count)
2242 self.assertEqual(dc2[:, if_idx].sum() - dc1[:, if_idx].sum(), 0)
2244 self.logger.info(self.vapi.cli("show trace"))
2247 tc1 = self.statistics['/nat44-ed/out2in/fastpath/tcp']
2248 uc1 = self.statistics['/nat44-ed/out2in/fastpath/udp']
2249 ic1 = self.statistics['/nat44-ed/out2in/fastpath/icmp']
2250 dc1 = self.statistics['/nat44-ed/out2in/fastpath/drops']
2252 recvd_tcp_ports = set()
2253 recvd_udp_ports = set()
2254 recvd_icmp_ids = set()
2258 recvd_tcp_ports.add(p[TCP].sport)
2260 recvd_udp_ports.add(p[UDP].sport)
2262 recvd_icmp_ids.add(p[ICMP].id)
2264 recvd_tcp_ports = list(recvd_tcp_ports)
2265 recvd_udp_ports = list(recvd_udp_ports)
2266 recvd_icmp_ids = list(recvd_icmp_ids)
2268 o2i_pkts = [[] for x in range(0, self.vpp_worker_count)]
2269 for i in range(pkt_count):
2270 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2271 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
2272 TCP(dport=choice(recvd_tcp_ports), sport=20))
2273 o2i_pkts[p[TCP].dport % self.vpp_worker_count].append(p)
2275 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2276 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
2277 UDP(dport=choice(recvd_udp_ports), sport=20))
2278 o2i_pkts[p[UDP].dport % self.vpp_worker_count].append(p)
2280 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2281 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
2282 ICMP(id=choice(recvd_icmp_ids), type='echo-reply'))
2283 o2i_pkts[p[ICMP].id % self.vpp_worker_count].append(p)
2285 for i in range(0, self.vpp_worker_count):
2286 if len(o2i_pkts[i]) > 0:
2287 self.pg1.add_stream(o2i_pkts[i], worker=i)
2289 self.pg_enable_capture(self.pg_interfaces)
2291 capture = self.pg0.get_capture(pkt_count * 3)
2292 for packet in capture:
2294 self.assert_packet_checksums_valid(packet)
2295 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2296 if packet.haslayer(TCP):
2297 self.assert_in_range(
2298 packet[TCP].dport, tcp_port_offset,
2299 tcp_port_offset + pkt_count, "dst TCP port")
2300 elif packet.haslayer(UDP):
2301 self.assert_in_range(
2302 packet[UDP].dport, udp_port_offset,
2303 udp_port_offset + pkt_count, "dst UDP port")
2305 self.assert_in_range(
2306 packet[ICMP].id, icmp_id_offset,
2307 icmp_id_offset + pkt_count, "ICMP id")
2309 self.logger.error(ppp("Unexpected or invalid packet "
2310 "(inside network):", packet))
2313 if_idx = self.pg1.sw_if_index
2314 tc2 = self.statistics['/nat44-ed/out2in/fastpath/tcp']
2315 uc2 = self.statistics['/nat44-ed/out2in/fastpath/udp']
2316 ic2 = self.statistics['/nat44-ed/out2in/fastpath/icmp']
2317 dc2 = self.statistics['/nat44-ed/out2in/fastpath/drops']
2320 tc2[:, if_idx].sum() - tc1[:, if_idx].sum(), pkt_count)
2322 uc2[:, if_idx].sum() - uc1[:, if_idx].sum(), pkt_count)
2324 ic2[:, if_idx].sum() - ic1[:, if_idx].sum(), pkt_count)
2325 self.assertEqual(dc2[:, if_idx].sum() - dc1[:, if_idx].sum(), 0)
2327 sc = self.statistics['/nat44-ed/total-sessions']
2328 self.assertEqual(sc[:, 0].sum(), len(recvd_tcp_ports) +
2329 len(recvd_udp_ports) + len(recvd_icmp_ids))
2331 def test_frag_in_order(self):
2332 """ NAT44ED translate fragments arriving in order """
2334 self.nat_add_address(self.nat_addr)
2335 self.nat_add_inside_interface(self.pg0)
2336 self.nat_add_outside_interface(self.pg1)
2338 self.frag_in_order(proto=IP_PROTOS.tcp, ignore_port=True)
2339 self.frag_in_order(proto=IP_PROTOS.udp, ignore_port=True)
2340 self.frag_in_order(proto=IP_PROTOS.icmp, ignore_port=True)
2342 def test_frag_in_order_do_not_translate(self):
2343 """ NAT44ED don't translate fragments arriving in order """
2345 self.nat_add_address(self.nat_addr)
2346 self.nat_add_inside_interface(self.pg0)
2347 self.nat_add_outside_interface(self.pg1)
2348 self.vapi.nat44_forwarding_enable_disable(enable=True)
2350 self.frag_in_order(proto=IP_PROTOS.tcp, dont_translate=True)
2352 def test_frag_out_of_order(self):
2353 """ NAT44ED translate fragments arriving out of order """
2355 self.nat_add_address(self.nat_addr)
2356 self.nat_add_inside_interface(self.pg0)
2357 self.nat_add_outside_interface(self.pg1)
2359 self.frag_out_of_order(proto=IP_PROTOS.tcp, ignore_port=True)
2360 self.frag_out_of_order(proto=IP_PROTOS.udp, ignore_port=True)
2361 self.frag_out_of_order(proto=IP_PROTOS.icmp, ignore_port=True)
2363 def test_frag_in_order_in_plus_out(self):
2364 """ NAT44ED in+out interface fragments in order """
2366 in_port = self.random_port()
2367 out_port = self.random_port()
2369 self.nat_add_address(self.nat_addr)
2370 self.nat_add_inside_interface(self.pg0)
2371 self.nat_add_outside_interface(self.pg0)
2372 self.nat_add_inside_interface(self.pg1)
2373 self.nat_add_outside_interface(self.pg1)
2375 # add static mappings for server
2376 self.nat_add_static_mapping(self.server_addr,
2380 proto=IP_PROTOS.tcp)
2381 self.nat_add_static_mapping(self.server_addr,
2385 proto=IP_PROTOS.udp)
2386 self.nat_add_static_mapping(self.server_addr,
2388 proto=IP_PROTOS.icmp)
2390 # run tests for each protocol
2391 self.frag_in_order_in_plus_out(self.server_addr,
2396 self.frag_in_order_in_plus_out(self.server_addr,
2401 self.frag_in_order_in_plus_out(self.server_addr,
2407 def test_frag_out_of_order_in_plus_out(self):
2408 """ NAT44ED in+out interface fragments out of order """
2410 in_port = self.random_port()
2411 out_port = self.random_port()
2413 self.nat_add_address(self.nat_addr)
2414 self.nat_add_inside_interface(self.pg0)
2415 self.nat_add_outside_interface(self.pg0)
2416 self.nat_add_inside_interface(self.pg1)
2417 self.nat_add_outside_interface(self.pg1)
2419 # add static mappings for server
2420 self.nat_add_static_mapping(self.server_addr,
2424 proto=IP_PROTOS.tcp)
2425 self.nat_add_static_mapping(self.server_addr,
2429 proto=IP_PROTOS.udp)
2430 self.nat_add_static_mapping(self.server_addr,
2432 proto=IP_PROTOS.icmp)
2434 # run tests for each protocol
2435 self.frag_out_of_order_in_plus_out(self.server_addr,
2440 self.frag_out_of_order_in_plus_out(self.server_addr,
2445 self.frag_out_of_order_in_plus_out(self.server_addr,
2451 def test_reass_hairpinning(self):
2452 """ NAT44ED fragments hairpinning """
2454 server_addr = self.pg0.remote_hosts[1].ip4
2456 host_in_port = self.random_port()
2457 server_in_port = self.random_port()
2458 server_out_port = self.random_port()
2460 self.nat_add_address(self.nat_addr)
2461 self.nat_add_inside_interface(self.pg0)
2462 self.nat_add_outside_interface(self.pg1)
2464 # add static mapping for server
2465 self.nat_add_static_mapping(server_addr, self.nat_addr,
2466 server_in_port, server_out_port,
2467 proto=IP_PROTOS.tcp)
2468 self.nat_add_static_mapping(server_addr, self.nat_addr,
2469 server_in_port, server_out_port,
2470 proto=IP_PROTOS.udp)
2471 self.nat_add_static_mapping(server_addr, self.nat_addr)
2473 self.reass_hairpinning(server_addr, server_in_port, server_out_port,
2474 host_in_port, proto=IP_PROTOS.tcp,
2476 self.reass_hairpinning(server_addr, server_in_port, server_out_port,
2477 host_in_port, proto=IP_PROTOS.udp,
2479 self.reass_hairpinning(server_addr, server_in_port, server_out_port,
2480 host_in_port, proto=IP_PROTOS.icmp,
2483 def test_session_limit_per_vrf(self):
2484 """ NAT44ED per vrf session limit """
2487 inside_vrf10 = self.pg2
2492 # 2 interfaces pg0, pg1 (vrf10, limit 1 tcp session)
2493 # non existing vrf_id makes process core dump
2494 self.vapi.nat44_set_session_limit(session_limit=limit, vrf_id=10)
2496 self.nat_add_inside_interface(inside)
2497 self.nat_add_inside_interface(inside_vrf10)
2498 self.nat_add_outside_interface(outside)
2501 self.nat_add_interface_address(outside)
2503 # BUG: causing core dump - when bad vrf_id is specified
2504 # self.nat_add_address(outside.local_ip4, vrf_id=20)
2506 stream = self.create_tcp_stream(inside_vrf10, outside, limit * 2)
2507 inside_vrf10.add_stream(stream)
2509 self.pg_enable_capture(self.pg_interfaces)
2512 capture = outside.get_capture(limit)
2514 stream = self.create_tcp_stream(inside, outside, limit * 2)
2515 inside.add_stream(stream)
2517 self.pg_enable_capture(self.pg_interfaces)
2520 capture = outside.get_capture(len(stream))
2522 def test_show_max_translations(self):
2523 """ NAT44ED API test - max translations per thread """
2524 config = self.vapi.nat44_show_running_config()
2525 self.assertEqual(self.max_sessions,
2528 def test_lru_cleanup(self):
2529 """ NAT44ED LRU cleanup algorithm """
2531 self.nat_add_address(self.nat_addr)
2532 self.nat_add_inside_interface(self.pg0)
2533 self.nat_add_outside_interface(self.pg1)
2535 self.vapi.nat_set_timeouts(
2536 udp=1, tcp_established=7440, tcp_transitory=30, icmp=1)
2538 tcp_port_out = self.init_tcp_session(self.pg0, self.pg1, 2000, 80)
2540 for i in range(0, self.max_sessions - 1):
2541 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2542 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
2543 UDP(sport=7000+i, dport=80))
2546 self.pg0.add_stream(pkts)
2547 self.pg_enable_capture(self.pg_interfaces)
2549 self.pg1.get_capture(len(pkts))
2550 self.virtual_sleep(1.5, "wait for timeouts")
2553 for i in range(0, self.max_sessions - 1):
2554 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2555 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, ttl=64) /
2556 ICMP(id=8000+i, type='echo-request'))
2559 self.pg0.add_stream(pkts)
2560 self.pg_enable_capture(self.pg_interfaces)
2562 self.pg1.get_capture(len(pkts))
2564 def test_session_rst_timeout(self):
2565 """ NAT44ED session RST timeouts """
2567 self.nat_add_address(self.nat_addr)
2568 self.nat_add_inside_interface(self.pg0)
2569 self.nat_add_outside_interface(self.pg1)
2571 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
2572 tcp_transitory=5, icmp=60)
2574 self.init_tcp_session(self.pg0, self.pg1, self.tcp_port_in,
2575 self.tcp_external_port)
2576 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2577 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2578 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
2580 self.send_and_expect(self.pg0, p, self.pg1)
2582 self.virtual_sleep(6)
2584 # The session is already closed
2585 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2586 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2587 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
2589 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
2591 # The session can be re-opened
2592 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2593 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2594 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
2596 self.send_and_expect(self.pg0, p, self.pg1)
2598 def test_session_rst_established_timeout(self):
2599 """ NAT44ED session RST timeouts """
2601 self.nat_add_address(self.nat_addr)
2602 self.nat_add_inside_interface(self.pg0)
2603 self.nat_add_outside_interface(self.pg1)
2605 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
2606 tcp_transitory=5, icmp=60)
2608 self.init_tcp_session(self.pg0, self.pg1, self.tcp_port_in,
2609 self.tcp_external_port)
2611 # Wait at least the transitory time, the session is in established
2612 # state anyway. RST followed by a data packet should keep it
2614 self.virtual_sleep(6)
2615 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2616 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2617 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
2619 self.send_and_expect(self.pg0, p, self.pg1)
2621 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2622 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2623 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
2625 self.send_and_expect(self.pg0, p, self.pg1)
2627 # State is established, session should be still open after 6 seconds
2628 self.virtual_sleep(6)
2630 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2631 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2632 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
2634 self.send_and_expect(self.pg0, p, self.pg1)
2636 # State is transitory, session should be closed after 6 seconds
2637 self.virtual_sleep(6)
2639 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2640 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2641 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
2643 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
2645 def test_dynamic_out_of_ports(self):
2646 """ NAT44ED dynamic translation test: out of ports """
2648 self.nat_add_inside_interface(self.pg0)
2649 self.nat_add_outside_interface(self.pg1)
2651 # in2out and no NAT addresses added
2652 pkts = self.create_stream_in(self.pg0, self.pg1)
2654 self.send_and_assert_no_replies(
2655 self.pg0, pkts, msg="i2o pkts",
2656 stats_diff=self.no_diff | {
2658 '/err/nat44-ed-in2out-slowpath/out of ports': len(pkts),
2660 self.pg0.sw_if_index: {
2661 '/nat44-ed/in2out/slowpath/drops': len(pkts),
2666 # in2out after NAT addresses added
2667 self.nat_add_address(self.nat_addr)
2669 tcpn, udpn, icmpn = (sum(x) for x in
2670 zip(*((TCP in p, UDP in p, ICMP in p)
2673 self.send_and_expect(
2674 self.pg0, pkts, self.pg1, msg="i2o pkts",
2675 stats_diff=self.no_diff | {
2677 '/err/nat44-ed-in2out-slowpath/out of ports': 0,
2679 self.pg0.sw_if_index: {
2680 '/nat44-ed/in2out/slowpath/drops': 0,
2681 '/nat44-ed/in2out/slowpath/tcp': tcpn,
2682 '/nat44-ed/in2out/slowpath/udp': udpn,
2683 '/nat44-ed/in2out/slowpath/icmp': icmpn,
2688 def test_unknown_proto(self):
2689 """ NAT44ED translate packet with unknown protocol """
2691 self.nat_add_address(self.nat_addr)
2692 self.nat_add_inside_interface(self.pg0)
2693 self.nat_add_outside_interface(self.pg1)
2696 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2697 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2698 TCP(sport=self.tcp_port_in, dport=20))
2699 self.pg0.add_stream(p)
2700 self.pg_enable_capture(self.pg_interfaces)
2702 p = self.pg1.get_capture(1)
2704 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2705 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2707 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2708 TCP(sport=1234, dport=1234))
2709 self.pg0.add_stream(p)
2710 self.pg_enable_capture(self.pg_interfaces)
2712 p = self.pg1.get_capture(1)
2715 self.assertEqual(packet[IP].src, self.nat_addr)
2716 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2717 self.assertEqual(packet.haslayer(GRE), 1)
2718 self.assert_packet_checksums_valid(packet)
2720 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2724 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2725 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
2727 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2728 TCP(sport=1234, dport=1234))
2729 self.pg1.add_stream(p)
2730 self.pg_enable_capture(self.pg_interfaces)
2732 p = self.pg0.get_capture(1)
2735 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
2736 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2737 self.assertEqual(packet.haslayer(GRE), 1)
2738 self.assert_packet_checksums_valid(packet)
2740 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2743 def test_hairpinning_unknown_proto(self):
2744 """ NAT44ED translate packet with unknown protocol - hairpinning """
2745 host = self.pg0.remote_hosts[0]
2746 server = self.pg0.remote_hosts[1]
2748 server_out_port = 8765
2749 server_nat_ip = "10.0.0.11"
2751 self.nat_add_address(self.nat_addr)
2752 self.nat_add_inside_interface(self.pg0)
2753 self.nat_add_outside_interface(self.pg1)
2755 # add static mapping for server
2756 self.nat_add_static_mapping(server.ip4, server_nat_ip)
2759 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2760 IP(src=host.ip4, dst=server_nat_ip) /
2761 TCP(sport=host_in_port, dport=server_out_port))
2762 self.pg0.add_stream(p)
2763 self.pg_enable_capture(self.pg_interfaces)
2765 self.pg0.get_capture(1)
2767 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
2768 IP(src=host.ip4, dst=server_nat_ip) /
2770 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2771 TCP(sport=1234, dport=1234))
2772 self.pg0.add_stream(p)
2773 self.pg_enable_capture(self.pg_interfaces)
2775 p = self.pg0.get_capture(1)
2778 self.assertEqual(packet[IP].src, self.nat_addr)
2779 self.assertEqual(packet[IP].dst, server.ip4)
2780 self.assertEqual(packet.haslayer(GRE), 1)
2781 self.assert_packet_checksums_valid(packet)
2783 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2787 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
2788 IP(src=server.ip4, dst=self.nat_addr) /
2790 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2791 TCP(sport=1234, dport=1234))
2792 self.pg0.add_stream(p)
2793 self.pg_enable_capture(self.pg_interfaces)
2795 p = self.pg0.get_capture(1)
2798 self.assertEqual(packet[IP].src, server_nat_ip)
2799 self.assertEqual(packet[IP].dst, host.ip4)
2800 self.assertEqual(packet.haslayer(GRE), 1)
2801 self.assert_packet_checksums_valid(packet)
2803 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2806 def test_output_feature_and_service(self):
2807 """ NAT44ED interface output feature and services """
2808 external_addr = '1.2.3.4'
2812 self.vapi.nat44_forwarding_enable_disable(enable=1)
2813 self.nat_add_address(self.nat_addr)
2814 flags = self.config_flags.NAT_IS_ADDR_ONLY
2815 self.vapi.nat44_add_del_identity_mapping(
2816 ip_address=self.pg1.remote_ip4, sw_if_index=0xFFFFFFFF,
2817 flags=flags, is_add=1)
2818 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2819 self.nat_add_static_mapping(self.pg0.remote_ip4, external_addr,
2820 local_port, external_port,
2821 proto=IP_PROTOS.tcp, flags=flags)
2823 self.nat_add_inside_interface(self.pg0)
2824 self.nat_add_outside_interface(self.pg0)
2825 self.vapi.nat44_ed_add_del_output_interface(
2826 sw_if_index=self.pg1.sw_if_index, is_add=1)
2828 # from client to service
2829 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2830 IP(src=self.pg1.remote_ip4, dst=external_addr) /
2831 TCP(sport=12345, dport=external_port))
2832 self.pg1.add_stream(p)
2833 self.pg_enable_capture(self.pg_interfaces)
2835 capture = self.pg0.get_capture(1)
2840 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2841 self.assertEqual(tcp.dport, local_port)
2842 self.assert_packet_checksums_valid(p)
2844 self.logger.error(ppp("Unexpected or invalid packet:", p))
2847 # from service back to client
2848 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2849 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2850 TCP(sport=local_port, dport=12345))
2851 self.pg0.add_stream(p)
2852 self.pg_enable_capture(self.pg_interfaces)
2854 capture = self.pg1.get_capture(1)
2859 self.assertEqual(ip.src, external_addr)
2860 self.assertEqual(tcp.sport, external_port)
2861 self.assert_packet_checksums_valid(p)
2863 self.logger.error(ppp("Unexpected or invalid packet:", p))
2866 # from local network host to external network
2867 pkts = self.create_stream_in(self.pg0, self.pg1)
2868 self.pg0.add_stream(pkts)
2869 self.pg_enable_capture(self.pg_interfaces)
2871 capture = self.pg1.get_capture(len(pkts))
2872 self.verify_capture_out(capture, ignore_port=True)
2873 pkts = self.create_stream_in(self.pg0, self.pg1)
2874 self.pg0.add_stream(pkts)
2875 self.pg_enable_capture(self.pg_interfaces)
2877 capture = self.pg1.get_capture(len(pkts))
2878 self.verify_capture_out(capture, ignore_port=True)
2880 # from external network back to local network host
2881 pkts = self.create_stream_out(self.pg1)
2882 self.pg1.add_stream(pkts)
2883 self.pg_enable_capture(self.pg_interfaces)
2885 capture = self.pg0.get_capture(len(pkts))
2886 self.verify_capture_in(capture, self.pg0)
2888 def test_output_feature_and_service3(self):
2889 """ NAT44ED interface output feature and DST NAT """
2890 external_addr = '1.2.3.4'
2894 self.vapi.nat44_forwarding_enable_disable(enable=1)
2895 self.nat_add_address(self.nat_addr)
2896 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2897 self.nat_add_static_mapping(self.pg1.remote_ip4, external_addr,
2898 local_port, external_port,
2899 proto=IP_PROTOS.tcp, flags=flags)
2901 self.nat_add_inside_interface(self.pg0)
2902 self.nat_add_outside_interface(self.pg0)
2903 self.vapi.nat44_ed_add_del_output_interface(
2904 sw_if_index=self.pg1.sw_if_index, is_add=1)
2906 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2907 IP(src=self.pg0.remote_ip4, dst=external_addr) /
2908 TCP(sport=12345, dport=external_port))
2909 self.pg0.add_stream(p)
2910 self.pg_enable_capture(self.pg_interfaces)
2912 capture = self.pg1.get_capture(1)
2917 self.assertEqual(ip.src, self.pg0.remote_ip4)
2918 self.assertEqual(tcp.sport, 12345)
2919 self.assertEqual(ip.dst, self.pg1.remote_ip4)
2920 self.assertEqual(tcp.dport, local_port)
2921 self.assert_packet_checksums_valid(p)
2923 self.logger.error(ppp("Unexpected or invalid packet:", p))
2926 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2927 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2928 TCP(sport=local_port, dport=12345))
2929 self.pg1.add_stream(p)
2930 self.pg_enable_capture(self.pg_interfaces)
2932 capture = self.pg0.get_capture(1)
2937 self.assertEqual(ip.src, external_addr)
2938 self.assertEqual(tcp.sport, external_port)
2939 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2940 self.assertEqual(tcp.dport, 12345)
2941 self.assert_packet_checksums_valid(p)
2943 self.logger.error(ppp("Unexpected or invalid packet:", p))
2946 def test_self_twice_nat_lb_negative(self):
2947 """ NAT44ED Self Twice NAT local service load balancing (negative test)
2949 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
2952 def test_self_twice_nat_negative(self):
2953 """ NAT44ED Self Twice NAT (negative test) """
2954 self.twice_nat_common(self_twice_nat=True)
2956 def test_static_lb_multi_clients(self):
2957 """ NAT44ED local service load balancing - multiple clients"""
2959 external_addr = self.nat_addr
2962 server1 = self.pg0.remote_hosts[0]
2963 server2 = self.pg0.remote_hosts[1]
2964 server3 = self.pg0.remote_hosts[2]
2966 locals = [{'addr': server1.ip4,
2970 {'addr': server2.ip4,
2975 flags = self.config_flags.NAT_IS_INSIDE
2976 self.vapi.nat44_interface_add_del_feature(
2977 sw_if_index=self.pg0.sw_if_index,
2978 flags=flags, is_add=1)
2979 self.vapi.nat44_interface_add_del_feature(
2980 sw_if_index=self.pg1.sw_if_index,
2983 self.nat_add_address(self.nat_addr)
2984 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
2985 external_addr=external_addr,
2986 external_port=external_port,
2987 protocol=IP_PROTOS.tcp,
2988 local_num=len(locals),
2993 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
2995 for client in clients:
2996 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2997 IP(src=client, dst=self.nat_addr) /
2998 TCP(sport=12345, dport=external_port))
3000 self.pg1.add_stream(pkts)
3001 self.pg_enable_capture(self.pg_interfaces)
3003 capture = self.pg0.get_capture(len(pkts))
3005 if p[IP].dst == server1.ip4:
3009 self.assertGreaterEqual(server1_n, server2_n)
3012 'addr': server3.ip4,
3019 self.vapi.nat44_lb_static_mapping_add_del_local(
3021 external_addr=external_addr,
3022 external_port=external_port,
3024 protocol=IP_PROTOS.tcp)
3028 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
3030 for client in clients:
3031 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3032 IP(src=client, dst=self.nat_addr) /
3033 TCP(sport=12346, dport=external_port))
3035 self.assertGreater(len(pkts), 0)
3036 self.pg1.add_stream(pkts)
3037 self.pg_enable_capture(self.pg_interfaces)
3039 capture = self.pg0.get_capture(len(pkts))
3041 if p[IP].dst == server1.ip4:
3043 elif p[IP].dst == server2.ip4:
3047 self.assertGreater(server1_n, 0)
3048 self.assertGreater(server2_n, 0)
3049 self.assertGreater(server3_n, 0)
3052 'addr': server2.ip4,
3058 # remove one back-end
3059 self.vapi.nat44_lb_static_mapping_add_del_local(
3061 external_addr=external_addr,
3062 external_port=external_port,
3064 protocol=IP_PROTOS.tcp)
3068 self.pg1.add_stream(pkts)
3069 self.pg_enable_capture(self.pg_interfaces)
3071 capture = self.pg0.get_capture(len(pkts))
3073 if p[IP].dst == server1.ip4:
3075 elif p[IP].dst == server2.ip4:
3079 self.assertGreater(server1_n, 0)
3080 self.assertEqual(server2_n, 0)
3081 self.assertGreater(server3_n, 0)
3083 # put zzz in front of syslog test name so that it runs as a last test
3084 # setting syslog sender cannot be undone and if it is set, it messes
3085 # with self.send_and_assert_no_replies functionality
3086 def test_zzz_syslog_sess(self):
3087 """ NAT44ED Test syslog session creation and deletion """
3088 self.vapi.syslog_set_filter(
3089 self.syslog_severity.SYSLOG_API_SEVERITY_INFO)
3090 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
3092 self.nat_add_address(self.nat_addr)
3093 self.nat_add_inside_interface(self.pg0)
3094 self.nat_add_outside_interface(self.pg1)
3096 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3097 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3098 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
3099 self.pg0.add_stream(p)
3100 self.pg_enable_capture(self.pg_interfaces)
3102 capture = self.pg1.get_capture(1)
3103 self.tcp_port_out = capture[0][TCP].sport
3104 capture = self.pg3.get_capture(1)
3105 self.verify_syslog_sess(capture[0][Raw].load, 'SADD')
3107 self.pg_enable_capture(self.pg_interfaces)
3109 self.nat_add_address(self.nat_addr, is_add=0)
3110 capture = self.pg3.get_capture(1)
3111 self.verify_syslog_sess(capture[0][Raw].load, 'SDEL')
3113 # put zzz in front of syslog test name so that it runs as a last test
3114 # setting syslog sender cannot be undone and if it is set, it messes
3115 # with self.send_and_assert_no_replies functionality
3116 def test_zzz_syslog_sess_reopen(self):
3117 """ Syslog events for session reopen """
3118 self.vapi.syslog_set_filter(
3119 self.syslog_severity.SYSLOG_API_SEVERITY_INFO)
3120 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
3122 self.nat_add_address(self.nat_addr)
3123 self.nat_add_inside_interface(self.pg0)
3124 self.nat_add_outside_interface(self.pg1)
3127 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3128 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3129 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
3130 capture = self.send_and_expect(self.pg0, p, self.pg1)[0]
3131 self.tcp_port_out = capture[0][TCP].sport
3132 capture = self.pg3.get_capture(1)
3133 self.verify_syslog_sess(capture[0][Raw].load, 'SADD')
3136 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3137 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3138 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
3139 self.send_and_expect(self.pg1, p, self.pg0)
3142 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3143 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3144 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3146 self.send_and_expect(self.pg0, p, self.pg1)
3149 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3150 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3151 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
3153 self.send_and_expect(self.pg1, p, self.pg0)
3156 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3157 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3158 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
3159 self.send_and_expect(self.pg0, p, self.pg1)
3162 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3163 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3164 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out))
3165 self.send_and_expect(self.pg1, p, self.pg0)
3167 # 2 records should be produced - first one del & add
3168 capture = self.pg3.get_capture(2)
3169 self.verify_syslog_sess(capture[0][Raw].load, 'SDEL')
3170 self.verify_syslog_sess(capture[1][Raw].load, 'SADD')
3172 def test_twice_nat_interface_addr(self):
3173 """ NAT44ED Acquire twice NAT addresses from interface """
3174 flags = self.config_flags.NAT_IS_TWICE_NAT
3175 self.vapi.nat44_add_del_interface_addr(
3176 sw_if_index=self.pg11.sw_if_index,
3177 flags=flags, is_add=1)
3179 # no address in NAT pool
3180 adresses = self.vapi.nat44_address_dump()
3181 self.assertEqual(0, len(adresses))
3183 # configure interface address and check NAT address pool
3184 self.pg11.config_ip4()
3185 adresses = self.vapi.nat44_address_dump()
3186 self.assertEqual(1, len(adresses))
3187 self.assertEqual(str(adresses[0].ip_address),
3188 self.pg11.local_ip4)
3189 self.assertEqual(adresses[0].flags, flags)
3191 # remove interface address and check NAT address pool
3192 self.pg11.unconfig_ip4()
3193 adresses = self.vapi.nat44_address_dump()
3194 self.assertEqual(0, len(adresses))
3196 def test_output_feature_stateful_acl(self):
3197 """ NAT44ED output feature works with stateful ACL """
3199 self.nat_add_address(self.nat_addr)
3200 self.vapi.nat44_ed_add_del_output_interface(
3201 sw_if_index=self.pg1.sw_if_index, is_add=1)
3203 # First ensure that the NAT is working sans ACL
3205 # send packets out2in, no sessions yet so packets should drop
3206 pkts_out2in = self.create_stream_out(self.pg1)
3207 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
3209 # send packets into inside intf, ensure received via outside intf
3210 pkts_in2out = self.create_stream_in(self.pg0, self.pg1)
3211 capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
3213 self.verify_capture_out(capture, ignore_port=True)
3215 # send out2in again, with sessions created it should work now
3216 pkts_out2in = self.create_stream_out(self.pg1)
3217 capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
3219 self.verify_capture_in(capture, self.pg0)
3221 # Create an ACL blocking everything
3222 out2in_deny_rule = AclRule(is_permit=0)
3223 out2in_acl = VppAcl(self, rules=[out2in_deny_rule])
3224 out2in_acl.add_vpp_config()
3226 # create an ACL to permit/reflect everything
3227 in2out_reflect_rule = AclRule(is_permit=2)
3228 in2out_acl = VppAcl(self, rules=[in2out_reflect_rule])
3229 in2out_acl.add_vpp_config()
3231 # apply as input acl on interface and confirm it blocks everything
3232 acl_if = VppAclInterface(self, sw_if_index=self.pg1.sw_if_index,
3233 n_input=1, acls=[out2in_acl])
3234 acl_if.add_vpp_config()
3235 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
3238 acl_if.acls = [out2in_acl, in2out_acl]
3239 acl_if.add_vpp_config()
3240 # send in2out to generate ACL state (NAT state was created earlier)
3241 capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
3243 self.verify_capture_out(capture, ignore_port=True)
3245 # send out2in again. ACL state exists so it should work now.
3246 # TCP packets with the syn flag set also need the ack flag
3247 for p in pkts_out2in:
3248 if p.haslayer(TCP) and p[TCP].flags & 0x02:
3249 p[TCP].flags |= 0x10
3250 capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
3252 self.verify_capture_in(capture, self.pg0)
3253 self.logger.info(self.vapi.cli("show trace"))
3255 def test_tcp_close(self):
3256 """ NAT44ED Close TCP session from inside network - output feature """
3257 config = self.vapi.nat44_show_running_config()
3258 old_timeouts = config.timeouts
3260 self.vapi.nat_set_timeouts(
3261 udp=old_timeouts.udp,
3262 tcp_established=old_timeouts.tcp_established,
3263 icmp=old_timeouts.icmp,
3264 tcp_transitory=new_transitory)
3266 self.vapi.nat44_forwarding_enable_disable(enable=1)
3267 self.nat_add_address(self.pg1.local_ip4)
3268 twice_nat_addr = '10.0.1.3'
3269 service_ip = '192.168.16.150'
3270 self.nat_add_address(twice_nat_addr, twice_nat=1)
3272 flags = self.config_flags.NAT_IS_INSIDE
3273 self.vapi.nat44_interface_add_del_feature(
3274 sw_if_index=self.pg0.sw_if_index,
3276 self.vapi.nat44_interface_add_del_feature(
3277 sw_if_index=self.pg0.sw_if_index,
3278 flags=flags, is_add=1)
3279 self.vapi.nat44_ed_add_del_output_interface(
3281 sw_if_index=self.pg1.sw_if_index)
3283 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
3284 self.config_flags.NAT_IS_TWICE_NAT)
3285 self.nat_add_static_mapping(self.pg0.remote_ip4,
3287 proto=IP_PROTOS.tcp,
3289 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3290 start_sessnum = len(sessions)
3292 # SYN packet out->in
3293 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3294 IP(src=self.pg1.remote_ip4, dst=service_ip) /
3295 TCP(sport=33898, dport=80, flags="S"))
3296 capture = self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
3298 tcp_port = p[TCP].sport
3300 # SYN + ACK packet in->out
3301 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3302 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
3303 TCP(sport=80, dport=tcp_port, flags="SA"))
3304 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
3306 # ACK packet out->in
3307 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3308 IP(src=self.pg1.remote_ip4, dst=service_ip) /
3309 TCP(sport=33898, dport=80, flags="A"))
3310 self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
3312 # FIN packet in -> out
3313 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3314 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
3315 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
3316 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
3318 # FIN+ACK packet out -> in
3319 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3320 IP(src=self.pg1.remote_ip4, dst=service_ip) /
3321 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
3322 self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
3324 # ACK packet in -> out
3325 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3326 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
3327 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
3328 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
3330 # session now in transitory timeout, but traffic still flows
3331 # try FIN packet out->in
3332 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3333 IP(src=self.pg1.remote_ip4, dst=service_ip) /
3334 TCP(sport=33898, dport=80, flags="F"))
3335 self.pg1.add_stream(p)
3336 self.pg_enable_capture(self.pg_interfaces)
3339 self.virtual_sleep(new_transitory, "wait for transitory timeout")
3340 self.pg0.get_capture(1)
3342 # session should still exist
3343 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3344 self.assertEqual(len(sessions) - start_sessnum, 1)
3346 # send FIN+ACK packet out -> in - will cause session to be wiped
3347 # but won't create a new session
3348 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3349 IP(src=self.pg1.remote_ip4, dst=service_ip) /
3350 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
3351 self.send_and_assert_no_replies(self.pg1, p)
3352 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3353 self.assertEqual(len(sessions) - start_sessnum, 0)
3355 def test_tcp_session_close_in(self):
3356 """ NAT44ED Close TCP session from inside network """
3358 in_port = self.tcp_port_in
3360 ext_port = self.tcp_external_port
3362 self.nat_add_address(self.nat_addr)
3363 self.nat_add_inside_interface(self.pg0)
3364 self.nat_add_outside_interface(self.pg1)
3365 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3366 in_port, out_port, proto=IP_PROTOS.tcp,
3367 flags=self.config_flags.NAT_IS_TWICE_NAT)
3369 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3370 session_n = len(sessions)
3372 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3373 tcp_transitory=2, icmp=5)
3375 self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3377 # FIN packet in -> out
3378 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3379 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3380 TCP(sport=in_port, dport=ext_port,
3381 flags="FA", seq=100, ack=300))
3382 self.send_and_expect(self.pg0, p, self.pg1)
3385 # ACK packet out -> in
3386 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3387 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3388 TCP(sport=ext_port, dport=out_port,
3389 flags="A", seq=300, ack=101))
3392 # FIN packet out -> in
3393 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3394 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3395 TCP(sport=ext_port, dport=out_port,
3396 flags="FA", seq=300, ack=101))
3399 self.send_and_expect(self.pg1, pkts, self.pg0)
3401 # ACK packet in -> out
3402 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3403 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3404 TCP(sport=in_port, dport=ext_port,
3405 flags="A", seq=101, ack=301))
3406 self.send_and_expect(self.pg0, p, self.pg1)
3408 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3409 self.assertEqual(len(sessions) - session_n, 1)
3411 # retransmit FIN packet out -> in
3412 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3413 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3414 TCP(sport=ext_port, dport=out_port,
3415 flags="FA", seq=300, ack=101))
3417 self.send_and_expect(self.pg1, p, self.pg0)
3419 # retransmit ACK packet in -> out
3420 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3421 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3422 TCP(sport=in_port, dport=ext_port,
3423 flags="A", seq=101, ack=301))
3424 self.send_and_expect(self.pg0, p, self.pg1)
3426 self.virtual_sleep(3)
3427 # retransmit ACK packet in -> out - this will cause session to be wiped
3428 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3429 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3430 TCP(sport=in_port, dport=ext_port,
3431 flags="A", seq=101, ack=301))
3432 self.send_and_assert_no_replies(self.pg0, p)
3433 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3434 self.assertEqual(len(sessions) - session_n, 0)
3436 def test_tcp_session_close_out(self):
3437 """ NAT44ED Close TCP session from outside network """
3439 in_port = self.tcp_port_in
3441 ext_port = self.tcp_external_port
3443 self.nat_add_address(self.nat_addr)
3444 self.nat_add_inside_interface(self.pg0)
3445 self.nat_add_outside_interface(self.pg1)
3446 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3447 in_port, out_port, proto=IP_PROTOS.tcp,
3448 flags=self.config_flags.NAT_IS_TWICE_NAT)
3450 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3451 session_n = len(sessions)
3453 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3454 tcp_transitory=2, icmp=5)
3456 _ = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3458 # FIN packet out -> in
3459 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3460 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3461 TCP(sport=ext_port, dport=out_port,
3462 flags="FA", seq=100, ack=300))
3463 self.pg1.add_stream(p)
3464 self.pg_enable_capture(self.pg_interfaces)
3466 self.pg0.get_capture(1)
3468 # FIN+ACK packet in -> out
3469 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3470 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3471 TCP(sport=in_port, dport=ext_port,
3472 flags="FA", seq=300, ack=101))
3474 self.pg0.add_stream(p)
3475 self.pg_enable_capture(self.pg_interfaces)
3477 self.pg1.get_capture(1)
3479 # ACK packet out -> in
3480 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3481 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3482 TCP(sport=ext_port, dport=out_port,
3483 flags="A", seq=101, ack=301))
3484 self.pg1.add_stream(p)
3485 self.pg_enable_capture(self.pg_interfaces)
3487 self.pg0.get_capture(1)
3489 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3490 self.assertEqual(len(sessions) - session_n, 1)
3492 # retransmit FIN packet out -> in
3493 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3494 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3495 TCP(sport=ext_port, dport=out_port,
3496 flags="FA", seq=300, ack=101))
3497 self.send_and_expect(self.pg1, p, self.pg0)
3499 # retransmit ACK packet in -> out
3500 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3501 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3502 TCP(sport=in_port, dport=ext_port,
3503 flags="A", seq=101, ack=301))
3504 self.send_and_expect(self.pg0, p, self.pg1)
3506 self.virtual_sleep(3)
3507 # retransmit ACK packet in -> out - this will cause session to be wiped
3508 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3509 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3510 TCP(sport=in_port, dport=ext_port,
3511 flags="A", seq=101, ack=301))
3512 self.send_and_assert_no_replies(self.pg0, p)
3513 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3514 self.assertEqual(len(sessions) - session_n, 0)
3516 def test_tcp_session_close_simultaneous(self):
3517 """ Simultaneous TCP close from both sides """
3519 in_port = self.tcp_port_in
3522 self.nat_add_address(self.nat_addr)
3523 self.nat_add_inside_interface(self.pg0)
3524 self.nat_add_outside_interface(self.pg1)
3525 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3526 in_port, ext_port, proto=IP_PROTOS.tcp,
3527 flags=self.config_flags.NAT_IS_TWICE_NAT)
3529 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3530 session_n = len(sessions)
3532 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3533 tcp_transitory=2, icmp=5)
3535 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3537 # FIN packet in -> out
3538 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3539 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3540 TCP(sport=in_port, dport=ext_port,
3541 flags="FA", seq=100, ack=300))
3542 self.send_and_expect(self.pg0, p, self.pg1)
3544 # FIN packet out -> in
3545 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3546 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3547 TCP(sport=ext_port, dport=out_port,
3548 flags="FA", seq=300, ack=100))
3549 self.send_and_expect(self.pg1, p, self.pg0)
3551 # ACK packet in -> out
3552 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3553 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3554 TCP(sport=in_port, dport=ext_port,
3555 flags="A", seq=101, ack=301))
3556 self.send_and_expect(self.pg0, p, self.pg1)
3558 # ACK packet out -> in
3559 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3560 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3561 TCP(sport=ext_port, dport=out_port,
3562 flags="A", seq=301, ack=101))
3563 self.send_and_expect(self.pg1, p, self.pg0)
3565 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3566 self.assertEqual(len(sessions) - session_n, 1)
3568 # retransmit FIN packet out -> in
3569 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3570 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3571 TCP(sport=ext_port, dport=out_port,
3572 flags="FA", seq=300, ack=101))
3573 self.send_and_expect(self.pg1, p, self.pg0)
3575 # retransmit ACK packet in -> out
3576 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3577 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3578 TCP(sport=in_port, dport=ext_port,
3579 flags="A", seq=101, ack=301))
3580 self.send_and_expect(self.pg0, p, self.pg1)
3582 self.virtual_sleep(3)
3583 # retransmit ACK packet in -> out - this will cause session to be wiped
3584 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3585 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3586 TCP(sport=in_port, dport=ext_port,
3587 flags="A", seq=101, ack=301))
3588 self.pg_send(self.pg0, p)
3589 self.send_and_assert_no_replies(self.pg0, p)
3590 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3591 self.assertEqual(len(sessions) - session_n, 0)
3593 def test_tcp_session_half_reopen_inside(self):
3594 """ TCP session in FIN/FIN state not reopened by in2out SYN only """
3595 in_port = self.tcp_port_in
3598 self.nat_add_address(self.nat_addr)
3599 self.nat_add_inside_interface(self.pg0)
3600 self.nat_add_outside_interface(self.pg1)
3601 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3602 in_port, ext_port, proto=IP_PROTOS.tcp,
3603 flags=self.config_flags.NAT_IS_TWICE_NAT)
3605 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3606 session_n = len(sessions)
3608 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3609 tcp_transitory=2, icmp=5)
3611 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3613 # FIN packet in -> out
3614 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3615 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3616 TCP(sport=in_port, dport=ext_port,
3617 flags="FA", seq=100, ack=300))
3618 self.send_and_expect(self.pg0, p, self.pg1)
3620 # FIN packet out -> in
3621 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3622 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3623 TCP(sport=ext_port, dport=out_port,
3624 flags="FA", seq=300, ack=100))
3625 self.send_and_expect(self.pg1, p, self.pg0)
3627 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3628 self.assertEqual(len(sessions) - session_n, 1)
3630 # send SYN packet in -> out
3631 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3632 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3633 TCP(sport=in_port, dport=ext_port,
3634 flags="S", seq=101, ack=301))
3635 self.send_and_expect(self.pg0, p, self.pg1)
3637 self.virtual_sleep(3)
3638 # send ACK packet in -> out - session should be wiped
3639 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3640 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3641 TCP(sport=in_port, dport=ext_port,
3642 flags="A", seq=101, ack=301))
3643 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
3644 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3645 self.assertEqual(len(sessions) - session_n, 0)
3647 def test_tcp_session_half_reopen_outside(self):
3648 """ TCP session in FIN/FIN state not reopened by out2in SYN only """
3649 in_port = self.tcp_port_in
3652 self.nat_add_address(self.nat_addr)
3653 self.nat_add_inside_interface(self.pg0)
3654 self.nat_add_outside_interface(self.pg1)
3655 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3656 in_port, ext_port, proto=IP_PROTOS.tcp,
3657 flags=self.config_flags.NAT_IS_TWICE_NAT)
3659 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3660 session_n = len(sessions)
3662 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3663 tcp_transitory=2, icmp=5)
3665 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3667 # FIN packet in -> out
3668 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3669 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3670 TCP(sport=in_port, dport=ext_port,
3671 flags="FA", seq=100, ack=300))
3672 self.send_and_expect(self.pg0, p, self.pg1)
3674 # FIN packet out -> in
3675 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3676 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3677 TCP(sport=ext_port, dport=out_port,
3678 flags="FA", seq=300, ack=100))
3679 self.send_and_expect(self.pg1, p, self.pg0)
3681 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3682 self.assertEqual(len(sessions) - session_n, 1)
3684 # send SYN packet out -> in
3685 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3686 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3687 TCP(sport=ext_port, dport=out_port,
3688 flags="S", seq=300, ack=101))
3689 self.send_and_expect(self.pg1, p, self.pg0)
3691 self.virtual_sleep(3)
3692 # send ACK packet in -> out - session should be wiped
3693 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3694 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3695 TCP(sport=in_port, dport=ext_port,
3696 flags="A", seq=101, ack=301))
3697 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
3698 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3699 self.assertEqual(len(sessions) - session_n, 0)
3701 def test_tcp_session_reopen(self):
3702 """ TCP session in FIN/FIN state reopened by SYN from both sides """
3703 in_port = self.tcp_port_in
3706 self.nat_add_address(self.nat_addr)
3707 self.nat_add_inside_interface(self.pg0)
3708 self.nat_add_outside_interface(self.pg1)
3709 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3710 in_port, ext_port, proto=IP_PROTOS.tcp,
3711 flags=self.config_flags.NAT_IS_TWICE_NAT)
3713 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3714 session_n = len(sessions)
3716 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3717 tcp_transitory=2, icmp=5)
3719 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3721 # FIN packet in -> out
3722 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3723 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3724 TCP(sport=in_port, dport=ext_port,
3725 flags="FA", seq=100, ack=300))
3726 self.send_and_expect(self.pg0, p, self.pg1)
3728 # FIN packet out -> in
3729 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3730 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3731 TCP(sport=ext_port, dport=out_port,
3732 flags="FA", seq=300, ack=100))
3733 self.send_and_expect(self.pg1, p, self.pg0)
3735 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3736 self.assertEqual(len(sessions) - session_n, 1)
3738 # send SYN packet out -> in
3739 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3740 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3741 TCP(sport=ext_port, dport=out_port,
3742 flags="S", seq=300, ack=101))
3743 self.send_and_expect(self.pg1, p, self.pg0)
3745 # send SYN packet in -> out
3746 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3747 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3748 TCP(sport=in_port, dport=ext_port,
3749 flags="S", seq=101, ack=301))
3750 self.send_and_expect(self.pg0, p, self.pg1)
3752 self.virtual_sleep(3)
3753 # send ACK packet in -> out - should be forwarded and session alive
3754 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3755 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3756 TCP(sport=in_port, dport=ext_port,
3757 flags="A", seq=101, ack=301))
3758 self.send_and_expect(self.pg0, p, self.pg1)
3759 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3760 self.assertEqual(len(sessions) - session_n, 1)
3762 def test_dynamic_vrf(self):
3763 """ NAT44ED dynamic translation test: different VRF"""
3768 self.nat_add_address(self.nat_addr, vrf_id=vrf_id_in)
3771 self.configure_ip4_interface(self.pg7, table_id=vrf_id_in)
3772 self.configure_ip4_interface(self.pg8, table_id=vrf_id_out)
3774 self.nat_add_inside_interface(self.pg7)
3775 self.nat_add_outside_interface(self.pg8)
3777 # just basic stuff nothing special
3778 pkts = self.create_stream_in(self.pg7, self.pg8)
3779 self.pg7.add_stream(pkts)
3780 self.pg_enable_capture(self.pg_interfaces)
3782 capture = self.pg8.get_capture(len(pkts))
3783 self.verify_capture_out(capture, ignore_port=True)
3785 pkts = self.create_stream_out(self.pg8)
3786 self.pg8.add_stream(pkts)
3787 self.pg_enable_capture(self.pg_interfaces)
3789 capture = self.pg7.get_capture(len(pkts))
3790 self.verify_capture_in(capture, self.pg7)
3796 self.vapi.ip_table_add_del(is_add=0,
3797 table={'table_id': vrf_id_in})
3798 self.vapi.ip_table_add_del(is_add=0,
3799 table={'table_id': vrf_id_out})
3801 def test_dynamic_output_feature_vrf(self):
3802 """ NAT44ED dynamic translation test: output-feature, VRF"""
3804 # other then default (0)
3807 self.nat_add_address(self.nat_addr)
3808 self.vapi.nat44_ed_add_del_output_interface(
3809 sw_if_index=self.pg8.sw_if_index,
3812 self.configure_ip4_interface(self.pg7, table_id=new_vrf_id)
3813 self.configure_ip4_interface(self.pg8, table_id=new_vrf_id)
3816 tcpn = self.statistics['/nat44-ed/in2out/slowpath/tcp']
3817 udpn = self.statistics['/nat44-ed/in2out/slowpath/udp']
3818 icmpn = self.statistics['/nat44-ed/in2out/slowpath/icmp']
3819 drops = self.statistics['/nat44-ed/in2out/slowpath/drops']
3821 pkts = self.create_stream_in(self.pg7, self.pg8)
3822 self.pg7.add_stream(pkts)
3823 self.pg_enable_capture(self.pg_interfaces)
3825 capture = self.pg8.get_capture(len(pkts))
3826 self.verify_capture_out(capture, ignore_port=True)
3828 if_idx = self.pg8.sw_if_index
3829 cnt = self.statistics['/nat44-ed/in2out/slowpath/tcp']
3830 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
3831 cnt = self.statistics['/nat44-ed/in2out/slowpath/udp']
3832 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
3833 cnt = self.statistics['/nat44-ed/in2out/slowpath/icmp']
3834 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
3835 cnt = self.statistics['/nat44-ed/in2out/slowpath/drops']
3836 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
3839 tcpn = self.statistics['/nat44-ed/out2in/fastpath/tcp']
3840 udpn = self.statistics['/nat44-ed/out2in/fastpath/udp']
3841 icmpn = self.statistics['/nat44-ed/out2in/fastpath/icmp']
3842 drops = self.statistics['/nat44-ed/out2in/fastpath/drops']
3844 pkts = self.create_stream_out(self.pg8)
3845 self.pg8.add_stream(pkts)
3846 self.pg_enable_capture(self.pg_interfaces)
3848 capture = self.pg7.get_capture(len(pkts))
3849 self.verify_capture_in(capture, self.pg7)
3851 if_idx = self.pg8.sw_if_index
3852 cnt = self.statistics['/nat44-ed/out2in/fastpath/tcp']
3853 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
3854 cnt = self.statistics['/nat44-ed/out2in/fastpath/udp']
3855 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
3856 cnt = self.statistics['/nat44-ed/out2in/fastpath/icmp']
3857 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
3858 cnt = self.statistics['/nat44-ed/out2in/fastpath/drops']
3859 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
3861 sessions = self.statistics['/nat44-ed/total-sessions']
3862 self.assertEqual(sessions[:, 0].sum(), 3)
3868 self.vapi.ip_table_add_del(is_add=0,
3869 table={'table_id': new_vrf_id})
3871 def test_next_src_nat(self):
3872 """ NAT44ED On way back forward packet to nat44-in2out node. """
3874 twice_nat_addr = '10.0.1.3'
3877 post_twice_nat_port = 0
3879 self.vapi.nat44_forwarding_enable_disable(enable=1)
3880 self.nat_add_address(twice_nat_addr, twice_nat=1)
3881 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
3882 self.config_flags.NAT_IS_SELF_TWICE_NAT)
3883 self.nat_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
3884 local_port, external_port,
3885 proto=IP_PROTOS.tcp, vrf_id=1,
3887 self.vapi.nat44_interface_add_del_feature(
3888 sw_if_index=self.pg6.sw_if_index,
3891 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
3892 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
3893 TCP(sport=12345, dport=external_port))
3894 self.pg6.add_stream(p)
3895 self.pg_enable_capture(self.pg_interfaces)
3897 capture = self.pg6.get_capture(1)
3902 self.assertEqual(ip.src, twice_nat_addr)
3903 self.assertNotEqual(tcp.sport, 12345)
3904 post_twice_nat_port = tcp.sport
3905 self.assertEqual(ip.dst, self.pg6.remote_ip4)
3906 self.assertEqual(tcp.dport, local_port)
3907 self.assert_packet_checksums_valid(p)
3909 self.logger.error(ppp("Unexpected or invalid packet:", p))
3912 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
3913 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
3914 TCP(sport=local_port, dport=post_twice_nat_port))
3915 self.pg6.add_stream(p)
3916 self.pg_enable_capture(self.pg_interfaces)
3918 capture = self.pg6.get_capture(1)
3923 self.assertEqual(ip.src, self.pg1.remote_ip4)
3924 self.assertEqual(tcp.sport, external_port)
3925 self.assertEqual(ip.dst, self.pg6.remote_ip4)
3926 self.assertEqual(tcp.dport, 12345)
3927 self.assert_packet_checksums_valid(p)
3929 self.logger.error(ppp("Unexpected or invalid packet:", p))
3932 def test_one_armed_nat44_static(self):
3933 """ NAT44ED One armed NAT and 1:1 NAPT asymmetrical rule """
3935 remote_host = self.pg4.remote_hosts[0]
3936 local_host = self.pg4.remote_hosts[1]
3941 self.vapi.nat44_forwarding_enable_disable(enable=1)
3942 self.nat_add_address(self.nat_addr, twice_nat=1)
3943 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
3944 self.config_flags.NAT_IS_TWICE_NAT)
3945 self.nat_add_static_mapping(local_host.ip4, self.nat_addr,
3946 local_port, external_port,
3947 proto=IP_PROTOS.tcp, flags=flags)
3948 flags = self.config_flags.NAT_IS_INSIDE
3949 self.vapi.nat44_interface_add_del_feature(
3950 sw_if_index=self.pg4.sw_if_index,
3952 self.vapi.nat44_interface_add_del_feature(
3953 sw_if_index=self.pg4.sw_if_index,
3954 flags=flags, is_add=1)
3956 # from client to service
3957 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
3958 IP(src=remote_host.ip4, dst=self.nat_addr) /
3959 TCP(sport=12345, dport=external_port))
3960 self.pg4.add_stream(p)
3961 self.pg_enable_capture(self.pg_interfaces)
3963 capture = self.pg4.get_capture(1)
3968 self.assertEqual(ip.dst, local_host.ip4)
3969 self.assertEqual(ip.src, self.nat_addr)
3970 self.assertEqual(tcp.dport, local_port)
3971 self.assertNotEqual(tcp.sport, 12345)
3972 eh_port_in = tcp.sport
3973 self.assert_packet_checksums_valid(p)
3975 self.logger.error(ppp("Unexpected or invalid packet:", p))
3978 # from service back to client
3979 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
3980 IP(src=local_host.ip4, dst=self.nat_addr) /
3981 TCP(sport=local_port, dport=eh_port_in))
3982 self.pg4.add_stream(p)
3983 self.pg_enable_capture(self.pg_interfaces)
3985 capture = self.pg4.get_capture(1)
3990 self.assertEqual(ip.src, self.nat_addr)
3991 self.assertEqual(ip.dst, remote_host.ip4)
3992 self.assertEqual(tcp.sport, external_port)
3993 self.assertEqual(tcp.dport, 12345)
3994 self.assert_packet_checksums_valid(p)
3996 self.logger.error(ppp("Unexpected or invalid packet:", p))
3999 def test_icmp_error_fwd_outbound(self):
4000 """ NAT44ED ICMP error outbound with forwarding enabled """
4002 # Ensure that an outbound ICMP error message is properly associated
4003 # with the inbound forward bypass session it is related to.
4006 self.nat_add_address(self.nat_addr)
4007 self.nat_add_inside_interface(self.pg0)
4008 self.nat_add_outside_interface(self.pg1)
4010 # enable forwarding and initiate connection out2in
4011 self.vapi.nat44_forwarding_enable_disable(enable=1)
4012 p1 = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4013 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
4014 UDP(sport=21, dport=20) / payload)
4016 self.pg1.add_stream(p1)
4017 self.pg_enable_capture(self.pg_interfaces)
4019 capture = self.pg0.get_capture(1)[0]
4021 self.logger.info(self.vapi.cli("show nat44 sessions"))
4023 # reply with ICMP error message in2out
4024 # We cannot reliably retrieve forward bypass sessions via the API.
4025 # session dumps for a user will only look on the worker that the
4026 # user is supposed to be mapped to in2out. The forward bypass session
4027 # is not necessarily created on that worker.
4028 p2 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4029 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4030 ICMP(type='dest-unreach', code='port-unreachable') /
4033 self.pg0.add_stream(p2)
4034 self.pg_enable_capture(self.pg_interfaces)
4036 capture = self.pg1.get_capture(1)[0]
4038 self.logger.info(self.vapi.cli("show nat44 sessions"))
4040 self.logger.info(ppp("p1 packet:", p1))
4041 self.logger.info(ppp("p2 packet:", p2))
4042 self.logger.info(ppp("capture packet:", capture))
4044 def test_tcp_session_open_retransmit1(self):
4045 """ NAT44ED Open TCP session with SYN,ACK retransmit 1
4047 The client does not receive the [SYN,ACK] or the
4048 ACK from the client is lost. Therefore, the [SYN, ACK]
4049 is retransmitted by the server.
4052 in_port = self.tcp_port_in
4053 ext_port = self.tcp_external_port
4056 self.nat_add_address(self.nat_addr)
4057 self.nat_add_inside_interface(self.pg0)
4058 self.nat_add_outside_interface(self.pg1)
4060 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
4061 tcp_transitory=5, icmp=60)
4062 # SYN packet in->out
4063 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4064 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4065 TCP(sport=in_port, dport=ext_port, flags="S"))
4066 p = self.send_and_expect(self.pg0, p, self.pg1)[0]
4067 out_port = p[TCP].sport
4069 # SYN + ACK packet out->in
4070 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4071 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4072 TCP(sport=ext_port, dport=out_port, flags="SA"))
4073 self.send_and_expect(self.pg1, p, self.pg0)
4075 # ACK in->out does not arrive
4077 # resent SYN + ACK packet out->in
4078 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4079 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4080 TCP(sport=ext_port, dport=out_port, flags="SA"))
4081 self.send_and_expect(self.pg1, p, self.pg0)
4083 # ACK packet in->out
4084 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4085 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4086 TCP(sport=in_port, dport=ext_port, flags="A"))
4087 self.send_and_expect(self.pg0, p, self.pg1)
4089 # Verify that the data can be transmitted after the transitory time
4090 self.virtual_sleep(6)
4092 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4093 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4094 TCP(sport=in_port, dport=ext_port, flags="PA") /
4096 self.send_and_expect(self.pg0, p, self.pg1)
4098 def test_tcp_session_open_retransmit2(self):
4099 """ NAT44ED Open TCP session with SYN,ACK retransmit 2
4101 The ACK is lost to the server after the TCP session is opened.
4102 Data is sent by the client, then the [SYN,ACK] is
4103 retransmitted by the server.
4106 in_port = self.tcp_port_in
4107 ext_port = self.tcp_external_port
4110 self.nat_add_address(self.nat_addr)
4111 self.nat_add_inside_interface(self.pg0)
4112 self.nat_add_outside_interface(self.pg1)
4114 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
4115 tcp_transitory=5, icmp=60)
4116 # SYN packet in->out
4117 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4118 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4119 TCP(sport=in_port, dport=ext_port, flags="S"))
4120 p = self.send_and_expect(self.pg0, p, self.pg1)[0]
4121 out_port = p[TCP].sport
4123 # SYN + ACK packet out->in
4124 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4125 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4126 TCP(sport=ext_port, dport=out_port, flags="SA"))
4127 self.send_and_expect(self.pg1, p, self.pg0)
4129 # ACK packet in->out -- not received by the server
4130 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4131 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4132 TCP(sport=in_port, dport=ext_port, flags="A"))
4133 self.send_and_expect(self.pg0, p, self.pg1)
4135 # PUSH + ACK packet in->out
4136 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4137 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4138 TCP(sport=in_port, dport=ext_port, flags="PA") /
4140 self.send_and_expect(self.pg0, p, self.pg1)
4142 # resent SYN + ACK packet out->in
4143 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4144 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4145 TCP(sport=ext_port, dport=out_port, flags="SA"))
4146 self.send_and_expect(self.pg1, p, self.pg0)
4148 # resent ACK packet in->out
4149 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4150 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4151 TCP(sport=in_port, dport=ext_port, flags="A"))
4152 self.send_and_expect(self.pg0, p, self.pg1)
4154 # resent PUSH + ACK packet in->out
4155 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4156 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4157 TCP(sport=in_port, dport=ext_port, flags="PA") /
4159 self.send_and_expect(self.pg0, p, self.pg1)
4161 # ACK packet out->in
4162 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4163 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4164 TCP(sport=ext_port, dport=out_port, flags="A"))
4165 self.send_and_expect(self.pg1, p, self.pg0)
4167 # Verify that the data can be transmitted after the transitory time
4168 self.virtual_sleep(6)
4170 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4171 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4172 TCP(sport=in_port, dport=ext_port, flags="PA") /
4174 self.send_and_expect(self.pg0, p, self.pg1)
4177 if __name__ == '__main__':
4178 unittest.main(testRunner=VppTestRunner)