@@ -8,7 +8,9 @@ libibverbs.so.1 libibverbs1 #MINVER#
IBVERBS_1.8@IBVERBS_1.8 28
IBVERBS_1.9@IBVERBS_1.9 30
IBVERBS_1.10@IBVERBS_1.10 31
+ IBVERBS_1.11@IBVERBS_1.11 32
(symver)IBVERBS_PRIVATE_25 25
+ _ibv_query_gid_ex@IBVERBS_1.11 32
ibv_ack_async_event@IBVERBS_1.0 1.1.6
ibv_ack_async_event@IBVERBS_1.1 1.1.6
ibv_ack_cq_events@IBVERBS_1.0 1.1.6
@@ -21,7 +21,7 @@ configure_file("libibverbs.map.in"
rdma_library(ibverbs "${CMAKE_CURRENT_BINARY_DIR}/libibverbs.map"
# See Documentation/versioning.md
- 1 1.10.${PACKAGE_VERSION}
+ 1 1.11.${PACKAGE_VERSION}
all_providers.c
cmd.c
cmd_ah.c
@@ -32,6 +32,8 @@
#include <infiniband/cmd_write.h>
+#include <net/if.h>
+
static void copy_query_port_resp_to_port_attr(struct ibv_port_attr *port_attr,
struct ib_uverbs_query_port_resp *resp)
{
@@ -202,3 +204,106 @@ int ibv_cmd_query_context(struct ibv_context *context,
return 0;
}
+
+static int is_zero_gid(union ibv_gid *gid)
+{
+ const union ibv_gid zgid = {};
+
+ return !memcmp(gid, &zgid, sizeof(*gid));
+}
+
+static int query_sysfs_gid_ndev_ifindex(struct ibv_context *context,
+ uint8_t port_num, uint32_t gid_index,
+ uint32_t *ndev_ifindex)
+{
+ struct verbs_device *verbs_device = verbs_get_device(context->device);
+ char buff[IF_NAMESIZE] = {};
+
+ if (ibv_read_ibdev_sysfs_file(buff, sizeof(buff), verbs_device->sysfs,
+ "ports/%d/gid_attrs/ndevs/%d", port_num,
+ gid_index) <= 0) {
+ *ndev_ifindex = 0;
+ return 0;
+ }
+
+ *ndev_ifindex = if_nametoindex(buff);
+ return *ndev_ifindex ? 0 : errno;
+}
+
+static int query_sysfs_gid_entry(struct ibv_context *context, uint32_t port_num,
+ uint32_t gid_index,
+ struct ibv_gid_entry *entry)
+{
+ enum ibv_gid_type_sysfs gid_type;
+ struct ibv_port_attr port_attr = {};
+ int ret;
+
+ entry->gid_index = gid_index;
+ entry->port_num = port_num;
+ ret = ibv_query_gid(context, port_num, gid_index, &entry->gid);
+ if (ret)
+ return EINVAL;
+
+ ret = ibv_query_gid_type(context, port_num, gid_index, &gid_type);
+ if (ret)
+ return EINVAL;
+
+ if (gid_type == IBV_GID_TYPE_SYSFS_IB_ROCE_V1) {
+ ret = ibv_query_port(context, port_num, &port_attr);
+ if (ret)
+ goto out;
+
+ if (port_attr.link_layer == IBV_LINK_LAYER_INFINIBAND) {
+ entry->gid_type = IBV_GID_TYPE_IB;
+ } else if (port_attr.link_layer == IBV_LINK_LAYER_ETHERNET) {
+ entry->gid_type = IBV_GID_TYPE_ROCE_V1;
+ } else {
+ ret = EINVAL;
+ goto out;
+ }
+ } else {
+ entry->gid_type = IBV_GID_TYPE_ROCE_V2;
+ }
+
+ ret = query_sysfs_gid_ndev_ifindex(context, port_num, gid_index,
+ &entry->ndev_ifindex);
+
+out:
+ return ret;
+}
+
+/* Using async_event cmd_name because query_gid_ex is not in
+ * verbs_context_ops while async_event is and doesn't use ioctl.
+ */
+#define query_gid_kernel_cap async_event
+int ibv_cmd_query_gid_entry(struct ibv_context *context, uint32_t port_num,
+ uint32_t gid_index, struct ibv_gid_entry *entry,
+ uint32_t flags, size_t entry_size)
+{
+ DECLARE_COMMAND_BUFFER(cmdb, UVERBS_OBJECT_DEVICE,
+ UVERBS_METHOD_QUERY_GID_ENTRY, 4);
+ int ret;
+
+ fill_attr_const_in(cmdb, UVERBS_ATTR_QUERY_GID_ENTRY_PORT, port_num);
+ fill_attr_const_in(cmdb, UVERBS_ATTR_QUERY_GID_ENTRY_GID_INDEX,
+ gid_index);
+ fill_attr_in_uint32(cmdb, UVERBS_ATTR_QUERY_GID_ENTRY_FLAGS, flags);
+ fill_attr_out(cmdb, UVERBS_ATTR_QUERY_GID_ENTRY_RESP_ENTRY, entry,
+ entry_size);
+
+ switch (execute_ioctl_fallback(context, query_gid_kernel_cap, cmdb,
+ &ret)) {
+ case TRY_WRITE:
+ if (flags)
+ return EOPNOTSUPP;
+
+ ret = query_sysfs_gid_entry(context, port_num, gid_index,
+ entry);
+ if (ret)
+ return ret;
+
+ return is_zero_gid(&entry->gid) ? ENODATA : 0;
+ default:
+ return ret;
+ }
+}
@@ -633,6 +633,10 @@ int ibv_cmd_reg_dm_mr(struct ibv_pd *pd, struct verbs_dm *dm,
unsigned int access, struct verbs_mr *vmr,
struct ibv_command_buffer *link);
+int ibv_cmd_query_gid_entry(struct ibv_context *context, uint32_t port_num,
+ uint32_t gid_index, struct ibv_gid_entry *entry,
+ uint32_t flags, size_t entry_size);
+
/*
* sysfs helper functions
*/
@@ -142,6 +142,11 @@ IBVERBS_1.10 {
ibv_unimport_pd;
} IBVERBS_1.9;
+IBVERBS_1.11 {
+ global:
+ _ibv_query_gid_ex;
+} IBVERBS_1.10;
+
/* If any symbols in this stanza change ABI then the entire staza gets a new symbol
version. See the top level CMakeLists.txt for this setting. */
@@ -57,6 +57,7 @@ rdma_man_pages(
ibv_query_device_ex.3
ibv_query_ece.3.md
ibv_query_gid.3.md
+ ibv_query_gid_ex.3.md
ibv_query_pkey.3.md
ibv_query_port.3
ibv_query_qp.3
new file mode 100644
@@ -0,0 +1,93 @@
+---
+date: 2020-04-24
+footer: libibverbs
+header: "Libibverbs Programmer's Manual"
+layout: page
+license: 'Licensed under the OpenIB.org BSD license (FreeBSD Variant) - See COPYING.md'
+section: 3
+title: IBV_QUERY_GID_EX
+---
+
+# NAME
+
+ibv_query_gid_ex - Query an InfiniBand port's GID table entry
+
+# SYNOPSIS
+
+```c
+#include <infiniband/verbs.h>
+
+int ibv_query_gid_ex(struct ibv_context *context,
+ uint32_t port_num,
+ uint32_t gid_index,
+ struct ibv_gid_entry *entry,
+ uint32_t flags);
+```
+
+# DESCRIPTION
+
+**ibv_query_gid_ex()** returns the GID entry at *entry* for
+*gid_index* of port *port_num* for device context *context*.
+
+# ARGUMENTS
+
+*context*
+: The context of the device to query.
+
+*port_num*
+: The number of port to query its GID table.
+
+*gid_index*
+: The index of the GID table entry to query.
+
+## *entry* Argument
+: An ibv_gid_entry struct, as defined in <infiniband/verbs.h>.
+```c
+struct ibv_gid_entry {
+ union ibv_gid gid;
+ uint32_t gid_index;
+ uint32_t port_num;
+ uint32_t gid_type;
+ uint32_t ndev_ifindex;
+};
+```
+
+ *gid*
+: The GID entry.
+
+ *gid_index*
+: The GID table index of this entry.
+
+ *port_num*
+: The port number that this GID belongs to.
+
+ *gid_type*
+: enum ibv_gid_type, can be one of IBV_GID_TYPE_IB, IBV_GID_TYPE_ROCE_V1 or IBV_GID_TYPE_ROCE_V2.
+
+ *ndev_ifindex*
+: The interface index of the net device associated with this GID.
+ It is 0 if there is no net device associated with it.
+
+*flags*
+: Extra fields to query post *ndev_ifindex*, for now must be 0.
+
+# RETURN VALUE
+
+**ibv_query_gid_ex()** returns 0 on success or errno value on error.
+
+# ERRORS
+
+ENODATA
+: *gid_index* is within the GID table size of port *port_num* but there is no data in this index.
+
+# SEE ALSO
+
+**ibv_open_device**(3),
+**ibv_query_device**(3),
+**ibv_query_pkey**(3),
+**ibv_query_port**(3),
+**ibv_query_gid_table**(3)
+
+# AUTHOR
+
+Parav Pandit <parav@nvidia.com>
@@ -240,6 +240,14 @@ LATEST_SYMVER_FUNC(ibv_query_gid, 1_1, "IBVERBS_1.1",
return 0;
}
+int _ibv_query_gid_ex(struct ibv_context *context, uint32_t port_num,
+ uint32_t gid_index, struct ibv_gid_entry *entry,
+ uint32_t flags, size_t entry_size)
+{
+ return ibv_cmd_query_gid_entry(context, port_num, gid_index, entry,
+ flags, entry_size);
+}
+
LATEST_SYMVER_FUNC(ibv_query_pkey, 1_1, "IBVERBS_1.1",
int,
struct ibv_context *context, uint8_t port_num,
@@ -68,6 +68,20 @@ union ibv_gid {
} global;
};
+enum ibv_gid_type {
+ IBV_GID_TYPE_IB,
+ IBV_GID_TYPE_ROCE_V1,
+ IBV_GID_TYPE_ROCE_V2,
+};
+
+struct ibv_gid_entry {
+ union ibv_gid gid;
+ uint32_t gid_index;
+ uint32_t port_num;
+ uint32_t gid_type; /* enum ibv_gid_type */
+ uint32_t ndev_ifindex;
+};
+
#define vext_field_avail(type, fld, sz) (offsetof(type, fld) < (sz))
#ifdef __cplusplus
@@ -2330,6 +2344,21 @@ static inline int ___ibv_query_port(struct ibv_context *context,
int ibv_query_gid(struct ibv_context *context, uint8_t port_num,
int index, union ibv_gid *gid);
+int _ibv_query_gid_ex(struct ibv_context *context, uint32_t port_num,
+ uint32_t gid_index, struct ibv_gid_entry *entry,
+ uint32_t flags, size_t entry_size);
+
+/**
+ * ibv_query_gid_ex - Read a GID table entry
+ */
+static inline int ibv_query_gid_ex(struct ibv_context *context,
+ uint32_t port_num, uint32_t gid_index,
+ struct ibv_gid_entry *entry, uint32_t flags)
+{
+ return _ibv_query_gid_ex(context, port_num, gid_index, entry, flags,
+ sizeof(*entry));
+}
+
/**
* ibv_query_pkey - Get a P_Key table entry
*/