From: Parav Pandit <parav@xxxxxxxxxxxx> Add an interface via netlink command to query whether rdma devices are shared among multiple net namespaces or not. When using rdma tool, it can be queried as, $rdma sys show netns netns: shared Signed-off-by: Parav Pandit <parav@xxxxxxxxxxxx> Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxxxx> --- drivers/infiniband/core/core_priv.h | 2 ++ drivers/infiniband/core/device.c | 10 ++++---- drivers/infiniband/core/net_namespace.c | 15 ++++++++++++ drivers/infiniband/core/nldev.c | 32 +++++++++++++++++++++++++ include/uapi/rdma/rdma_netlink.h | 10 +++++++- 5 files changed, 64 insertions(+), 5 deletions(-) diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h index 9ebce87c7961..1ba188efec44 100644 --- a/drivers/infiniband/core/core_priv.h +++ b/drivers/infiniband/core/core_priv.h @@ -59,6 +59,8 @@ extern struct list_head ib_device_list; extern struct mutex ib_device_mutex; extern struct rw_semaphore ib_lists_rwsem; +extern ushort ib_devices_shared_netns; + int ib_device_register_sysfs(struct ib_device *device, int (*port_callback)(struct ib_device *, u8, struct kobject *)); diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index 12877984b10c..68934bf14f76 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -676,11 +676,13 @@ int ib_register_device(struct ib_device *device, const char *name, goto cg_cleanup; } - device->netns_shared = 1; - /* Perform this under device mutex lock, so that it can synchronize - * with _init_net() to avoid duplicate additions for a given device. + /* Perform compat device creation under device mutex lock, so that it + * can synchronize with _init_net() notifier to avoid duplicate + * additions for a given device. */ - rdma_compatdev_add(device); + device->netns_shared = ib_devices_shared_netns; + if (ib_devices_shared_netns) + rdma_compatdev_add(device); device->reg_state = IB_DEV_REGISTERED; diff --git a/drivers/infiniband/core/net_namespace.c b/drivers/infiniband/core/net_namespace.c index 569049dd4216..57b1fe3d1d16 100644 --- a/drivers/infiniband/core/net_namespace.c +++ b/drivers/infiniband/core/net_namespace.c @@ -32,6 +32,17 @@ struct rdma_dev_net { }; static unsigned int rdma_dev_net_id; +/** + * ib_devices_shared_netns - rdma devices shared between multiple + * network namespaces or not. + * true = shared mode: + * All IB devices can be shared among multiple network namespace. + * This is default mode. + * false = single namespace mode: + * IB device resides in only one net namespace. + * + */ +ushort ib_devices_shared_netns = 1; static void rdma_compatdev_release(struct device *dev) { @@ -180,6 +191,9 @@ static __net_init int rdma_dev_init_net(struct net *net) * which also tries to add compat devices. */ mutex_lock(&ib_device_mutex); + if (!ib_devices_shared_netns) + goto done; + /* Hold ib_lists_rwsem read lock; thereby not assume that * ib_device_mutex is always locked while accessing ib_device_list. */ @@ -187,6 +201,7 @@ static __net_init int rdma_dev_init_net(struct net *net) list_for_each_entry(device, &ib_device_list, core_list) rdma_compatdev_create(device, net); up_read(&ib_lists_rwsem); +done: mutex_unlock(&ib_device_mutex); return 0; } diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c index 9591193cf285..881b620bed7a 100644 --- a/drivers/infiniband/core/nldev.c +++ b/drivers/infiniband/core/nldev.c @@ -107,6 +107,7 @@ static const struct nla_policy nldev_policy[RDMA_NLDEV_ATTR_MAX] = { [RDMA_NLDEV_ATTR_DRIVER_U32] = { .type = NLA_U32 }, [RDMA_NLDEV_ATTR_DRIVER_S64] = { .type = NLA_S64 }, [RDMA_NLDEV_ATTR_DRIVER_U64] = { .type = NLA_U64 }, + [RDMA_NLDEV_SYS_ATTR_NETNS_MODE] = { .type = NLA_U8 }, }; static int put_driver_name_print_type(struct sk_buff *msg, const char *name, @@ -1107,6 +1108,34 @@ static int nldev_res_get_pd_dumpit(struct sk_buff *skb, return res_get_common_dumpit(skb, cb, RDMA_RESTRACK_PD); } +static int nldev_get_sys_get_dumpit(struct sk_buff *skb, + struct netlink_callback *cb) +{ + struct nlattr *tb[RDMA_NLDEV_ATTR_MAX]; + struct nlmsghdr *nlh; + int err; + + err = nlmsg_parse(cb->nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1, + nldev_policy, NULL); + if (err) + return err; + + nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, + RDMA_NL_GET_TYPE(RDMA_NL_NLDEV, + RDMA_NLDEV_CMD_SYS_GET), + 0, 0); + + err = nla_put_u8(skb, RDMA_NLDEV_SYS_ATTR_NETNS_MODE, + (u8)ib_devices_shared_netns); + if (err) { + nlmsg_cancel(skb, nlh); + return err; + } + + nlmsg_end(skb, nlh); + return skb->len; +} + static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = { [RDMA_NLDEV_CMD_GET] = { .doit = nldev_get_doit, @@ -1149,6 +1178,9 @@ static const struct rdma_nl_cbs nldev_cb_table[RDMA_NLDEV_NUM_OPS] = { [RDMA_NLDEV_CMD_RES_PD_GET] = { .dump = nldev_res_get_pd_dumpit, }, + [RDMA_NLDEV_CMD_SYS_GET] = { + .dump = nldev_get_sys_get_dumpit, + }, }; void __init nldev_init(void) diff --git a/include/uapi/rdma/rdma_netlink.h b/include/uapi/rdma/rdma_netlink.h index 2e18b77a817f..1cda30f392e7 100644 --- a/include/uapi/rdma/rdma_netlink.h +++ b/include/uapi/rdma/rdma_netlink.h @@ -229,7 +229,9 @@ enum rdma_nldev_command { RDMA_NLDEV_CMD_GET, /* can dump */ RDMA_NLDEV_CMD_SET, - /* 3 - 4 are free to use */ + RDMA_NLDEV_CMD_SYS_GET, /* can dump */ + + /* 4 is free to use */ RDMA_NLDEV_CMD_PORT_GET = 5, /* can dump */ @@ -430,6 +432,12 @@ enum rdma_nldev_attr { RDMA_NLDEV_ATTR_DRIVER_S64, /* s64 */ RDMA_NLDEV_ATTR_DRIVER_U64, /* u64 */ + /* + * net namespace mode for rdma subsystem: + * either shared or exclusive among multiple net namespaces. + */ + RDMA_NLDEV_SYS_ATTR_NETNS_MODE, /* u8 */ + /* * Always the end */ -- 2.19.1