@@ -1,6 +1,8 @@
# SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB)
# Copyright (c) 2019 Mellanox Technologies, Inc. All rights reserved. See COPYING file
+include 'mlx5dv_enums.pxd'
+
from libcpp cimport bool
cimport pyverbs.libibverbs as v
@@ -40,7 +42,20 @@ cdef extern from 'infiniband/mlx5dv.h':
unsigned int flow_action_flags
unsigned int dc_odp_caps
+ cdef struct mlx5dv_dc_init_attr:
+ mlx5dv_dc_type dc_type
+ unsigned long dct_access_key
+
+ cdef struct mlx5dv_qp_init_attr:
+ unsigned long comp_mask
+ unsigned int create_flags
+ mlx5dv_dc_init_attr dc_init_attr
+ unsigned long send_ops_flags
+
bool mlx5dv_is_supported(v.ibv_device *device)
v.ibv_context* mlx5dv_open_device(v.ibv_device *device,
mlx5dv_context_attr *attr)
int mlx5dv_query_device(v.ibv_context *ctx, mlx5dv_context *attrs_out)
+ v.ibv_qp *mlx5dv_create_qp(v.ibv_context *context,
+ v.ibv_qp_init_attr_ex *qp_attr,
+ mlx5dv_qp_init_attr *mlx5_qp_attr)
@@ -6,6 +6,8 @@
cimport pyverbs.providers.mlx5.libmlx5 as dv
from pyverbs.base cimport PyverbsObject
from pyverbs.device cimport Context
+from pyverbs.qp cimport QP
+
cdef class Mlx5Context(Context):
pass
@@ -15,3 +17,12 @@ cdef class Mlx5DVContextAttr(PyverbsObject):
cdef class Mlx5DVContext(PyverbsObject):
cdef dv.mlx5dv_context dv
+
+cdef class Mlx5DVDCInitAttr(PyverbsObject):
+ cdef dv.mlx5dv_dc_init_attr attr
+
+cdef class Mlx5DVQPInitAttr(PyverbsObject):
+ cdef dv.mlx5dv_qp_init_attr attr
+
+cdef class Mlx5QP(QP):
+ cdef object dc_type
@@ -6,7 +6,8 @@ cimport pyverbs.providers.mlx5.mlx5dv_enums as dve
cimport pyverbs.providers.mlx5.libmlx5 as dv
from pyverbs.base import PyverbsRDMAErrno
cimport pyverbs.libibverbs_enums as e
-
+from pyverbs.qp cimport QPInitAttrEx
+from pyverbs.pd cimport PD
cdef class Mlx5DVContextAttr(PyverbsObject):
"""
@@ -179,8 +180,159 @@ cdef class Mlx5DVContext(PyverbsObject):
print_format.format('DC ODP caps', self.dv.dc_odp_caps)
+cdef class Mlx5DVDCInitAttr(PyverbsObject):
+ """
+ Represents mlx5dv_dc_init_attr struct, which defines initial attributes
+ for DC QP creation.
+ """
+ def __cinit__(self, dc_type=dve.MLX5DV_DCTYPE_DCI, dct_access_key=0):
+ """
+ Initializes an Mlx5DVDCInitAttr object with the given DC type and DCT
+ access key.
+ :param dc_type: Which DC QP to create (DCI/DCT).
+ :param dct_access_key: Access key to be used by the DCT
+ :return: An initializes object
+ """
+ self.attr.dc_type = dc_type
+ self.attr.dct_access_key = dct_access_key
+
+ def __str__(self):
+ print_format = '{:20}: {:<20}\n'
+ return print_format.format('DC type', dc_type_to_str(self.attr.dc_type)) +\
+ print_format.format('DCT access key', self.attr.dct_access_key)
+
+ @property
+ def dc_type(self):
+ return self.attr.dc_type
+ @dc_type.setter
+ def dc_type(self, val):
+ self.attr.dc_type = val
+
+ @property
+ def dct_access_key(self):
+ return self.attr.dct_access_key
+ @dct_access_key.setter
+ def dct_access_key(self, val):
+ self.attr.dct_access_key = val
+
+
+cdef class Mlx5DVQPInitAttr(PyverbsObject):
+ """
+ Represents mlx5dv_qp_init_attr struct, initial attributes used for mlx5 QP
+ creation.
+ """
+ def __cinit__(self, comp_mask=0, create_flags=0,
+ Mlx5DVDCInitAttr dc_init_attr=None, send_ops_flags=0):
+ """
+ Initializes an Mlx5DVQPInitAttr object with the given user data.
+ :param comp_mask: A bitmask specifying which fields are valid
+ :param create_flags: A bitwise OR of mlx5dv_qp_create_flags
+ :param dc_init_attr: Mlx5DVDCInitAttr object
+ :param send_ops_flags: A bitwise OR of mlx5dv_qp_create_send_ops_flags
+ :return: An initialized Mlx5DVQPInitAttr object
+ """
+ self.attr.comp_mask = comp_mask
+ self.attr.create_flags = create_flags
+ self.attr.send_ops_flags = send_ops_flags
+ if dc_init_attr is not None:
+ self.attr.dc_init_attr.dc_type = dc_init_attr.dc_type
+ self.attr.dc_init_attr.dct_access_key = dc_init_attr.dct_access_key
+
+ def __str__(self):
+ print_format = '{:20}: {:<20}\n'
+ return print_format.format('Comp mask',
+ qp_comp_mask_to_str(self.attr.comp_mask)) +\
+ print_format.format('Create flags',
+ qp_create_flags_to_str(self.attr.create_flags)) +\
+ 'DC init attr:\n' +\
+ print_format.format(' DC type',
+ dc_type_to_str(self.attr.dc_init_attr.dc_type)) +\
+ print_format.format(' DCT access key',
+ self.attr.dc_init_attr.dct_access_key) +\
+ print_format.format('Send ops flags',
+ send_ops_flags_to_str(self.attr.send_ops_flags))
+
+ @property
+ def comp_mask(self):
+ return self.attr.comp_mask
+ @comp_mask.setter
+ def comp_mask(self, val):
+ self.attr.comp_mask = val
+
+ @property
+ def create_flags(self):
+ return self.attr.create_flags
+ @create_flags.setter
+ def create_flags(self, val):
+ self.attr.create_flags = val
+
+ @property
+ def send_ops_flags(self):
+ return self.attr.send_ops_flags
+ @send_ops_flags.setter
+ def send_ops_flags(self, val):
+ self.attr.send_ops_flags = val
+
+ @property
+ def dc_type(self):
+ return self.attr.dc_init_attr.dc_type
+ @dc_type.setter
+ def dc_type(self, val):
+ self.attr.dc_init_attr.dc_type = val
+
+ @property
+ def dct_access_key(self):
+ return self.attr.dc_init_attr.dct_access_key
+ @dct_access_key.setter
+ def dct_access_key(self, val):
+ self.attr.dc_init_attr.dct_access_key = val
+
+
+cdef class Mlx5QP(QP):
+ def __cinit__(self, Mlx5Context context, QPInitAttrEx init_attr,
+ Mlx5DVQPInitAttr dv_init_attr):
+ """
+ Initializes an mlx5 QP according to the user-provided data.
+ :param context: mlx5 Context object
+ :param init_attr: QPInitAttrEx object
+ :param dv_init_attr: Mlx5DVQPInitAttr object
+ :return: An initialized Mlx5QP
+ """
+ cdef PD pd
+ self.dc_type = dv_init_attr.dc_type if dv_init_attr else 0
+ if init_attr.pd is not None:
+ pd = <PD>init_attr.pd
+ pd.add_ref(self)
+ self.qp = \
+ dv.mlx5dv_create_qp(context.context,
+ &init_attr.attr,
+ &dv_init_attr.attr if dv_init_attr is not None
+ else NULL)
+ if self.qp == NULL:
+ raise PyverbsRDMAErrno('Failed to create MLX5 QP.\nQPInitAttrEx '
+ 'attributes:\n{}\nMLX5DVQPInitAttr:\n{}'.
+ format(init_attr, dv_init_attr))
+
+ def _get_comp_mask(self, dst):
+ masks = {dve.MLX5DV_DCTYPE_DCT: {'INIT': e.IBV_QP_PKEY_INDEX |
+ e.IBV_QP_PORT | e.IBV_QP_ACCESS_FLAGS,
+ 'RTR': e.IBV_QP_AV |\
+ e.IBV_QP_PATH_MTU |\
+ e.IBV_QP_MIN_RNR_TIMER},
+ dve.MLX5DV_DCTYPE_DCI: {'INIT': e.IBV_QP_PKEY_INDEX |\
+ e.IBV_QP_PORT,
+ 'RTR': e.IBV_QP_PATH_MTU,
+ 'RTS': e.IBV_QP_TIMEOUT |\
+ e.IBV_QP_RETRY_CNT |\
+ e.IBV_QP_RNR_RETRY | e.IBV_QP_SQ_PSN |\
+ e.IBV_QP_MAX_QP_RD_ATOMIC}}
+ if self.dc_type == 0:
+ return super()._get_comp_mask(dst)
+ return masks[self.dc_type][dst] | e.IBV_QP_STATE
+
+
def qpts_to_str(qp_types):
- numberic_types = qp_types
+ numeric_types = qp_types
qpts_str = ''
qpts = {e.IBV_QPT_RC: 'RC', e.IBV_QPT_UC: 'UC', e.IBV_QPT_UD: 'UD',
e.IBV_QPT_RAW_PACKET: 'Raw Packet', e.IBV_QPT_XRC_SEND: 'XRC Send',
@@ -191,7 +343,7 @@ def qpts_to_str(qp_types):
qp_types -= t
if qp_types == 0:
break
- return qpts_str[:-2] + ' ({})'.format(numberic_types)
+ return qpts_str[:-2] + ' ({})'.format(numeric_types)
def bitmask_to_str(bits, values):
@@ -251,3 +403,37 @@ def tunnel_offloads_to_str(tun):
dve.MLX5DV_RAW_PACKET_CAP_TUNNELED_OFFLOAD_CW_MPLS_OVER_UDP:\
'Ctrl word + MPLS over UDP'}
return bitmask_to_str(tun, l)
+
+
+def dc_type_to_str(dctype):
+ l = {dve.MLX5DV_DCTYPE_DCT: 'DCT', dve.MLX5DV_DCTYPE_DCI: 'DCI'}
+ try:
+ return l[dctype]
+ except KeyError:
+ return 'Unknown DC type ({dc})'.format(dc=dctype)
+
+
+def qp_comp_mask_to_str(flags):
+ l = {dve.MLX5DV_QP_INIT_ATTR_MASK_QP_CREATE_FLAGS: 'Create flags',
+ dve.MLX5DV_QP_INIT_ATTR_MASK_DC: 'DC',
+ dve.MLX5DV_QP_INIT_ATTR_MASK_SEND_OPS_FLAGS: 'Send ops flags'}
+ return bitmask_to_str(flags, l)
+
+
+def qp_create_flags_to_str(flags):
+ l = {dve.MLX5DV_QP_CREATE_TUNNEL_OFFLOADS: 'Tunnel offloads',
+ dve.MLX5DV_QP_CREATE_TIR_ALLOW_SELF_LOOPBACK_UC:
+ 'Allow UC self loopback',
+ dve.MLX5DV_QP_CREATE_TIR_ALLOW_SELF_LOOPBACK_MC:
+ 'Allow MC self loopback',
+ dve.MLX5DV_QP_CREATE_DISABLE_SCATTER_TO_CQE: 'Disable scatter to CQE',
+ dve.MLX5DV_QP_CREATE_ALLOW_SCATTER_TO_CQE: 'Allow scatter to CQE',
+ dve.MLX5DV_QP_CREATE_PACKET_BASED_CREDIT_MODE:
+ 'Packet based credit mode'}
+ return bitmask_to_str(flags, l)
+
+
+def send_ops_flags_to_str(flags):
+ l = {dve.MLX5DV_QP_EX_WITH_MR_INTERLEAVED: 'With MR interleaved',
+ dve.MLX5DV_QP_EX_WITH_MR_LIST: 'With MR list'}
+ return bitmask_to_str(flags, l)
@@ -45,3 +45,24 @@ cdef extern from 'infiniband/mlx5dv.h':
MLX5DV_FLOW_ACTION_FLAGS_ESP_AES_GCM_SPI_STEERING = 1 << 2
MLX5DV_FLOW_ACTION_FLAGS_ESP_AES_GCM_FULL_OFFLOAD = 1 << 3
MLX5DV_FLOW_ACTION_FLAGS_ESP_AES_GCM_TX_IV_IS_ESN = 1 << 4
+
+ cpdef enum mlx5dv_qp_init_attr_mask:
+ MLX5DV_QP_INIT_ATTR_MASK_QP_CREATE_FLAGS = 1 << 0
+ MLX5DV_QP_INIT_ATTR_MASK_DC = 1 << 1
+ MLX5DV_QP_INIT_ATTR_MASK_SEND_OPS_FLAGS = 1 << 2
+
+ cpdef enum mlx5dv_qp_create_flags:
+ MLX5DV_QP_CREATE_TUNNEL_OFFLOADS = 1 << 0
+ MLX5DV_QP_CREATE_TIR_ALLOW_SELF_LOOPBACK_UC = 1 << 1
+ MLX5DV_QP_CREATE_TIR_ALLOW_SELF_LOOPBACK_MC = 1 << 2
+ MLX5DV_QP_CREATE_DISABLE_SCATTER_TO_CQE = 1 << 3
+ MLX5DV_QP_CREATE_ALLOW_SCATTER_TO_CQE = 1 << 4
+ MLX5DV_QP_CREATE_PACKET_BASED_CREDIT_MODE = 1 << 5
+
+ cpdef enum mlx5dv_dc_type:
+ MLX5DV_DCTYPE_DCT = 1
+ MLX5DV_DCTYPE_DCI = 2
+
+ cpdef enum mlx5dv_qp_create_send_ops_flags:
+ MLX5DV_QP_EX_WITH_MR_INTERLEAVED = 1 << 0
+ MLX5DV_QP_EX_WITH_MR_LIST = 1 << 1
Add the needed declarations and structs to allow users to create a QP via the mlx5dv interface. Creation process is similar to that of a legacy QP but the user shall use an Mlx5Context and provide an Mlx5DVQPInitAttr object as well as a QPInitAttrEx object. Signed-off-by: Noa Osherovich <noaos@mellanox.com> --- pyverbs/providers/mlx5/libmlx5.pxd | 15 ++ pyverbs/providers/mlx5/mlx5dv.pxd | 11 ++ pyverbs/providers/mlx5/mlx5dv.pyx | 192 +++++++++++++++++++++++- pyverbs/providers/mlx5/mlx5dv_enums.pxd | 21 +++ 4 files changed, 236 insertions(+), 3 deletions(-)