diff options
author | Sean Hefty <sean.hefty@intel.com> | 2013-05-29 13:09:33 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2013-06-21 02:35:45 -0400 |
commit | 5bc2b7b397b02026a0596a7807443a18422733fa (patch) | |
tree | 23da8bd5f5932882a8f5524e862134c85fb3116e | |
parent | 209cf2a751f9ff2a516102339e54fcac0176fa78 (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.c | 9 | ||||
-rw-r--r-- | drivers/infiniband/core/ucma.c | 55 | ||||
-rw-r--r-- | include/uapi/rdma/rdma_user_cm.h | 12 |
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 | ||
1232 | static ssize_t ucma_join_ip_multicast(struct ucma_file *file, | 1232 | static 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 | ||
1291 | static 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 | |||
1311 | static 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 | |||
1291 | static ssize_t ucma_leave_multicast(struct ucma_file *file, | 1323 | static 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 | ||
1457 | static ssize_t ucma_write(struct file *filp, const char __user *buf, | 1490 | static 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 | ||
246 | struct 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 | |||
245 | struct rdma_ucm_get_event { | 255 | struct rdma_ucm_get_event { |
246 | __u64 response; | 256 | __u64 response; |
247 | }; | 257 | }; |