Skip to content

Commit 925d046

Browse files
PatrisiousHaddadrleon
authored andcommitted
RDMA/core: Add a netevent notifier to cma
Add a netevent callback for cma, mainly to catch NETEVENT_NEIGH_UPDATE. Previously, when a system with failover MAC mechanism change its MAC address during a CM connection attempt, the RDMA-CM would take a lot of time till it disconnects and timesout due to the incorrect MAC address. Now when we get a NETEVENT_NEIGH_UPDATE we check if it is due to a failover MAC change and if so, we instantly destroy the CM and notify the user in order to spare the unnecessary waiting for the timeout. Link: https://lore.kernel.org/r/bb255c9e301cd50b905663b8e73f7f5133d0e4c5.1654601342.git.leonro@nvidia.com Signed-off-by: Patrisious Haddad <phaddad@nvidia.com> Reviewed-by: Mark Zhang <markzhang@nvidia.com> Signed-off-by: Leon Romanovsky <leon@kernel.org>
1 parent fc008bd commit 925d046

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

drivers/infiniband/core/cma.c

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include <net/net_namespace.h>
2323
#include <net/netns/generic.h>
24+
#include <net/netevent.h>
2425
#include <net/tcp.h>
2526
#include <net/ipv6.h>
2627
#include <net/ip_fib.h>
@@ -5047,10 +5048,87 @@ static int cma_netdev_callback(struct notifier_block *self, unsigned long event,
50475048
return ret;
50485049
}
50495050

5051+
static void cma_netevent_work_handler(struct work_struct *_work)
5052+
{
5053+
struct rdma_id_private *id_priv =
5054+
container_of(_work, struct rdma_id_private, id.net_work);
5055+
struct rdma_cm_event event = {};
5056+
5057+
mutex_lock(&id_priv->handler_mutex);
5058+
5059+
if (READ_ONCE(id_priv->state) == RDMA_CM_DESTROYING ||
5060+
READ_ONCE(id_priv->state) == RDMA_CM_DEVICE_REMOVAL)
5061+
goto out_unlock;
5062+
5063+
event.event = RDMA_CM_EVENT_UNREACHABLE;
5064+
event.status = -ETIMEDOUT;
5065+
5066+
if (cma_cm_event_handler(id_priv, &event)) {
5067+
__acquire(&id_priv->handler_mutex);
5068+
id_priv->cm_id.ib = NULL;
5069+
cma_id_put(id_priv);
5070+
destroy_id_handler_unlock(id_priv);
5071+
return;
5072+
}
5073+
5074+
out_unlock:
5075+
mutex_unlock(&id_priv->handler_mutex);
5076+
cma_id_put(id_priv);
5077+
}
5078+
5079+
static int cma_netevent_callback(struct notifier_block *self,
5080+
unsigned long event, void *ctx)
5081+
{
5082+
struct id_table_entry *ips_node = NULL;
5083+
struct rdma_id_private *current_id;
5084+
struct neighbour *neigh = ctx;
5085+
unsigned long flags;
5086+
5087+
if (event != NETEVENT_NEIGH_UPDATE)
5088+
return NOTIFY_DONE;
5089+
5090+
spin_lock_irqsave(&id_table_lock, flags);
5091+
if (neigh->tbl->family == AF_INET6) {
5092+
struct sockaddr_in6 neigh_sock_6;
5093+
5094+
neigh_sock_6.sin6_family = AF_INET6;
5095+
neigh_sock_6.sin6_addr = *(struct in6_addr *)neigh->primary_key;
5096+
ips_node = node_from_ndev_ip(&id_table, neigh->dev->ifindex,
5097+
(struct sockaddr *)&neigh_sock_6);
5098+
} else if (neigh->tbl->family == AF_INET) {
5099+
struct sockaddr_in neigh_sock_4;
5100+
5101+
neigh_sock_4.sin_family = AF_INET;
5102+
neigh_sock_4.sin_addr.s_addr = *(__be32 *)(neigh->primary_key);
5103+
ips_node = node_from_ndev_ip(&id_table, neigh->dev->ifindex,
5104+
(struct sockaddr *)&neigh_sock_4);
5105+
} else
5106+
goto out;
5107+
5108+
if (!ips_node)
5109+
goto out;
5110+
5111+
list_for_each_entry(current_id, &ips_node->id_list, id_list_entry) {
5112+
if (!memcmp(current_id->id.route.addr.dev_addr.dst_dev_addr,
5113+
neigh->ha, ETH_ALEN))
5114+
continue;
5115+
INIT_WORK(&current_id->id.net_work, cma_netevent_work_handler);
5116+
cma_id_get(current_id);
5117+
queue_work(cma_wq, &current_id->id.net_work);
5118+
}
5119+
out:
5120+
spin_unlock_irqrestore(&id_table_lock, flags);
5121+
return NOTIFY_DONE;
5122+
}
5123+
50505124
static struct notifier_block cma_nb = {
50515125
.notifier_call = cma_netdev_callback
50525126
};
50535127

5128+
static struct notifier_block cma_netevent_cb = {
5129+
.notifier_call = cma_netevent_callback
5130+
};
5131+
50545132
static void cma_send_device_removal_put(struct rdma_id_private *id_priv)
50555133
{
50565134
struct rdma_cm_event event = { .event = RDMA_CM_EVENT_DEVICE_REMOVAL };
@@ -5273,6 +5351,7 @@ static int __init cma_init(void)
52735351

52745352
ib_sa_register_client(&sa_client);
52755353
register_netdevice_notifier(&cma_nb);
5354+
register_netevent_notifier(&cma_netevent_cb);
52765355

52775356
ret = ib_register_client(&cma_client);
52785357
if (ret)
@@ -5287,6 +5366,7 @@ static int __init cma_init(void)
52875366
err_ib:
52885367
ib_unregister_client(&cma_client);
52895368
err:
5369+
unregister_netevent_notifier(&cma_netevent_cb);
52905370
unregister_netdevice_notifier(&cma_nb);
52915371
ib_sa_unregister_client(&sa_client);
52925372
unregister_pernet_subsys(&cma_pernet_operations);
@@ -5299,6 +5379,7 @@ static void __exit cma_cleanup(void)
52995379
{
53005380
cma_configfs_exit();
53015381
ib_unregister_client(&cma_client);
5382+
unregister_netevent_notifier(&cma_netevent_cb);
53025383
unregister_netdevice_notifier(&cma_nb);
53035384
ib_sa_unregister_client(&sa_client);
53045385
unregister_pernet_subsys(&cma_pernet_operations);

include/rdma/rdma_cm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ struct rdma_cm_id {
108108
enum rdma_ucm_port_space ps;
109109
enum ib_qp_type qp_type;
110110
u32 port_num;
111+
struct work_struct net_work;
111112
};
112113

113114
struct rdma_cm_id *

0 commit comments

Comments
 (0)