The current query_route command only supports 2 path records. Add support for query_path, which is capable of supporting multiple paths.
Signed-off-by: Sean Hefty <[email protected]> --- include/rdma/rdma_cma_abi.h | 10 +++++ src/cma.c | 82 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 1 deletions(-) diff --git a/include/rdma/rdma_cma_abi.h b/include/rdma/rdma_cma_abi.h index 5c736fb..6c83fe8 100644 --- a/include/rdma/rdma_cma_abi.h +++ b/include/rdma/rdma_cma_abi.h @@ -35,6 +35,7 @@ #include <infiniband/kern-abi.h> #include <infiniband/sa-kern-abi.h> +#include <infiniband/sa.h> /* * This file must be kept in sync with the kernel's version of rdma_user_cm.h @@ -114,7 +115,8 @@ struct ucma_abi_resolve_route { }; enum { - UCMA_QUERY_ADDR + UCMA_QUERY_ADDR, + UCMA_QUERY_PATH }; struct ucma_abi_query { @@ -144,6 +146,12 @@ struct ucma_abi_query_addr_resp { struct sockaddr_storage dst_addr; }; +struct ucma_abi_query_path_resp { + __u32 num_paths; + __u32 reserved; + struct ib_path_data path_data[0]; +}; + struct ucma_abi_conn_param { __u32 qp_num; __u32 reserved; diff --git a/src/cma.c b/src/cma.c index 2aef594..c3c6b73 100644 --- a/src/cma.c +++ b/src/cma.c @@ -506,6 +506,88 @@ static int ucma_query_addr(struct rdma_cm_id *id) return 0; } +static void ucma_convert_path(struct ib_path_data *path_data, + struct ibv_sa_path_rec *sa_path) +{ + uint32_t fl_hop; + + sa_path->dgid = path_data->path.dgid; + sa_path->sgid = path_data->path.sgid; + sa_path->dlid = path_data->path.dlid; + sa_path->slid = path_data->path.slid; + sa_path->raw_traffic = 0; + + fl_hop = ntohl(path_data->path.flowlabel_hoplimit); + sa_path->flow_label = htonl(fl_hop >> 8); + sa_path->hop_limit = (uint8_t) fl_hop; + + sa_path->traffic_class = path_data->path.tclass; + sa_path->reversible = path_data->path.reversible_numpath >> 7; + sa_path->numb_path = 1; + sa_path->pkey = path_data->path.pkey; + sa_path->sl = ntohs(path_data->path.qosclass_sl) & 0xF; + sa_path->mtu_selector = 1; + sa_path->mtu = path_data->path.mtu & 0x1F; + sa_path->rate_selector = 1; + sa_path->rate = path_data->path.rate & 0x1F; + sa_path->packet_life_time_selector = 1; + sa_path->packet_life_time = path_data->path.packetlifetime & 0x1F; + + sa_path->preference = (uint8_t) path_data->flags; +} + +static int ucma_query_path(struct rdma_cm_id *id) +{ + struct ucma_abi_query_path_resp *resp; + struct ucma_abi_query *cmd; + struct ucma_abi_cmd_hdr *hdr; + struct cma_id_private *id_priv; + void *msg; + int ret, size, i; + + size = sizeof(*hdr) + sizeof(*cmd); + msg = alloca(size); + if (!msg) + return ERR(ENOMEM); + + hdr = msg; + cmd = msg + sizeof(*hdr); + + hdr->cmd = UCMA_CMD_QUERY; + hdr->in = sizeof(*cmd); + hdr->out = sizeof(*resp) + sizeof(struct ib_path_data) * 6; + + memset(cmd, 0, sizeof(*cmd)); + + resp = alloca(hdr->out); + if (!resp) + return ERR(ENOMEM); + + id_priv = container_of(id, struct cma_id_private, id); + cmd->response = (uintptr_t) resp; + cmd->id = id_priv->handle; + cmd->option = UCMA_QUERY_PATH; + + ret = write(id->channel->fd, msg, size); + if (ret != size) + return (ret >= 0) ? ERR(ENODATA) : -1; + + VALGRIND_MAKE_MEM_DEFINED(resp, hdr->out); + + if (resp->num_paths) { + id->route.path_rec = malloc(sizeof(*id->route.path_rec) * + resp->num_paths); + if (!id->route.path_rec) + return ERR(ENOMEM); + + id->route.num_paths = resp->num_paths; + for (i = 0; i < resp->num_paths; i++) + ucma_convert_path(&resp->path_data[i], &id->route.path_rec[i]); + } + + return 0; +} + static int ucma_query_route(struct rdma_cm_id *id) { struct ucma_abi_query_route_resp *resp; -- To unsubscribe from this list: send the line "unsubscribe linux-rdma" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
