diff mbox series

[V1,rdma-core,4/8] verbs: Implement ibv_query_gid and ibv_query_gid_type over ioctl

Message ID 20200923102702.590008-5-yishaih@nvidia.com (mailing list archive)
State Not Applicable
Headers show
Series verbs: Query GID table API | expand

Commit Message

Yishai Hadas Sept. 23, 2020, 10:26 a.m. UTC
From: Avihai Horon <avihaih@nvidia.com>

Currently ibv_query_gid and ibv_query_gid_type are implemented over
sysfs. In order to improve their performance we implement them using
the new query GID entry API, so now they will use ioctl and fallback
to sysfs.

Signed-off-by: Avihai Horon <avihaih@nvidia.com>
Signed-off-by: Yishai Hadas <yishaih@nvidia.com>
---
 libibverbs/cmd_device.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++--
 libibverbs/verbs.c      | 92 +++++++++++++++----------------------------------
 2 files changed, 117 insertions(+), 67 deletions(-)
diff mbox series

Patch

diff --git a/libibverbs/cmd_device.c b/libibverbs/cmd_device.c
index 8643cc6..f707273 100644
--- a/libibverbs/cmd_device.c
+++ b/libibverbs/cmd_device.c
@@ -30,6 +30,10 @@ 
  * SOFTWARE.
  */
 
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <dirent.h>
 #include <infiniband/cmd_write.h>
 
 #include <net/if.h>
@@ -230,6 +234,90 @@  static int query_sysfs_gid_ndev_ifindex(struct ibv_context *context,
 	return *ndev_ifindex ? 0 : errno;
 }
 
+static int query_sysfs_gid(struct ibv_context *context, uint8_t port_num, int index,
+			   union ibv_gid *gid)
+{
+	struct verbs_device *verbs_device = verbs_get_device(context->device);
+	char attr[41];
+	uint16_t val;
+	int i;
+
+	if (ibv_read_ibdev_sysfs_file(attr, sizeof(attr), verbs_device->sysfs,
+				      "ports/%d/gids/%d", port_num, index) < 0)
+		return -1;
+
+	for (i = 0; i < 8; ++i) {
+		if (sscanf(attr + i * 5, "%hx", &val) != 1)
+			return -1;
+		gid->raw[i * 2] = val >> 8;
+		gid->raw[i * 2 + 1] = val & 0xff;
+	}
+
+	return 0;
+}
+
+/* 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"
+static int query_sysfs_gid_type(struct ibv_context *context, uint8_t port_num,
+				unsigned int index, enum ibv_gid_type_sysfs *type)
+{
+	struct verbs_device *verbs_device = verbs_get_device(context->device);
+	char buff[11];
+
+	/* Reset errno so that we can rely on its value upon any error flow in
+	 * ibv_read_sysfs_file.
+	 */
+	errno = 0;
+	if (ibv_read_ibdev_sysfs_file(buff, sizeof(buff), verbs_device->sysfs,
+				      "ports/%d/gid_attrs/types/%d", port_num,
+				      index) <= 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_SYSFS_IB_ROCE_V1;
+			return 0;
+		}
+		if (asprintf(&dir_path, "%s/%s/%d/%s/",
+			     verbs_device->sysfs->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_SYSFS_IB_ROCE_V1;
+			else
+				return -1;
+		} else {
+			closedir(dir);
+			errno = EFAULT;
+			return -1;
+		}
+	} else {
+		if (!strcmp(buff, V1_TYPE)) {
+			*type = IBV_GID_TYPE_SYSFS_IB_ROCE_V1;
+		} else if (!strcmp(buff, V2_TYPE)) {
+			*type = IBV_GID_TYPE_SYSFS_ROCE_V2;
+		} else {
+			errno = ENOTSUP;
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
 static int query_sysfs_gid_entry(struct ibv_context *context, uint32_t port_num,
 				 uint32_t gid_index,
 				 struct ibv_gid_entry *entry)
@@ -240,11 +328,11 @@  static int query_sysfs_gid_entry(struct ibv_context *context, uint32_t port_num,
 
 	entry->gid_index = gid_index;
 	entry->port_num = port_num;
-	ret = ibv_query_gid(context, port_num, gid_index, &entry->gid);
+	ret = query_sysfs_gid(context, port_num, gid_index, &entry->gid);
 	if (ret)
 		return EINVAL;
 
-	ret = ibv_query_gid_type(context, port_num, gid_index, &gid_type);
+	ret = query_sysfs_gid_type(context, port_num, gid_index, &gid_type);
 	if (ret)
 		return EINVAL;
 
diff --git a/libibverbs/verbs.c b/libibverbs/verbs.c
index 9507ffd..99a48d5 100644
--- a/libibverbs/verbs.c
+++ b/libibverbs/verbs.c
@@ -221,21 +221,20 @@  LATEST_SYMVER_FUNC(ibv_query_gid, 1_1, "IBVERBS_1.1",
 		   struct ibv_context *context, uint8_t port_num,
 		   int index, union ibv_gid *gid)
 {
-	struct verbs_device *verbs_device = verbs_get_device(context->device);
-	char attr[41];
-	uint16_t val;
-	int i;
+	struct ibv_gid_entry entry = {};
+	int ret;
 
-	if (ibv_read_ibdev_sysfs_file(attr, sizeof(attr), verbs_device->sysfs,
-				      "ports/%d/gids/%d", port_num, index) < 0)
+	ret = _ibv_query_gid_ex(context, port_num, index, &entry, 0,
+				sizeof(entry));
+	/* Preserve API behavior for empty GID */
+	if (ret == ENODATA) {
+		memset(gid, 0, sizeof(*gid));
+		return 0;
+	}
+	if (ret)
 		return -1;
 
-	for (i = 0; i < 8; ++i) {
-		if (sscanf(attr + i * 5, "%hx", &val) != 1)
-			return -1;
-		gid->raw[i * 2    ] = val >> 8;
-		gid->raw[i * 2 + 1] = val & 0xff;
-	}
+	memcpy(gid, &entry.gid, sizeof(entry.gid));
 
 	return 0;
 }
@@ -698,64 +697,27 @@  LATEST_SYMVER_FUNC(ibv_create_ah, 1_1, "IBVERBS_1.1",
 	return 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_sysfs *type)
 {
-	struct verbs_device *verbs_device = verbs_get_device(context->device);
-	char buff[11];
+	struct ibv_gid_entry entry = {};
+	int ret;
 
-	/* Reset errno so that we can rely on its value upon any error flow in
-	 * ibv_read_sysfs_file.
-	 */
-	errno = 0;
-	if (ibv_read_ibdev_sysfs_file(buff, sizeof(buff), verbs_device->sysfs,
-				      "ports/%d/gid_attrs/types/%d", port_num,
-				      index) <= 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_SYSFS_IB_ROCE_V1;
-			return 0;
-		}
-		if (asprintf(&dir_path, "%s/%s/%d/%s/",
-			     verbs_device->sysfs->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_SYSFS_IB_ROCE_V1;
-			else
-				return -1;
-		} else {
-			closedir(dir);
-			errno = EFAULT;
-			return -1;
-		}
-	} else {
-		if (!strcmp(buff, V1_TYPE)) {
-			*type = IBV_GID_TYPE_SYSFS_IB_ROCE_V1;
-		} else if (!strcmp(buff, V2_TYPE)) {
-			*type = IBV_GID_TYPE_SYSFS_ROCE_V2;
-		} else {
-			errno = ENOTSUP;
-			return -1;
-		}
+	ret = _ibv_query_gid_ex(context, port_num, index, &entry, 0,
+				sizeof(entry));
+	/* Preserve API behavior for empty GID */
+	if (ret == ENODATA) {
+		*type = IBV_GID_TYPE_SYSFS_IB_ROCE_V1;
+		return 0;
 	}
+	if (ret)
+		return -1;
+
+	if (entry.gid_type == IBV_GID_TYPE_IB ||
+	    entry.gid_type == IBV_GID_TYPE_ROCE_V1)
+		*type = IBV_GID_TYPE_SYSFS_IB_ROCE_V1;
+	else
+		*type = IBV_GID_TYPE_SYSFS_ROCE_V2;
 
 	return 0;
 }