summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/nat/nat64_in2out.c29
-rw-r--r--test/test_nat.py62
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')