Skip to content

Commit

Permalink
RDMA/ucma: Allow user space to specify AF_IB when joining multicast
Browse files Browse the repository at this point in the history
Allow user space applications to join multicast groups using MGIDs
directly.  MGIDs may be passed using AF_IB addresses.  Since the
current multicast join command only supports addresses as large as
sockaddr_in6, define a new structure for joining addresses specified
using sockaddr_ib.

Since AF_IB allows the user to specify the qkey when resolving a
remote UD QP address, when joining the multicast group use the qkey
value, if one has been assigned.

Signed-off-by: Sean Hefty <sean.hefty@intel.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
  • Loading branch information
shefty authored and rolandd committed Jun 21, 2013
1 parent 209cf2a commit 5bc2b7b
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 14 deletions.
9 changes: 7 additions & 2 deletions drivers/infiniband/core/cma.c
Original file line number Diff line number Diff line change
Expand Up @@ -3149,6 +3149,8 @@ static void cma_set_mgid(struct rdma_id_private *id_priv,
0xFF10A01B)) {
/* IPv6 address is an SA assigned MGID. */
memcpy(mgid, &sin6->sin6_addr, sizeof *mgid);
} else if (addr->sa_family == AF_IB) {
memcpy(mgid, &((struct sockaddr_ib *) addr)->sib_addr, sizeof *mgid);
} else if ((addr->sa_family == AF_INET6)) {
ipv6_ib_mc_map(&sin6->sin6_addr, dev_addr->broadcast, mc_map);
if (id_priv->id.ps == RDMA_PS_UDP)
Expand Down Expand Up @@ -3176,9 +3178,12 @@ static int cma_join_ib_multicast(struct rdma_id_private *id_priv,
if (ret)
return ret;

ret = cma_set_qkey(id_priv, 0);
if (ret)
return ret;

cma_set_mgid(id_priv, (struct sockaddr *) &mc->addr, &rec.mgid);
if (id_priv->id.ps == RDMA_PS_UDP)
rec.qkey = cpu_to_be32(RDMA_UDP_QKEY);
rec.qkey = cpu_to_be32(id_priv->qkey);
rdma_addr_get_sgid(dev_addr, &rec.port_gid);
rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr));
rec.join_state = 1;
Expand Down
55 changes: 44 additions & 11 deletions drivers/infiniband/core/ucma.c
Original file line number Diff line number Diff line change
Expand Up @@ -1229,23 +1229,23 @@ static ssize_t ucma_notify(struct ucma_file *file, const char __user *inbuf,
return ret;
}

static ssize_t ucma_join_ip_multicast(struct ucma_file *file,
const char __user *inbuf,
int in_len, int out_len)
static ssize_t ucma_process_join(struct ucma_file *file,
struct rdma_ucm_join_mcast *cmd, int out_len)
{
struct rdma_ucm_join_ip_mcast cmd;
struct rdma_ucm_create_id_resp resp;
struct ucma_context *ctx;
struct ucma_multicast *mc;
struct sockaddr *addr;
int ret;

if (out_len < sizeof(resp))
return -ENOSPC;

if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
return -EFAULT;
addr = (struct sockaddr *) &cmd->addr;
if (cmd->reserved || !cmd->addr_size || (cmd->addr_size != rdma_addr_size(addr)))
return -EINVAL;

ctx = ucma_get_ctx(file, cmd.id);
ctx = ucma_get_ctx(file, cmd->id);
if (IS_ERR(ctx))
return PTR_ERR(ctx);

Expand All @@ -1256,14 +1256,14 @@ static ssize_t ucma_join_ip_multicast(struct ucma_file *file,
goto err1;
}

mc->uid = cmd.uid;
memcpy(&mc->addr, &cmd.addr, sizeof cmd.addr);
mc->uid = cmd->uid;
memcpy(&mc->addr, addr, cmd->addr_size);
ret = rdma_join_multicast(ctx->cm_id, (struct sockaddr *) &mc->addr, mc);
if (ret)
goto err2;

resp.id = mc->id;
if (copy_to_user((void __user *)(unsigned long)cmd.response,
if (copy_to_user((void __user *)(unsigned long) cmd->response,
&resp, sizeof(resp))) {
ret = -EFAULT;
goto err3;
Expand All @@ -1288,6 +1288,38 @@ static ssize_t ucma_join_ip_multicast(struct ucma_file *file,
return ret;
}

static ssize_t ucma_join_ip_multicast(struct ucma_file *file,
const char __user *inbuf,
int in_len, int out_len)
{
struct rdma_ucm_join_ip_mcast cmd;
struct rdma_ucm_join_mcast join_cmd;

if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
return -EFAULT;

join_cmd.response = cmd.response;
join_cmd.uid = cmd.uid;
join_cmd.id = cmd.id;
join_cmd.addr_size = rdma_addr_size((struct sockaddr *) &cmd.addr);
join_cmd.reserved = 0;
memcpy(&join_cmd.addr, &cmd.addr, join_cmd.addr_size);

return ucma_process_join(file, &join_cmd, out_len);
}

static ssize_t ucma_join_multicast(struct ucma_file *file,
const char __user *inbuf,
int in_len, int out_len)
{
struct rdma_ucm_join_mcast cmd;

if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
return -EFAULT;

return ucma_process_join(file, &cmd, out_len);
}

static ssize_t ucma_leave_multicast(struct ucma_file *file,
const char __user *inbuf,
int in_len, int out_len)
Expand Down Expand Up @@ -1451,7 +1483,8 @@ static ssize_t (*ucma_cmd_table[])(struct ucma_file *file,
[RDMA_USER_CM_CMD_MIGRATE_ID] = ucma_migrate_id,
[RDMA_USER_CM_CMD_QUERY] = ucma_query,
[RDMA_USER_CM_CMD_BIND] = ucma_bind,
[RDMA_USER_CM_CMD_RESOLVE_ADDR] = ucma_resolve_addr
[RDMA_USER_CM_CMD_RESOLVE_ADDR] = ucma_resolve_addr,
[RDMA_USER_CM_CMD_JOIN_MCAST] = ucma_join_multicast
};

static ssize_t ucma_write(struct file *filp, const char __user *buf,
Expand Down
12 changes: 11 additions & 1 deletion include/uapi/rdma/rdma_user_cm.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ enum {
RDMA_USER_CM_CMD_MIGRATE_ID,
RDMA_USER_CM_CMD_QUERY,
RDMA_USER_CM_CMD_BIND,
RDMA_USER_CM_CMD_RESOLVE_ADDR
RDMA_USER_CM_CMD_RESOLVE_ADDR,
RDMA_USER_CM_CMD_JOIN_MCAST
};

/*
Expand Down Expand Up @@ -242,6 +243,15 @@ struct rdma_ucm_join_ip_mcast {
__u32 id;
};

struct rdma_ucm_join_mcast {
__u64 response; /* rdma_ucma_create_id_resp */
__u64 uid;
__u32 id;
__u16 addr_size;
__u16 reserved;
struct sockaddr_storage addr;
};

struct rdma_ucm_get_event {
__u64 response;
};
Expand Down

0 comments on commit 5bc2b7b

Please sign in to comment.