RDMA/nes: Fix stale ARP issue
When the remote node's ethernet address changes, the connection keeps trying to connect using the old address. The connection wil continue failing until the driver is unloaded and loaded again (eiter reboot or rmmod). Fix this by checking that the NIC has the correct address before starting a connection. Signed-off-by: Faisal Latif <faisal.latif@intel.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
This commit is contained in:
parent
b1190d3e0d
commit
7a576dfd9e
|
@ -1098,12 +1098,13 @@ static inline int mini_cm_accelerated(struct nes_cm_core *cm_core,
|
||||||
/**
|
/**
|
||||||
* nes_addr_resolve_neigh
|
* nes_addr_resolve_neigh
|
||||||
*/
|
*/
|
||||||
static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip)
|
static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpindex)
|
||||||
{
|
{
|
||||||
struct rtable *rt;
|
struct rtable *rt;
|
||||||
struct flowi fl;
|
struct flowi fl;
|
||||||
struct neighbour *neigh;
|
struct neighbour *neigh;
|
||||||
int rc = -1;
|
int rc = arpindex;
|
||||||
|
struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter;
|
||||||
|
|
||||||
memset(&fl, 0, sizeof fl);
|
memset(&fl, 0, sizeof fl);
|
||||||
fl.nl_u.ip4_u.daddr = htonl(dst_ip);
|
fl.nl_u.ip4_u.daddr = htonl(dst_ip);
|
||||||
|
@ -1119,6 +1120,21 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip)
|
||||||
nes_debug(NES_DBG_CM, "Neighbor MAC address for 0x%08X"
|
nes_debug(NES_DBG_CM, "Neighbor MAC address for 0x%08X"
|
||||||
" is %pM, Gateway is 0x%08X \n", dst_ip,
|
" is %pM, Gateway is 0x%08X \n", dst_ip,
|
||||||
neigh->ha, ntohl(rt->rt_gateway));
|
neigh->ha, ntohl(rt->rt_gateway));
|
||||||
|
|
||||||
|
if (arpindex >= 0) {
|
||||||
|
if (!memcmp(nesadapter->arp_table[arpindex].mac_addr,
|
||||||
|
neigh->ha, ETH_ALEN)){
|
||||||
|
/* Mac address same as in nes_arp_table */
|
||||||
|
neigh_release(neigh);
|
||||||
|
ip_rt_put(rt);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
nes_manage_arp_cache(nesvnic->netdev,
|
||||||
|
nesadapter->arp_table[arpindex].mac_addr,
|
||||||
|
dst_ip, NES_ARP_DELETE);
|
||||||
|
}
|
||||||
|
|
||||||
nes_manage_arp_cache(nesvnic->netdev, neigh->ha,
|
nes_manage_arp_cache(nesvnic->netdev, neigh->ha,
|
||||||
dst_ip, NES_ARP_ADD);
|
dst_ip, NES_ARP_ADD);
|
||||||
rc = nes_arp_table(nesvnic->nesdev, dst_ip, NULL,
|
rc = nes_arp_table(nesvnic->nesdev, dst_ip, NULL,
|
||||||
|
@ -1134,7 +1150,6 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* make_cm_node - create a new instance of a cm node
|
* make_cm_node - create a new instance of a cm node
|
||||||
*/
|
*/
|
||||||
|
@ -1144,6 +1159,7 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
|
||||||
{
|
{
|
||||||
struct nes_cm_node *cm_node;
|
struct nes_cm_node *cm_node;
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
|
int oldarpindex = 0;
|
||||||
int arpindex = 0;
|
int arpindex = 0;
|
||||||
struct nes_device *nesdev;
|
struct nes_device *nesdev;
|
||||||
struct nes_adapter *nesadapter;
|
struct nes_adapter *nesadapter;
|
||||||
|
@ -1197,17 +1213,18 @@ static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
|
||||||
nesadapter = nesdev->nesadapter;
|
nesadapter = nesdev->nesadapter;
|
||||||
|
|
||||||
cm_node->loopbackpartner = NULL;
|
cm_node->loopbackpartner = NULL;
|
||||||
|
|
||||||
/* get the mac addr for the remote node */
|
/* get the mac addr for the remote node */
|
||||||
if (ipv4_is_loopback(htonl(cm_node->rem_addr)))
|
if (ipv4_is_loopback(htonl(cm_node->rem_addr)))
|
||||||
arpindex = nes_arp_table(nesdev, ntohl(nesvnic->local_ipaddr), NULL, NES_ARP_RESOLVE);
|
arpindex = nes_arp_table(nesdev, ntohl(nesvnic->local_ipaddr), NULL, NES_ARP_RESOLVE);
|
||||||
else
|
else {
|
||||||
arpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE);
|
oldarpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE);
|
||||||
|
arpindex = nes_addr_resolve_neigh(nesvnic, cm_info->rem_addr, oldarpindex);
|
||||||
|
|
||||||
|
}
|
||||||
if (arpindex < 0) {
|
if (arpindex < 0) {
|
||||||
arpindex = nes_addr_resolve_neigh(nesvnic, cm_info->rem_addr);
|
kfree(cm_node);
|
||||||
if (arpindex < 0) {
|
return NULL;
|
||||||
kfree(cm_node);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy the mac addr to node context */
|
/* copy the mac addr to node context */
|
||||||
|
|
Loading…
Reference in a new issue