diff options
author | Juraj Sloboda <jsloboda@cisco.com> | 2018-07-09 02:36:37 +0200 |
---|---|---|
committer | Damjan Marion <dmarion@me.com> | 2018-07-10 10:10:05 +0000 |
commit | c746a15272f1430926cdd3d00745e19a8fe596dc (patch) | |
tree | c8010fff8e168b61e5fad99391e5b99766ba1c34 | |
parent | 3ecef99484463666d62568da931fd908f3e86d7c (diff) |
Do not translate packets destined for NAT64 inside interface (VPP-1331)
Change-Id: Ieb8020f57ed5ad20daf552cd62ae3fdd8c573926
Signed-off-by: Juraj Sloboda <jsloboda@cisco.com>
-rw-r--r-- | src/plugins/nat/nat64_in2out.c | 29 | ||||
-rw-r--r-- | test/test_nat.py | 62 |
2 files changed, 89 insertions, 2 deletions
diff --git a/src/plugins/nat/nat64_in2out.c b/src/plugins/nat/nat64_in2out.c index 603b30ee11a..6ff428bbb86 100644 --- a/src/plugins/nat/nat64_in2out.c +++ b/src/plugins/nat/nat64_in2out.c @@ -116,6 +116,26 @@ typedef struct nat64_in2out_set_ctx_t_ u32 thread_index; } nat64_in2out_set_ctx_t; +static inline u8 +nat64_not_translate (u32 sw_if_index, ip6_address_t ip6_addr) +{ + ip6_address_t *addr; + ip6_main_t *im6 = &ip6_main; + ip_lookup_main_t *lm6 = &im6->lookup_main; + ip_interface_address_t *ia = 0; + + /* *INDENT-OFF* */ + foreach_ip_interface_address (lm6, ia, sw_if_index, 0, + ({ + addr = ip_interface_address_get_address (lm6, ia); + if (0 == ip6_address_compare (addr, &ip6_addr)) + return 1; + })); + /* *INDENT-ON* */ + + return 0; +} + /** * @brief Check whether is a hairpinning. * @@ -927,6 +947,7 @@ nat64_in2out_node_fn_inline (vlib_main_t * vm, vlib_node_runtime_t * node, u8 l4_protocol0; u32 proto0; nat64_in2out_set_ctx_t ctx0; + u32 sw_if_index0; /* speculatively enqueue b0 to the current next frame */ bi0 = from[0]; @@ -955,6 +976,14 @@ nat64_in2out_node_fn_inline (vlib_main_t * vm, vlib_node_runtime_t * node, goto trace0; } + sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; + + if (nat64_not_translate (sw_if_index0, ip60->dst_address)) + { + next0 = NAT64_IN2OUT_NEXT_IP6_LOOKUP; + goto trace0; + } + proto0 = ip_proto_to_snat_proto (l4_protocol0); if (is_slow_path) diff --git a/test/test_nat.py b/test/test_nat.py index 35e89e39b9c..4ae2850678d 100644 --- a/test/test_nat.py +++ b/test/test_nat.py @@ -9,7 +9,8 @@ import random from framework import VppTestCase, VppTestRunner, running_extended_tests from scapy.layers.inet import IP, TCP, UDP, ICMP from scapy.layers.inet import IPerror, TCPerror, UDPerror, ICMPerror -from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply +from scapy.layers.inet6 import IPv6, ICMPv6EchoRequest, ICMPv6EchoReply, \ + ICMPv6ND_NS, ICMPv6ND_NA, ICMPv6NDOptDstLLAddr from scapy.layers.inet6 import ICMPv6DestUnreach, IPerror6, IPv6ExtHdrFragment from scapy.layers.l2 import Ether, ARP, GRE from scapy.data import IP_PROTOS @@ -5189,7 +5190,7 @@ class TestNAT64(MethodHolder): cls.ipfix_src_port = 4739 cls.ipfix_domain_id = 1 - cls.create_pg_interfaces(range(5)) + cls.create_pg_interfaces(range(6)) cls.ip6_interfaces = list(cls.pg_interfaces[0:1]) cls.ip6_interfaces.append(cls.pg_interfaces[2]) cls.ip4_interfaces = list(cls.pg_interfaces[1:2]) @@ -5216,10 +5217,67 @@ class TestNAT64(MethodHolder): cls.pg3.config_ip6() cls.pg3.configure_ipv6_neighbors() + cls.pg5.admin_up() + cls.pg5.config_ip6() + except Exception: super(TestNAT64, cls).tearDownClass() raise + def test_nat64_inside_interface_handles_neighbor_advertisement(self): + """ NAT64 inside interface handles Neighbor Advertisement """ + + self.vapi.nat64_add_del_interface(self.pg5.sw_if_index) + + # Try to send ping + ping = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) / + IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) / + ICMPv6EchoRequest()) + pkts = [ping] + self.pg5.add_stream(pkts) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + # Wait for Neighbor Solicitation + capture = self.pg5.get_capture(len(pkts)) + self.assertEqual(1, len(capture)) + packet = capture[0] + try: + self.assertEqual(packet[IPv6].src, self.pg5.local_ip6) + self.assertTrue(packet.haslayer(ICMPv6ND_NS)) + tgt = packet[ICMPv6ND_NS].tgt + except: + self.logger.error(ppp("Unexpected or invalid packet:", packet)) + raise + + # Send Neighbor Advertisement + p = (Ether(dst=self.pg5.local_mac, src=self.pg5.remote_mac) / + IPv6(src=self.pg5.remote_ip6, dst=self.pg5.local_ip6) / + ICMPv6ND_NA(tgt=tgt) / + ICMPv6NDOptDstLLAddr(lladdr=self.pg5.remote_mac)) + pkts = [p] + self.pg5.add_stream(pkts) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + # Try to send ping again + pkts = [ping] + self.pg5.add_stream(pkts) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + # Wait for ping reply + capture = self.pg5.get_capture(len(pkts)) + self.assertEqual(1, len(capture)) + packet = capture[0] + try: + self.assertEqual(packet[IPv6].src, self.pg5.local_ip6) + self.assertEqual(packet[IPv6].dst, self.pg5.remote_ip6) + self.assertTrue(packet.haslayer(ICMPv6EchoReply)) + except: + self.logger.error(ppp("Unexpected or invalid packet:", packet)) + raise + def test_pool(self): """ Add/delete address to NAT64 pool """ nat_addr = socket.inet_pton(socket.AF_INET, '1.2.3.4') |