aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Hefty <sean.hefty@intel.com>2013-05-29 13:09:33 -0400
committerRoland Dreier <roland@purestorage.com>2013-06-21 02:35:45 -0400
commit5bc2b7b397b02026a0596a7807443a18422733fa (patch)
tree23da8bd5f5932882a8f5524e862134c85fb3116e
parent209cf2a751f9ff2a516102339e54fcac0176fa78 (diff)
RDMA/ucma: Allow user space to specify AF_IB when joining multicast
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>
-rw-r--r--drivers/infiniband/core/cma.c9
-rw-r--r--drivers/infiniband/core/ucma.c55
-rw-r--r--include/uapi/rdma/rdma_user_cm.h12
3 files changed, 62 insertions, 14 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 32d74c76e638..3d30c388e043 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -3149,6 +3149,8 @@ static void cma_set_mgid(struct rdma_id_private *id_priv,
3149 0xFF10A01B)) { 3149 0xFF10A01B)) {
3150 /* IPv6 address is an SA assigned MGID. */ 3150 /* IPv6 address is an SA assigned MGID. */
3151 memcpy(mgid, &sin6->sin6_addr, sizeof *mgid); 3151 memcpy(mgid, &sin6->sin6_addr, sizeof *mgid);
3152 } else if (addr->sa_family == AF_IB) {
3153 memcpy(mgid, &((struct sockaddr_ib *) addr)->sib_addr, sizeof *mgid);
3152 } else if ((addr->sa_family == AF_INET6)) { 3154 } else if ((addr->sa_family == AF_INET6)) {
3153 ipv6_ib_mc_map(&sin6->sin6_addr, dev_addr->broadcast, mc_map); 3155 ipv6_ib_mc_map(&sin6->sin6_addr, dev_addr->broadcast, mc_map);
3154 if (id_priv->id.ps == RDMA_PS_UDP) 3156 if (id_priv->id.ps == RDMA_PS_UDP)
@@ -3176,9 +3178,12 @@ static int cma_join_ib_multicast(struct rdma_id_private *id_priv,
3176 if (ret) 3178 if (ret)
3177 return ret; 3179 return ret;
3178 3180
3181 ret = cma_set_qkey(id_priv, 0);
3182 if (ret)
3183 return ret;
3184
3179 cma_set_mgid(id_priv, (struct sockaddr *) &mc->addr, &rec.mgid); 3185 cma_set_mgid(id_priv, (struct sockaddr *) &mc->addr, &rec.mgid);
3180 if (id_priv->id.ps == RDMA_PS_UDP) 3186 rec.qkey = cpu_to_be32(id_priv->qkey);
3181 rec.qkey = cpu_to_be32(RDMA_UDP_QKEY);
3182 rdma_addr_get_sgid(dev_addr, &rec.port_gid); 3187 rdma_addr_get_sgid(dev_addr, &rec.port_gid);
3183 rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr)); 3188 rec.pkey = cpu_to_be16(ib_addr_get_pkey(dev_addr));
3184 rec.join_state = 1; 3189 rec.join_state = 1;
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index 00ce99044a48..b0f189be543b 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -1229,23 +1229,23 @@ static ssize_t ucma_notify(struct ucma_file *file, const char __user *inbuf,
1229 return ret; 1229 return ret;
1230} 1230}
1231 1231
1232static ssize_t ucma_join_ip_multicast(struct ucma_file *file, 1232static ssize_t ucma_process_join(struct ucma_file *file,
1233 const char __user *inbuf, 1233 struct rdma_ucm_join_mcast *cmd, int out_len)
1234 int in_len, int out_len)
1235{ 1234{
1236 struct rdma_ucm_join_ip_mcast cmd;
1237 struct rdma_ucm_create_id_resp resp; 1235 struct rdma_ucm_create_id_resp resp;
1238 struct ucma_context *ctx; 1236 struct ucma_context *ctx;
1239 struct ucma_multicast *mc; 1237 struct ucma_multicast *mc;
1238 struct sockaddr *addr;
1240 int ret; 1239 int ret;
1241 1240
1242 if (out_len < sizeof(resp)) 1241 if (out_len < sizeof(resp))
1243 return -ENOSPC; 1242 return -ENOSPC;
1244 1243
1245 if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 1244 addr = (struct sockaddr *) &cmd->addr;
1246 return -EFAULT; 1245 if (cmd->reserved || !cmd->addr_size || (cmd->addr_size != rdma_addr_size(addr)))
1246 return -EINVAL;
1247 1247
1248 ctx = ucma_get_ctx(file, cmd.id); 1248 ctx = ucma_get_ctx(file, cmd->id);
1249 if (IS_ERR(ctx)) 1249 if (IS_ERR(ctx))
1250 return PTR_ERR(ctx); 1250 return PTR_ERR(ctx);
1251 1251
@@ -1256,14 +1256,14 @@ static ssize_t ucma_join_ip_multicast(struct ucma_file *file,
1256 goto err1; 1256 goto err1;
1257 } 1257 }
1258 1258
1259 mc->uid = cmd.uid; 1259 mc->uid = cmd->uid;
1260 memcpy(&mc->addr, &cmd.addr, sizeof cmd.addr); 1260 memcpy(&mc->addr, addr, cmd->addr_size);
1261 ret = rdma_join_multicast(ctx->cm_id, (struct sockaddr *) &mc->addr, mc); 1261 ret = rdma_join_multicast(ctx->cm_id, (struct sockaddr *) &mc->addr, mc);
1262 if (ret) 1262 if (ret)
1263 goto err2; 1263 goto err2;
1264 1264
1265 resp.id = mc->id; 1265 resp.id = mc->id;
1266 if (copy_to_user((void __user *)(unsigned long)cmd.response, 1266 if (copy_to_user((void __user *)(unsigned long) cmd->response,
1267 &resp, sizeof(resp))) { 1267 &resp, sizeof(resp))) {
1268 ret = -EFAULT; 1268 ret = -EFAULT;
1269 goto err3; 1269 goto err3;
@@ -1288,6 +1288,38 @@ err1:
1288 return ret; 1288 return ret;
1289} 1289}
1290 1290
1291static ssize_t ucma_join_ip_multicast(struct ucma_file *file,
1292 const char __user *inbuf,
1293 int in_len, int out_len)
1294{
1295 struct rdma_ucm_join_ip_mcast cmd;
1296 struct rdma_ucm_join_mcast join_cmd;
1297
1298 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1299 return -EFAULT;
1300
1301 join_cmd.response = cmd.response;
1302 join_cmd.uid = cmd.uid;
1303 join_cmd.id = cmd.id;
1304 join_cmd.addr_size = rdma_addr_size((struct sockaddr *) &cmd.addr);
1305 join_cmd.reserved = 0;
1306 memcpy(&join_cmd.addr, &cmd.addr, join_cmd.addr_size);
1307
1308 return ucma_process_join(file, &join_cmd, out_len);
1309}
1310
1311static ssize_t ucma_join_multicast(struct ucma_file *file,
1312 const char __user *inbuf,
1313 int in_len, int out_len)
1314{
1315 struct rdma_ucm_join_mcast cmd;
1316
1317 if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
1318 return -EFAULT;
1319
1320 return ucma_process_join(file, &cmd, out_len);
1321}
1322
1291static ssize_t ucma_leave_multicast(struct ucma_file *file, 1323static ssize_t ucma_leave_multicast(struct ucma_file *file,
1292 const char __user *inbuf, 1324 const char __user *inbuf,
1293 int in_len, int out_len) 1325 int in_len, int out_len)
@@ -1451,7 +1483,8 @@ static ssize_t (*ucma_cmd_table[])(struct ucma_file *file,
1451 [RDMA_USER_CM_CMD_MIGRATE_ID] = ucma_migrate_id, 1483 [RDMA_USER_CM_CMD_MIGRATE_ID] = ucma_migrate_id,
1452 [RDMA_USER_CM_CMD_QUERY] = ucma_query, 1484 [RDMA_USER_CM_CMD_QUERY] = ucma_query,
1453 [RDMA_USER_CM_CMD_BIND] = ucma_bind, 1485 [RDMA_USER_CM_CMD_BIND] = ucma_bind,
1454 [RDMA_USER_CM_CMD_RESOLVE_ADDR] = ucma_resolve_addr 1486 [RDMA_USER_CM_CMD_RESOLVE_ADDR] = ucma_resolve_addr,
1487 [RDMA_USER_CM_CMD_JOIN_MCAST] = ucma_join_multicast
1455}; 1488};
1456 1489
1457static ssize_t ucma_write(struct file *filp, const char __user *buf, 1490static ssize_t ucma_write(struct file *filp, const char __user *buf,
diff --git a/include/uapi/rdma/rdma_user_cm.h b/include/uapi/rdma/rdma_user_cm.h
index 6d03f9c16f1e..99b80abf360a 100644
--- a/include/uapi/rdma/rdma_user_cm.h
+++ b/include/uapi/rdma/rdma_user_cm.h
@@ -64,7 +64,8 @@ enum {
64 RDMA_USER_CM_CMD_MIGRATE_ID, 64 RDMA_USER_CM_CMD_MIGRATE_ID,
65 RDMA_USER_CM_CMD_QUERY, 65 RDMA_USER_CM_CMD_QUERY,
66 RDMA_USER_CM_CMD_BIND, 66 RDMA_USER_CM_CMD_BIND,
67 RDMA_USER_CM_CMD_RESOLVE_ADDR 67 RDMA_USER_CM_CMD_RESOLVE_ADDR,
68 RDMA_USER_CM_CMD_JOIN_MCAST
68}; 69};
69 70
70/* 71/*
@@ -242,6 +243,15 @@ struct rdma_ucm_join_ip_mcast {
242 __u32 id; 243 __u32 id;
243}; 244};
244 245
246struct rdma_ucm_join_mcast {
247 __u64 response; /* rdma_ucma_create_id_resp */
248 __u64 uid;
249 __u32 id;
250 __u16 addr_size;
251 __u16 reserved;
252 struct sockaddr_storage addr;
253};
254
245struct rdma_ucm_get_event { 255struct rdma_ucm_get_event {
246 __u64 response; 256 __u64 response;
247}; 257};