# 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 = 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 = (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(dst_addr) dst_addr += spec.size self.flow = v.ibv_create_flow(qp.qp, 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