aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNoa Osherovich <noaos@mellanox.com>2016-09-15 15:51:16 +0300
committerDoug Ledford <dledford@redhat.com>2016-09-15 14:18:04 -0400
commit5094378e7e07231a82bc31296c3fe98c1cd80a58 (patch)
tree00c90d84cc8cda7a370cffb5f81eade24bc79991
parent047ca9ea884060a0122e875c3305afcac00dd8a6 (diff)
Add ibv_query_gid_type to support RoCE v2 UD traffic
Currently, libibverbs does not support UD traffic for RoCE v2 since it can't differ between v1 and v2 GIDs (both have the same GID, only the version is different). This means that GID index can't be selected correctly. This patch introduces ibv_query_gid_type helper function to be used by libibverbs and its vendors to return GID type based on its GID index by using the relevant sysfs. Signed-off-by: Noa Osherovich <noaos@mellanox.com> Reviewed-by: Yishai Hadas <yishaih@mellanox.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--include/infiniband/driver.h7
-rw-r--r--src/libibverbs.map1
-rw-r--r--src/verbs.c65
3 files changed, 73 insertions, 0 deletions
diff --git a/include/infiniband/driver.h b/include/infiniband/driver.h
index 72866a0..ea3dade 100644
--- a/include/infiniband/driver.h
+++ b/include/infiniband/driver.h
@@ -86,6 +86,11 @@ enum verbs_qp_mask {
VERBS_QP_RESERVED = 1 << 1
};
+enum ibv_gid_type {
+ IBV_GID_TYPE_IB_ROCE_V1,
+ IBV_GID_TYPE_ROCE_V2,
+};
+
struct verbs_qp {
struct ibv_qp qp;
uint32_t comp_mask;
@@ -281,4 +286,6 @@ static inline int verbs_get_srq_num(struct ibv_srq *srq, uint32_t *srq_num)
return ENOSYS;
}
+int ibv_query_gid_type(struct ibv_context *context, uint8_t port_num,
+ unsigned int index, enum ibv_gid_type *type);
#endif /* INFINIBAND_DRIVER_H */
diff --git a/src/libibverbs.map b/src/libibverbs.map
index 6f66eac..46744e5 100644
--- a/src/libibverbs.map
+++ b/src/libibverbs.map
@@ -128,4 +128,5 @@ IBVERBS_1.3 {
ibv_cmd_destroy_wq;
ibv_cmd_create_rwq_ind_table;
ibv_cmd_destroy_rwq_ind_table;
+ ibv_query_gid_type;
} IBVERBS_1.1;
diff --git a/src/verbs.c b/src/verbs.c
index 68888c3..08f03e3 100644
--- a/src/verbs.c
+++ b/src/verbs.c
@@ -41,6 +41,7 @@
#include <stdlib.h>
#include <errno.h>
#include <string.h>
+#include <dirent.h>
#include "ibverbs.h"
#ifndef NRESOLVE_NEIGH
@@ -585,6 +586,70 @@ struct ibv_ah *__ibv_create_ah(struct ibv_pd *pd, struct ibv_ah_attr *attr)
}
default_symver(__ibv_create_ah, ibv_create_ah);
+/* GID types as appear in sysfs, no change is expected as of ABI
+ * compatibility.
+ */
+#define V1_TYPE "IB/RoCE v1"
+#define V2_TYPE "RoCE v2"
+int ibv_query_gid_type(struct ibv_context *context, uint8_t port_num,
+ unsigned int index, enum ibv_gid_type *type)
+{
+ char name[32];
+ char buff[11];
+
+ snprintf(name, sizeof(name), "ports/%d/gid_attrs/types/%d", port_num,
+ index);
+
+ /* Reset errno so that we can rely on its value upon any error flow in
+ * ibv_read_sysfs_file.
+ */
+ errno = 0;
+ if (ibv_read_sysfs_file(context->device->ibdev_path, name, buff,
+ sizeof(buff)) <= 0) {
+ char *dir_path;
+ DIR *dir;
+
+ if (errno == EINVAL) {
+ /* In IB, this file doesn't exist and the kernel sets
+ * errno to -EINVAL.
+ */
+ *type = IBV_GID_TYPE_IB_ROCE_V1;
+ return 0;
+ }
+ if (asprintf(&dir_path, "%s/%s/%d/%s/",
+ context->device->ibdev_path, "ports", port_num,
+ "gid_attrs") < 0)
+ return -1;
+ dir = opendir(dir_path);
+ free(dir_path);
+ if (!dir) {
+ if (errno == ENOENT)
+ /* Assuming that if gid_attrs doesn't exist,
+ * we have an old kernel and all GIDs are
+ * IB/RoCE v1
+ */
+ *type = IBV_GID_TYPE_IB_ROCE_V1;
+ else
+ return -1;
+ } else {
+ closedir(dir);
+ errno = EFAULT;
+ return -1;
+ }
+ } else {
+ if (!strcmp(buff, V1_TYPE)) {
+ *type = IBV_GID_TYPE_IB_ROCE_V1;
+ } else if (!strcmp(buff, V2_TYPE)) {
+ *type = IBV_GID_TYPE_ROCE_V2;
+ } else {
+ errno = ENOTSUP;
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
static int ibv_find_gid_index(struct ibv_context *context, uint8_t port_num,
union ibv_gid *gid)
{