diff options
author | Noa Osherovich <noaos@mellanox.com> | 2016-09-15 15:51:16 +0300 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2016-09-15 14:18:04 -0400 |
commit | 5094378e7e07231a82bc31296c3fe98c1cd80a58 (patch) | |
tree | 00c90d84cc8cda7a370cffb5f81eade24bc79991 | |
parent | 047ca9ea884060a0122e875c3305afcac00dd8a6 (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.h | 7 | ||||
-rw-r--r-- | src/libibverbs.map | 1 | ||||
-rw-r--r-- | src/verbs.c | 65 |
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) { |