| # SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB) |
| # Copyright (c) 2018, Mellanox Technologies. All rights reserved. See COPYING file |
| |
| from libc.stdint cimport uint8_t, uintptr_t |
| |
| from .pyverbs_error import PyverbsUserError, PyverbsRDMAError |
| from pyverbs.utils import gid_str_to_array, gid_str |
| from pyverbs.base import PyverbsRDMAErrno |
| from pyverbs.cmid cimport UDParam |
| cimport pyverbs.libibverbs as v |
| from pyverbs.pd cimport PD |
| from pyverbs.cq cimport WC |
| |
| cdef extern from 'endian.h': |
| unsigned long be64toh(unsigned long host_64bits) |
| |
| |
| cdef class GID(PyverbsObject): |
| """ |
| GID class represents ibv_gid. It enables user to query for GIDs values. |
| """ |
| def __init__(self, val=None): |
| super().__init__() |
| if val is not None: |
| vals = gid_str_to_array(val) |
| |
| for i in range(16): |
| self.gid.raw[i] = <uint8_t>int(vals[i],16) |
| |
| @property |
| def gid(self): |
| """ |
| Expose the inner GID |
| :return: A GID string in an 8 words format: |
| 'xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx' |
| """ |
| return self.__str__() |
| @gid.setter |
| def gid(self, val): |
| """ |
| Sets the inner GID |
| :param val: A GID string in an 8 words format: |
| 'xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx' |
| :return: None |
| """ |
| self._set_gid(val) |
| |
| def _set_gid(self, val): |
| vals = gid_str_to_array(val) |
| |
| for i in range(16): |
| self.gid.raw[i] = <uint8_t>int(vals[i],16) |
| |
| def __str__(self): |
| return gid_str(self.gid._global.subnet_prefix, |
| self.gid._global.interface_id) |
| |
| |
| cdef class GRH(PyverbsObject): |
| """ |
| Represents ibv_grh struct. Used when creating or initializing an |
| Address Handle from a Work Completion. |
| """ |
| def __init__(self, GID sgid=None, GID dgid=None, version_tclass_flow=0, |
| paylen=0, next_hdr=0, hop_limit=1): |
| """ |
| Initializes a GRH object |
| :param sgid: Source GID |
| :param dgid: Destination GID |
| :param version_tclass_flow: A 32b big endian used to communicate |
| service level e.g. across subnets |
| :param paylen: A 16b big endian that is the packet length in bytes, |
| starting from the first byte after the GRH up to and |
| including the last byte of the ICRC |
| :param next_hdr: An 8b unsigned integer specifying the next header |
| For non-raw packets: 0x1B |
| For raw packets: According to IETF RFC 1700 |
| :param hop_limit: An 8b unsigned integer specifying the number of hops |
| (i.e. routers) that the packet is permitted to take |
| prior to being discarded |
| :return: A GRH object |
| """ |
| super().__init__() |
| self.grh.dgid = dgid.gid |
| self.grh.sgid = sgid.gid |
| self.grh.version_tclass_flow = version_tclass_flow |
| self.grh.paylen = paylen |
| self.grh.next_hdr = next_hdr |
| self.grh.hop_limit = hop_limit |
| |
| @property |
| def dgid(self): |
| return gid_str(self.grh.dgid._global.subnet_prefix, |
| self.grh.dgid._global.interface_id) |
| @dgid.setter |
| def dgid(self, val): |
| vals = gid_str_to_array(val) |
| for i in range(16): |
| self.grh.dgid.raw[i] = <uint8_t>int(vals[i],16) |
| |
| @property |
| def sgid(self): |
| return gid_str(self.grh.sgid._global.subnet_prefix, |
| self.grh.sgid._global.interface_id) |
| @sgid.setter |
| def sgid(self, val): |
| vals = gid_str_to_array(val) |
| for i in range(16): |
| self.grh.sgid.raw[i] = <uint8_t>int(vals[i],16) |
| |
| @property |
| def version_tclass_flow(self): |
| return self.grh.version_tclass_flow |
| |
| @version_tclass_flow.setter |
| def version_tclass_flow(self, val): |
| self.grh.version_tclass_flow = val |
| |
| @property |
| def paylen(self): |
| return self.grh.paylen |
| @paylen.setter |
| def paylen(self, val): |
| self.grh.paylen = val |
| |
| @property |
| def next_hdr(self): |
| return self.grh.next_hdr |
| @next_hdr.setter |
| def next_hdr(self, val): |
| self.grh.next_hdr = val |
| |
| @property |
| def hop_limit(self): |
| return self.grh.hop_limit |
| @hop_limit.setter |
| def hop_limit(self, val): |
| self.grh.hop_limit = val |
| |
| def __str__(self): |
| print_format = '{:22}: {:<20}\n' |
| return print_format.format('DGID', self.dgid) +\ |
| print_format.format('SGID', self.sgid) +\ |
| print_format.format('version tclass flow', self.version_tclass_flow) +\ |
| print_format.format('paylen', self.paylen) +\ |
| print_format.format('next header', self.next_hdr) +\ |
| print_format.format('hop limit', self.hop_limit) |
| |
| |
| cdef class GlobalRoute(PyverbsObject): |
| """ |
| Represents ibv_global_route. Used in Address Handle creation and describes |
| the values to be used in the GRH of the packets that will be sent using |
| this Address Handle. |
| """ |
| def __init__(self, GID dgid=None, flow_label=0, sgid_index=0, hop_limit=1, |
| traffic_class=0): |
| """ |
| Initializes a GlobalRoute object with given parameters. |
| :param dgid: Destination GID |
| :param flow_label: A 20b value. If non-zero, gives a hint to switches |
| and routers that this sequence of packets must be |
| delivered in order |
| :param sgid_index: An index in the port's GID table that identifies the |
| originator of the packet |
| :param hop_limit: An 8b unsigned integer specifying the number of hops |
| (i.e. routers) that the packet is permitted to take |
| prior to being discarded |
| :param traffic_class: An 8b unsigned integer specifying the required |
| delivery priority for routers |
| :return: A GlobalRoute object |
| """ |
| super().__init__() |
| self.gr.dgid=dgid.gid |
| self.gr.flow_label = flow_label |
| self.gr.sgid_index = sgid_index |
| self.gr.hop_limit = hop_limit |
| self.gr.traffic_class = traffic_class |
| |
| @property |
| def dgid(self): |
| return gid_str(self.gr.dgid._global.subnet_prefix, |
| self.gr.dgid._global.interface_id) |
| @dgid.setter |
| def dgid(self, val): |
| vals = gid_str_to_array(val) |
| for i in range(16): |
| self.gr.dgid.raw[i] = <uint8_t>int(vals[i],16) |
| |
| @property |
| def flow_label(self): |
| return self.gr.flow_label |
| @flow_label.setter |
| def flow_label(self, val): |
| self.gr.flow_label = val |
| |
| @property |
| def sgid_index(self): |
| return self.gr.sgid_index |
| @sgid_index.setter |
| def sgid_index(self, val): |
| self.gr.sgid_index = val |
| |
| @property |
| def hop_limit(self): |
| return self.gr.hop_limit |
| @hop_limit.setter |
| def hop_limit(self, val): |
| self.gr.hop_limit = val |
| |
| @property |
| def traffic_class(self): |
| return self.gr.traffic_class |
| @traffic_class.setter |
| def traffic_class(self, val): |
| self.gr.traffic_class = val |
| |
| def __str__(self): |
| print_format = '{:22}: {:<20}\n' |
| return print_format.format('DGID', self.dgid) +\ |
| print_format.format('flow label', self.flow_label) +\ |
| print_format.format('sgid index', self.sgid_index) +\ |
| print_format.format('hop limit', self.hop_limit) +\ |
| print_format.format('traffic class', self.traffic_class) |
| |
| |
| cdef class AHAttr(PyverbsObject): |
| """ Represents ibv_ah_attr struct """ |
| def __init__(self, dlid=0, sl=0, src_path_bits=0, static_rate=0, |
| is_global=0, port_num=1, GlobalRoute gr=None): |
| """ |
| Initializes an AHAttr object. |
| :param dlid: Destination LID, a 16b unsigned integer |
| :param sl: Service level, an 8b unsigned integer |
| :param src_path_bits: When LMC (LID mask count) is used in the port, |
| packets are being sent with the port's base LID, |
| bitwise ORed with the value of the src_path_bits. |
| An 8b unsigned integer |
| :param static_rate: An 8b unsigned integer limiting the rate of packets |
| that are being sent to the subnet |
| :param is_global: If non-zero, GRH information exists in the Address |
| Handle |
| :param port_num: The local physical port from which the packets will be |
| sent |
| :param grh: Attributes of a global routing header. Will only be used if |
| is_global is non zero. |
| :return: An AHAttr object |
| """ |
| super().__init__() |
| self.ah_attr.port_num = port_num |
| self.ah_attr.sl = sl |
| self.ah_attr.src_path_bits = src_path_bits |
| self.ah_attr.dlid = dlid |
| self.ah_attr.static_rate = static_rate |
| self.ah_attr.is_global = is_global |
| # Do not set GRH fields for a non-global AH |
| if is_global: |
| if gr is None: |
| raise PyverbsUserError('Global AH Attr is created but gr parameter is None') |
| self.ah_attr.grh.dgid = gr.gr.dgid |
| self.ah_attr.grh.flow_label = gr.flow_label |
| self.ah_attr.grh.sgid_index = gr.sgid_index |
| self.ah_attr.grh.hop_limit = gr.hop_limit |
| self.ah_attr.grh.traffic_class = gr.traffic_class |
| |
| cdef init_from_ud_param(self, UDParam udparam): |
| """ |
| Initiate the AHAttr from UDParam's ah_attr. |
| :param udparam: UDParam that contains the AHAttr. |
| :return: None |
| """ |
| self.ah_attr = udparam.ud_param.ah_attr |
| |
| @property |
| def port_num(self): |
| return self.ah_attr.port_num |
| @port_num.setter |
| def port_num(self, val): |
| self.ah_attr.port_num = val |
| |
| @property |
| def sl(self): |
| return self.ah_attr.sl |
| @sl.setter |
| def sl(self, val): |
| self.ah_attr.sl = val |
| |
| @property |
| def src_path_bits(self): |
| return self.ah_attr.src_path_bits |
| @src_path_bits.setter |
| def src_path_bits(self, val): |
| self.ah_attr.src_path_bits = val |
| |
| @property |
| def dlid(self): |
| return self.ah_attr.dlid |
| @dlid.setter |
| def dlid(self, val): |
| self.ah_attr.dlid = val |
| |
| @property |
| def static_rate(self): |
| return self.ah_attr.static_rate |
| @static_rate.setter |
| def static_rate(self, val): |
| self.ah_attr.static_rate = val |
| |
| @property |
| def is_global(self): |
| return self.ah_attr.is_global |
| @is_global.setter |
| def is_global(self, val): |
| self.ah_attr.is_global = val |
| |
| @property |
| def dgid(self): |
| if self.ah_attr.is_global: |
| return gid_str(self.ah_attr.grh.dgid._global.subnet_prefix, |
| self.ah_attr.grh.dgid._global.interface_id) |
| @dgid.setter |
| def dgid(self, val): |
| if self.ah_attr.is_global: |
| vals = gid_str_to_array(val) |
| for i in range(16): |
| self.ah_attr.grh.dgid.raw[i] = <uint8_t>int(vals[i],16) |
| |
| @property |
| def flow_label(self): |
| if self.ah_attr.is_global: |
| return self.ah_attr.grh.flow_label |
| @flow_label.setter |
| def flow_label(self, val): |
| self.ah_attr.grh.flow_label = val |
| |
| @property |
| def sgid_index(self): |
| if self.ah_attr.is_global: |
| return self.ah_attr.grh.sgid_index |
| @sgid_index.setter |
| def sgid_index(self, val): |
| self.ah_attr.grh.sgid_index = val |
| |
| @property |
| def hop_limit(self): |
| if self.ah_attr.is_global: |
| return self.ah_attr.grh.hop_limit |
| @hop_limit.setter |
| def hop_limit(self, val): |
| self.ah_attr.grh.hop_limit = val |
| |
| @property |
| def traffic_class(self): |
| if self.ah_attr.is_global: |
| return self.ah_attr.grh.traffic_class |
| @traffic_class.setter |
| def traffic_class(self, val): |
| self.ah_attr.grh.traffic_class = val |
| |
| def __str__(self): |
| print_format = ' {:22}: {:<20}\n' |
| if self.is_global: |
| global_format = print_format.format('dgid', self.dgid) +\ |
| print_format.format('flow label', self.flow_label) +\ |
| print_format.format('sgid index', self.sgid_index) +\ |
| print_format.format('hop limit', self.hop_limit) +\ |
| print_format.format('traffic_class', self.traffic_class) |
| else: |
| global_format = '' |
| return print_format.format('port num', self.port_num) +\ |
| print_format.format('sl', self.sl) +\ |
| print_format.format('source path bits', self.src_path_bits) +\ |
| print_format.format('dlid', self.dlid) +\ |
| print_format.format('static rate', self.static_rate) +\ |
| print_format.format('is global', self.is_global) + global_format |
| |
| |
| cdef class AH(PyverbsCM): |
| def __init__(self, PD pd, **kwargs): |
| """ |
| Initializes an AH object with the given values. |
| Two creation methods are supported: |
| - Creation via AHAttr object (calls ibv_create_ah) |
| - Creation via a WC object (calls ibv_create_ah_from_wc) |
| :param pd: PD object this AH belongs to |
| :param kwargs: Arguments: |
| * *attr* (AHAttr) |
| An AHAttr object (represents ibv_ah_attr struct) |
| * *wc* |
| A WC object to use for AH initialization |
| * *grh* |
| Pointer to GRH object to use for AH initialization (when using |
| wc) |
| * *port_num* |
| Port number to be used for this AH (when using wc) |
| :return: An AH object on success |
| """ |
| super().__init__() |
| if len(kwargs) == 1: |
| # Create AH via ib_create_ah |
| ah_attr = <AHAttr>kwargs['attr'] |
| self.ah = v.ibv_create_ah(pd.pd, &ah_attr.ah_attr) |
| else: |
| # Create AH from WC |
| wc = <WC>kwargs['wc'] |
| grh = <v.ibv_grh*><uintptr_t>kwargs['grh'] |
| port_num = kwargs['port_num'] |
| self.ah = v.ibv_create_ah_from_wc(pd.pd, &wc.wc, grh, port_num) |
| if self.ah == NULL: |
| raise PyverbsRDMAErrno('Failed to create AH') |
| pd.add_ref(self) |
| self.pd = pd |
| |
| def __dealloc__(self): |
| self.close() |
| |
| cpdef close(self): |
| if self.ah != NULL: |
| if self.logger: |
| self.logger.debug('Closing AH') |
| rc = v.ibv_destroy_ah(self.ah) |
| if rc: |
| raise PyverbsRDMAError('Failed to destroy AH', rc) |
| self.ah = NULL |
| self.pd = None |