Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fa20105e authored by Guy Shapiro's avatar Guy Shapiro Committed by Doug Ledford
Browse files

IB/cma: Add support for network namespaces



Add support for network namespaces in the ib_cma module. This is
accomplished by:

1. Adding network namespace parameter for rdma_create_id. This parameter is
   used to populate the network namespace field in rdma_id_private.
   rdma_create_id keeps a reference on the network namespace.
2. Using the network namespace from the rdma_id instead of init_net inside
   of ib_cma, when listening on an ID and when looking for an ID for an
   incoming request.
3. Decrementing the reference count for the appropriate network namespace
   when calling rdma_destroy_id.

In order to preserve the current behavior init_net is passed when calling
from other modules.

Signed-off-by: default avatarGuy Shapiro <guysh@mellanox.com>
Signed-off-by: default avatarHaggai Eran <haggaie@mellanox.com>
Signed-off-by: default avatarYotam Kenneth <yotamke@mellanox.com>
Signed-off-by: default avatarShachar Raindel <raindel@mellanox.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 4be74b42
Loading
Loading
Loading
Loading
+28 −18
Original line number Diff line number Diff line
@@ -600,7 +600,8 @@ static int cma_disable_callback(struct rdma_id_private *id_priv,
	return 0;
}

struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
struct rdma_cm_id *rdma_create_id(struct net *net,
				  rdma_cm_event_handler event_handler,
				  void *context, enum rdma_port_space ps,
				  enum ib_qp_type qp_type)
{
@@ -624,7 +625,7 @@ struct rdma_cm_id *rdma_create_id(rdma_cm_event_handler event_handler,
	INIT_LIST_HEAD(&id_priv->listen_list);
	INIT_LIST_HEAD(&id_priv->mc_list);
	get_random_bytes(&id_priv->seq_num, sizeof id_priv->seq_num);
	id_priv->id.route.addr.dev_addr.net = &init_net;
	id_priv->id.route.addr.dev_addr.net = get_net(net);

	return &id_priv->id;
}
@@ -1278,7 +1279,7 @@ static bool cma_match_net_dev(const struct rdma_id_private *id_priv,
		       cma_protocol_roce(&id_priv->id);

	return !addr->dev_addr.bound_dev_if ||
	       (net_eq(dev_net(net_dev), &init_net) &&
	       (net_eq(dev_net(net_dev), addr->dev_addr.net) &&
		addr->dev_addr.bound_dev_if == net_dev->ifindex);
}

@@ -1339,7 +1340,7 @@ static struct rdma_id_private *cma_id_from_event(struct ib_cm_id *cm_id,
		}
	}

	bind_list = cma_ps_find(&init_net,
	bind_list = cma_ps_find(*net_dev ? dev_net(*net_dev) : &init_net,
				rdma_ps_from_service_id(req.service_id),
				cma_port_from_service_id(req.service_id));
	id_priv = cma_find_listener(bind_list, cm_id, ib_event, &req, *net_dev);
@@ -1411,6 +1412,7 @@ static void cma_cancel_operation(struct rdma_id_private *id_priv,
static void cma_release_port(struct rdma_id_private *id_priv)
{
	struct rdma_bind_list *bind_list = id_priv->bind_list;
	struct net *net = id_priv->id.route.addr.dev_addr.net;

	if (!bind_list)
		return;
@@ -1418,7 +1420,7 @@ static void cma_release_port(struct rdma_id_private *id_priv)
	mutex_lock(&lock);
	hlist_del(&id_priv->node);
	if (hlist_empty(&bind_list->owners)) {
		cma_ps_remove(&init_net, bind_list->ps, bind_list->port);
		cma_ps_remove(net, bind_list->ps, bind_list->port);
		kfree(bind_list);
	}
	mutex_unlock(&lock);
@@ -1477,6 +1479,7 @@ void rdma_destroy_id(struct rdma_cm_id *id)
		cma_deref_id(id_priv->id.context);

	kfree(id_priv->id.route.path_rec);
	put_net(id_priv->id.route.addr.dev_addr.net);
	kfree(id_priv);
}
EXPORT_SYMBOL(rdma_destroy_id);
@@ -1607,7 +1610,8 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
		      ib_event->param.req_rcvd.primary_path->service_id;
	int ret;

	id = rdma_create_id(listen_id->event_handler, listen_id->context,
	id = rdma_create_id(listen_id->route.addr.dev_addr.net,
			    listen_id->event_handler, listen_id->context,
			    listen_id->ps, ib_event->param.req_rcvd.qp_type);
	if (IS_ERR(id))
		return NULL;
@@ -1662,9 +1666,10 @@ static struct rdma_id_private *cma_new_udp_id(struct rdma_cm_id *listen_id,
	struct rdma_id_private *id_priv;
	struct rdma_cm_id *id;
	const sa_family_t ss_family = listen_id->route.addr.src_addr.ss_family;
	struct net *net = listen_id->route.addr.dev_addr.net;
	int ret;

	id = rdma_create_id(listen_id->event_handler, listen_id->context,
	id = rdma_create_id(net, listen_id->event_handler, listen_id->context,
			    listen_id->ps, IB_QPT_UD);
	if (IS_ERR(id))
		return NULL;
@@ -1901,7 +1906,8 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
		return -ECONNABORTED;

	/* Create a new RDMA id for the new IW CM ID */
	new_cm_id = rdma_create_id(listen_id->id.event_handler,
	new_cm_id = rdma_create_id(listen_id->id.route.addr.dev_addr.net,
				   listen_id->id.event_handler,
				   listen_id->id.context,
				   RDMA_PS_TCP, IB_QPT_RC);
	if (IS_ERR(new_cm_id)) {
@@ -2029,12 +2035,13 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv,
{
	struct rdma_id_private *dev_id_priv;
	struct rdma_cm_id *id;
	struct net *net = id_priv->id.route.addr.dev_addr.net;
	int ret;

	if (cma_family(id_priv) == AF_IB && !rdma_cap_ib_cm(cma_dev->device, 1))
		return;

	id = rdma_create_id(cma_listen_handler, id_priv, id_priv->id.ps,
	id = rdma_create_id(net, cma_listen_handler, id_priv, id_priv->id.ps,
			    id_priv->id.qp_type);
	if (IS_ERR(id))
		return;
@@ -2708,7 +2715,8 @@ static int cma_alloc_port(enum rdma_port_space ps,
	if (!bind_list)
		return -ENOMEM;

	ret = cma_ps_alloc(&init_net, ps, bind_list, snum);
	ret = cma_ps_alloc(id_priv->id.route.addr.dev_addr.net, ps, bind_list,
			   snum);
	if (ret < 0)
		goto err;

@@ -2727,13 +2735,14 @@ static int cma_alloc_any_port(enum rdma_port_space ps,
	static unsigned int last_used_port;
	int low, high, remaining;
	unsigned int rover;
	struct net *net = id_priv->id.route.addr.dev_addr.net;

	inet_get_local_port_range(&init_net, &low, &high);
	inet_get_local_port_range(net, &low, &high);
	remaining = (high - low) + 1;
	rover = prandom_u32() % remaining + low;
retry:
	if (last_used_port != rover &&
	    !cma_ps_find(&init_net, ps, (unsigned short)rover)) {
	    !cma_ps_find(net, ps, (unsigned short)rover)) {
		int ret = cma_alloc_port(ps, id_priv, rover);
		/*
		 * Remember previously used port number in order to avoid
@@ -2799,7 +2808,7 @@ static int cma_use_port(enum rdma_port_space ps,
	if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
		return -EACCES;

	bind_list = cma_ps_find(&init_net, ps, snum);
	bind_list = cma_ps_find(id_priv->id.route.addr.dev_addr.net, ps, snum);
	if (!bind_list) {
		ret = cma_alloc_port(ps, id_priv, snum);
	} else {
@@ -2991,8 +3000,11 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
		if (addr->sa_family == AF_INET)
			id_priv->afonly = 1;
#if IS_ENABLED(CONFIG_IPV6)
		else if (addr->sa_family == AF_INET6)
			id_priv->afonly = init_net.ipv6.sysctl.bindv6only;
		else if (addr->sa_family == AF_INET6) {
			struct net *net = id_priv->id.route.addr.dev_addr.net;

			id_priv->afonly = net->ipv6.sysctl.bindv6only;
		}
#endif
	}
	ret = cma_get_port(id_priv);
@@ -3797,6 +3809,7 @@ static int cma_netdev_change(struct net_device *ndev, struct rdma_id_private *id
	dev_addr = &id_priv->id.route.addr.dev_addr;

	if ((dev_addr->bound_dev_if == ndev->ifindex) &&
	    (net_eq(dev_net(ndev), dev_addr->net)) &&
	    memcmp(dev_addr->src_dev_addr, ndev->dev_addr, ndev->addr_len)) {
		printk(KERN_INFO "RDMA CM addr change for ndev %s used by id %p\n",
		       ndev->name, &id_priv->id);
@@ -3822,9 +3835,6 @@ static int cma_netdev_callback(struct notifier_block *self, unsigned long event,
	struct rdma_id_private *id_priv;
	int ret = NOTIFY_DONE;

	if (dev_net(ndev) != &init_net)
		return NOTIFY_DONE;

	if (event != NETDEV_BONDING_FAILOVER)
		return NOTIFY_DONE;

+2 −1
Original line number Diff line number Diff line
@@ -472,7 +472,8 @@ static ssize_t ucma_create_id(struct ucma_file *file, const char __user *inbuf,
		return -ENOMEM;

	ctx->uid = cmd.uid;
	ctx->cm_id = rdma_create_id(ucma_event_handler, ctx, cmd.ps, qp_type);
	ctx->cm_id = rdma_create_id(&init_net, ucma_event_handler, ctx, cmd.ps,
				    qp_type);
	if (IS_ERR(ctx->cm_id)) {
		ret = PTR_ERR(ctx->cm_id);
		goto err1;
+1 −1
Original line number Diff line number Diff line
@@ -1017,7 +1017,7 @@ int iser_connect(struct iser_conn *iser_conn,
	ib_conn->beacon.wr_id = ISER_BEACON_WRID;
	ib_conn->beacon.opcode = IB_WR_SEND;

	ib_conn->cma_id = rdma_create_id(iser_cma_handler,
	ib_conn->cma_id = rdma_create_id(&init_net, iser_cma_handler,
					 (void *)iser_conn,
					 RDMA_PS_TCP, IB_QPT_RC);
	if (IS_ERR(ib_conn->cma_id)) {
+1 −1
Original line number Diff line number Diff line
@@ -3096,7 +3096,7 @@ isert_setup_id(struct isert_np *isert_np)
	sa = (struct sockaddr *)&np->np_sockaddr;
	isert_dbg("ksockaddr: %p, sa: %p\n", &np->np_sockaddr, sa);

	id = rdma_create_id(isert_cma_handler, isert_np,
	id = rdma_create_id(&init_net, isert_cma_handler, isert_np,
			    RDMA_PS_TCP, IB_QPT_RC);
	if (IS_ERR(id)) {
		isert_err("rdma_create_id() failed: %ld\n", PTR_ERR(id));
+3 −1
Original line number Diff line number Diff line
@@ -128,7 +128,9 @@ extern kib_tunables_t kiblnd_tunables;
				     IBLND_CREDIT_HIGHWATER_V1 : \
				     *kiblnd_tunables.kib_peercredits_hiw) /* when eagerly to return credits */

#define kiblnd_rdma_create_id(cb, dev, ps, qpt) rdma_create_id(cb, dev, ps, qpt)
#define kiblnd_rdma_create_id(cb, dev, ps, qpt) rdma_create_id(&init_net, \
							       cb, dev, \
							       ps, qpt)

static inline int
kiblnd_concurrent_sends_v1(void)
Loading