@@ -10,6 +10,7 @@ cdef class Context(PyverbsCM):
cdef object name
cdef add_ref(self, obj)
cdef object pds
+ cdef object dms
cdef class DeviceAttr(PyverbsObject):
cdef v.ibv_device_attr dev_attr
@@ -37,3 +38,12 @@ cdef class TSOCaps(PyverbsObject):
cdef class DeviceAttrEx(PyverbsObject):
cdef v.ibv_device_attr_ex dev_attr
+
+cdef class AllocDmAttr(PyverbsObject):
+ cdef v.ibv_alloc_dm_attr alloc_dm_attr
+
+cdef class DM(PyverbsCM):
+ cdef v.ibv_dm *dm
+ cdef object dm_mrs
+ cdef object context
+ cdef add_ref(self, obj)
@@ -13,13 +13,21 @@ from .pyverbs_error import PyverbsUserError
from pyverbs.base import PyverbsRDMAErrno
cimport pyverbs.libibverbs as v
from pyverbs.addr cimport GID
+from pyverbs.mr import DMMR
from pyverbs.pd cimport PD
cdef extern from 'errno.h':
int errno
-
cdef extern from 'endian.h':
unsigned long be64toh(unsigned long host_64bits);
+cdef extern from 'stdlib.h':
+ void free(void *ptr)
+cdef extern from 'string.h':
+ void *memset(void *s, int c, size_t n)
+cdef extern from 'malloc.h':
+ void *malloc(size_t size)
+cdef extern from 'stdint.h':
+ ctypedef int uint64_t
class Device(PyverbsObject):
@@ -75,6 +83,8 @@ cdef class Context(PyverbsCM):
cdef v.ibv_device **dev_list
self.pds = weakref.WeakSet()
+ self.dms = weakref.WeakSet()
+
dev_name = kwargs.get('name')
if dev_name is not None:
@@ -110,7 +120,7 @@ cdef class Context(PyverbsCM):
cpdef close(self):
self.logger.debug('Closing Context')
- self.close_weakrefs([self.pds])
+ self.close_weakrefs([self.dms, self.pds])
if self.context != NULL:
rc = v.ibv_close_device(self.context)
if rc != 0:
@@ -158,6 +168,8 @@ cdef class Context(PyverbsCM):
cdef add_ref(self, obj):
if isinstance(obj, PD):
self.pds.add(obj)
+ elif isinstance(obj, DM):
+ self.dms.add(obj)
else:
raise PyverbsError('Unrecognized object type')
@@ -477,6 +489,102 @@ cdef class DeviceAttrEx(PyverbsObject):
return self.dev_attr.max_dm_size
+cdef class AllocDmAttr(PyverbsObject):
+ def __cinit__(self, length, log_align_req = 0, comp_mask = 0):
+ """
+ Creates an AllocDmAttr object with the given parameters. This object
+ can than be used to create a DM object.
+ :param length: Length of the future device memory
+ :param log_align_req: log2 of address alignment requirement
+ :param comp_mask: compatibility mask
+ :return: An AllocDmAttr object
+ """
+ self.alloc_dm_attr.length = length
+ self.alloc_dm_attr.log_align_req = log_align_req
+ self.alloc_dm_attr.comp_mask = comp_mask
+
+ @property
+ def length(self):
+ return self.alloc_dm_attr.length
+
+ @length.setter
+ def length(self, val):
+ self.alloc_dm_attr.length = val
+
+ @property
+ def log_align_req(self):
+ return self.alloc_dm_attr.log_align_req
+
+ @log_align_req.setter
+ def log_align_req(self, val):
+ self.alloc_dm_attr.log_align_req = val
+
+ @property
+ def comp_mask(self):
+ return self.alloc_dm_attr.comp_mask
+
+ @comp_mask.setter
+ def comp_mask(self, val):
+ self.alloc_dm_attr.comp_mask = val
+
+
+cdef class DM(PyverbsCM):
+ def __cinit__(self, Context context, AllocDmAttr dm_attr not None):
+ """
+ Allocate a device (direct) memory.
+ :param context: The context of the device on which to allocate memory
+ :param dm_attr: Attributes that define the DM
+ :return: A DM object on success
+ """
+ self.dm_mrs = weakref.WeakSet()
+ device_attr = context.query_device_ex()
+ if device_attr.max_dm_size <= 0:
+ raise PyverbsUserError('Device doesn\'t support dm allocation')
+ self.dm = v.ibv_alloc_dm(<v.ibv_context*>context.context,
+ &dm_attr.alloc_dm_attr)
+ if self.dm == NULL:
+ raise PyverbsRDMAErrno('Failed to allocate device memory of size '
+ '{size}. Max available size {max}.'
+ .format(size=dm_attr.length,
+ max=device_attr.max_dm_size))
+ self.context = context
+ context.add_ref(self)
+
+ def __dealloc__(self):
+ self.close()
+
+ cpdef close(self):
+ self.logger.debug('Closing DM')
+ self.close_weakrefs([self.dm_mrs])
+ if self.dm != NULL:
+ rc = v.ibv_free_dm(self.dm)
+ if rc != 0:
+ raise PyverbsRDMAErrno('Failed to free dm')
+ self.dm = NULL
+ self.context = None
+
+ cdef add_ref(self, obj):
+ if isinstance(obj, DMMR):
+ self.dm_mrs.add(obj)
+
+ def copy_to_dm(self, dm_offset, data, length):
+ rc = v.ibv_memcpy_to_dm(<v.ibv_dm *>self.dm, <uint64_t>dm_offset,
+ <char *>data, <size_t>length)
+ if rc != 0:
+ raise PyverbsRDMAErrno('Failed to copy to dm')
+
+ def copy_from_dm(self, dm_offset, length):
+ cdef char *data =<char*>malloc(length)
+ memset(data, 0, length)
+ rc = v.ibv_memcpy_from_dm(<void *>data, <v.ibv_dm *>self.dm,
+ <uint64_t>dm_offset, <size_t>length)
+ if rc != 0:
+ raise PyverbsRDMAErrno('Failed to copy from dm')
+ res = data[:length]
+ free(data)
+ return res
+
+
def guid_format(num):
"""
Get GUID representation of the given number, including change of endianness.
@@ -139,6 +139,15 @@ cdef extern from 'infiniband/verbs.h':
unsigned int handle
ibv_mw_type mw_type
+ cdef struct ibv_alloc_dm_attr:
+ size_t length
+ unsigned int log_align_req
+ unsigned int comp_mask
+
+ cdef struct ibv_dm:
+ ibv_context *context
+ unsigned int comp_mask
+
ibv_device **ibv_get_device_list(int *n)
void ibv_free_device_list(ibv_device **list)
ibv_context *ibv_open_device(ibv_device *device)
@@ -156,3 +165,11 @@ cdef extern from 'infiniband/verbs.h':
int ibv_dereg_mr(ibv_mr *mr)
ibv_mw *ibv_alloc_mw(ibv_pd *pd, ibv_mw_type type)
int ibv_dealloc_mw(ibv_mw *mw)
+ ibv_dm *ibv_alloc_dm(ibv_context *context, ibv_alloc_dm_attr *attr)
+ int ibv_free_dm(ibv_dm *dm)
+ ibv_mr *ibv_reg_dm_mr(ibv_pd *pd, ibv_dm *dm, unsigned long dm_offset,
+ size_t length, unsigned int access)
+ int ibv_memcpy_to_dm(ibv_dm *dm, unsigned long dm_offset, void *host_addr,
+ size_t length)
+ int ibv_memcpy_from_dm(void *host_addr, ibv_dm *dm, unsigned long dm_offset,
+ size_t length)
@@ -14,3 +14,6 @@ cdef class MR(PyverbsCM):
cdef class MW(PyverbsCM):
cdef object pd
cdef v.ibv_mw *mw
+
+cdef class DMMR(MR):
+ cdef object dm
@@ -3,6 +3,7 @@
from pyverbs.pyverbs_error import PyverbsRDMAError, PyverbsError
from pyverbs.base import PyverbsRDMAErrno
+from pyverbs.device cimport DM
from .pd cimport PD
import resource
@@ -22,7 +23,7 @@ cdef class MR(PyverbsCM):
MR class represents ibv_mr. Buffer allocation in done in the c'tor. Freeing
it is done in close().
"""
- def __cinit__(self, PD pd not None, length, access):
+ def __cinit__(self, PD pd not None, length, access, **kwargs):
"""
Allocate a user-level buffer of length <length> and register a Memory
Region of the given length and access flags.
@@ -31,6 +32,8 @@ cdef class MR(PyverbsCM):
:param access: Access flags, see ibv_access_flags enum
:return: The newly created MR on success
"""
+ if len(kwargs) != 0:
+ return
#We want to enable registering an MR of size 0 but this fails with a
#buffer of size 0, so in this case lets increase the buffer
if length == 0:
@@ -146,6 +149,44 @@ cdef class MW(PyverbsCM):
self.pd = None
+cdef class DMMR(MR):
+ def __cinit__(self, PD pd not None, length, access, **kwargs):
+ """
+ Initializes a DMMR (Device Memory Memory Region) of the given length
+ and access flags using the given PD and DM objects.
+ :param pd: A PD object
+ :param length: Length in bytes
+ :param access: Access flags, see ibv_access_flags enum
+ :param kwargs: see below
+ :return: The newly create DMMR
+
+ :keyword Arguments:
+ * *dm* (DM)
+ A DM (device memory) object to be used for this DMMR
+ * *offset*
+ Byte offset from the beginning of the allocated device memory
+ buffer
+ """
+ dm = <DM>kwargs['dm']
+ offset = kwargs['offset']
+ self.mr = v.ibv_reg_dm_mr(pd.pd, (<DM>dm).dm, offset, length, access)
+ if self.mr == NULL:
+ raise PyverbsRDMAErrno('Failed to register a device MR. length: {len}, access flags: {flags}'.
+ format(len=length, flags=access,))
+ self.pd = pd
+ self.dm = dm
+ pd.add_ref(self)
+ dm.add_ref(self)
+ self.logger.debug('Registered device ibv_mr. Length: {len}, access flags {flags}'.
+ format(len=length, flags=access))
+
+ def write(self, data, length):
+ return self.dm.copy_to_dm(0, data, length)
+
+ cpdef read(self, length, offset):
+ return self.dm.copy_from_dm(offset, length)
+
+
def mwtype2str(mw_type):
mw_types = {1:'IBV_MW_TYPE_1', 2:'IBV_MW_TYPE_2'}
try:
@@ -4,7 +4,8 @@ import weakref
from pyverbs.pyverbs_error import PyverbsRDMAError, PyverbsError
from pyverbs.base import PyverbsRDMAErrno
-from .mr cimport MR, MW
+from pyverbs.device cimport Context, DM
+from .mr cimport MR, MW, DMMR
cdef extern from 'errno.h':
int errno
@@ -52,7 +53,7 @@ cdef class PD(PyverbsCM):
self.ctx = None
cdef add_ref(self, obj):
- if isinstance(obj, MR):
+ if isinstance(obj, MR) or isinstance(obj, DMMR):
self.mrs.add(obj)
elif isinstance(obj, MW):
self.mws.add(obj)