diff options
author | Sean Hefty <sean.hefty@intel.com> | 2013-05-29 13:09:25 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2013-06-21 02:35:39 -0400 |
commit | ee7aed4528fb3c44a36abd79eb23fd5401a5b697 (patch) | |
tree | 16e084d5abbf42b117b8a4b4cb24dcb6d5bd281e /drivers/infiniband/core/ucma.c | |
parent | 94d0c939416480066d4e4d69e0d3c217bc083cea (diff) |
RDMA/ucma: Support querying for AF_IB addresses
The sockaddr structure for AF_IB is larger than sockaddr_in6. The
rdma cm user space ABI uses the latter to exchange address information
between user space and the kernel.
To support querying for larger addresses, define a new query command
that exchanges data using sockaddr_storage, rather than sockaddr_in6.
Unlike the existing query_route command, the new command only returns
address information. Route (i.e. path record) data is separated.
Signed-off-by: Sean Hefty <sean.hefty@intel.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/core/ucma.c')
-rw-r--r-- | drivers/infiniband/core/ucma.c | 76 |
1 files changed, 74 insertions, 2 deletions
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index e813774bf7a7..18bdccc0c2ec 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <rdma/ib_marshall.h> | 47 | #include <rdma/ib_marshall.h> |
48 | #include <rdma/rdma_cm.h> | 48 | #include <rdma/rdma_cm.h> |
49 | #include <rdma/rdma_cm_ib.h> | 49 | #include <rdma/rdma_cm_ib.h> |
50 | #include <rdma/ib_addr.h> | ||
50 | 51 | ||
51 | MODULE_AUTHOR("Sean Hefty"); | 52 | MODULE_AUTHOR("Sean Hefty"); |
52 | MODULE_DESCRIPTION("RDMA Userspace Connection Manager Access"); | 53 | MODULE_DESCRIPTION("RDMA Userspace Connection Manager Access"); |
@@ -649,7 +650,7 @@ static ssize_t ucma_query_route(struct ucma_file *file, | |||
649 | const char __user *inbuf, | 650 | const char __user *inbuf, |
650 | int in_len, int out_len) | 651 | int in_len, int out_len) |
651 | { | 652 | { |
652 | struct rdma_ucm_query_route cmd; | 653 | struct rdma_ucm_query cmd; |
653 | struct rdma_ucm_query_route_resp resp; | 654 | struct rdma_ucm_query_route_resp resp; |
654 | struct ucma_context *ctx; | 655 | struct ucma_context *ctx; |
655 | struct sockaddr *addr; | 656 | struct sockaddr *addr; |
@@ -709,6 +710,76 @@ out: | |||
709 | return ret; | 710 | return ret; |
710 | } | 711 | } |
711 | 712 | ||
713 | static void ucma_query_device_addr(struct rdma_cm_id *cm_id, | ||
714 | struct rdma_ucm_query_addr_resp *resp) | ||
715 | { | ||
716 | if (!cm_id->device) | ||
717 | return; | ||
718 | |||
719 | resp->node_guid = (__force __u64) cm_id->device->node_guid; | ||
720 | resp->port_num = cm_id->port_num; | ||
721 | resp->pkey = (__force __u16) cpu_to_be16( | ||
722 | ib_addr_get_pkey(&cm_id->route.addr.dev_addr)); | ||
723 | } | ||
724 | |||
725 | static ssize_t ucma_query_addr(struct ucma_context *ctx, | ||
726 | void __user *response, int out_len) | ||
727 | { | ||
728 | struct rdma_ucm_query_addr_resp resp; | ||
729 | struct sockaddr *addr; | ||
730 | int ret = 0; | ||
731 | |||
732 | if (out_len < sizeof(resp)) | ||
733 | return -ENOSPC; | ||
734 | |||
735 | memset(&resp, 0, sizeof resp); | ||
736 | |||
737 | addr = (struct sockaddr *) &ctx->cm_id->route.addr.src_addr; | ||
738 | resp.src_size = rdma_addr_size(addr); | ||
739 | memcpy(&resp.src_addr, addr, resp.src_size); | ||
740 | |||
741 | addr = (struct sockaddr *) &ctx->cm_id->route.addr.dst_addr; | ||
742 | resp.dst_size = rdma_addr_size(addr); | ||
743 | memcpy(&resp.dst_addr, addr, resp.dst_size); | ||
744 | |||
745 | ucma_query_device_addr(ctx->cm_id, &resp); | ||
746 | |||
747 | if (copy_to_user(response, &resp, sizeof(resp))) | ||
748 | ret = -EFAULT; | ||
749 | |||
750 | return ret; | ||
751 | } | ||
752 | |||
753 | static ssize_t ucma_query(struct ucma_file *file, | ||
754 | const char __user *inbuf, | ||
755 | int in_len, int out_len) | ||
756 | { | ||
757 | struct rdma_ucm_query cmd; | ||
758 | struct ucma_context *ctx; | ||
759 | void __user *response; | ||
760 | int ret; | ||
761 | |||
762 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) | ||
763 | return -EFAULT; | ||
764 | |||
765 | response = (void __user *)(unsigned long) cmd.response; | ||
766 | ctx = ucma_get_ctx(file, cmd.id); | ||
767 | if (IS_ERR(ctx)) | ||
768 | return PTR_ERR(ctx); | ||
769 | |||
770 | switch (cmd.option) { | ||
771 | case RDMA_USER_CM_QUERY_ADDR: | ||
772 | ret = ucma_query_addr(ctx, response, out_len); | ||
773 | break; | ||
774 | default: | ||
775 | ret = -ENOSYS; | ||
776 | break; | ||
777 | } | ||
778 | |||
779 | ucma_put_ctx(ctx); | ||
780 | return ret; | ||
781 | } | ||
782 | |||
712 | static void ucma_copy_conn_param(struct rdma_cm_id *id, | 783 | static void ucma_copy_conn_param(struct rdma_cm_id *id, |
713 | struct rdma_conn_param *dst, | 784 | struct rdma_conn_param *dst, |
714 | struct rdma_ucm_conn_param *src) | 785 | struct rdma_ucm_conn_param *src) |
@@ -1241,7 +1312,8 @@ static ssize_t (*ucma_cmd_table[])(struct ucma_file *file, | |||
1241 | [RDMA_USER_CM_CMD_NOTIFY] = ucma_notify, | 1312 | [RDMA_USER_CM_CMD_NOTIFY] = ucma_notify, |
1242 | [RDMA_USER_CM_CMD_JOIN_MCAST] = ucma_join_multicast, | 1313 | [RDMA_USER_CM_CMD_JOIN_MCAST] = ucma_join_multicast, |
1243 | [RDMA_USER_CM_CMD_LEAVE_MCAST] = ucma_leave_multicast, | 1314 | [RDMA_USER_CM_CMD_LEAVE_MCAST] = ucma_leave_multicast, |
1244 | [RDMA_USER_CM_CMD_MIGRATE_ID] = ucma_migrate_id | 1315 | [RDMA_USER_CM_CMD_MIGRATE_ID] = ucma_migrate_id, |
1316 | [RDMA_USER_CM_CMD_QUERY] = ucma_query | ||
1245 | }; | 1317 | }; |
1246 | 1318 | ||
1247 | static ssize_t ucma_write(struct file *filp, const char __user *buf, | 1319 | static ssize_t ucma_write(struct file *filp, const char __user *buf, |