aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEd Warnicke <user@example.com>2021-08-14 16:19:43 -0500
committerOle Tr�an <otroan@employees.org>2021-10-07 13:57:45 +0000
commit9e17887db97bb9f6507270f9fa9923c10816e0df (patch)
tree1694df3523a35cd74119585e896b671115a47053
parent12ba95bff55362b17acddac0b9063d9109ec0646 (diff)
arp: source address selection
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>
-rw-r--r--src/vnet/ip-neighbor/ip4_neighbor.c11
-rw-r--r--src/vnet/ip-neighbor/ip6_neighbor.c7
2 files changed, 13 insertions, 5 deletions
diff --git a/src/vnet/ip-neighbor/ip4_neighbor.c b/src/vnet/ip-neighbor/ip4_neighbor.c
index 9dda50ee911..cf0e81a0b43 100644
--- a/src/vnet/ip-neighbor/ip4_neighbor.c
+++ b/src/vnet/ip-neighbor/ip4_neighbor.c
@@ -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];
diff --git a/src/vnet/ip-neighbor/ip6_neighbor.c b/src/vnet/ip-neighbor/ip6_neighbor.c
index ec323543e32..0f923fe6673 100644
--- a/src/vnet/ip-neighbor/ip6_neighbor.c
+++ b/src/vnet/ip-neighbor/ip6_neighbor.c
@@ -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];