diff options
author | Ed Warnicke <user@example.com> | 2021-08-14 16:19:43 -0500 |
---|---|---|
committer | Ole Tr�an <otroan@employees.org> | 2021-10-07 13:57:45 +0000 |
commit | 9e17887db97bb9f6507270f9fa9923c10816e0df (patch) | |
tree | 1694df3523a35cd74119585e896b671115a47053 | |
parent | 12ba95bff55362b17acddac0b9063d9109ec0646 (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.c | 11 | ||||
-rw-r--r-- | src/vnet/ip-neighbor/ip6_neighbor.c | 7 |
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]; |