]> git.openfabrics.org - ~shefty/librdmacm.git/commitdiff
librdmacm: add ability to query IB path records
authorSean Hefty <sean.hefty@intel.com>
Thu, 6 May 2010 22:43:08 +0000 (15:43 -0700)
committerSean Hefty <sean.hefty@intel.com>
Thu, 6 May 2010 22:43:08 +0000 (15:43 -0700)
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 <sean.hefty@intel.com>
include/rdma/rdma_cma_abi.h
src/cma.c

index 5c736fb72d045791c13e5c3827a2d8dc3bd7fe6d..2b23d7a19ced4a69f41dcc0f7c8075e7df944f20 100644 (file)
@@ -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 ibv_path_data path_data[0];
+};
+
 struct ucma_abi_conn_param {
        __u32 qp_num;
        __u32 reserved;
index 2aef594e38d5626590bb992fa72c90a99464c0a8..5f4764a9959eeb69dca3101d8232737b42513d33 100644 (file)
--- 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 ibv_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 ibv_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;