arp: source address selection 95/33495/7
authorEd Warnicke <user@example.com>
Sat, 14 Aug 2021 21:19:43 +0000 (16:19 -0500)
committerOle Tr�an <otroan@employees.org>
Thu, 7 Oct 2021 13:57:45 +0000 (13:57 +0000)
https://gerrit.fd.io/r/c/vpp/+/30197 introduced SAS and inadvertently
broke ping in a variety of situations:

https://jira.fd.io/browse/VPP-1992
https://jira.fd.io/browse/VPP-1970
https://lists.fd.io/g/vpp-dev/topic/84038840

all of which seem to be rooted in situations where there's literally
nothing smarter ping can do for source address selection than
to pick the first IP on the interface.  This can happen for:

1. P2P interfaces, see attempted fix: https://gerrit.fd.io/r/c/vpp/+/32801
2. Interfaces with /32 IP addresses intentionally assigned

After some discussion, this problem was partially fixed in
https://gerrit.fd.io/r/c/vpp/+/33449

Unforunately, while source selection was fixed in ping, it continued
to be broken in arp/nd.  This gerrit builds on
https://gerrit.fd.io/r/c/vpp/+/33449
and fixes arp/nd.

Type: fix
Ticket: VPP-1970
Ticket: VPP-1992
Fixes: e2fe097424fb169dfe01421ff17b8ccd0c26b4a6

Change-Id: Ief60c321676a15f4f30bf4cd84d50b2f1efec432
Signed-off-by: Ed Warnicke <hagbard@gmail.com>
src/vnet/ip-neighbor/ip4_neighbor.c
src/vnet/ip-neighbor/ip6_neighbor.c

index 9dda50e..cf0e81a 100644 (file)
@@ -41,6 +41,7 @@
 #include <vnet/ethernet/ethernet.h>
 #include <vnet/util/throttle.h>
 #include <vnet/fib/fib_sas.h>
+#include <vnet/ip/ip_sas.h>
 
 /** ARP throttling */
 static throttle_t arp_throttle;
@@ -62,7 +63,9 @@ ip4_neighbor_probe_dst (u32 sw_if_index, const ip4_address_t * dst)
   /* any glean will do, it's just for the rewrite */
   ai = adj_glean_get (FIB_PROTOCOL_IP4, sw_if_index, NULL);
 
-  if (ADJ_INDEX_INVALID != ai && fib_sas4_get (sw_if_index, dst, &src))
+  if (ADJ_INDEX_INVALID != ai &&
+      (fib_sas4_get (sw_if_index, dst, &src) ||
+       ip4_sas_by_sw_if_index (sw_if_index, dst, &src)))
     ip4_neighbor_probe (vlib_get_main (),
                        vnet_get_main (), adj_get (ai), &src, dst);
 }
@@ -79,7 +82,8 @@ ip4_neighbor_advertise (vlib_main_t * vm,
 
   if (NULL == addr)
     {
-      if (fib_sas4_get (sw_if_index, NULL, &tmp))
+      if (fib_sas4_get (sw_if_index, NULL, &tmp) ||
+         ip4_sas_by_sw_if_index (sw_if_index, NULL, &tmp))
        addr = &tmp;
     }
 
@@ -185,7 +189,8 @@ ip4_arp_inline (vlib_main_t * vm,
              /* resolve the incomplete adj */
              resolve0 = adj0->sub_type.nbr.next_hop.ip4;
              /* Src IP address in ARP header. */
-             if (!fib_sas4_get (sw_if_index0, &resolve0, &src0))
+             if (!fib_sas4_get (sw_if_index0, &resolve0, &src0) &&
+                 !ip4_sas_by_sw_if_index (sw_if_index0, &resolve0, &src0))
                {
                  /* No source address available */
                  p0->error = node->errors[IP4_ARP_ERROR_NO_SOURCE_ADDRESS];
index ec32354..0f923fe 100644 (file)
@@ -18,6 +18,7 @@
 #include <vnet/ip-neighbor/ip6_neighbor.h>
 #include <vnet/util/throttle.h>
 #include <vnet/fib/fib_sas.h>
+#include <vnet/ip/ip_sas.h>
 
 /** ND throttling */
 static throttle_t nd_throttle;
@@ -34,7 +35,8 @@ ip6_neighbor_probe_dst (u32 sw_if_index, const ip6_address_t * dst)
 {
   ip6_address_t src;
 
-  if (fib_sas6_get (sw_if_index, dst, &src))
+  if (fib_sas6_get (sw_if_index, dst, &src) ||
+      ip6_sas_by_sw_if_index (sw_if_index, dst, &src))
     ip6_neighbor_probe (vlib_get_main (), vnet_get_main (),
                        sw_if_index, &src, dst);
 }
@@ -212,7 +214,8 @@ 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))
+         if (!fib_sas6_get (sw_if_index0, &ip0->dst_address, &src) &&
+             !ip6_sas_by_sw_if_index (sw_if_index0, &ip0->dst_address, &src))
            {
              /* There is no address on the interface */
              p0->error = node->errors[IP6_NBR_ERROR_NO_SOURCE_ADDRESS];