blob: 1cd8c6ced348c7dd9a6f3395c57412f97b7770b5 [file] [log] [blame] [edit]
# SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB)
# Copyright 2020-2023 Amazon.com, Inc. or its affiliates. All rights reserved.
cimport pyverbs.providers.efa.efadv_enums as dve
cimport pyverbs.providers.efa.libefa as dv
from pyverbs.addr cimport GID
from pyverbs.base import PyverbsRDMAErrno, PyverbsRDMAError
from pyverbs.cq cimport CQEX, CqInitAttrEx
import pyverbs.enums as e
cimport pyverbs.libibverbs as v
from pyverbs.pd cimport PD
from pyverbs.qp cimport QP, QPEx, QPInitAttr, QPInitAttrEx
def dev_cap_to_str(flags):
l = {
dve.EFADV_DEVICE_ATTR_CAPS_RDMA_READ: 'RDMA Read',
dve.EFADV_DEVICE_ATTR_CAPS_RNR_RETRY: 'RNR Retry',
dve.EFADV_DEVICE_ATTR_CAPS_CQ_WITH_SGID: 'CQ entries with source GID',
dve.EFADV_DEVICE_ATTR_CAPS_RDMA_WRITE: 'RDMA Write',
}
return bitmask_to_str(flags, l)
def bitmask_to_str(bits, values):
numeric_bits = bits
flags = []
for k, v in sorted(values.items()):
if bits & k:
flags.append(v)
bits -= k
if bits:
flags.append(f'??({bits:x})')
if not flags:
flags.append('None')
return ', '.join(flags) + f' ({numeric_bits:x})'
cdef class EfaContext(Context):
"""
Represent efa context, which extends Context.
"""
def __init__(self, name=''):
"""
Open an efa device
:param name: The RDMA device's name (used by parent class)
:return: None
"""
super().__init__(name=name)
def query_efa_device(self):
"""
Queries the provider for device-specific attributes.
:return: An EfaDVDeviceAttr containing the attributes.
"""
dv_attr = EfaDVDeviceAttr()
rc = dv.efadv_query_device(self.context, &dv_attr.device_attr, sizeof(dv_attr.device_attr))
if rc:
raise PyverbsRDMAError(f'Failed to query efa device {self.name}', rc)
return dv_attr
cdef class EfaDVDeviceAttr(PyverbsObject):
"""
Represents efadv_context struct, which exposes efa-specific capabilities,
reported by efadv_query_device.
"""
@property
def comp_mask(self):
return self.device_attr.comp_mask
@property
def max_sq_wr(self):
return self.device_attr.max_sq_wr
@property
def max_rq_wr(self):
return self.device_attr.max_rq_wr
@property
def max_sq_sge(self):
return self.device_attr.max_sq_sge
@property
def max_rq_sge(self):
return self.device_attr.max_rq_sge
@property
def inline_buf_size(self):
return self.device_attr.inline_buf_size
@property
def device_caps(self):
return self.device_attr.device_caps
@property
def max_rdma_size(self):
return self.device_attr.max_rdma_size
def __str__(self):
print_format = '{:20}: {:<20}\n'
return print_format.format('comp_mask', self.device_attr.comp_mask) + \
print_format.format('Max SQ WR', self.device_attr.max_sq_wr) + \
print_format.format('Max RQ WR', self.device_attr.max_rq_wr) + \
print_format.format('Max SQ SQE', self.device_attr.max_sq_sge) + \
print_format.format('Max RQ SQE', self.device_attr.max_rq_sge) + \
print_format.format('Inline buffer size', self.device_attr.inline_buf_size) + \
print_format.format('Device Capabilities', dev_cap_to_str(self.device_attr.device_caps)) + \
print_format.format('Max RDMA Size', self.device_attr.max_rdma_size)
cdef class EfaDVAHAttr(PyverbsObject):
"""
Represents efadv_ah_attr struct
"""
@property
def comp_mask(self):
return self.ah_attr.comp_mask
@property
def ahn(self):
return self.ah_attr.ahn
def __str__(self):
print_format = '{:20}: {:<20}\n'
return print_format.format('comp_mask', self.ah_attr.comp_mask) + \
print_format.format('ahn', self.ah_attr.ahn)
cdef class EfaAH(AH):
def query_efa_ah(self):
"""
Queries the provider for EFA specific AH attributes.
:return: An EfaDVAHAttr containing the attributes.
"""
ah_attr = EfaDVAHAttr()
err = dv.efadv_query_ah(self.ah, &ah_attr.ah_attr, sizeof(ah_attr.ah_attr))
if err:
raise PyverbsRDMAError('Failed to query efa ah', err)
return ah_attr
cdef class SRDQP(QP):
"""
Initializes an SRD QP according to the user-provided data.
:param pd: PD object
:param init_attr: QPInitAttr object
:return: An initialized SRDQP
"""
def __init__(self, PD pd not None, QPInitAttr init_attr not None):
pd.add_ref(self)
self.qp = dv.efadv_create_driver_qp(pd.pd, &init_attr.attr, dve.EFADV_QP_DRIVER_TYPE_SRD)
if self.qp == NULL:
raise PyverbsRDMAErrno('Failed to create SRD QP')
super().__init__(pd, init_attr)
cdef class EfaQPInitAttr(PyverbsObject):
"""
Represents efadv_qp_init_attr struct.
"""
@property
def comp_mask(self):
return self.qp_init_attr.comp_mask
@property
def driver_qp_type(self):
return self.qp_init_attr.driver_qp_type
@driver_qp_type.setter
def driver_qp_type(self,val):
self.qp_init_attr.driver_qp_type = val
cdef class SRDQPEx(QPEx):
"""
Initializes an SRD QPEx according to the user-provided data.
:param ctx: Context object
:param init_attr: QPInitAttrEx object
:param dv_init_attr: EFAQPInitAttr object
:return: An initialized SRDQPEx
"""
def __init__(self, Context ctx not None, QPInitAttrEx attr_ex not None, EfaQPInitAttr efa_init_attr not None):
cdef PD pd
self.qp = dv.efadv_create_qp_ex(ctx.context, &attr_ex.attr, &efa_init_attr.qp_init_attr, sizeof(efa_init_attr.qp_init_attr))
if self.qp == NULL:
raise PyverbsRDMAErrno('Failed to create SRD QPEx')
self.context = ctx
ctx.add_ref(self)
if attr_ex.pd is not None:
pd=<PD>attr_ex.pd
pd.add_ref(self)
super().__init__(ctx, attr_ex)
def _get_comp_mask(self, dst):
srd_mask = {'INIT': e.IBV_QP_PKEY_INDEX | e.IBV_QP_PORT | e.IBV_QP_QKEY,
'RTR': 0,
'RTS': e.IBV_QP_SQ_PSN}
return srd_mask [dst] | e.IBV_QP_STATE
cdef class EfaDVCQInitAttr(PyverbsObject):
"""
Represents efadv_cq_init_attr struct.
"""
def __init__(self, wc_flags=0):
super().__init__()
self.cq_init_attr.wc_flags = wc_flags
@property
def comp_mask(self):
return self.cq_init_attr.comp_mask
@property
def wc_flags(self):
return self.cq_init_attr.wc_flags
@wc_flags.setter
def wc_flags(self, val):
self.cq_init_attr.wc_flags = val
cdef class EfaCQ(CQEX):
"""
Initializes an Efa CQ according to the user-provided data.
:param ctx: Context object
:param attr_ex: CQInitAttrEx object
:param efa_init_attr: EfaDVCQInitAttr object
:return: An initialized EfaCQ
"""
def __init__(self, Context ctx not None, CqInitAttrEx attr_ex not None, EfaDVCQInitAttr efa_init_attr):
if efa_init_attr is None:
efa_init_attr = EfaDVCQInitAttr()
self.cq = dv.efadv_create_cq(ctx.context, &attr_ex.attr, &efa_init_attr.cq_init_attr, sizeof(efa_init_attr.cq_init_attr))
if self.cq == NULL:
raise PyverbsRDMAErrno('Failed to create EFA CQ')
self.ibv_cq = v.ibv_cq_ex_to_cq(self.cq)
self.dv_cq = dv.efadv_cq_from_ibv_cq_ex(self.cq)
self.context = ctx
ctx.add_ref(self)
super().__init__(ctx, attr_ex)
def read_sgid(self):
"""
Read SGID from last work completion, if AH is unknown.
"""
sgid = GID()
err = dv.efadv_wc_read_sgid(self.dv_cq, &sgid.gid)
if err:
return None
return sgid