Blame SOURCES/0001-tests-Add-mlx5-CQ-tests.patch

3bcb62
From 8aae7abe241c81ef7d461940d7bb7f2973172b99 Mon Sep 17 00:00:00 2001
3bcb62
From: Ido Kalir <idok@mellanox.com>
3bcb62
Date: Tue, 18 Aug 2020 16:03:05 +0300
3bcb62
Subject: [PATCH] tests: Add mlx5 CQ tests
3bcb62
3bcb62
Add tests for mlx5dv CQ, including traffic and some bad creation flows.
3bcb62
3bcb62
Signed-off-by: Ido Kalir <idok@mellanox.com>
3bcb62
Signed-off-by: Edward Srouji <edwards@nvidia.com>
3bcb62
---
3bcb62
 tests/CMakeLists.txt  |   1 +
3bcb62
 tests/base.py         |  28 ++++-
3bcb62
 tests/mlx5_base.py    |   6 +-
3bcb62
 tests/test_mlx5_cq.py | 237 ++++++++++++++++++++++++++++++++++++++++++
3bcb62
 4 files changed, 269 insertions(+), 3 deletions(-)
3bcb62
 create mode 100644 tests/test_mlx5_cq.py
3bcb62
3bcb62
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
3bcb62
index 4de98d08a81e..ce3b5ef25b81 100644
3bcb62
--- a/tests/CMakeLists.txt
3bcb62
+++ b/tests/CMakeLists.txt
3bcb62
@@ -14,6 +14,7 @@ rdma_python_test(tests
3bcb62
   test_cqex.py
3bcb62
   test_device.py
3bcb62
   test_efadv.py
3bcb62
+  test_mlx5_cq.py
3bcb62
   test_mlx5_dc.py
3bcb62
   test_mlx5_lag_affinity.py
3bcb62
   test_mlx5_pp.py
3bcb62
diff --git a/tests/base.py b/tests/base.py
3bcb62
index 3eb5f5db9648..1ca52f0ce5bf 100644
3bcb62
--- a/tests/base.py
3bcb62
+++ b/tests/base.py
3bcb62
@@ -104,6 +104,29 @@ class RDMATestCase(unittest.TestCase):
3bcb62
         self.gid_index = gid_index
3bcb62
         self.pkey_index = pkey_index
3bcb62
         self.ip_addr = None
3bcb62
+        self.pre_environment = {}
3bcb62
+
3bcb62
+    def set_env_variable(self, var, value):
3bcb62
+        """
3bcb62
+        Set environment variable. The current value for each variable is stored
3bcb62
+        and is set back at the end of the test.
3bcb62
+        :param var: The name of the environment variable
3bcb62
+        :param value: The requested new value of this environment variable
3bcb62
+        """
3bcb62
+        if var not in self.pre_environment.keys():
3bcb62
+            self.pre_environment[var] = os.environ.get(var)
3bcb62
+        os.environ[var] = value
3bcb62
+
3bcb62
+    def tearDown(self):
3bcb62
+        """
3bcb62
+        Restore the previous environment variables values before ending the test.
3bcb62
+        """
3bcb62
+        for k, v in self.pre_environment.items():
3bcb62
+            if v is None:
3bcb62
+                os.environ.pop(k)
3bcb62
+            else:
3bcb62
+                os.environ[k] = v
3bcb62
+        super().tearDown()
3bcb62
 
3bcb62
     def is_eth_and_has_roce_hw_bug(self):
3bcb62
         """
3bcb62
@@ -256,7 +279,7 @@ class TrafficResources(BaseResources):
3bcb62
     needed for traffic.
3bcb62
     """
3bcb62
     def __init__(self, dev_name, ib_port, gid_index, with_srq=False,
3bcb62
-                 qp_count=1):
3bcb62
+                 qp_count=1, msg_size=1024):
3bcb62
         """
3bcb62
         Initializes a TrafficResources object with the given values and creates
3bcb62
         basic RDMA resources.
3bcb62
@@ -265,11 +288,12 @@ class TrafficResources(BaseResources):
3bcb62
         :param gid_index: Which GID index to use
3bcb62
         :param with_srq: If True, create SRQ and attach to QPs
3bcb62
         :param qp_count: Number of QPs to create
3bcb62
+        :param msg_size: Size of resource msg. If None, use 1024 as default.
3bcb62
         """
3bcb62
         super(TrafficResources, self).__init__(dev_name=dev_name,
3bcb62
                                                ib_port=ib_port,
3bcb62
                                                gid_index=gid_index)
3bcb62
-        self.msg_size = 1024
3bcb62
+        self.msg_size = msg_size
3bcb62
         self.num_msgs = 1000
3bcb62
         self.port_attr = None
3bcb62
         self.mr = None
3bcb62
diff --git a/tests/mlx5_base.py b/tests/mlx5_base.py
3bcb62
index 099906f35129..a4202bae6a0d 100644
3bcb62
--- a/tests/mlx5_base.py
3bcb62
+++ b/tests/mlx5_base.py
3bcb62
@@ -18,8 +18,9 @@ from pyverbs.mr import MR
3bcb62
 
3bcb62
 class Mlx5DcResources(TrafficResources):
3bcb62
     def __init__(self, dev_name, ib_port, gid_index, send_ops_flags,
3bcb62
-                 qp_count=1):
3bcb62
+                 qp_count=1, create_flags=0):
3bcb62
         self.send_ops_flags = send_ops_flags
3bcb62
+        self.create_flags = create_flags
3bcb62
         super().__init__(dev_name, ib_port, gid_index, with_srq=True,
3bcb62
                          qp_count=qp_count)
3bcb62
 
3bcb62
@@ -77,7 +78,10 @@ class Mlx5DcResources(TrafficResources):
3bcb62
         try:
3bcb62
             for _ in range(self.qp_count):
3bcb62
                 comp_mask = dve.MLX5DV_QP_INIT_ATTR_MASK_DC
3bcb62
+                if self.create_flags:
3bcb62
+                    comp_mask |= dve.MLX5DV_QP_INIT_ATTR_MASK_QP_CREATE_FLAGS
3bcb62
                 attr = Mlx5DVQPInitAttr(comp_mask=comp_mask,
3bcb62
+                                        create_flags=self.create_flags,
3bcb62
                                         dc_init_attr=Mlx5DVDCInitAttr())
3bcb62
                 qp = Mlx5QP(self.ctx, qp_init_attr, attr)
3bcb62
                 self.qps.append(qp)
3bcb62
diff --git a/tests/test_mlx5_cq.py b/tests/test_mlx5_cq.py
3bcb62
new file mode 100644
3bcb62
index 000000000000..1f757c27345e
3bcb62
--- /dev/null
3bcb62
+++ b/tests/test_mlx5_cq.py
3bcb62
@@ -0,0 +1,237 @@
3bcb62
+import unittest
3bcb62
+import errno
3bcb62
+
3bcb62
+from pyverbs.providers.mlx5.mlx5dv import Mlx5Context, Mlx5DVContextAttr, \
3bcb62
+    Mlx5DVCQInitAttr, Mlx5CQ, context_flags_to_str
3bcb62
+from pyverbs.pyverbs_error import PyverbsRDMAError, PyverbsUserError
3bcb62
+from tests.base import RDMATestCase, RCResources
3bcb62
+import pyverbs.providers.mlx5.mlx5_enums as dve
3bcb62
+from tests.mlx5_base import Mlx5DcResources
3bcb62
+from pyverbs.cq import CqInitAttrEx
3bcb62
+import pyverbs.enums as e
3bcb62
+import tests.utils as u
3bcb62
+
3bcb62
+
3bcb62
+def create_dv_cq(res):
3bcb62
+    """
3bcb62
+    Create Mlx5 DV CQ.
3bcb62
+    :param res: An instance of BaseResources.
3bcb62
+    :return: None
3bcb62
+    """
3bcb62
+    dvcq_init_attr = Mlx5DVCQInitAttr()
3bcb62
+    if res.cqe_comp_res_format:
3bcb62
+        dvcq_init_attr.cqe_comp_res_format = res.cqe_comp_res_format
3bcb62
+        dvcq_init_attr.comp_mask |= dve.MLX5DV_CQ_INIT_ATTR_MASK_COMPRESSED_CQE
3bcb62
+    if res.flags:
3bcb62
+        dvcq_init_attr.flags = res.flags
3bcb62
+        dvcq_init_attr.comp_mask |= dve.MLX5DV_CQ_INIT_ATTR_MASK_FLAGS
3bcb62
+    if res.cqe_size:
3bcb62
+        dvcq_init_attr.cqe_size = res.cqe_size
3bcb62
+        dvcq_init_attr.comp_mask |= dve.MLX5DV_CQ_INIT_ATTR_MASK_CQE_SIZE
3bcb62
+    try:
3bcb62
+        res.cq = Mlx5CQ(res.ctx, CqInitAttrEx(), dvcq_init_attr)
3bcb62
+    except PyverbsRDMAError as ex:
3bcb62
+        if ex.error_code == errno.EOPNOTSUPP:
3bcb62
+            raise unittest.SkipTest('Create Mlx5DV CQ is not supported')
3bcb62
+        raise ex
3bcb62
+
3bcb62
+
3bcb62
+class Mlx5CQRes(RCResources):
3bcb62
+    def __init__(self, dev_name, ib_port, gid_index, cqe_comp_res_format=None,
3bcb62
+                 flags=None, cqe_size=None, msg_size=1024, requested_dev_cap=None):
3bcb62
+        """
3bcb62
+        Initialize Mlx5 DV CQ resources based on RC resources that include RC
3bcb62
+        QP.
3bcb62
+        :param dev_name: Device name to be used
3bcb62
+        :param ib_port: IB port of the device to use
3bcb62
+        :param gid_index: Which GID index to use
3bcb62
+        :param cqe_comp_res_format: Type of compression to use
3bcb62
+        :param flags: DV CQ specific flags
3bcb62
+        :param cqe_size: The CQE size
3bcb62
+        :param msg_size: The resource msg size
3bcb62
+        :param requested_dev_cap: A necessary device cap. If it's not supported
3bcb62
+                                  by the device, the test will be skipped.
3bcb62
+        """
3bcb62
+        self.cqe_comp_res_format = cqe_comp_res_format
3bcb62
+        self.flags = flags
3bcb62
+        self.cqe_size = cqe_size
3bcb62
+        self.requested_dev_cap = requested_dev_cap
3bcb62
+        super().__init__(dev_name, ib_port, gid_index, msg_size=msg_size)
3bcb62
+
3bcb62
+    def create_context(self):
3bcb62
+        mlx5dv_attr = Mlx5DVContextAttr()
3bcb62
+        try:
3bcb62
+            self.ctx = Mlx5Context(mlx5dv_attr, name=self.dev_name)
3bcb62
+        except PyverbsUserError as ex:
3bcb62
+            raise unittest.SkipTest(f'Could not open mlx5 context ({ex})')
3bcb62
+        except PyverbsRDMAError:
3bcb62
+            raise unittest.SkipTest('Opening mlx5 context is not supported')
3bcb62
+        if self.requested_dev_cap:
3bcb62
+            if not self.ctx.query_mlx5_device().flags & self.requested_dev_cap:
3bcb62
+                miss_caps = context_flags_to_str(self.requested_dev_cap)
3bcb62
+                raise unittest.SkipTest(f'Device caps doesn\'t support {miss_caps}')
3bcb62
+
3bcb62
+    def create_cq(self):
3bcb62
+        create_dv_cq(self)
3bcb62
+
3bcb62
+
3bcb62
+class Mlx5DvCqDcRes(Mlx5DcResources):
3bcb62
+    def __init__(self, dev_name, ib_port, gid_index, cqe_comp_res_format=None,
3bcb62
+                 flags=None, cqe_size=None, create_flags=None):
3bcb62
+        """
3bcb62
+        Initialize Mlx5 DV CQ resources based on RC resources that include RC
3bcb62
+        QP.
3bcb62
+        :param dev_name: Device name to be used
3bcb62
+        :param ib_port: IB port of the device to use
3bcb62
+        :param gid_index: Which GID index to use
3bcb62
+        :param cqe_comp_res_format: Type of compression to use
3bcb62
+        :param flags: DV CQ specific flags
3bcb62
+        :param cqe_size: The CQ's CQe size
3bcb62
+        :param create_flags: DV QP specific flags
3bcb62
+        """
3bcb62
+        self.cqe_comp_res_format = cqe_comp_res_format
3bcb62
+        self.flags = flags
3bcb62
+        self.cqe_size = cqe_size
3bcb62
+        super().__init__(dev_name, ib_port, gid_index,
3bcb62
+                         send_ops_flags=e.IBV_QP_EX_WITH_SEND,
3bcb62
+                         create_flags=create_flags)
3bcb62
+
3bcb62
+    def create_cq(self):
3bcb62
+        create_dv_cq(self)
3bcb62
+
3bcb62
+
3bcb62
+class DvCqTest(RDMATestCase):
3bcb62
+    def setUp(self):
3bcb62
+        super().setUp()
3bcb62
+        self.iters = 10
3bcb62
+        self.server = None
3bcb62
+        self.client = None
3bcb62
+        self.traffic_args = None
3bcb62
+
3bcb62
+    def create_players(self, resource, **resource_arg):
3bcb62
+        """
3bcb62
+        Init DV CQ tests resources.
3bcb62
+        :param resource: The RDMA resources to use.
3bcb62
+        :param resource_arg: Dict of args that specify the resource specific
3bcb62
+        attributes.
3bcb62
+        :return: None
3bcb62
+        """
3bcb62
+        self.client = resource(**self.dev_info, **resource_arg)
3bcb62
+        self.server = resource(**self.dev_info, **resource_arg)
3bcb62
+        self.client.pre_run(self.server.psns, self.server.qps_num)
3bcb62
+        self.server.pre_run(self.client.psns, self.client.qps_num)
3bcb62
+        if resource == Mlx5DvCqDcRes:
3bcb62
+            self.client.remote_dct_num = self.server.dct_qp.qp_num
3bcb62
+            self.server.remote_dct_num = self.client.dct_qp.qp_num
3bcb62
+        self.traffic_args = {'client': self.client, 'server': self.server,
3bcb62
+                             'iters': self.iters, 'gid_idx': self.gid_index,
3bcb62
+                             'port': self.ib_port}
3bcb62
+
3bcb62
+    def test_dv_cq_traffic(self):
3bcb62
+        """
3bcb62
+        Run SEND traffic using DC CQ.
3bcb62
+        """
3bcb62
+        self.create_players(Mlx5CQRes)
3bcb62
+        u.traffic(**self.traffic_args, is_cq_ex=True)
3bcb62
+
3bcb62
+    def test_dv_cq_compression_flags(self):
3bcb62
+        """
3bcb62
+        Create DV CQ with different types of CQE compression formats. The test
3bcb62
+        also does bad flow and try to use more than one compression formats.
3bcb62
+        """
3bcb62
+        # Create DV CQ with all legal compression flags.
3bcb62
+        for comp_type in [dve.MLX5DV_CQE_RES_FORMAT_CSUM_STRIDX,
3bcb62
+                          dve.MLX5DV_CQE_RES_FORMAT_CSUM,
3bcb62
+                          dve.MLX5DV_CQE_RES_FORMAT_HASH]:
3bcb62
+            self.create_players(Mlx5CQRes, cqe_comp_res_format=comp_type,
3bcb62
+                                requested_dev_cap=dve.MLX5DV_CONTEXT_FLAGS_CQE_128B_COMP)
3bcb62
+            u.traffic(**self.traffic_args, is_cq_ex=True)
3bcb62
+
3bcb62
+        # Try to create DV CQ with more than one compression flags.
3bcb62
+        cqe_multi_format = dve.MLX5DV_CQE_RES_FORMAT_HASH | \
3bcb62
+            dve.MLX5DV_CQE_RES_FORMAT_CSUM
3bcb62
+        with self.assertRaises(PyverbsRDMAError) as ex:
3bcb62
+            self.create_players(Mlx5CQRes, cqe_comp_res_format=cqe_multi_format)
3bcb62
+        self.assertEqual(ex.exception.error_code, errno.EINVAL)
3bcb62
+
3bcb62
+    def test_dv_cq_padding(self):
3bcb62
+        """
3bcb62
+        Create DV CQ with padding flag.
3bcb62
+        """
3bcb62
+        self.create_players(Mlx5CQRes, cqe_size=128,
3bcb62
+                            flags=dve.MLX5DV_CQ_INIT_ATTR_FLAGS_CQE_PAD,
3bcb62
+                            requested_dev_cap=dve.MLX5DV_CONTEXT_FLAGS_CQE_128B_PAD)
3bcb62
+        u.traffic(**self.traffic_args, is_cq_ex=True)
3bcb62
+
3bcb62
+    def test_dv_cq_padding_not_aligned_cqe_size(self):
3bcb62
+        """
3bcb62
+        Create DV CQ with padding flag when CQE size is not 128B. The creation
3bcb62
+        should fail because padding is supported only with CQE size of 128B.
3bcb62
+        """
3bcb62
+        # Padding flag works only when the cqe size is 128.
3bcb62
+        with self.assertRaises(PyverbsRDMAError) as ex:
3bcb62
+            self.create_players(Mlx5CQRes, cqe_size=64,
3bcb62
+                                flags=dve.MLX5DV_CQ_INIT_ATTR_FLAGS_CQE_PAD,
3bcb62
+                                requested_dev_cap=dve.MLX5DV_CONTEXT_FLAGS_CQE_128B_PAD)
3bcb62
+        self.assertEqual(ex.exception.error_code, errno.EINVAL)
3bcb62
+
3bcb62
+    def test_dv_cq_cqe_size_128(self):
3bcb62
+        """
3bcb62
+        Test multiple sizes of msg using CQE size of 128B.
3bcb62
+        """
3bcb62
+        msg_sizes = [60,  # Lower than 64B
3bcb62
+                     70,  # In range of 64B - 128B
3bcb62
+                     140]  # Bigger than 128B
3bcb62
+        for size in msg_sizes:
3bcb62
+            self.create_players(Mlx5CQRes, cqe_size=128, msg_size=size)
3bcb62
+            u.traffic(**self.traffic_args, is_cq_ex=True)
3bcb62
+
3bcb62
+    def test_dv_cq_cqe_size_64(self):
3bcb62
+        """
3bcb62
+        Test multiple sizes of msg using CQE size of 64B.
3bcb62
+        """
3bcb62
+        msg_sizes = [16,  # Lower than 32B
3bcb62
+                     60,  # In range of 32B - 64B
3bcb62
+                     70]  # Bigger than 64B
3bcb62
+        for size in msg_sizes:
3bcb62
+            self.create_players(Mlx5CQRes, cqe_size=64, msg_size=size)
3bcb62
+            u.traffic(**self.traffic_args, is_cq_ex=True)
3bcb62
+
3bcb62
+    def test_dv_cq_cqe_size_with_bad_size(self):
3bcb62
+        """
3bcb62
+        Create CQ with ilegal cqe_size value.
3bcb62
+        """
3bcb62
+        # Set the CQE size in the CQE creation.
3bcb62
+        with self.assertRaises(PyverbsRDMAError) as ex:
3bcb62
+            self.create_players(Mlx5CQRes, cqe_size=100)
3bcb62
+        self.assertEqual(ex.exception.error_code, errno.EINVAL)
3bcb62
+
3bcb62
+        # Set the CQE size using the environment value.
3bcb62
+        self.set_env_variable('MLX5_CQE_SIZE', '100')
3bcb62
+        with self.assertRaises(PyverbsRDMAError) as ex:
3bcb62
+            self.create_players(Mlx5CQRes)
3bcb62
+        self.assertEqual(ex.exception.error_code, errno.EINVAL)
3bcb62
+
3bcb62
+    def test_dv_cq_cqe_size_environment_var(self):
3bcb62
+        """
3bcb62
+        Create DV CQs with all the legal cqe_size values using the environment
3bcb62
+        variable mechanism.
3bcb62
+        """
3bcb62
+        for cqe_size in ['64', '128']:
3bcb62
+            self.set_env_variable('MLX5_CQE_SIZE', cqe_size)
3bcb62
+            self.create_players(Mlx5CQRes)
3bcb62
+
3bcb62
+    def test_scatter_to_cqe_control_by_qp(self):
3bcb62
+        """
3bcb62
+        Create QP with specific SCATTER_TO_CQE flags. The test set different
3bcb62
+        values in the scatter2cqe environment variable and create the QP with
3bcb62
+        enable/disable flags. The QP should ignore the environment variable
3bcb62
+        value and behave according to the specific creation flag.
3bcb62
+        """
3bcb62
+        for s2c_env_val in ['0', '1']:
3bcb62
+            for qp_s2c_value in [dve.MLX5DV_QP_CREATE_DISABLE_SCATTER_TO_CQE,
3bcb62
+                                 dve.MLX5DV_QP_CREATE_ALLOW_SCATTER_TO_CQE]:
3bcb62
+                self.set_env_variable('MLX5_SCATTER_TO_CQE', s2c_env_val)
3bcb62
+                self.create_players(Mlx5DvCqDcRes, create_flags=qp_s2c_value)
3bcb62
+                u.traffic(**self.traffic_args, new_send=True,
3bcb62
+                          send_op=e.IBV_QP_EX_WITH_SEND, is_cq_ex=True)
3bcb62
-- 
3bcb62
2.25.4
3bcb62