From: Avihai Horon <avihaih@xxxxxxxxxx> Add two new methods to Context class: query_gid_table and query_gid_ex. query_gid_table queries all GID tables of the device and returns a list of GIDEntry objects containing all valid GID entries. query_gid_ex queries the GID table of the given port in the given index and returns a GIDEntry object. Signed-off-by: Avihai Horon <avihaih@xxxxxxxxxx> Signed-off-by: Edward Srouji <edwards@xxxxxxxxxx> --- pyverbs/device.pxd | 3 ++ pyverbs/device.pyx | 106 +++++++++++++++++++++++++++++++++++++++++++ pyverbs/libibverbs.pxd | 13 ++++++ pyverbs/libibverbs_enums.pxd | 5 ++ 4 files changed, 127 insertions(+) diff --git a/pyverbs/device.pxd b/pyverbs/device.pxd index 73328d3..0519c4b 100755 --- a/pyverbs/device.pxd +++ b/pyverbs/device.pxd @@ -64,3 +64,6 @@ cdef class DM(PyverbsCM): cdef class PortAttr(PyverbsObject): cdef v.ibv_port_attr attr + +cdef class GIDEntry(PyverbsObject): + cdef v.ibv_gid_entry entry diff --git a/pyverbs/device.pyx b/pyverbs/device.pyx index c1323cd..b16d6d0 100755 --- a/pyverbs/device.pyx +++ b/pyverbs/device.pyx @@ -26,6 +26,8 @@ from libc.stdlib cimport free, malloc from libc.string cimport memset from libc.stdint cimport uint64_t from libc.stdint cimport uint16_t +from libc.stdint cimport uint32_t +from pyverbs.utils import gid_str cdef extern from 'endian.h': unsigned long be64toh(unsigned long host_64bits); @@ -240,6 +242,53 @@ cdef class Context(PyverbsCM): format(p=port_num), rc) return port_attrs + def query_gid_table(self, size_t max_entries, uint32_t flags=0): + """ + Queries the GID tables of the device for at most <max_entries> entries + and returns them. + :param max_entries: Maximum number of GID entries to retrieve + :param flags: Specifies new extra members of struct ibv_gid_entry to + query + :return: List of GIDEntry objects on success + """ + cdef v.ibv_gid_entry *entries + cdef v.ibv_gid_entry entry + + entries = <v.ibv_gid_entry *>malloc(max_entries * + sizeof(v.ibv_gid_entry)) + rc = v.ibv_query_gid_table(self.context, entries, max_entries, flags) + if rc < 0: + raise PyverbsRDMAError('Failed to query gid tables of the device', + rc) + gid_entries = [] + for i in range(rc): + entry = entries[i] + gid_entries.append(GIDEntry(entry.gid._global.subnet_prefix, + entry.gid._global.interface_id, entry.gid_index, + entry.port_num, entry.gid_type, + entry.ndev_ifindex)) + free(entries) + return gid_entries + + def query_gid_ex(self, uint32_t port_num, uint32_t gid_index, + uint32_t flags=0): + """ + Queries the GID table of port <port_num> in index <gid_index>, and + returns the GID entry. + :param port_num: The port number to query + :param gid_index: The index in the GID table to query + :param flags: Specifies new extra members of struct ibv_gid_entry to + query + :return: GIDEntry object on success + """ + entry = GIDEntry() + rc = v.ibv_query_gid_ex(self.context, port_num, gid_index, + &entry.entry, flags) + if rc != 0: + raise PyverbsRDMAError(f'Failed to query gid table of port '\ + f'{port_num} in index {gid_index}', rc) + return entry + cdef add_ref(self, obj): if isinstance(obj, PD): self.pds.add(obj) @@ -816,6 +865,63 @@ cdef class PortAttr(PyverbsObject): print_format.format('Flags', self.attr.flags) +cdef class GIDEntry(PyverbsObject): + def __init__(self, subnet_prefix=0, interface_id=0, gid_index=0, + port_num=0, gid_type=0, ndev_ifindex=0): + super().__init__() + self.entry.gid._global.subnet_prefix = subnet_prefix + self.entry.gid._global.interface_id = interface_id + self.entry.gid_index = gid_index + self.entry.port_num = port_num + self.entry.gid_type = gid_type + self.entry.ndev_ifindex = ndev_ifindex + + @property + def gid_subnet_prefix(self): + return self.entry.gid._global.subnet_prefix + + @property + def gid_interface_id(self): + return self.entry.gid._global.interface_id + + @property + def gid_index(self): + return self.entry.gid_index + + @property + def port_num(self): + return self.entry.port_num + + @property + def gid_type(self): + return self.entry.gid_type + + @property + def ndev_ifindex(self): + return self.entry.ndev_ifindex + + def gid_str(self): + return gid_str(self.gid_subnet_prefix, self.gid_interface_id) + + def __str__(self): + print_format = '{:<24}: {:<20}\n' + return print_format.format('GID', self.gid_str()) +\ + print_format.format('GID Index', self.gid_index) +\ + print_format.format('Port number', self.port_num) +\ + print_format.format('GID type', translate_gid_type( + self.gid_type)) +\ + print_format.format('Ndev ifindex', self.ndev_ifindex) + + +def translate_gid_type(gid_type): + types = {e.IBV_GID_TYPE_IB: 'IB', e.IBV_GID_TYPE_ROCE_V1: 'RoCEv1', + e.IBV_GID_TYPE_ROCE_V2: 'RoCEv2'} + try: + return types[gid_type] + except KeyError: + return f'Unknown gid_type ({gid_type})' + + def guid_format(num): """ Get GUID representation of the given number, including change of endianness. diff --git a/pyverbs/libibverbs.pxd b/pyverbs/libibverbs.pxd index c84b9fc..6fbba54 100755 --- a/pyverbs/libibverbs.pxd +++ b/pyverbs/libibverbs.pxd @@ -483,6 +483,13 @@ cdef extern from 'infiniband/verbs.h': uint32_t options uint32_t comp_mask + cdef struct ibv_gid_entry: + ibv_gid gid + uint32_t gid_index + uint32_t port_num + uint32_t gid_type + uint32_t ndev_ifindex + ibv_device **ibv_get_device_list(int *n) int ibv_get_device_index(ibv_device *device); void ibv_free_device_list(ibv_device **list) @@ -613,6 +620,12 @@ cdef extern from 'infiniband/verbs.h': void ibv_unimport_mr(ibv_mr *mr) ibv_pd *ibv_import_pd(ibv_context *context, uint32_t handle) void ibv_unimport_pd(ibv_pd *pd) + int ibv_query_gid_ex(ibv_context *context, uint32_t port_num, + uint32_t gid_index, ibv_gid_entry *entry, + uint32_t flags) + ssize_t ibv_query_gid_table(ibv_context *context, + ibv_gid_entry *entries, size_t max_entries, + uint32_t flags) cdef extern from 'infiniband/driver.h': diff --git a/pyverbs/libibverbs_enums.pxd b/pyverbs/libibverbs_enums.pxd index 83ca516..a5c07b3 100755 --- a/pyverbs/libibverbs_enums.pxd +++ b/pyverbs/libibverbs_enums.pxd @@ -427,6 +427,11 @@ cdef extern from '<infiniband/verbs.h>': cdef void *IBV_ALLOCATOR_USE_DEFAULT + cpdef enum ibv_gid_type: + IBV_GID_TYPE_IB + IBV_GID_TYPE_ROCE_V1 + IBV_GID_TYPE_ROCE_V2 + cdef extern from "<infiniband/verbs_api.h>": cdef unsigned long long IBV_ADVISE_MR_ADVICE_PREFETCH -- 1.8.3.1