ip-neighbor: do not use sas to determine NS source address 75/39675/5
authorOle Troan <otroan@employees.org>
Fri, 13 Oct 2023 07:19:45 +0000 (09:19 +0200)
committerAndrew Yourtchenko <ayourtch@gmail.com>
Mon, 16 Oct 2023 14:48:46 +0000 (14:48 +0000)
Using the source address selection algorithm to determine the best source
of an NS for address resolution risks incompatible behavior.
It may choose a source address that is off-link to the other host.
Which may drop it.

A safer approach is to always use the link-local address as the SA.
It's recommended to pick a source that an application will later use,
as VPP is mostly a router, that rarely applies. And regardlessly we have
no mechanism to signal from an application that triggered address resolutiuon
what source address it intends to use.

Type: fix
Change-Id: I3c5de66e41505f3682767706ef1195a20e4f0e54
Signed-off-by: Ole Troan <otroan@employees.org>
src/vnet/ip-neighbor/ip6_neighbor.c
test/test_ip6.py
test/test_ip6_nd_mirror_proxy.py
test/test_nat64.py

index e3a47df..fd0dbfc 100644 (file)
@@ -217,13 +217,14 @@ ip6_discover_neighbor_inline (vlib_main_t * vm,
           * Choose source address based on destination lookup
           * adjacency.
           */
-         if (!fib_sas6_get (sw_if_index0, &ip0->dst_address, &src) ||
-             !ip6_sas_by_sw_if_index (sw_if_index0, &ip0->dst_address, &src))
+         const ip6_address_t *ll = ip6_get_link_local_address (sw_if_index0);
+         if (!ll)
            {
              /* There is no address on the interface */
              p0->error = node->errors[IP6_NEIGHBOR_ERROR_NO_SOURCE_ADDRESS];
              continue;
            }
+         ip6_address_copy (&src, ll);
 
          b0 = ip6_neighbor_probe (vm, vnm, sw_if_index0, thread_index, &src,
                                   &ip0->dst_address);
index 36c4122..c78b844 100644 (file)
@@ -141,7 +141,7 @@ class TestIPv6ND(VppTestCase):
         self.assertEqual(in6_ptop(ns.tgt), in6_ptop(tgt_ip))
 
         # packet is from the router's local address
-        self.assertEqual(in6_ptop(rx[IPv6].src), intf.local_ip6)
+        self.assertEqual(in6_ptop(rx[IPv6].src), intf.local_ip6_ll)
 
         # Src link-layer options should have the router's MAC
         sll = rx[ICMPv6NDOptSrcLLAddr]
index 9214e32..bb7c967 100644 (file)
@@ -121,7 +121,7 @@ class TestNDPROXY(VppTestCase):
         rx = self.send_and_expect(self.pg1, [unicast_nd_req_from_host], self.pg0)
         self.assertEqual(rx[0][Ether].src, self.pg0.local_mac)
         self.assertEqual(rx[0][Ether].dst, in6_getnsmac(nsma))
-        self.assertEqual(rx[0][IPv6].src, self.pg0.local_ip6)
+        self.assertEqual(rx[0][IPv6].src, self.pg0.local_ip6_ll)
         self.assertEqual(rx[0][IPv6].dst, d)
         self.assertEqual(ipv6nh[rx[0][IPv6].nh], "ICMPv6")
         self.assertEqual(rx[0][ICMPv6ND_NS].tgt, self.pg0.remote_ip6)
index 4ae9f66..5c0fe73 100644 (file)
@@ -651,7 +651,7 @@ class TestNAT64(VppTestCase):
         capture = self.pg5.get_capture(len(pkts))
         packet = capture[0]
         try:
-            self.assertEqual(packet[IPv6].src, self.pg5.local_ip6)
+            self.assertEqual(packet[IPv6].src, self.pg5.local_ip6_ll)
             self.assertEqual(packet.haslayer(ICMPv6ND_NS), 1)
             tgt = packet[ICMPv6ND_NS].tgt
         except: