| # 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 |