aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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)
{