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 move it to
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 transitory, session should be closed 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_assert_no_replies(self.pg0, p, self.pg1)
2636 def test_dynamic_out_of_ports(self):
2637 """ NAT44ED dynamic translation test: out of ports """
2639 self.nat_add_inside_interface(self.pg0)
2640 self.nat_add_outside_interface(self.pg1)
2642 # in2out and no NAT addresses added
2643 pkts = self.create_stream_in(self.pg0, self.pg1)
2645 self.send_and_assert_no_replies(
2646 self.pg0, pkts, msg="i2o pkts",
2647 stats_diff=self.no_diff | {
2649 '/err/nat44-ed-in2out-slowpath/out of ports': len(pkts),
2651 self.pg0.sw_if_index: {
2652 '/nat44-ed/in2out/slowpath/drops': len(pkts),
2657 # in2out after NAT addresses added
2658 self.nat_add_address(self.nat_addr)
2660 tcpn, udpn, icmpn = (sum(x) for x in
2661 zip(*((TCP in p, UDP in p, ICMP in p)
2664 self.send_and_expect(
2665 self.pg0, pkts, self.pg1, msg="i2o pkts",
2666 stats_diff=self.no_diff | {
2668 '/err/nat44-ed-in2out-slowpath/out of ports': 0,
2670 self.pg0.sw_if_index: {
2671 '/nat44-ed/in2out/slowpath/drops': 0,
2672 '/nat44-ed/in2out/slowpath/tcp': tcpn,
2673 '/nat44-ed/in2out/slowpath/udp': udpn,
2674 '/nat44-ed/in2out/slowpath/icmp': icmpn,
2679 def test_unknown_proto(self):
2680 """ NAT44ED translate packet with unknown protocol """
2682 self.nat_add_address(self.nat_addr)
2683 self.nat_add_inside_interface(self.pg0)
2684 self.nat_add_outside_interface(self.pg1)
2687 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2688 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2689 TCP(sport=self.tcp_port_in, dport=20))
2690 self.pg0.add_stream(p)
2691 self.pg_enable_capture(self.pg_interfaces)
2693 p = self.pg1.get_capture(1)
2695 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
2696 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2698 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2699 TCP(sport=1234, dport=1234))
2700 self.pg0.add_stream(p)
2701 self.pg_enable_capture(self.pg_interfaces)
2703 p = self.pg1.get_capture(1)
2706 self.assertEqual(packet[IP].src, self.nat_addr)
2707 self.assertEqual(packet[IP].dst, self.pg1.remote_ip4)
2708 self.assertEqual(packet.haslayer(GRE), 1)
2709 self.assert_packet_checksums_valid(packet)
2711 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2715 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
2716 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
2718 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2719 TCP(sport=1234, dport=1234))
2720 self.pg1.add_stream(p)
2721 self.pg_enable_capture(self.pg_interfaces)
2723 p = self.pg0.get_capture(1)
2726 self.assertEqual(packet[IP].src, self.pg1.remote_ip4)
2727 self.assertEqual(packet[IP].dst, self.pg0.remote_ip4)
2728 self.assertEqual(packet.haslayer(GRE), 1)
2729 self.assert_packet_checksums_valid(packet)
2731 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2734 def test_hairpinning_unknown_proto(self):
2735 """ NAT44ED translate packet with unknown protocol - hairpinning """
2736 host = self.pg0.remote_hosts[0]
2737 server = self.pg0.remote_hosts[1]
2739 server_out_port = 8765
2740 server_nat_ip = "10.0.0.11"
2742 self.nat_add_address(self.nat_addr)
2743 self.nat_add_inside_interface(self.pg0)
2744 self.nat_add_outside_interface(self.pg1)
2746 # add static mapping for server
2747 self.nat_add_static_mapping(server.ip4, server_nat_ip)
2750 p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
2751 IP(src=host.ip4, dst=server_nat_ip) /
2752 TCP(sport=host_in_port, dport=server_out_port))
2753 self.pg0.add_stream(p)
2754 self.pg_enable_capture(self.pg_interfaces)
2756 self.pg0.get_capture(1)
2758 p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
2759 IP(src=host.ip4, dst=server_nat_ip) /
2761 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2762 TCP(sport=1234, dport=1234))
2763 self.pg0.add_stream(p)
2764 self.pg_enable_capture(self.pg_interfaces)
2766 p = self.pg0.get_capture(1)
2769 self.assertEqual(packet[IP].src, self.nat_addr)
2770 self.assertEqual(packet[IP].dst, server.ip4)
2771 self.assertEqual(packet.haslayer(GRE), 1)
2772 self.assert_packet_checksums_valid(packet)
2774 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2778 p = (Ether(dst=self.pg0.local_mac, src=server.mac) /
2779 IP(src=server.ip4, dst=self.nat_addr) /
2781 IP(src=self.pg2.remote_ip4, dst=self.pg2.remote_ip4) /
2782 TCP(sport=1234, dport=1234))
2783 self.pg0.add_stream(p)
2784 self.pg_enable_capture(self.pg_interfaces)
2786 p = self.pg0.get_capture(1)
2789 self.assertEqual(packet[IP].src, server_nat_ip)
2790 self.assertEqual(packet[IP].dst, host.ip4)
2791 self.assertEqual(packet.haslayer(GRE), 1)
2792 self.assert_packet_checksums_valid(packet)
2794 self.logger.error(ppp("Unexpected or invalid packet:", packet))
2797 def test_output_feature_and_service(self):
2798 """ NAT44ED interface output feature and services """
2799 external_addr = '1.2.3.4'
2803 self.vapi.nat44_forwarding_enable_disable(enable=1)
2804 self.nat_add_address(self.nat_addr)
2805 flags = self.config_flags.NAT_IS_ADDR_ONLY
2806 self.vapi.nat44_add_del_identity_mapping(
2807 ip_address=self.pg1.remote_ip4, sw_if_index=0xFFFFFFFF,
2808 flags=flags, is_add=1)
2809 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2810 self.nat_add_static_mapping(self.pg0.remote_ip4, external_addr,
2811 local_port, external_port,
2812 proto=IP_PROTOS.tcp, flags=flags)
2814 self.nat_add_inside_interface(self.pg0)
2815 self.nat_add_outside_interface(self.pg0)
2816 self.vapi.nat44_ed_add_del_output_interface(
2817 sw_if_index=self.pg1.sw_if_index, is_add=1)
2819 # from client to service
2820 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2821 IP(src=self.pg1.remote_ip4, dst=external_addr) /
2822 TCP(sport=12345, dport=external_port))
2823 self.pg1.add_stream(p)
2824 self.pg_enable_capture(self.pg_interfaces)
2826 capture = self.pg0.get_capture(1)
2831 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2832 self.assertEqual(tcp.dport, local_port)
2833 self.assert_packet_checksums_valid(p)
2835 self.logger.error(ppp("Unexpected or invalid packet:", p))
2838 # from service back to client
2839 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2840 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
2841 TCP(sport=local_port, dport=12345))
2842 self.pg0.add_stream(p)
2843 self.pg_enable_capture(self.pg_interfaces)
2845 capture = self.pg1.get_capture(1)
2850 self.assertEqual(ip.src, external_addr)
2851 self.assertEqual(tcp.sport, external_port)
2852 self.assert_packet_checksums_valid(p)
2854 self.logger.error(ppp("Unexpected or invalid packet:", p))
2857 # from local network host to external network
2858 pkts = self.create_stream_in(self.pg0, self.pg1)
2859 self.pg0.add_stream(pkts)
2860 self.pg_enable_capture(self.pg_interfaces)
2862 capture = self.pg1.get_capture(len(pkts))
2863 self.verify_capture_out(capture, ignore_port=True)
2864 pkts = self.create_stream_in(self.pg0, self.pg1)
2865 self.pg0.add_stream(pkts)
2866 self.pg_enable_capture(self.pg_interfaces)
2868 capture = self.pg1.get_capture(len(pkts))
2869 self.verify_capture_out(capture, ignore_port=True)
2871 # from external network back to local network host
2872 pkts = self.create_stream_out(self.pg1)
2873 self.pg1.add_stream(pkts)
2874 self.pg_enable_capture(self.pg_interfaces)
2876 capture = self.pg0.get_capture(len(pkts))
2877 self.verify_capture_in(capture, self.pg0)
2879 def test_output_feature_and_service3(self):
2880 """ NAT44ED interface output feature and DST NAT """
2881 external_addr = '1.2.3.4'
2885 self.vapi.nat44_forwarding_enable_disable(enable=1)
2886 self.nat_add_address(self.nat_addr)
2887 flags = self.config_flags.NAT_IS_OUT2IN_ONLY
2888 self.nat_add_static_mapping(self.pg1.remote_ip4, external_addr,
2889 local_port, external_port,
2890 proto=IP_PROTOS.tcp, flags=flags)
2892 self.nat_add_inside_interface(self.pg0)
2893 self.nat_add_outside_interface(self.pg0)
2894 self.vapi.nat44_ed_add_del_output_interface(
2895 sw_if_index=self.pg1.sw_if_index, is_add=1)
2897 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
2898 IP(src=self.pg0.remote_ip4, dst=external_addr) /
2899 TCP(sport=12345, dport=external_port))
2900 self.pg0.add_stream(p)
2901 self.pg_enable_capture(self.pg_interfaces)
2903 capture = self.pg1.get_capture(1)
2908 self.assertEqual(ip.src, self.pg0.remote_ip4)
2909 self.assertEqual(tcp.sport, 12345)
2910 self.assertEqual(ip.dst, self.pg1.remote_ip4)
2911 self.assertEqual(tcp.dport, local_port)
2912 self.assert_packet_checksums_valid(p)
2914 self.logger.error(ppp("Unexpected or invalid packet:", p))
2917 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2918 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
2919 TCP(sport=local_port, dport=12345))
2920 self.pg1.add_stream(p)
2921 self.pg_enable_capture(self.pg_interfaces)
2923 capture = self.pg0.get_capture(1)
2928 self.assertEqual(ip.src, external_addr)
2929 self.assertEqual(tcp.sport, external_port)
2930 self.assertEqual(ip.dst, self.pg0.remote_ip4)
2931 self.assertEqual(tcp.dport, 12345)
2932 self.assert_packet_checksums_valid(p)
2934 self.logger.error(ppp("Unexpected or invalid packet:", p))
2937 def test_self_twice_nat_lb_negative(self):
2938 """ NAT44ED Self Twice NAT local service load balancing (negative test)
2940 self.twice_nat_common(lb=True, self_twice_nat=True, same_pg=True,
2943 def test_self_twice_nat_negative(self):
2944 """ NAT44ED Self Twice NAT (negative test) """
2945 self.twice_nat_common(self_twice_nat=True)
2947 def test_static_lb_multi_clients(self):
2948 """ NAT44ED local service load balancing - multiple clients"""
2950 external_addr = self.nat_addr
2953 server1 = self.pg0.remote_hosts[0]
2954 server2 = self.pg0.remote_hosts[1]
2955 server3 = self.pg0.remote_hosts[2]
2957 locals = [{'addr': server1.ip4,
2961 {'addr': server2.ip4,
2966 flags = self.config_flags.NAT_IS_INSIDE
2967 self.vapi.nat44_interface_add_del_feature(
2968 sw_if_index=self.pg0.sw_if_index,
2969 flags=flags, is_add=1)
2970 self.vapi.nat44_interface_add_del_feature(
2971 sw_if_index=self.pg1.sw_if_index,
2974 self.nat_add_address(self.nat_addr)
2975 self.vapi.nat44_add_del_lb_static_mapping(is_add=1,
2976 external_addr=external_addr,
2977 external_port=external_port,
2978 protocol=IP_PROTOS.tcp,
2979 local_num=len(locals),
2984 clients = ip4_range(self.pg1.remote_ip4, 10, 50)
2986 for client in clients:
2987 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
2988 IP(src=client, dst=self.nat_addr) /
2989 TCP(sport=12345, dport=external_port))
2991 self.pg1.add_stream(pkts)
2992 self.pg_enable_capture(self.pg_interfaces)
2994 capture = self.pg0.get_capture(len(pkts))
2996 if p[IP].dst == server1.ip4:
3000 self.assertGreaterEqual(server1_n, server2_n)
3003 'addr': server3.ip4,
3010 self.vapi.nat44_lb_static_mapping_add_del_local(
3012 external_addr=external_addr,
3013 external_port=external_port,
3015 protocol=IP_PROTOS.tcp)
3019 clients = ip4_range(self.pg1.remote_ip4, 60, 110)
3021 for client in clients:
3022 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3023 IP(src=client, dst=self.nat_addr) /
3024 TCP(sport=12346, dport=external_port))
3026 self.assertGreater(len(pkts), 0)
3027 self.pg1.add_stream(pkts)
3028 self.pg_enable_capture(self.pg_interfaces)
3030 capture = self.pg0.get_capture(len(pkts))
3032 if p[IP].dst == server1.ip4:
3034 elif p[IP].dst == server2.ip4:
3038 self.assertGreater(server1_n, 0)
3039 self.assertGreater(server2_n, 0)
3040 self.assertGreater(server3_n, 0)
3043 'addr': server2.ip4,
3049 # remove one back-end
3050 self.vapi.nat44_lb_static_mapping_add_del_local(
3052 external_addr=external_addr,
3053 external_port=external_port,
3055 protocol=IP_PROTOS.tcp)
3059 self.pg1.add_stream(pkts)
3060 self.pg_enable_capture(self.pg_interfaces)
3062 capture = self.pg0.get_capture(len(pkts))
3064 if p[IP].dst == server1.ip4:
3066 elif p[IP].dst == server2.ip4:
3070 self.assertGreater(server1_n, 0)
3071 self.assertEqual(server2_n, 0)
3072 self.assertGreater(server3_n, 0)
3074 # put zzz in front of syslog test name so that it runs as a last test
3075 # setting syslog sender cannot be undone and if it is set, it messes
3076 # with self.send_and_assert_no_replies functionality
3077 def test_zzz_syslog_sess(self):
3078 """ NAT44ED Test syslog session creation and deletion """
3079 self.vapi.syslog_set_filter(
3080 self.syslog_severity.SYSLOG_API_SEVERITY_INFO)
3081 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
3083 self.nat_add_address(self.nat_addr)
3084 self.nat_add_inside_interface(self.pg0)
3085 self.nat_add_outside_interface(self.pg1)
3087 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3088 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3089 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
3090 self.pg0.add_stream(p)
3091 self.pg_enable_capture(self.pg_interfaces)
3093 capture = self.pg1.get_capture(1)
3094 self.tcp_port_out = capture[0][TCP].sport
3095 capture = self.pg3.get_capture(1)
3096 self.verify_syslog_sess(capture[0][Raw].load, 'SADD')
3098 self.pg_enable_capture(self.pg_interfaces)
3100 self.nat_add_address(self.nat_addr, is_add=0)
3101 capture = self.pg3.get_capture(1)
3102 self.verify_syslog_sess(capture[0][Raw].load, 'SDEL')
3104 # put zzz in front of syslog test name so that it runs as a last test
3105 # setting syslog sender cannot be undone and if it is set, it messes
3106 # with self.send_and_assert_no_replies functionality
3107 def test_zzz_syslog_sess_reopen(self):
3108 """ Syslog events for session reopen """
3109 self.vapi.syslog_set_filter(
3110 self.syslog_severity.SYSLOG_API_SEVERITY_INFO)
3111 self.vapi.syslog_set_sender(self.pg3.local_ip4, self.pg3.remote_ip4)
3113 self.nat_add_address(self.nat_addr)
3114 self.nat_add_inside_interface(self.pg0)
3115 self.nat_add_outside_interface(self.pg1)
3118 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3119 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3120 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port))
3121 capture = self.send_and_expect(self.pg0, p, self.pg1)[0]
3122 self.tcp_port_out = capture[0][TCP].sport
3123 capture = self.pg3.get_capture(1)
3124 self.verify_syslog_sess(capture[0][Raw].load, 'SADD')
3127 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3128 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3129 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
3131 self.send_and_expect(self.pg1, p, self.pg0)
3133 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3134 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3135 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3137 self.send_and_expect(self.pg0, p, self.pg1)
3140 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
3141 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3142 TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
3144 self.send_and_expect(self.pg0, p, self.pg1)
3147 p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
3148 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3149 TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
3151 self.send_and_expect(self.pg1, p, self.pg0)
3153 self.init_tcp_session(self.pg0, self.pg1, self.tcp_port_in,
3154 self.tcp_external_port)
3156 # 2 records should be produced - first one del & add
3157 capture = self.pg3.get_capture(2)
3158 self.verify_syslog_sess(capture[0][Raw].load, 'SDEL')
3159 self.verify_syslog_sess(capture[1][Raw].load, 'SADD')
3161 def test_twice_nat_interface_addr(self):
3162 """ NAT44ED Acquire twice NAT addresses from interface """
3163 flags = self.config_flags.NAT_IS_TWICE_NAT
3164 self.vapi.nat44_add_del_interface_addr(
3165 sw_if_index=self.pg11.sw_if_index,
3166 flags=flags, is_add=1)
3168 # no address in NAT pool
3169 adresses = self.vapi.nat44_address_dump()
3170 self.assertEqual(0, len(adresses))
3172 # configure interface address and check NAT address pool
3173 self.pg11.config_ip4()
3174 adresses = self.vapi.nat44_address_dump()
3175 self.assertEqual(1, len(adresses))
3176 self.assertEqual(str(adresses[0].ip_address),
3177 self.pg11.local_ip4)
3178 self.assertEqual(adresses[0].flags, flags)
3180 # remove interface address and check NAT address pool
3181 self.pg11.unconfig_ip4()
3182 adresses = self.vapi.nat44_address_dump()
3183 self.assertEqual(0, len(adresses))
3185 def test_output_feature_stateful_acl(self):
3186 """ NAT44ED output feature works with stateful ACL """
3188 self.nat_add_address(self.nat_addr)
3189 self.vapi.nat44_ed_add_del_output_interface(
3190 sw_if_index=self.pg1.sw_if_index, is_add=1)
3192 # First ensure that the NAT is working sans ACL
3194 # send packets out2in, no sessions yet so packets should drop
3195 pkts_out2in = self.create_stream_out(self.pg1)
3196 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
3198 # send packets into inside intf, ensure received via outside intf
3199 pkts_in2out = self.create_stream_in(self.pg0, self.pg1)
3200 capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
3202 self.verify_capture_out(capture, ignore_port=True)
3204 # send out2in again, with sessions created it should work now
3205 pkts_out2in = self.create_stream_out(self.pg1)
3206 capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
3208 self.verify_capture_in(capture, self.pg0)
3210 # Create an ACL blocking everything
3211 out2in_deny_rule = AclRule(is_permit=0)
3212 out2in_acl = VppAcl(self, rules=[out2in_deny_rule])
3213 out2in_acl.add_vpp_config()
3215 # create an ACL to permit/reflect everything
3216 in2out_reflect_rule = AclRule(is_permit=2)
3217 in2out_acl = VppAcl(self, rules=[in2out_reflect_rule])
3218 in2out_acl.add_vpp_config()
3220 # apply as input acl on interface and confirm it blocks everything
3221 acl_if = VppAclInterface(self, sw_if_index=self.pg1.sw_if_index,
3222 n_input=1, acls=[out2in_acl])
3223 acl_if.add_vpp_config()
3224 self.send_and_assert_no_replies(self.pg1, pkts_out2in)
3227 acl_if.acls = [out2in_acl, in2out_acl]
3228 acl_if.add_vpp_config()
3229 # send in2out to generate ACL state (NAT state was created earlier)
3230 capture = self.send_and_expect(self.pg0, pkts_in2out, self.pg1,
3232 self.verify_capture_out(capture, ignore_port=True)
3234 # send out2in again. ACL state exists so it should work now.
3235 # TCP packets with the syn flag set also need the ack flag
3236 for p in pkts_out2in:
3237 if p.haslayer(TCP) and p[TCP].flags & 0x02:
3238 p[TCP].flags |= 0x10
3239 capture = self.send_and_expect(self.pg1, pkts_out2in, self.pg0,
3241 self.verify_capture_in(capture, self.pg0)
3242 self.logger.info(self.vapi.cli("show trace"))
3244 def test_tcp_close(self):
3245 """ NAT44ED Close TCP session from inside network - output feature """
3246 config = self.vapi.nat44_show_running_config()
3247 old_timeouts = config.timeouts
3249 self.vapi.nat_set_timeouts(
3250 udp=old_timeouts.udp,
3251 tcp_established=old_timeouts.tcp_established,
3252 icmp=old_timeouts.icmp,
3253 tcp_transitory=new_transitory)
3255 self.vapi.nat44_forwarding_enable_disable(enable=1)
3256 self.nat_add_address(self.pg1.local_ip4)
3257 twice_nat_addr = '10.0.1.3'
3258 service_ip = '192.168.16.150'
3259 self.nat_add_address(twice_nat_addr, twice_nat=1)
3261 flags = self.config_flags.NAT_IS_INSIDE
3262 self.vapi.nat44_interface_add_del_feature(
3263 sw_if_index=self.pg0.sw_if_index,
3265 self.vapi.nat44_interface_add_del_feature(
3266 sw_if_index=self.pg0.sw_if_index,
3267 flags=flags, is_add=1)
3268 self.vapi.nat44_ed_add_del_output_interface(
3270 sw_if_index=self.pg1.sw_if_index)
3272 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
3273 self.config_flags.NAT_IS_TWICE_NAT)
3274 self.nat_add_static_mapping(self.pg0.remote_ip4,
3276 proto=IP_PROTOS.tcp,
3278 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3279 start_sessnum = len(sessions)
3281 # SYN packet out->in
3282 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3283 IP(src=self.pg1.remote_ip4, dst=service_ip) /
3284 TCP(sport=33898, dport=80, flags="S"))
3285 capture = self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
3287 tcp_port = p[TCP].sport
3289 # SYN + ACK packet in->out
3290 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3291 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
3292 TCP(sport=80, dport=tcp_port, flags="SA"))
3293 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
3295 # ACK packet out->in
3296 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3297 IP(src=self.pg1.remote_ip4, dst=service_ip) /
3298 TCP(sport=33898, dport=80, flags="A"))
3299 self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
3301 # FIN packet in -> out
3302 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3303 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
3304 TCP(sport=80, dport=tcp_port, flags="FA", seq=100, ack=300))
3305 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
3307 # FIN+ACK packet out -> in
3308 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3309 IP(src=self.pg1.remote_ip4, dst=service_ip) /
3310 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
3311 self.send_and_expect(self.pg1, p, self.pg0, n_rx=1)
3313 # ACK packet in -> out
3314 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3315 IP(src=self.pg0.remote_ip4, dst=twice_nat_addr) /
3316 TCP(sport=80, dport=tcp_port, flags="A", seq=101, ack=301))
3317 self.send_and_expect(self.pg0, p, self.pg1, n_rx=1)
3319 # session now in transitory timeout, but traffic still flows
3320 # try FIN packet out->in
3321 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3322 IP(src=self.pg1.remote_ip4, dst=service_ip) /
3323 TCP(sport=33898, dport=80, flags="F"))
3324 self.pg1.add_stream(p)
3325 self.pg_enable_capture(self.pg_interfaces)
3328 self.virtual_sleep(new_transitory, "wait for transitory timeout")
3329 self.pg0.get_capture(1)
3331 # session should still exist
3332 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3333 self.assertEqual(len(sessions) - start_sessnum, 1)
3335 # send FIN+ACK packet out -> in - will cause session to be wiped
3336 # but won't create a new session
3337 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3338 IP(src=self.pg1.remote_ip4, dst=service_ip) /
3339 TCP(sport=33898, dport=80, flags="FA", seq=300, ack=101))
3340 self.send_and_assert_no_replies(self.pg1, p)
3341 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3342 self.assertEqual(len(sessions) - start_sessnum, 0)
3344 def test_tcp_session_close_in(self):
3345 """ NAT44ED Close TCP session from inside network """
3347 in_port = self.tcp_port_in
3349 ext_port = self.tcp_external_port
3351 self.nat_add_address(self.nat_addr)
3352 self.nat_add_inside_interface(self.pg0)
3353 self.nat_add_outside_interface(self.pg1)
3354 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3355 in_port, out_port, proto=IP_PROTOS.tcp,
3356 flags=self.config_flags.NAT_IS_TWICE_NAT)
3358 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3359 session_n = len(sessions)
3361 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3362 tcp_transitory=2, icmp=5)
3364 self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3366 # FIN packet in -> out
3367 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3368 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3369 TCP(sport=in_port, dport=ext_port,
3370 flags="FA", seq=100, ack=300))
3371 self.send_and_expect(self.pg0, p, self.pg1)
3374 # ACK packet out -> in
3375 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3376 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3377 TCP(sport=ext_port, dport=out_port,
3378 flags="A", seq=300, ack=101))
3381 # FIN packet out -> in
3382 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3383 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3384 TCP(sport=ext_port, dport=out_port,
3385 flags="FA", seq=300, ack=101))
3388 self.send_and_expect(self.pg1, pkts, self.pg0)
3390 # ACK packet in -> out
3391 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3392 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3393 TCP(sport=in_port, dport=ext_port,
3394 flags="A", seq=101, ack=301))
3395 self.send_and_expect(self.pg0, p, self.pg1)
3397 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3398 self.assertEqual(len(sessions) - session_n, 1)
3400 # retransmit FIN packet out -> in
3401 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3402 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3403 TCP(sport=ext_port, dport=out_port,
3404 flags="FA", seq=300, ack=101))
3406 self.send_and_expect(self.pg1, p, self.pg0)
3408 # retransmit ACK packet in -> out
3409 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3410 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3411 TCP(sport=in_port, dport=ext_port,
3412 flags="A", seq=101, ack=301))
3413 self.send_and_expect(self.pg0, p, self.pg1)
3415 self.virtual_sleep(3)
3416 # retransmit ACK packet in -> out - this will cause session to be wiped
3417 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3418 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3419 TCP(sport=in_port, dport=ext_port,
3420 flags="A", seq=101, ack=301))
3421 self.send_and_assert_no_replies(self.pg0, p)
3422 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3423 self.assertEqual(len(sessions) - session_n, 0)
3425 def test_tcp_session_close_out(self):
3426 """ NAT44ED Close TCP session from outside network """
3428 in_port = self.tcp_port_in
3430 ext_port = self.tcp_external_port
3432 self.nat_add_address(self.nat_addr)
3433 self.nat_add_inside_interface(self.pg0)
3434 self.nat_add_outside_interface(self.pg1)
3435 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3436 in_port, out_port, proto=IP_PROTOS.tcp,
3437 flags=self.config_flags.NAT_IS_TWICE_NAT)
3439 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3440 session_n = len(sessions)
3442 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3443 tcp_transitory=2, icmp=5)
3445 _ = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3447 # FIN packet out -> in
3448 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3449 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3450 TCP(sport=ext_port, dport=out_port,
3451 flags="FA", seq=100, ack=300))
3452 self.pg1.add_stream(p)
3453 self.pg_enable_capture(self.pg_interfaces)
3455 self.pg0.get_capture(1)
3457 # FIN+ACK packet in -> out
3458 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3459 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3460 TCP(sport=in_port, dport=ext_port,
3461 flags="FA", seq=300, ack=101))
3463 self.pg0.add_stream(p)
3464 self.pg_enable_capture(self.pg_interfaces)
3466 self.pg1.get_capture(1)
3468 # ACK packet out -> in
3469 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3470 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3471 TCP(sport=ext_port, dport=out_port,
3472 flags="A", seq=101, ack=301))
3473 self.pg1.add_stream(p)
3474 self.pg_enable_capture(self.pg_interfaces)
3476 self.pg0.get_capture(1)
3478 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3479 self.assertEqual(len(sessions) - session_n, 1)
3481 # retransmit FIN packet out -> in
3482 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3483 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3484 TCP(sport=ext_port, dport=out_port,
3485 flags="FA", seq=300, ack=101))
3486 self.send_and_expect(self.pg1, p, self.pg0)
3488 # retransmit ACK packet in -> out
3489 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3490 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3491 TCP(sport=in_port, dport=ext_port,
3492 flags="A", seq=101, ack=301))
3493 self.send_and_expect(self.pg0, p, self.pg1)
3495 self.virtual_sleep(3)
3496 # retransmit ACK packet in -> out - this will cause session to be wiped
3497 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3498 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3499 TCP(sport=in_port, dport=ext_port,
3500 flags="A", seq=101, ack=301))
3501 self.send_and_assert_no_replies(self.pg0, p)
3502 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3503 self.assertEqual(len(sessions) - session_n, 0)
3505 def test_tcp_session_close_simultaneous(self):
3506 """ Simultaneous TCP close from both sides """
3508 in_port = self.tcp_port_in
3511 self.nat_add_address(self.nat_addr)
3512 self.nat_add_inside_interface(self.pg0)
3513 self.nat_add_outside_interface(self.pg1)
3514 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3515 in_port, ext_port, proto=IP_PROTOS.tcp,
3516 flags=self.config_flags.NAT_IS_TWICE_NAT)
3518 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3519 session_n = len(sessions)
3521 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3522 tcp_transitory=2, icmp=5)
3524 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3526 # FIN packet in -> out
3527 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3528 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3529 TCP(sport=in_port, dport=ext_port,
3530 flags="FA", seq=100, ack=300))
3531 self.send_and_expect(self.pg0, p, self.pg1)
3533 # FIN packet out -> in
3534 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3535 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3536 TCP(sport=ext_port, dport=out_port,
3537 flags="FA", seq=300, ack=100))
3538 self.send_and_expect(self.pg1, p, self.pg0)
3540 # ACK packet in -> out
3541 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3542 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3543 TCP(sport=in_port, dport=ext_port,
3544 flags="A", seq=101, ack=301))
3545 self.send_and_expect(self.pg0, p, self.pg1)
3547 # ACK packet out -> in
3548 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3549 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3550 TCP(sport=ext_port, dport=out_port,
3551 flags="A", seq=301, ack=101))
3552 self.send_and_expect(self.pg1, p, self.pg0)
3554 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3555 self.assertEqual(len(sessions) - session_n, 1)
3557 # retransmit FIN packet out -> in
3558 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3559 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3560 TCP(sport=ext_port, dport=out_port,
3561 flags="FA", seq=300, ack=101))
3562 self.send_and_expect(self.pg1, p, self.pg0)
3564 # retransmit ACK packet in -> out
3565 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3566 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3567 TCP(sport=in_port, dport=ext_port,
3568 flags="A", seq=101, ack=301))
3569 self.send_and_expect(self.pg0, p, self.pg1)
3571 self.virtual_sleep(3)
3572 # retransmit ACK packet in -> out - this will cause session to be wiped
3573 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3574 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3575 TCP(sport=in_port, dport=ext_port,
3576 flags="A", seq=101, ack=301))
3577 self.pg_send(self.pg0, p)
3578 self.send_and_assert_no_replies(self.pg0, p)
3579 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3580 self.assertEqual(len(sessions) - session_n, 0)
3582 def test_tcp_session_half_reopen_inside(self):
3583 """ TCP session in FIN/FIN state not reopened by in2out SYN only """
3584 in_port = self.tcp_port_in
3587 self.nat_add_address(self.nat_addr)
3588 self.nat_add_inside_interface(self.pg0)
3589 self.nat_add_outside_interface(self.pg1)
3590 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3591 in_port, ext_port, proto=IP_PROTOS.tcp,
3592 flags=self.config_flags.NAT_IS_TWICE_NAT)
3594 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3595 session_n = len(sessions)
3597 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3598 tcp_transitory=2, icmp=5)
3600 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3602 # FIN packet in -> out
3603 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3604 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3605 TCP(sport=in_port, dport=ext_port,
3606 flags="FA", seq=100, ack=300))
3607 self.send_and_expect(self.pg0, p, self.pg1)
3609 # FIN packet out -> in
3610 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3611 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3612 TCP(sport=ext_port, dport=out_port,
3613 flags="FA", seq=300, ack=100))
3614 self.send_and_expect(self.pg1, p, self.pg0)
3616 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3617 self.assertEqual(len(sessions) - session_n, 1)
3619 # send SYN packet in -> out
3620 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3621 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3622 TCP(sport=in_port, dport=ext_port,
3623 flags="S", seq=101, ack=301))
3624 self.send_and_expect(self.pg0, p, self.pg1)
3626 self.virtual_sleep(3)
3627 # send ACK packet in -> out - session should be wiped
3628 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3629 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3630 TCP(sport=in_port, dport=ext_port,
3631 flags="A", seq=101, ack=301))
3632 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
3633 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3634 self.assertEqual(len(sessions) - session_n, 0)
3636 def test_tcp_session_half_reopen_outside(self):
3637 """ TCP session in FIN/FIN state not reopened by out2in SYN only """
3638 in_port = self.tcp_port_in
3641 self.nat_add_address(self.nat_addr)
3642 self.nat_add_inside_interface(self.pg0)
3643 self.nat_add_outside_interface(self.pg1)
3644 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3645 in_port, ext_port, proto=IP_PROTOS.tcp,
3646 flags=self.config_flags.NAT_IS_TWICE_NAT)
3648 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3649 session_n = len(sessions)
3651 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3652 tcp_transitory=2, icmp=5)
3654 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3656 # FIN packet in -> out
3657 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3658 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3659 TCP(sport=in_port, dport=ext_port,
3660 flags="FA", seq=100, ack=300))
3661 self.send_and_expect(self.pg0, p, self.pg1)
3663 # FIN packet out -> in
3664 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3665 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3666 TCP(sport=ext_port, dport=out_port,
3667 flags="FA", seq=300, ack=100))
3668 self.send_and_expect(self.pg1, p, self.pg0)
3670 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3671 self.assertEqual(len(sessions) - session_n, 1)
3673 # send SYN packet out -> in
3674 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3675 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3676 TCP(sport=ext_port, dport=out_port,
3677 flags="S", seq=300, ack=101))
3678 self.send_and_expect(self.pg1, p, self.pg0)
3680 self.virtual_sleep(3)
3681 # send ACK packet in -> out - session should be wiped
3682 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3683 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3684 TCP(sport=in_port, dport=ext_port,
3685 flags="A", seq=101, ack=301))
3686 self.send_and_assert_no_replies(self.pg0, p, self.pg1)
3687 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3688 self.assertEqual(len(sessions) - session_n, 0)
3690 def test_tcp_session_reopen(self):
3691 """ TCP session in FIN/FIN state reopened by SYN from both sides """
3692 in_port = self.tcp_port_in
3695 self.nat_add_address(self.nat_addr)
3696 self.nat_add_inside_interface(self.pg0)
3697 self.nat_add_outside_interface(self.pg1)
3698 self.nat_add_static_mapping(self.pg0.remote_ip4, self.nat_addr,
3699 in_port, ext_port, proto=IP_PROTOS.tcp,
3700 flags=self.config_flags.NAT_IS_TWICE_NAT)
3702 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3703 session_n = len(sessions)
3705 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
3706 tcp_transitory=2, icmp=5)
3708 out_port = self.init_tcp_session(self.pg0, self.pg1, in_port, ext_port)
3710 # FIN packet in -> out
3711 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3712 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3713 TCP(sport=in_port, dport=ext_port,
3714 flags="FA", seq=100, ack=300))
3715 self.send_and_expect(self.pg0, p, self.pg1)
3717 # FIN packet out -> in
3718 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3719 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3720 TCP(sport=ext_port, dport=out_port,
3721 flags="FA", seq=300, ack=100))
3722 self.send_and_expect(self.pg1, p, self.pg0)
3724 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3725 self.assertEqual(len(sessions) - session_n, 1)
3727 # send SYN packet out -> in
3728 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3729 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3730 TCP(sport=ext_port, dport=out_port,
3731 flags="S", seq=300, ack=101))
3732 self.send_and_expect(self.pg1, p, self.pg0)
3734 # send SYN packet in -> out
3735 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3736 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3737 TCP(sport=in_port, dport=ext_port,
3738 flags="SA", seq=101, ack=301))
3739 self.send_and_expect(self.pg0, p, self.pg1)
3741 # send ACK packet out -> in
3742 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
3743 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
3744 TCP(sport=ext_port, dport=out_port,
3745 flags="A", seq=300, ack=101))
3746 self.send_and_expect(self.pg1, p, self.pg0)
3748 self.virtual_sleep(3)
3749 # send ACK packet in -> out - should be forwarded and session alive
3750 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
3751 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
3752 TCP(sport=in_port, dport=ext_port,
3753 flags="A", seq=101, ack=301))
3754 self.send_and_expect(self.pg0, p, self.pg1)
3755 sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4, 0)
3756 self.assertEqual(len(sessions) - session_n, 1)
3758 def test_dynamic_vrf(self):
3759 """ NAT44ED dynamic translation test: different VRF"""
3764 self.nat_add_address(self.nat_addr, vrf_id=vrf_id_in)
3767 self.configure_ip4_interface(self.pg7, table_id=vrf_id_in)
3768 self.configure_ip4_interface(self.pg8, table_id=vrf_id_out)
3770 self.nat_add_inside_interface(self.pg7)
3771 self.nat_add_outside_interface(self.pg8)
3773 # just basic stuff nothing special
3774 pkts = self.create_stream_in(self.pg7, self.pg8)
3775 self.pg7.add_stream(pkts)
3776 self.pg_enable_capture(self.pg_interfaces)
3778 capture = self.pg8.get_capture(len(pkts))
3779 self.verify_capture_out(capture, ignore_port=True)
3781 pkts = self.create_stream_out(self.pg8)
3782 self.pg8.add_stream(pkts)
3783 self.pg_enable_capture(self.pg_interfaces)
3785 capture = self.pg7.get_capture(len(pkts))
3786 self.verify_capture_in(capture, self.pg7)
3792 self.vapi.ip_table_add_del(is_add=0,
3793 table={'table_id': vrf_id_in})
3794 self.vapi.ip_table_add_del(is_add=0,
3795 table={'table_id': vrf_id_out})
3797 def test_dynamic_output_feature_vrf(self):
3798 """ NAT44ED dynamic translation test: output-feature, VRF"""
3800 # other then default (0)
3803 self.nat_add_address(self.nat_addr)
3804 self.vapi.nat44_ed_add_del_output_interface(
3805 sw_if_index=self.pg8.sw_if_index,
3808 self.configure_ip4_interface(self.pg7, table_id=new_vrf_id)
3809 self.configure_ip4_interface(self.pg8, table_id=new_vrf_id)
3812 tcpn = self.statistics['/nat44-ed/in2out/slowpath/tcp']
3813 udpn = self.statistics['/nat44-ed/in2out/slowpath/udp']
3814 icmpn = self.statistics['/nat44-ed/in2out/slowpath/icmp']
3815 drops = self.statistics['/nat44-ed/in2out/slowpath/drops']
3817 pkts = self.create_stream_in(self.pg7, self.pg8)
3818 self.pg7.add_stream(pkts)
3819 self.pg_enable_capture(self.pg_interfaces)
3821 capture = self.pg8.get_capture(len(pkts))
3822 self.verify_capture_out(capture, ignore_port=True)
3824 if_idx = self.pg8.sw_if_index
3825 cnt = self.statistics['/nat44-ed/in2out/slowpath/tcp']
3826 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
3827 cnt = self.statistics['/nat44-ed/in2out/slowpath/udp']
3828 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
3829 cnt = self.statistics['/nat44-ed/in2out/slowpath/icmp']
3830 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
3831 cnt = self.statistics['/nat44-ed/in2out/slowpath/drops']
3832 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
3835 tcpn = self.statistics['/nat44-ed/out2in/fastpath/tcp']
3836 udpn = self.statistics['/nat44-ed/out2in/fastpath/udp']
3837 icmpn = self.statistics['/nat44-ed/out2in/fastpath/icmp']
3838 drops = self.statistics['/nat44-ed/out2in/fastpath/drops']
3840 pkts = self.create_stream_out(self.pg8)
3841 self.pg8.add_stream(pkts)
3842 self.pg_enable_capture(self.pg_interfaces)
3844 capture = self.pg7.get_capture(len(pkts))
3845 self.verify_capture_in(capture, self.pg7)
3847 if_idx = self.pg8.sw_if_index
3848 cnt = self.statistics['/nat44-ed/out2in/fastpath/tcp']
3849 self.assertEqual(cnt[:, if_idx].sum() - tcpn[:, if_idx].sum(), 2)
3850 cnt = self.statistics['/nat44-ed/out2in/fastpath/udp']
3851 self.assertEqual(cnt[:, if_idx].sum() - udpn[:, if_idx].sum(), 1)
3852 cnt = self.statistics['/nat44-ed/out2in/fastpath/icmp']
3853 self.assertEqual(cnt[:, if_idx].sum() - icmpn[:, if_idx].sum(), 1)
3854 cnt = self.statistics['/nat44-ed/out2in/fastpath/drops']
3855 self.assertEqual(cnt[:, if_idx].sum() - drops[:, if_idx].sum(), 0)
3857 sessions = self.statistics['/nat44-ed/total-sessions']
3858 self.assertEqual(sessions[:, 0].sum(), 3)
3864 self.vapi.ip_table_add_del(is_add=0,
3865 table={'table_id': new_vrf_id})
3867 def test_next_src_nat(self):
3868 """ NAT44ED On way back forward packet to nat44-in2out node. """
3870 twice_nat_addr = '10.0.1.3'
3873 post_twice_nat_port = 0
3875 self.vapi.nat44_forwarding_enable_disable(enable=1)
3876 self.nat_add_address(twice_nat_addr, twice_nat=1)
3877 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
3878 self.config_flags.NAT_IS_SELF_TWICE_NAT)
3879 self.nat_add_static_mapping(self.pg6.remote_ip4, self.pg1.remote_ip4,
3880 local_port, external_port,
3881 proto=IP_PROTOS.tcp, vrf_id=1,
3883 self.vapi.nat44_interface_add_del_feature(
3884 sw_if_index=self.pg6.sw_if_index,
3887 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
3888 IP(src=self.pg6.remote_ip4, dst=self.pg1.remote_ip4) /
3889 TCP(sport=12345, dport=external_port))
3890 self.pg6.add_stream(p)
3891 self.pg_enable_capture(self.pg_interfaces)
3893 capture = self.pg6.get_capture(1)
3898 self.assertEqual(ip.src, twice_nat_addr)
3899 self.assertNotEqual(tcp.sport, 12345)
3900 post_twice_nat_port = tcp.sport
3901 self.assertEqual(ip.dst, self.pg6.remote_ip4)
3902 self.assertEqual(tcp.dport, local_port)
3903 self.assert_packet_checksums_valid(p)
3905 self.logger.error(ppp("Unexpected or invalid packet:", p))
3908 p = (Ether(src=self.pg6.remote_mac, dst=self.pg6.local_mac) /
3909 IP(src=self.pg6.remote_ip4, dst=twice_nat_addr) /
3910 TCP(sport=local_port, dport=post_twice_nat_port))
3911 self.pg6.add_stream(p)
3912 self.pg_enable_capture(self.pg_interfaces)
3914 capture = self.pg6.get_capture(1)
3919 self.assertEqual(ip.src, self.pg1.remote_ip4)
3920 self.assertEqual(tcp.sport, external_port)
3921 self.assertEqual(ip.dst, self.pg6.remote_ip4)
3922 self.assertEqual(tcp.dport, 12345)
3923 self.assert_packet_checksums_valid(p)
3925 self.logger.error(ppp("Unexpected or invalid packet:", p))
3928 def test_one_armed_nat44_static(self):
3929 """ NAT44ED One armed NAT and 1:1 NAPT asymmetrical rule """
3931 remote_host = self.pg4.remote_hosts[0]
3932 local_host = self.pg4.remote_hosts[1]
3937 self.vapi.nat44_forwarding_enable_disable(enable=1)
3938 self.nat_add_address(self.nat_addr, twice_nat=1)
3939 flags = (self.config_flags.NAT_IS_OUT2IN_ONLY |
3940 self.config_flags.NAT_IS_TWICE_NAT)
3941 self.nat_add_static_mapping(local_host.ip4, self.nat_addr,
3942 local_port, external_port,
3943 proto=IP_PROTOS.tcp, flags=flags)
3944 flags = self.config_flags.NAT_IS_INSIDE
3945 self.vapi.nat44_interface_add_del_feature(
3946 sw_if_index=self.pg4.sw_if_index,
3948 self.vapi.nat44_interface_add_del_feature(
3949 sw_if_index=self.pg4.sw_if_index,
3950 flags=flags, is_add=1)
3952 # from client to service
3953 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
3954 IP(src=remote_host.ip4, dst=self.nat_addr) /
3955 TCP(sport=12345, dport=external_port))
3956 self.pg4.add_stream(p)
3957 self.pg_enable_capture(self.pg_interfaces)
3959 capture = self.pg4.get_capture(1)
3964 self.assertEqual(ip.dst, local_host.ip4)
3965 self.assertEqual(ip.src, self.nat_addr)
3966 self.assertEqual(tcp.dport, local_port)
3967 self.assertNotEqual(tcp.sport, 12345)
3968 eh_port_in = tcp.sport
3969 self.assert_packet_checksums_valid(p)
3971 self.logger.error(ppp("Unexpected or invalid packet:", p))
3974 # from service back to client
3975 p = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) /
3976 IP(src=local_host.ip4, dst=self.nat_addr) /
3977 TCP(sport=local_port, dport=eh_port_in))
3978 self.pg4.add_stream(p)
3979 self.pg_enable_capture(self.pg_interfaces)
3981 capture = self.pg4.get_capture(1)
3986 self.assertEqual(ip.src, self.nat_addr)
3987 self.assertEqual(ip.dst, remote_host.ip4)
3988 self.assertEqual(tcp.sport, external_port)
3989 self.assertEqual(tcp.dport, 12345)
3990 self.assert_packet_checksums_valid(p)
3992 self.logger.error(ppp("Unexpected or invalid packet:", p))
3995 def test_icmp_error_fwd_outbound(self):
3996 """ NAT44ED ICMP error outbound with forwarding enabled """
3998 # Ensure that an outbound ICMP error message is properly associated
3999 # with the inbound forward bypass session it is related to.
4002 self.nat_add_address(self.nat_addr)
4003 self.nat_add_inside_interface(self.pg0)
4004 self.nat_add_outside_interface(self.pg1)
4006 # enable forwarding and initiate connection out2in
4007 self.vapi.nat44_forwarding_enable_disable(enable=1)
4008 p1 = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4009 IP(src=self.pg1.remote_ip4, dst=self.pg0.remote_ip4) /
4010 UDP(sport=21, dport=20) / payload)
4012 self.pg1.add_stream(p1)
4013 self.pg_enable_capture(self.pg_interfaces)
4015 capture = self.pg0.get_capture(1)[0]
4017 self.logger.info(self.vapi.cli("show nat44 sessions"))
4019 # reply with ICMP error message in2out
4020 # We cannot reliably retrieve forward bypass sessions via the API.
4021 # session dumps for a user will only look on the worker that the
4022 # user is supposed to be mapped to in2out. The forward bypass session
4023 # is not necessarily created on that worker.
4024 p2 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4025 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4026 ICMP(type='dest-unreach', code='port-unreachable') /
4029 self.pg0.add_stream(p2)
4030 self.pg_enable_capture(self.pg_interfaces)
4032 capture = self.pg1.get_capture(1)[0]
4034 self.logger.info(self.vapi.cli("show nat44 sessions"))
4036 self.logger.info(ppp("p1 packet:", p1))
4037 self.logger.info(ppp("p2 packet:", p2))
4038 self.logger.info(ppp("capture packet:", capture))
4040 def test_tcp_session_open_retransmit1(self):
4041 """ NAT44ED Open TCP session with SYN,ACK retransmit 1
4043 The client does not receive the [SYN,ACK] or the
4044 ACK from the client is lost. Therefore, the [SYN, ACK]
4045 is retransmitted by the server.
4048 in_port = self.tcp_port_in
4049 ext_port = self.tcp_external_port
4052 self.nat_add_address(self.nat_addr)
4053 self.nat_add_inside_interface(self.pg0)
4054 self.nat_add_outside_interface(self.pg1)
4056 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
4057 tcp_transitory=5, icmp=60)
4058 # SYN packet in->out
4059 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4060 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4061 TCP(sport=in_port, dport=ext_port, flags="S"))
4062 p = self.send_and_expect(self.pg0, p, self.pg1)[0]
4063 out_port = p[TCP].sport
4065 # SYN + ACK packet out->in
4066 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4067 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4068 TCP(sport=ext_port, dport=out_port, flags="SA"))
4069 self.send_and_expect(self.pg1, p, self.pg0)
4071 # ACK in->out does not arrive
4073 # resent SYN + ACK packet out->in
4074 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4075 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4076 TCP(sport=ext_port, dport=out_port, flags="SA"))
4077 self.send_and_expect(self.pg1, p, self.pg0)
4079 # ACK packet in->out
4080 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4081 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4082 TCP(sport=in_port, dport=ext_port, flags="A"))
4083 self.send_and_expect(self.pg0, p, self.pg1)
4085 # Verify that the data can be transmitted after the transitory time
4086 self.virtual_sleep(6)
4088 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4089 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4090 TCP(sport=in_port, dport=ext_port, flags="PA") /
4092 self.send_and_expect(self.pg0, p, self.pg1)
4094 def test_tcp_session_open_retransmit2(self):
4095 """ NAT44ED Open TCP session with SYN,ACK retransmit 2
4097 The ACK is lost to the server after the TCP session is opened.
4098 Data is sent by the client, then the [SYN,ACK] is
4099 retransmitted by the server.
4102 in_port = self.tcp_port_in
4103 ext_port = self.tcp_external_port
4106 self.nat_add_address(self.nat_addr)
4107 self.nat_add_inside_interface(self.pg0)
4108 self.nat_add_outside_interface(self.pg1)
4110 self.vapi.nat_set_timeouts(udp=300, tcp_established=7440,
4111 tcp_transitory=5, icmp=60)
4112 # SYN packet in->out
4113 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4114 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4115 TCP(sport=in_port, dport=ext_port, flags="S"))
4116 p = self.send_and_expect(self.pg0, p, self.pg1)[0]
4117 out_port = p[TCP].sport
4119 # SYN + ACK packet out->in
4120 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4121 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4122 TCP(sport=ext_port, dport=out_port, flags="SA"))
4123 self.send_and_expect(self.pg1, p, self.pg0)
4125 # ACK packet in->out -- not received by the server
4126 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4127 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4128 TCP(sport=in_port, dport=ext_port, flags="A"))
4129 self.send_and_expect(self.pg0, p, self.pg1)
4131 # PUSH + ACK packet in->out
4132 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4133 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4134 TCP(sport=in_port, dport=ext_port, flags="PA") /
4136 self.send_and_expect(self.pg0, p, self.pg1)
4138 # resent SYN + ACK packet out->in
4139 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4140 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4141 TCP(sport=ext_port, dport=out_port, flags="SA"))
4142 self.send_and_expect(self.pg1, p, self.pg0)
4144 # resent ACK packet in->out
4145 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4146 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4147 TCP(sport=in_port, dport=ext_port, flags="A"))
4148 self.send_and_expect(self.pg0, p, self.pg1)
4150 # resent PUSH + ACK packet in->out
4151 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4152 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4153 TCP(sport=in_port, dport=ext_port, flags="PA") /
4155 self.send_and_expect(self.pg0, p, self.pg1)
4157 # ACK packet out->in
4158 p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
4159 IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
4160 TCP(sport=ext_port, dport=out_port, flags="A"))
4161 self.send_and_expect(self.pg1, p, self.pg0)
4163 # Verify that the data can be transmitted after the transitory time
4164 self.virtual_sleep(6)
4166 p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
4167 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
4168 TCP(sport=in_port, dport=ext_port, flags="PA") /
4170 self.send_and_expect(self.pg0, p, self.pg1)
4173 if __name__ == '__main__':
4174 unittest.main(testRunner=VppTestRunner)