Commit 1d2fedd8 authored by Parav Pandit's avatar Parav Pandit Committed by Jason Gunthorpe
Browse files

RDMA/core: Support netlink commands in non init_net net namespaces

Now that IB core supports RDMA device binding with specific net namespace,
enable IB core to accept netlink commands in non init_net namespaces.

This is done by having per net namespace netlink socket.

At present only netlink device handling client RDMA_NL_NLDEV supports
device handling in multiple net namespaces.  Hence do not accept netlink
messages for other clients in non init_net net namespaces.

Link: https://lore.kernel.org/r/20190723070205.6247-1-leon@kernel.org


Signed-off-by: default avatarParav Pandit <parav@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
Reviewed-by: default avatarJason Gunthorpe <jgg@mellanox.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent 913df8c3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -183,7 +183,7 @@ static int ib_nl_ip_send_msg(struct rdma_dev_addr *dev_addr,

	/* Repair the nlmsg header length */
	nlmsg_end(skb, nlh);
	rdma_nl_multicast(skb, RDMA_NL_GROUP_LS, GFP_KERNEL);
	rdma_nl_multicast(&init_net, skb, RDMA_NL_GROUP_LS, GFP_KERNEL);

	/* Make the request retry, so when we get the response from userspace
	 * we will have something.
+23 −1
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/cgroup_rdma.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>

#include <rdma/ib_verbs.h>
#include <rdma/opa_addr.h>
@@ -54,8 +56,26 @@ struct pkey_index_qp_list {
	struct list_head    qp_list;
};

/**
 * struct rdma_dev_net - rdma net namespace metadata for a net
 * @nl_sock:	Pointer to netlink socket
 * @net:	Pointer to owner net namespace
 * @id:		xarray id to identify the net namespace.
 */
struct rdma_dev_net {
	struct sock *nl_sock;
	possible_net_t net;
	u32 id;
};

extern const struct attribute_group ib_dev_attr_group;
extern bool ib_devices_shared_netns;
extern unsigned int rdma_dev_net_id;

static inline struct rdma_dev_net *rdma_net_to_dev_net(struct net *net)
{
	return net_generic(net, rdma_dev_net_id);
}

int ib_device_register_sysfs(struct ib_device *device);
void ib_device_unregister_sysfs(struct ib_device *device);
@@ -179,7 +199,6 @@ void ib_mad_cleanup(void);
int ib_sa_init(void);
void ib_sa_cleanup(void);

int rdma_nl_init(void);
void rdma_nl_exit(void);

int ib_nl_handle_resolve_resp(struct sk_buff *skb,
@@ -362,4 +381,7 @@ void ib_port_unregister_module_stat(struct kobject *kobj);

int ib_device_set_netns_put(struct sk_buff *skb,
			    struct ib_device *dev, u32 ns_fd);

int rdma_nl_net_init(struct rdma_dev_net *rnet);
void rdma_nl_net_exit(struct rdma_dev_net *rnet);
#endif /* _CORE_PRIV_H */
+13 −25
Original line number Diff line number Diff line
@@ -39,7 +39,6 @@
#include <linux/init.h>
#include <linux/netdevice.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
#include <linux/security.h>
#include <linux/notifier.h>
#include <linux/hashtable.h>
@@ -105,17 +104,7 @@ static DECLARE_RWSEM(clients_rwsem);
 */
#define CLIENT_DATA_REGISTERED XA_MARK_1

/**
 * struct rdma_dev_net - rdma net namespace metadata for a net
 * @net:	Pointer to owner net namespace
 * @id:		xarray id to identify the net namespace.
 */
struct rdma_dev_net {
	possible_net_t net;
	u32 id;
};

static unsigned int rdma_dev_net_id;
unsigned int rdma_dev_net_id;

/*
 * A list of net namespaces is maintained in an xarray. This is necessary
@@ -1050,7 +1039,7 @@ int rdma_compatdev_set(u8 enable)

static void rdma_dev_exit_net(struct net *net)
{
	struct rdma_dev_net *rnet = net_generic(net, rdma_dev_net_id);
	struct rdma_dev_net *rnet = rdma_net_to_dev_net(net);
	struct ib_device *dev;
	unsigned long index;
	int ret;
@@ -1084,25 +1073,32 @@ static void rdma_dev_exit_net(struct net *net)
	}
	up_read(&devices_rwsem);

	rdma_nl_net_exit(rnet);
	xa_erase(&rdma_nets, rnet->id);
}

static __net_init int rdma_dev_init_net(struct net *net)
{
	struct rdma_dev_net *rnet = net_generic(net, rdma_dev_net_id);
	struct rdma_dev_net *rnet = rdma_net_to_dev_net(net);
	unsigned long index;
	struct ib_device *dev;
	int ret;

	write_pnet(&rnet->net, net);

	ret = rdma_nl_net_init(rnet);
	if (ret)
		return ret;

	/* No need to create any compat devices in default init_net. */
	if (net_eq(net, &init_net))
		return 0;

	write_pnet(&rnet->net, net);

	ret = xa_alloc(&rdma_nets, &rnet->id, rnet, xa_limit_32b, GFP_KERNEL);
	if (ret)
	if (ret) {
		rdma_nl_net_exit(rnet);
		return ret;
	}

	down_read(&devices_rwsem);
	xa_for_each_marked (&devices, index, dev, DEVICE_REGISTERED) {
@@ -2629,12 +2625,6 @@ static int __init ib_core_init(void)
		goto err_comp_unbound;
	}

	ret = rdma_nl_init();
	if (ret) {
		pr_warn("Couldn't init IB netlink interface: err %d\n", ret);
		goto err_sysfs;
	}

	ret = addr_init();
	if (ret) {
		pr_warn("Could't init IB address resolution\n");
@@ -2680,8 +2670,6 @@ err_mad:
err_addr:
	addr_cleanup();
err_ibnl:
	rdma_nl_exit();
err_sysfs:
	class_unregister(&ib_class);
err_comp_unbound:
	destroy_workqueue(ib_comp_unbound_wq);
+4 −4
Original line number Diff line number Diff line
@@ -112,7 +112,7 @@ int iwpm_register_pid(struct iwpm_dev_data *pm_msg, u8 nl_client)
	pr_debug("%s: Multicasting a nlmsg (dev = %s ifname = %s iwpm = %s)\n",
		__func__, pm_msg->dev_name, pm_msg->if_name, iwpm_ulib_name);

	ret = rdma_nl_multicast(skb, RDMA_NL_GROUP_IWPM, GFP_KERNEL);
	ret = rdma_nl_multicast(&init_net, skb, RDMA_NL_GROUP_IWPM, GFP_KERNEL);
	if (ret) {
		skb = NULL; /* skb is freed in the netlink send-op handling */
		iwpm_user_pid = IWPM_PID_UNAVAILABLE;
@@ -202,7 +202,7 @@ int iwpm_add_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)
	nlmsg_end(skb, nlh);
	nlmsg_request->req_buffer = pm_msg;

	ret = rdma_nl_unicast_wait(skb, iwpm_user_pid);
	ret = rdma_nl_unicast_wait(&init_net, skb, iwpm_user_pid);
	if (ret) {
		skb = NULL; /* skb is freed in the netlink send-op handling */
		iwpm_user_pid = IWPM_PID_UNDEFINED;
@@ -297,7 +297,7 @@ int iwpm_add_and_query_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)
	nlmsg_end(skb, nlh);
	nlmsg_request->req_buffer = pm_msg;

	ret = rdma_nl_unicast_wait(skb, iwpm_user_pid);
	ret = rdma_nl_unicast_wait(&init_net, skb, iwpm_user_pid);
	if (ret) {
		skb = NULL; /* skb is freed in the netlink send-op handling */
		err_str = "Unable to send a nlmsg";
@@ -364,7 +364,7 @@ int iwpm_remove_mapping(struct sockaddr_storage *local_addr, u8 nl_client)

	nlmsg_end(skb, nlh);

	ret = rdma_nl_unicast_wait(skb, iwpm_user_pid);
	ret = rdma_nl_unicast_wait(&init_net, skb, iwpm_user_pid);
	if (ret) {
		skb = NULL; /* skb is freed in the netlink send-op handling */
		iwpm_user_pid = IWPM_PID_UNDEFINED;
+3 −3
Original line number Diff line number Diff line
@@ -645,7 +645,7 @@ static int send_mapinfo_num(u32 mapping_num, u8 nl_client, int iwpm_pid)

	nlmsg_end(skb, nlh);

	ret = rdma_nl_unicast(skb, iwpm_pid);
	ret = rdma_nl_unicast(&init_net, skb, iwpm_pid);
	if (ret) {
		skb = NULL;
		err_str = "Unable to send a nlmsg";
@@ -674,7 +674,7 @@ static int send_nlmsg_done(struct sk_buff *skb, u8 nl_client, int iwpm_pid)
		return -ENOMEM;
	}
	nlh->nlmsg_type = NLMSG_DONE;
	ret = rdma_nl_unicast(skb, iwpm_pid);
	ret = rdma_nl_unicast(&init_net, skb, iwpm_pid);
	if (ret)
		pr_warn("%s Unable to send a nlmsg\n", __func__);
	return ret;
@@ -824,7 +824,7 @@ int iwpm_send_hello(u8 nl_client, int iwpm_pid, u16 abi_version)
		goto hello_num_error;
	nlmsg_end(skb, nlh);

	ret = rdma_nl_unicast(skb, iwpm_pid);
	ret = rdma_nl_unicast(&init_net, skb, iwpm_pid);
	if (ret) {
		skb = NULL;
		err_str = "Unable to send a nlmsg";
Loading