blob: e66d821e6f8245143170c498480ae62f2271825e [file] [log] [blame] [edit]
# SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB)
# Copyright (c) 2020 Nvidia All rights reserved.
from pyverbs.pyverbs_error import PyverbsRDMAError, PyverbsError
from pyverbs.base import PyverbsRDMAErrno
from libc.stdlib cimport calloc, free
from libc.string cimport memcpy
from pyverbs.qp cimport QP
cdef class FlowAttr(PyverbsObject):
def __init__(self, num_of_specs=0, flow_type=v.IBV_FLOW_ATTR_NORMAL,
priority=0, port=1, flags=0):
"""
Initialize a FlowAttr object over an underlying ibv_flow_attr C object
which contains attributes for creating a steering flow.
:param num_of_specs: number of specs
:param flow_type: flow type
:param priority: flow priority
:param port: port number
:param flags: flow flags
"""
super().__init__()
self.attr.type = flow_type
self.attr.size = sizeof(v.ibv_flow_attr)
self.attr.priority = priority
self.attr.num_of_specs = num_of_specs
self.attr.port = port
self.attr.flags = flags
self.specs = list()
@property
def type(self):
return self.attr.type
@type.setter
def type(self, val):
self.attr.type = val
@property
def priority(self):
return self.attr.priority
@priority.setter
def priority(self, val):
self.attr.priority = val
@property
def num_of_specs(self):
return self.attr.num_of_specs
@num_of_specs.setter
def num_of_specs(self, val):
self.attr.num_of_specs = val
@property
def port(self):
return self.attr.port
@port.setter
def port(self, val):
self.attr.port = val
@property
def flags(self):
return self.attr.flags
@flags.setter
def flags(self, val):
self.attr.flags = val
@property
def specs(self):
return self.specs
cdef class Flow(PyverbsCM):
def __init__(self, QP qp, FlowAttr flow_attr):
"""
Initialize a Flow object over an underlying ibv_flow C object which
represents a steering flow.
:param qp: QP to create flow for
:param flow_attr: Flow attributes for flow creation
"""
super().__init__()
cdef char *flow_addr
cdef char *dst_addr
cdef v.ibv_flow_attr attr = flow_attr.attr
if flow_attr.num_of_specs != len(flow_attr.specs):
self.logger.warn(f'The number of appended specs '
f'({len(flow_attr.specs)}) is not equal to the '
f'number of declared specs '
f'({flow_attr.flow_attr.num_of_specs})')
# Calculate total size for allocation
total_size = sizeof(v.ibv_flow_attr)
for spec in flow_attr.specs:
total_size += spec.size
flow_addr = <char*>calloc(1, total_size)
if flow_addr == NULL:
raise PyverbsError(f'Failed to allocate memory of size '
f'{total_size}')
dst_addr = flow_addr
# Copy flow_attr at the beginning of the allocated memory
memcpy(dst_addr, &attr, sizeof(v.ibv_flow_attr))
dst_addr = <char*>(dst_addr + sizeof(v.ibv_flow_attr))
# Copy specs one after another into the allocated memory after flow_attr
for spec in flow_attr.specs:
spec._copy_data(<unsigned long>dst_addr)
dst_addr += spec.size
self.flow = v.ibv_create_flow(qp.qp, <v.ibv_flow_attr*>flow_addr)
free(flow_addr)
if self.flow == NULL:
raise PyverbsRDMAErrno('Flow creation failed')
self.qp = qp
qp.add_ref(self)
def __dealloc__(self):
self.close()
cpdef close(self):
if self.flow != NULL:
if self.logger:
self.logger.debug('Closing Flow')
rc = v.ibv_destroy_flow(self.flow)
if rc != 0:
raise PyverbsRDMAError('Failed to destroy Flow', rc)
self.flow = NULL
self.qp = None
cdef class FlowAction(PyverbsObject):
def __cinit__(self):
self.action = NULL