@@ -25,6 +25,7 @@ rdma_python_test(tests
test_qpex.py
test_rdmacm.py
test_relaxed_ordering.py
+ test_shared_pd.py
utils.py
)
@@ -244,10 +244,17 @@ class BaseResources(object):
:param ib_port: IB port of the device to use (default: 1)
:param gid_index: Which GID index to use (default: 0)
"""
- self.ctx = Context(name=dev_name)
+ self.dev_name = dev_name
self.gid_index = gid_index
- self.pd = PD(self.ctx)
self.ib_port = ib_port
+ self.create_context()
+ self.create_pd()
+
+ def create_context(self):
+ self.ctx = Context(name=self.dev_name)
+
+ def create_pd(self):
+ self.pd = PD(self.ctx)
class TrafficResources(BaseResources):
new file mode 100644
@@ -0,0 +1,95 @@
+# SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB)
+# Copyright (c) 2020 Mellanox Technologies, Inc. All rights reserved. See COPYING file
+"""
+Test module for Shared PD.
+"""
+import unittest
+import errno
+import os
+
+from tests.test_qpex import QpExRCRDMAWrite
+from tests.base import RDMATestCase
+from pyverbs.device import Context
+from pyverbs.pd import PD
+from pyverbs.mr import MR
+import pyverbs.enums as e
+import tests.utils as u
+
+
+def get_import_res_class(base_class):
+ """
+ This function creates a class that inherits base_class of any BaseResources
+ type. Its purpose is to behave exactly as base_class does, except for the
+ objects creation, which instead of creating context, PD and MR, it imports
+ them. Hence the returned class must be initialized with (cmd_fd, pd_handle,
+ mr_handle, mr_addr, **kwargs), while kwargs are the arguments needed
+ (if any) for base_class. In addition it has unimport_resources() method
+ which unimprot all the resources and closes the imported PD object.
+ :param base_class: The base resources class to inherit from
+ :return: ImportResources(cmd_fd, pd_handle, mr_handle, mr_addr, **kwargs)
+ class
+ """
+ class ImportResources(base_class):
+ def __init__(self, cmd_fd, pd_handle, mr_handle, mr_addr=None, **kwargs):
+ self.cmd_fd = cmd_fd
+ self.pd_handle = pd_handle
+ self.mr_handle = mr_handle
+ self.mr_addr = mr_addr
+ super(ImportResources, self).__init__(**kwargs)
+
+ def create_context(self):
+ try:
+ self.ctx = Context(cmd_fd=self.cmd_fd)
+ except u.PyverbsRDMAError as ex:
+ if ex.error_code in [errno.EOPNOTSUPP, errno.EPROTONOSUPPORT]:
+ raise unittest.SkipTest('Importing a device is not supported')
+ raise ex
+
+ def create_pd(self):
+ self.pd = PD(self.ctx, handle=self.pd_handle)
+
+ def create_mr(self):
+ self.mr = MR(self.pd, handle=self.mr_handle, address=self.mr_addr)
+
+ def unimport_resources(self):
+ self.mr.unimport()
+ self.pd.unimport()
+ self.pd.close()
+
+ return ImportResources
+
+
+class SharedPDTestCase(RDMATestCase):
+ def setUp(self):
+ super().setUp()
+ self.iters = 10
+ self.server_res = None
+ self.imported_res = []
+
+ def tearDown(self):
+ for res in self.imported_res:
+ res.unimport_resources()
+ super().tearDown()
+
+ def test_imported_rc_ex_rdma_write(self):
+ setup_params = {'dev_name': self.dev_name, 'ib_port': self.ib_port,
+ 'gid_index': self.gid_index}
+ self.server_res = QpExRCRDMAWrite(**setup_params)
+ cmd_fd_dup = os.dup(self.server_res.ctx.cmd_fd)
+ import_cls = get_import_res_class(QpExRCRDMAWrite)
+ server_import = import_cls(
+ cmd_fd_dup, self.server_res.pd.handle, self.server_res.mr.handle,
+ # The imported MR's address is NULL, so using the address of the
+ # "main" MR object to be able to validate the message
+ self.server_res.mr.buf,
+ **setup_params)
+ self.imported_res.append(server_import)
+ client = QpExRCRDMAWrite(**setup_params)
+ client.pre_run(server_import.psn, server_import.qpn)
+ server_import.pre_run(client.psn, client.qpn)
+ client.rkey = server_import.mr.rkey
+ server_import.rkey = client.mr.rkey
+ client.raddr = server_import.mr.buf
+ server_import.raddr = client.mr.buf
+ u.rdma_traffic(client, server_import, self.iters, self.gid_index,
+ self.ib_port, send_op=e.IBV_QP_EX_WITH_RDMA_WRITE)