@@ -13,3 +13,27 @@ cdef class Context(PyverbsCM):
cdef class DeviceAttr(PyverbsObject):
cdef v.ibv_device_attr dev_attr
+
+cdef class QueryDeviceExInput(PyverbsObject):
+ cdef v.ibv_query_device_ex_input input
+
+cdef class ODPCaps(PyverbsObject):
+ cdef v.ibv_odp_caps odp_caps
+
+cdef class RSSCaps(PyverbsObject):
+ cdef v.ibv_rss_caps rss_caps
+
+cdef class PacketPacingCaps(PyverbsObject):
+ cdef v.ibv_packet_pacing_caps packet_pacing_caps
+
+cdef class TMCaps(PyverbsObject):
+ cdef v.ibv_tm_caps tm_caps
+
+cdef class CQModerationCaps(PyverbsObject):
+ cdef v.ibv_cq_moderation_caps cq_mod_caps
+
+cdef class TSOCaps(PyverbsObject):
+ cdef v.ibv_tso_caps tso_caps
+
+cdef class DeviceAttrEx(PyverbsObject):
+ cdef v.ibv_device_attr_ex dev_attr
@@ -131,6 +131,22 @@ cdef class Context(PyverbsCM):
format(name=self.name), errno)
return dev_attr
+ def query_device_ex(self, QueryDeviceExInput ex_input = None):
+ """
+ Queries the device's extended attributes.
+ :param ex_input: An extensible input struct for possible future
+ extensions
+ :return: DeviceAttrEx object
+ """
+ dev_attr_ex = DeviceAttrEx()
+ rc = v.ibv_query_device_ex(self.context,
+ &ex_input.input if ex_input is not None else NULL,
+ &dev_attr_ex.dev_attr)
+ if rc != 0:
+ raise PyverbsRDMAErrno('Failed to query EX device {name}'.
+ format(name=self.name))
+ return dev_attr_ex
+
def query_gid(self, unsigned int port_num, int index):
gid = GID()
rc = v.ibv_query_gid(self.context, port_num, index, &gid.gid)
@@ -312,6 +328,155 @@ cdef class DeviceAttr(PyverbsObject):
print_format.format('local CA ack delay', self.local_ca_ack_delay) +\
print_format.format('Phys port count', self.phys_port_cnt)
+
+cdef class QueryDeviceExInput(PyverbsObject):
+ def __cinit__(self, comp_mask):
+ self.ex_input.comp_mask = comp_mask
+
+
+cdef class ODPCaps(PyverbsObject):
+ @property
+ def general_caps(self):
+ return self.odp_caps.general_caps
+ @property
+ def rc_odp_caps(self):
+ return self.odp_caps.per_transport_caps.rc_odp_caps
+ @property
+ def uc_odp_caps(self):
+ return self.odp_caps.per_transport_caps.uc_odp_caps
+ @property
+ def ud_odp_caps(self):
+ return self.odp_caps.per_transport_caps.ud_odp_caps
+
+
+cdef class TSOCaps(PyverbsObject):
+ @property
+ def max_tso(self):
+ return self.tso_caps.max_tso
+ @property
+ def supported_qpts(self):
+ return self.tso_caps.supported_qpts
+
+
+cdef class RSSCaps(PyverbsObject):
+ @property
+ def supported_qpts(self):
+ return self.rss_caps.supported_qpts
+ @property
+ def max_rwq_indirection_tables(self):
+ return self.rss_caps.max_rwq_indirection_tables
+ @property
+ def rx_hash_fields_mask(self):
+ return self.rss_caps.rx_hash_fields_mask
+ @property
+ def rx_hash_function(self):
+ return self.rss_caps.rx_hash_function
+ @property
+ def max_rwq_indirection_table_size(self):
+ return self.rss_caps.max_rwq_indirection_table_size
+
+
+cdef class PacketPacingCaps(PyverbsObject):
+ @property
+ def qp_rate_limit_min(self):
+ return self.packet_pacing_caps.qp_rate_limit_min
+ @property
+ def qp_rate_limit_max(self):
+ return self.packet_pacing_caps.qp_rate_limit_max
+ @property
+ def supported_qpts(self):
+ return self.packet_pacing_caps.supported_qpts
+
+
+cdef class TMCaps(PyverbsObject):
+ @property
+ def max_rndv_hdr_size(self):
+ return self.tm_caps.max_rndv_hdr_size
+ @property
+ def max_num_tags(self):
+ return self.tm_caps.max_num_tags
+ @property
+ def flags(self):
+ return self.tm_caps.flags
+ @property
+ def max_ops(self):
+ return self.tm_caps.max_ops
+ @property
+ def max_sge(self):
+ return self.tm_caps.max_sge
+
+
+cdef class CQModerationCaps(PyverbsObject):
+ @property
+ def max_cq_count(self):
+ return self.cq_mod_caps.max_cq_count
+ @property
+ def max_cq_period(self):
+ return self.cq_mod_caps.max_cq_period
+
+
+cdef class DeviceAttrEx(PyverbsObject):
+ @property
+ def orig_attr(self):
+ attr = DeviceAttr()
+ attr.dev_attr = self.dev_attr.orig_attr
+ return attr
+ @property
+ def comp_mask(self):
+ return self.dev_attr.comp_mask
+ @comp_mask.setter
+ def comp_mask(self, val):
+ self.dev_attr.comp_mask = val
+ @property
+ def odp_caps(self):
+ caps = ODPCaps()
+ caps.odp_caps = self.dev_attr.odp_caps
+ return caps
+ @property
+ def completion_timestamp_mask(self):
+ return self.dev_attr.completion_timestamp_mask
+ @property
+ def hca_core_clock(self):
+ return self.dev_attr.hca_core_clock
+ @property
+ def device_cap_flags_ex(self):
+ return self.dev_attr.device_cap_flags_ex
+ @property
+ def tso_caps(self):
+ caps = TSOCaps()
+ caps.tso_caps = self.dev_attr.tso_caps
+ return caps
+ @property
+ def rss_caps(self):
+ caps = RSSCaps()
+ caps.rss_caps = self.dev_attr.rss_caps
+ return caps
+ @property
+ def max_wq_type_rq(self):
+ return self.dev_attr.max_wq_type_rq
+ @property
+ def packet_pacing_caps(self):
+ caps = PacketPacingCaps()
+ caps.packet_pacing_caps = self.dev_attr.packet_pacing_caps
+ return caps
+ @property
+ def raw_packet_caps(self):
+ return self.dev_attr.raw_packet_caps
+ @property
+ def tm_caps(self):
+ caps = TMCaps()
+ caps.tm_caps = self.dev_attr.tm_caps
+ return caps
+ @property
+ def cq_mod_caps(self):
+ caps = CQModerationCaps()
+ caps.cq_mod_caps = self.dev_attr.cq_mod_caps
+ return caps
+ @property
+ def max_dm_size(self):
+ return self.dev_attr.max_dm_size
+
+
def guid_format(num):
"""
Get GUID representation of the given number, including change of endianness.
@@ -2,7 +2,7 @@
# Copyright (c) 2018, Mellanox Technologies. All rights reserved. See COPYING file
include 'libibverbs_enums.pxd'
-from libc.stdint cimport uint8_t, uint64_t
+from libc.stdint cimport uint8_t, uint32_t, uint64_t
cdef extern from 'infiniband/verbs.h':
@@ -77,11 +77,69 @@ cdef extern from 'infiniband/verbs.h':
unsigned int lkey
unsigned int rkey
+ cdef struct ibv_query_device_ex_input:
+ unsigned int comp_mask
+
+ cdef struct per_transport_caps:
+ uint32_t rc_odp_caps
+ uint32_t uc_odp_caps
+ uint32_t ud_odp_caps
+
+ cdef struct ibv_odp_caps:
+ uint64_t general_caps
+ per_transport_caps per_transport_caps
+
+ cdef struct ibv_tso_caps:
+ unsigned int max_tso
+ unsigned int supported_qpts
+
+ cdef struct ibv_rss_caps:
+ unsigned int supported_qpts
+ unsigned int max_rwq_indirection_tables
+ unsigned int max_rwq_indirection_table_size
+ unsigned long rx_hash_fields_mask
+ unsigned int rx_hash_function
+
+ cdef struct ibv_packet_pacing_caps:
+ unsigned int qp_rate_limit_min
+ unsigned int qp_rate_limit_max
+ unsigned int supported_qpts
+
+ cdef struct ibv_tm_caps:
+ unsigned int max_rndv_hdr_size
+ unsigned int max_num_tags
+ unsigned int flags
+ unsigned int max_ops
+ unsigned int max_sge
+
+ cdef struct ibv_cq_moderation_caps:
+ unsigned int max_cq_count
+ unsigned int max_cq_period
+
+ cdef struct ibv_device_attr_ex:
+ ibv_device_attr orig_attr
+ unsigned int comp_mask
+ ibv_odp_caps odp_caps
+ unsigned long completion_timestamp_mask
+ unsigned long hca_core_clock
+ unsigned long device_cap_flags_ex
+ ibv_tso_caps tso_caps
+ ibv_rss_caps rss_caps
+ unsigned int max_wq_type_rq
+ ibv_packet_pacing_caps packet_pacing_caps
+ unsigned int raw_packet_caps
+ ibv_tm_caps tm_caps
+ ibv_cq_moderation_caps cq_mod_caps
+ unsigned long max_dm_size
+
ibv_device **ibv_get_device_list(int *n)
void ibv_free_device_list(ibv_device **list)
ibv_context *ibv_open_device(ibv_device *device)
int ibv_close_device(ibv_context *context)
int ibv_query_device(ibv_context *context, ibv_device_attr *device_attr)
+ int ibv_query_device_ex(ibv_context *context,
+ ibv_query_device_ex_input *input,
+ ibv_device_attr_ex *attr)
unsigned long ibv_get_device_guid(ibv_device *device)
int ibv_query_gid(ibv_context *context, unsigned int port_num,
int index, ibv_gid *gid)
@@ -1,8 +1,14 @@
# SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB)
# Copyright (c) 2018, Mellanox Technologies. All rights reserved. See COPYING file
import unittest
+import resource
+
import pyverbs.device as d
+
+PAGE_SIZE = resource.getpagesize()
+
+
class device_test(unittest.TestCase):
"""
Test various functionalities of the Device class.
@@ -27,8 +33,9 @@ class device_test(unittest.TestCase):
"""
lst = d.get_device_list()
for dev in lst:
- ctx = d.Context(name=dev.name.decode())
- ctx.query_device()
+ with d.Context(name=dev.name.decode()) as ctx:
+ attr = ctx.query_device()
+ self.verify_device_attr(attr)
def test_query_gid(self):
"""
@@ -36,6 +43,33 @@ class device_test(unittest.TestCase):
"""
lst = d.get_device_list()
for dev in lst:
- ctx = d.Context(name=dev.name.decode())
- ctx.query_gid(port_num=1, index=0)
+ with d.Context(name=dev.name.decode()) as ctx:
+ ctx.query_gid(port_num=1, index=0)
+ @staticmethod
+ def verify_device_attr(attr):
+ assert attr.node_guid != 0
+ assert attr.sys_image_guid != 0
+ assert attr.max_mr_size > PAGE_SIZE
+ assert attr.page_size_cap > PAGE_SIZE
+ assert attr.vendor_id != 0
+ assert attr.vendor_part_id != 0
+ assert attr.max_qp > 0
+ assert attr.max_qp_wr > 0
+ assert attr.max_sge > 0
+ assert attr.max_sge_rd > 0
+ assert attr.max_cq > 0
+ assert attr.max_cqe > 0
+ assert attr.max_mr > 0
+ assert attr.max_pd > 0
+ assert attr.max_pkeys > 0
+
+ def test_query_device_ex(self):
+ """
+ Test ibv_query_device_ex()
+ """
+ lst = d.get_device_list()
+ for dev in lst:
+ with d.Context(name=dev.name.decode()) as ctx:
+ attr_ex = ctx.query_device_ex()
+ self.verify_device_attr(attr_ex.orig_attr)
ibv_query_device_ex() is needed for extended capabilities checks. Signed-off-by: Noa Osherovich <noaos@mellanox.com> --- pyverbs/device.pxd | 24 ++++++ pyverbs/device.pyx | 165 ++++++++++++++++++++++++++++++++++++++++ pyverbs/libibverbs.pxd | 60 ++++++++++++++- pyverbs/tests/device.py | 42 +++++++++- 4 files changed, 286 insertions(+), 5 deletions(-)