Context class can now query its ports. A PortAttr object with a user-friendly print function is returned to the user. Signed-off-by: Noa Osherovich <noaos@xxxxxxxxxxxx> --- pyverbs/device.pxd | 3 + pyverbs/device.pyx | 196 +++++++++++++++++++++++++++++++++++ pyverbs/libibverbs.pxd | 26 +++++ pyverbs/libibverbs_enums.pxd | 14 +++ 4 files changed, 239 insertions(+) diff --git a/pyverbs/device.pxd b/pyverbs/device.pxd index c9e346539e58..a7089972985b 100644 --- a/pyverbs/device.pxd +++ b/pyverbs/device.pxd @@ -47,3 +47,6 @@ cdef class DM(PyverbsCM): cdef object dm_mrs cdef object context cdef add_ref(self, obj) + +cdef class PortAttr(PyverbsObject): + cdef v.ibv_port_attr attr diff --git a/pyverbs/device.pyx b/pyverbs/device.pyx index 7bfcda8bc177..757eebf67c48 100644 --- a/pyverbs/device.pyx +++ b/pyverbs/device.pyx @@ -11,6 +11,7 @@ import weakref from .pyverbs_error import PyverbsRDMAError, PyverbsError from .pyverbs_error import PyverbsUserError from pyverbs.base import PyverbsRDMAErrno +cimport pyverbs.libibverbs_enums as e cimport pyverbs.libibverbs as v from pyverbs.addr cimport GID from pyverbs.mr import DMMR @@ -165,6 +166,18 @@ cdef class Context(PyverbsCM): format(idx=index, port=port_num)) return gid + def query_port(self, unsigned int port_num): + """ + Query port <port_num> of the device and returns its attributes. + :param port_num: Port number to query + :return: PortAttr object on success + """ + port_attrs = PortAttr() + rc = v.ibv_query_port(self.context, port_num, &port_attrs.attr) + if rc != 0: + raise PyverbsRDMAErrno('Failed to query port {p}'.format(p=port_num)) + return port_attrs + cdef add_ref(self, obj): if isinstance(obj, PD): self.pds.add(obj) @@ -585,6 +598,99 @@ cdef class DM(PyverbsCM): return res +cdef class PortAttr(PyverbsObject): + @property + def state(self): + return self.attr.state + @property + def max_mtu(self): + return self.attr.max_mtu + @property + def active_mtu(self): + return self.attr.active_mtu + @property + def gid_tbl_len(self): + return self.attr.gid_tbl_len + @property + def port_cap_flags(self): + return self.attr.port_cap_flags + @property + def max_msg_sz(self): + return self.attr.max_msg_sz + @property + def bad_pkey_cntr(self): + return self.attr.bad_pkey_cntr + @property + def qkey_viol_cntr(self): + return self.attr.qkey_viol_cntr + @property + def pkey_tbl_len(self): + return self.attr.pkey_tbl_len + @property + def lid(self): + return self.attr.lid + @property + def sm_lid(self): + return self.attr.sm_lid + @property + def lmc(self): + return self.attr.lmc + @property + def max_vl_num(self): + return self.attr.max_vl_num + @property + def sm_sl(self): + return self.attr.sm_sl + @property + def subnet_timeout(self): + return self.attr.subnet_timeout + @property + def init_type_reply(self): + return self.attr.init_type_reply + @property + def active_width(self): + return self.attr.active_width + @property + def active_speed(self): + return self.attr.active_speed + @property + def phys_state(self): + return self.attr.phys_state + @property + def link_layer(self): + return self.attr.link_layer + @property + def flags(self): + return self.attr.flags + @property + def port_cap_flags2(self): + return self.attr.port_cap_flags2 + + def __str__(self): + print_format = '{:<24}: {:<20}\n' + return print_format.format('Port state', port_state_to_str(self.attr.state)) +\ + print_format.format('Max MTU', translate_mtu(self.attr.max_mtu)) +\ + print_format.format('Active MTU', translate_mtu(self.attr.active_mtu)) +\ + print_format.format('SM lid', self.attr.sm_lid) +\ + print_format.format('Port lid', self.attr.lid) +\ + print_format.format('lmc', hex(self.attr.lmc)) +\ + print_format.format('Link layer', translate_link_layer(self.attr.link_layer)) +\ + print_format.format('Max message size', hex(self.attr.max_msg_sz)) +\ + print_format.format('Port cap flags', translate_port_cap_flags(self.attr.port_cap_flags)) +\ + print_format.format('Port cap flags 2', translate_port_cap_flags2(self.attr.port_cap_flags2)) +\ + print_format.format('max VL num', self.attr.max_vl_num) +\ + print_format.format('Bad Pkey counter', self.attr.bad_pkey_cntr) +\ + print_format.format('Qkey violations counter', self.attr.qkey_viol_cntr) +\ + print_format.format('GID table len', self.attr.gid_tbl_len) +\ + print_format.format('Pkey table len', self.attr.pkey_tbl_len) +\ + print_format.format('SM sl', self.attr.sm_sl) +\ + print_format.format('Subnet timeout', self.attr.subnet_timeout) +\ + print_format.format('Init type reply', self.attr.init_type_reply) +\ + print_format.format('Active width', width_to_str(self.attr.active_width)) +\ + print_format.format('Active speed', speed_to_str(self.attr.active_speed)) +\ + print_format.format('Phys state', phys_state_to_str(self.attr.phys_state)) +\ + print_format.format('Flags', self.attr.flags) + def guid_format(num): """ Get GUID representation of the given number, including change of endianness. @@ -608,6 +714,96 @@ def translate_node_type(node_type): def guid_to_hex(node_guid): return hex(node_guid).replace('L', '').replace('0x', '') +def port_state_to_str(port_state): + l = {0: 'NOP', 1: 'Down', 2: 'Init', 3: 'Armed',4: 'Active', + 5: 'Active defer'} + try: + return '{s} ({n})'.format(s=l[port_state], n=port_state) + except: + return 'Invalid state' + +def translate_mtu(mtu): + l = {1: 256, 2: 512, 3: 1024, 4: 2048, 5: 4096} + try: + return '{s} ({n})'.format(s=l[mtu], n=mtu) + except: + return 'Invalid MTU' + +def translate_link_layer(ll): + l = {0: 'Unspecified', 1:'InfiniBand', 2:'Ethernet'} + try: + return l[ll] + except: + return 'Invalid link layer {ll}'.format(ll=ll) + +def translate_port_cap_flags(flags): + l = {e.IBV_PORT_SM: 'IBV_PORT_SM', + e.IBV_PORT_NOTICE_SUP: 'IBV_PORT_NOTICE_SUP', + e.IBV_PORT_TRAP_SUP: 'IBV_PORT_TRAP_SUP', + e.IBV_PORT_OPT_IPD_SUP: 'IBV_PORT_OPT_IPD_SUP', + e.IBV_PORT_AUTO_MIGR_SUP: 'IBV_PORT_AUTO_MIGR_SUP', + e.IBV_PORT_SL_MAP_SUP: 'IBV_PORT_SL_MAP_SUP', + e.IBV_PORT_MKEY_NVRAM: 'IBV_PORT_MKEY_NVRAM', + e.IBV_PORT_PKEY_NVRAM: 'IBV_PORT_PKEY_NVRAM', + e.IBV_PORT_LED_INFO_SUP: 'IBV_PORT_LED_INFO_SUP', + e.IBV_PORT_SYS_IMAGE_GUID_SUP: 'IBV_PORT_SYS_IMAGE_GUID_SUP', + e.IBV_PORT_PKEY_SW_EXT_PORT_TRAP_SUP: 'IBV_PORT_PKEY_SW_EXT_PORT_TRAP_SUP', + e.IBV_PORT_EXTENDED_SPEEDS_SUP: 'IBV_PORT_EXTENDED_SPEEDS_SUP', + e.IBV_PORT_CAP_MASK2_SUP: 'IBV_PORT_CAP_MASK2_SUP', + e.IBV_PORT_CM_SUP: 'IBV_PORT_CM_SUP', + e.IBV_PORT_SNMP_TUNNEL_SUP: 'IBV_PORT_SNMP_TUNNEL_SUP', + e.IBV_PORT_REINIT_SUP: 'IBV_PORT_REINIT_SUP', + e.IBV_PORT_DEVICE_MGMT_SUP: 'IBV_PORT_DEVICE_MGMT_SUP', + e.IBV_PORT_VENDOR_CLASS_SUP: 'IBV_PORT_VENDOR_CLASS_SUP', + e.IBV_PORT_DR_NOTICE_SUP: 'IBV_PORT_DR_NOTICE_SUP', + e.IBV_PORT_CAP_MASK_NOTICE_SUP: 'IBV_PORT_CAP_MASK_NOTICE_SUP', + e.IBV_PORT_BOOT_MGMT_SUP: 'IBV_PORT_BOOT_MGMT_SUP', + e.IBV_PORT_LINK_LATENCY_SUP: 'IBV_PORT_LINK_LATENCY_SUP', + e.IBV_PORT_CLIENT_REG_SUP: 'IBV_PORT_CLIENT_REG_SUP', + e.IBV_PORT_IP_BASED_GIDS: 'IBV_PORT_IP_BASED_GIDS'} + return str_from_flags(flags, l) + +def translate_port_cap_flags2(flags): + l = {e.IBV_PORT_SET_NODE_DESC_SUP: 'IBV_PORT_SET_NODE_DESC_SUP', + e.IBV_PORT_INFO_EXT_SUP: 'IBV_PORT_INFO_EXT_SUP', + e.IBV_PORT_VIRT_SUP: 'IBV_PORT_VIRT_SUP', + e.IBV_PORT_SWITCH_PORT_STATE_TABLE_SUP: 'IBV_PORT_SWITCH_PORT_STATE_TABLE_SUP', + e.IBV_PORT_LINK_WIDTH_2X_SUP: 'IBV_PORT_LINK_WIDTH_2X_SUP', + e.IBV_PORT_LINK_SPEED_HDR_SUP: 'IBV_PORT_LINK_SPEED_HDR_SUP'} + return str_from_flags(flags, l) + +def str_from_flags(flags, dictionary): + str_flags = "" + for bit in dictionary: + if flags & bit: + str_flags += dictionary[bit] + str_flags += ' ' + return str_flags + +def phys_state_to_str(phys): + l = {1: 'Sleep', 2: 'Polling', 3: 'Disabled', + 4: 'Port configuration training', 5: 'Link up', + 6: 'Link error recovery', 7: 'Phy test'} + try: + return '{s} ({n})'.format(s=l[phys], n=phys) + except: + return 'Invalid physical state' + +def width_to_str(width): + l = {1: '1X', 2: '4X', 4: '8X', 16: '2X'} + try: + return '{s} ({n})'.format(s=l[width], n=width) + except: + return 'Invalid width' + +def speed_to_str(speed): + l = {1: '2.5 Gbps', 2: '5.0 Gbps', 4: '5.0 Gbps', 8: '10.0 Gbps', + 16: '14.0 Gbps', 32: '25.0 Gbps', 64: '50.0 Gbps'} + try: + return '{s} ({n})'.format(s=l[speed], n=speed) + except: + return 'Invalid speed' + def get_device_list(): """ :return: list of IB_devices on current node diff --git a/pyverbs/libibverbs.pxd b/pyverbs/libibverbs.pxd index 5dd3ba013e5e..c6b564c4d487 100644 --- a/pyverbs/libibverbs.pxd +++ b/pyverbs/libibverbs.pxd @@ -148,6 +148,30 @@ cdef extern from 'infiniband/verbs.h': ibv_context *context unsigned int comp_mask + cdef struct ibv_port_attr: + ibv_port_state state + ibv_mtu max_mtu + ibv_mtu active_mtu + int gid_tbl_len + unsigned int port_cap_flags + unsigned int max_msg_sz + unsigned int bad_pkey_cntr + unsigned int qkey_viol_cntr + unsigned short pkey_tbl_len + unsigned short lid + unsigned short sm_lid + unsigned char lmc + unsigned char max_vl_num + unsigned char sm_sl + unsigned char subnet_timeout + unsigned char init_type_reply + unsigned char active_width + unsigned char active_speed + unsigned char phys_state + unsigned char link_layer + unsigned char flags + unsigned short port_cap_flags2 + ibv_device **ibv_get_device_list(int *n) void ibv_free_device_list(ibv_device **list) ibv_context *ibv_open_device(ibv_device *device) @@ -173,3 +197,5 @@ cdef extern from 'infiniband/verbs.h': size_t length) int ibv_memcpy_from_dm(void *host_addr, ibv_dm *dm, unsigned long dm_offset, size_t length) + int ibv_query_port(ibv_context *context, uint8_t port_num, + ibv_port_attr *port_attr) diff --git a/pyverbs/libibverbs_enums.pxd b/pyverbs/libibverbs_enums.pxd index d6e81199fae3..2525e869a201 100644 --- a/pyverbs/libibverbs_enums.pxd +++ b/pyverbs/libibverbs_enums.pxd @@ -3,6 +3,11 @@ cdef extern from '<infiniband/verbs.h>': + cpdef enum: + IBV_LINK_LAYER_UNSPECIFIED + IBV_LINK_LAYER_INFINIBAND + IBV_LINK_LAYER_ETHERNET + cpdef enum ibv_atomic_cap: IBV_ATOMIC_NONE IBV_ATOMIC_HCA @@ -29,6 +34,7 @@ cdef extern from '<infiniband/verbs.h>': IBV_PORT_SYS_IMAGE_GUID_SUP = 1 << 11 IBV_PORT_PKEY_SW_EXT_PORT_TRAP_SUP = 1 << 12 IBV_PORT_EXTENDED_SPEEDS_SUP = 1 << 14 + IBV_PORT_CAP_MASK2_SUP = 1 << 15, IBV_PORT_CM_SUP = 1 << 16 IBV_PORT_SNMP_TUNNEL_SUP = 1 << 17 IBV_PORT_REINIT_SUP = 1 << 18 @@ -41,6 +47,14 @@ cdef extern from '<infiniband/verbs.h>': IBV_PORT_CLIENT_REG_SUP = 1 << 25 IBV_PORT_IP_BASED_GIDS = 1 << 26 + cpdef enum ibv_port_cap_flags2: + IBV_PORT_SET_NODE_DESC_SUP = 1 << 0 + IBV_PORT_INFO_EXT_SUP = 1 << 1 + IBV_PORT_VIRT_SUP = 1 << 2 + IBV_PORT_SWITCH_PORT_STATE_TABLE_SUP = 1 << 3 + IBV_PORT_LINK_WIDTH_2X_SUP = 1 << 4 + IBV_PORT_LINK_SPEED_HDR_SUP = 1 << 5 + cpdef enum ibv_mtu: IBV_MTU_256 = 1 IBV_MTU_512 = 2 -- 2.17.2