blob: 968c0b45fe0968f9641a6c3d6a82872997363187 [file] [log] [blame] [edit]
import weakref
from libc.errno cimport errno
from libc.string cimport memcpy
from libc.stdlib cimport malloc, free
from pyverbs.pyverbs_error import PyverbsRDMAError, PyverbsError
from pyverbs.wr cimport RecvWR, SGE, copy_sg_array
from pyverbs.base import PyverbsRDMAErrno
from pyverbs.base cimport close_weakrefs
cimport pyverbs.libibverbs_enums as e
from pyverbs.device cimport Context
from pyverbs.cq cimport CQEX, CQ
cimport pyverbs.libibverbs as v
from pyverbs.xrcd cimport XRCD
from pyverbs.qp cimport QP
from pyverbs.pd cimport PD
cdef class SrqAttr(PyverbsObject):
def __init__(self, max_wr=100, max_sge=1, srq_limit=0):
super().__init__()
self.attr.max_wr = max_wr
self.attr.max_sge = max_sge
self.attr.srq_limit = srq_limit
@property
def max_wr(self):
return self.attr.max_wr
@max_wr.setter
def max_wr(self, val):
self.attr.max_wr = val
@property
def max_sge(self):
return self.attr.max_sge
@max_sge.setter
def max_sge(self, val):
self.attr.max_sge = val
@property
def srq_limit(self):
return self.attr.srq_limit
@srq_limit.setter
def srq_limit(self, val):
self.attr.srq_limit = val
cdef class SrqInitAttr(PyverbsObject):
def __init__(self, SrqAttr attr = None):
super().__init__()
if attr is not None:
self.attr.attr.max_wr = attr.max_wr
self.attr.attr.max_sge = attr.max_sge
self.attr.attr.srq_limit = attr.srq_limit
@property
def max_wr(self):
return self.attr.attr.max_wr
@property
def max_sge(self):
return self.attr.attr.max_sge
@property
def srq_limit(self):
return self.attr.attr.srq_limit
cdef class SrqInitAttrEx(PyverbsObject):
def __init__(self, max_wr=100, max_sge=1, srq_limit=0):
super().__init__()
self.attr.attr.max_wr = max_wr
self.attr.attr.max_sge = max_sge
self.attr.attr.srq_limit = srq_limit
self._cq = None
self._pd = None
self._xrcd = None
@property
def max_wr(self):
return self.attr.attr.max_wr
@property
def max_sge(self):
return self.attr.attr.max_sge
@property
def srq_limit(self):
return self.attr.attr.srq_limit
@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 srq_type(self):
return self.attr.srq_type
@srq_type.setter
def srq_type(self, val):
self.attr.srq_type = val
@property
def pd(self):
return self._pd
@pd.setter
def pd(self, PD val):
self._pd = val
self.attr.pd = val.pd
@property
def xrcd(self):
return self._xrcd
@xrcd.setter
def xrcd(self, XRCD val):
self._xrcd = val
self.attr.xrcd = val.xrcd
@property
def max_num_tags(self):
return self.attr.tm_cap.max_num_tags
@max_num_tags.setter
def max_num_tags(self, val):
self.attr.tm_cap.max_num_tags = val
@property
def max_ops(self):
return self.attr.tm_cap.max_ops
@max_ops.setter
def max_ops(self, val):
self.attr.tm_cap.max_ops = val
@property
def cq(self):
return self._cq
@cq.setter
def cq(self, val):
if type(val) == CQ:
self.attr.cq = (<CQ>val).cq
self._cq = val
else:
self.attr.cq = (<CQEX>val).ibv_cq
self._cq = val
cdef class OpsWr(PyverbsCM):
def __init__(self, wr_id=0, opcode=e.IBV_WR_TAG_ADD, flags=e.IBV_OPS_SIGNALED,
OpsWr next_wr=None, unexpected_cnt=0, recv_wr_id=0,
num_sge=None, tag=0, mask=0, sg_list=None):
self.ops_wr.wr_id = wr_id
self.ops_wr.opcode = opcode
self.ops_wr.flags = flags
self.ops_wr.tm.unexpected_cnt = unexpected_cnt
self.ops_wr.tm.add.recv_wr_id = recv_wr_id
self.ops_wr.tm.add.tag = tag
self.ops_wr.tm.add.mask = mask
if next_wr is not None:
self.ops_wr.next = &next_wr.ops_wr
if num_sge is not None:
self.ops_wr.tm.add.num_sge = num_sge
cdef v.ibv_sge *dst
if sg_list is not None:
self.ops_wr.tm.add.sg_list = <v.ibv_sge*>malloc(num_sge * sizeof(v.ibv_sge))
if self.ops_wr.tm.add.sg_list == NULL:
raise MemoryError('Failed to malloc SG buffer')
dst = self.ops_wr.tm.add.sg_list
copy_sg_array(dst, sg_list, num_sge)
def __dealloc__(self):
self.close()
cpdef close(self):
if self.ops_wr.tm.add.sg_list != NULL:
free(self.ops_wr.tm.add.sg_list)
self.ops_wr.tm.add.sg_list = NULL
@property
def wr_id(self):
return self.ops_wr.wr_id
@wr_id.setter
def wr_id(self, val):
self.ops_wr.wr_id = val
@property
def next_wr(self):
if self.ops_wr.next == NULL:
return None
val = OpsWr()
val.ops_wr = self.ops_wr.next[0]
return val
@next_wr.setter
def next_wr(self, OpsWr val not None):
self.ops_wr.next = &val.ops_wr
@property
def opcode(self):
return self.ops_wr.opcode
@opcode.setter
def opcode(self, val):
self.ops_wr.opcode = val
@property
def flags(self):
return self.ops_wr.flags
@flags.setter
def flags(self, val):
self.ops_wr.flags = val
@property
def unexpected_cnt(self):
return self.ops_wr.tm.unexpected_cnt
@unexpected_cnt.setter
def unexpected_cnt(self, val):
self.ops_wr.tm.unexpected_cnt = val
@property
def recv_wr_id(self):
return self.ops_wr.tm.add.recv_wr_id
@recv_wr_id.setter
def recv_wr_id(self, val):
self.ops_wr.tm.add.recv_wr_id = val
@property
def tag(self):
return self.ops_wr.tm.add.tag
@tag.setter
def tag(self, val):
self.ops_wr.tm.add.tag = val
@property
def handle(self):
return self.ops_wr.tm.handle
@handle.setter
def handle(self, val):
self.ops_wr.tm.handle = val
@property
def mask(self):
return self.ops_wr.tm.add.mask
@mask.setter
def mask(self, val):
self.ops_wr.tm.add.mask = val
cdef class SRQ(PyverbsCM):
def __init__(self, object creator not None, object attr not None):
super().__init__()
self.srq = NULL
self.cq = None
self.qps = weakref.WeakSet()
if isinstance(creator, PD):
self._create_srq(creator, attr)
elif type(creator) == Context:
self._create_srq_ex(creator, attr)
else:
raise PyverbsRDMAError('Srq needs either Context or PD for creation')
if self.srq == NULL:
raise PyverbsRDMAErrno('Failed to create SRQ (errno is {err})'.
format(err=errno))
self.logger.debug('SRQ Created')
def __dealloc__(self):
self.close()
cpdef close(self):
if self.srq != NULL:
if self.logger:
self.logger.debug('Closing SRQ')
close_weakrefs([self.qps])
rc = v.ibv_destroy_srq(self.srq)
if rc != 0:
raise PyverbsRDMAError('Failed to destroy SRQ', rc)
self.srq = NULL
self.cq =None
cdef add_ref(self, obj):
if isinstance(obj, QP):
self.qps.add(obj)
else:
raise PyverbsError('Unrecognized object type')
def _create_srq(self, PD pd, SrqInitAttr init_attr):
self.srq = v.ibv_create_srq(pd.pd, &init_attr.attr)
pd.add_ref(self)
def _create_srq_ex(self, Context context, SrqInitAttrEx init_attr_ex):
self.srq = v.ibv_create_srq_ex(context.context, &init_attr_ex.attr)
if init_attr_ex.cq:
cq = <CQ>init_attr_ex.cq
cq.add_ref(self)
self.cq = cq
if init_attr_ex.xrcd:
xrcd = <XRCD>init_attr_ex.xrcd
xrcd.add_ref(self)
if init_attr_ex.pd:
pd = <PD>init_attr_ex.pd
pd.add_ref(self)
def get_srq_num(self):
cdef unsigned int srqn
rc = v.ibv_get_srq_num(self.srq, &srqn)
if rc != 0:
raise PyverbsRDMAError('Failed to retrieve SRQ number', rc)
return srqn
def modify(self, SrqAttr attr, comp_mask):
rc = v.ibv_modify_srq(self.srq, &attr.attr, comp_mask)
if rc != 0:
raise PyverbsRDMAError('Failed to modify SRQ', rc)
def query(self):
attr = SrqAttr()
rc = v.ibv_query_srq(self.srq, &attr.attr)
if rc != 0:
raise PyverbsRDMAError('Failed to query SRQ', rc)
return attr
def post_srq_ops(self, OpsWr wr not None, OpsWr bad_wr=None):
"""
Perform on a special shared receive queue (SRQ) configuration manipulations
:param wr: Ops Work Requests to be posted to the TM-Shared Receive Queue
:param bad_wr: A pointer that will be filled with the first Ops Work Request,
that its processing failed
"""
cdef v.ibv_ops_wr *my_bad_wr
rc= v.ibv_post_srq_ops(self.srq, &wr.ops_wr, &my_bad_wr)
if rc != 0:
if bad_wr:
memcpy(&bad_wr.ops_wr, my_bad_wr, sizeof(bad_wr.ops_wr))
raise PyverbsRDMAError('post SRQ ops failed.', rc)
def post_recv(self, RecvWR wr not None, RecvWR bad_wr=None):
cdef v.ibv_recv_wr *my_bad_wr
rc = v.ibv_post_srq_recv(self.srq, &wr.recv_wr, &my_bad_wr)
if rc != 0:
if bad_wr:
memcpy(&bad_wr.recv_wr, my_bad_wr, sizeof(bad_wr.recv_wr))
raise PyverbsRDMAError('Failed to post receive to SRQ.', rc)