blob: 6ae71293bb56d526e0d9b782afc84fe211fd613b [file] [log] [blame] [edit]
import unittest
import errno
from pyverbs.providers.mlx5.mlx5dv import Mlx5Context, Mlx5DVContextAttr, \
Mlx5DVCQInitAttr, Mlx5CQ, context_flags_to_str, cqe_comp_to_str
from pyverbs.pyverbs_error import PyverbsRDMAError, PyverbsUserError
import pyverbs.providers.mlx5.mlx5_enums as dve
from tests.mlx5_base import Mlx5RDMATestCase
from tests.mlx5_base import Mlx5DcResources
from pyverbs.cq import CqInitAttrEx
from tests.base import RCResources
import pyverbs.enums as e
import tests.utils as u
def create_dv_cq(res):
"""
Create Mlx5 DV CQ.
:param res: An instance of BaseResources.
:return: None
"""
dvcq_init_attr = Mlx5DVCQInitAttr()
if res.cqe_comp_res_format:
dvcq_init_attr.cqe_comp_res_format = res.cqe_comp_res_format
dvcq_init_attr.comp_mask |= dve.MLX5DV_CQ_INIT_ATTR_MASK_COMPRESSED_CQE
# Check CQE compression capability
cqe_comp_caps = res.ctx.query_mlx5_device().cqe_comp_caps
if not (cqe_comp_caps['supported_format'] & res.cqe_comp_res_format) or \
not cqe_comp_caps['max_num']:
cqe_comp_str = cqe_comp_to_str(res.cqe_comp_res_format)
raise unittest.SkipTest(f'CQE compression {cqe_comp_str} is not supported')
if res.flags:
dvcq_init_attr.flags = res.flags
dvcq_init_attr.comp_mask |= dve.MLX5DV_CQ_INIT_ATTR_MASK_FLAGS
if res.cqe_size:
dvcq_init_attr.cqe_size = res.cqe_size
dvcq_init_attr.comp_mask |= dve.MLX5DV_CQ_INIT_ATTR_MASK_CQE_SIZE
try:
res.cq = Mlx5CQ(res.ctx, CqInitAttrEx(), dvcq_init_attr)
except PyverbsRDMAError as ex:
if ex.error_code == errno.EOPNOTSUPP:
raise unittest.SkipTest('Create Mlx5DV CQ is not supported')
raise ex
class Mlx5CQRes(RCResources):
def __init__(self, dev_name, ib_port, gid_index, cqe_comp_res_format=None,
flags=None, cqe_size=None, msg_size=1024, requested_dev_cap=None):
"""
Initialize Mlx5 DV CQ resources based on RC resources that include RC
QP.
:param dev_name: Device name to be used
:param ib_port: IB port of the device to use
:param gid_index: Which GID index to use
:param cqe_comp_res_format: Type of compression to use
:param flags: DV CQ specific flags
:param cqe_size: The CQE size
:param msg_size: The resource msg size
:param requested_dev_cap: A necessary device cap. If it's not supported
by the device, the test will be skipped.
"""
self.cqe_comp_res_format = cqe_comp_res_format
self.flags = flags
self.cqe_size = cqe_size
self.requested_dev_cap = requested_dev_cap
super().__init__(dev_name, ib_port, gid_index, msg_size=msg_size)
def create_context(self):
mlx5dv_attr = Mlx5DVContextAttr()
try:
self.ctx = Mlx5Context(mlx5dv_attr, name=self.dev_name)
except PyverbsUserError as ex:
raise unittest.SkipTest(f'Could not open mlx5 context ({ex})')
except PyverbsRDMAError:
raise unittest.SkipTest('Opening mlx5 context is not supported')
if self.requested_dev_cap:
if not self.ctx.query_mlx5_device().flags & self.requested_dev_cap:
miss_caps = context_flags_to_str(self.requested_dev_cap)
raise unittest.SkipTest(f'Device caps doesn\'t support {miss_caps}')
def create_cq(self):
create_dv_cq(self)
class Mlx5DvCqDcRes(Mlx5DcResources):
def __init__(self, dev_name, ib_port, gid_index, cqe_comp_res_format=None,
flags=None, cqe_size=None, create_flags=None):
"""
Initialize Mlx5 DV CQ resources based on RC resources that include RC
QP.
:param dev_name: Device name to be used
:param ib_port: IB port of the device to use
:param gid_index: Which GID index to use
:param cqe_comp_res_format: Type of compression to use
:param flags: DV CQ specific flags
:param cqe_size: The CQ's CQe size
:param create_flags: DV QP specific flags
"""
self.cqe_comp_res_format = cqe_comp_res_format
self.flags = flags
self.cqe_size = cqe_size
super().__init__(dev_name, ib_port, gid_index,
send_ops_flags=e.IBV_QP_EX_WITH_SEND,
create_flags=create_flags)
def create_cq(self):
create_dv_cq(self)
class DvCqTest(Mlx5RDMATestCase):
def setUp(self):
super().setUp()
self.iters = 10
self.server = None
self.client = None
self.traffic_args = None
def create_players(self, resource, **resource_arg):
"""
Init DV CQ tests resources.
:param resource: The RDMA resources to use.
:param resource_arg: Dict of args that specify the resource specific
attributes.
:return: None
"""
self.client = resource(**self.dev_info, **resource_arg)
self.server = resource(**self.dev_info, **resource_arg)
self.client.pre_run(self.server.psns, self.server.qps_num)
self.server.pre_run(self.client.psns, self.client.qps_num)
if resource == Mlx5DvCqDcRes:
self.client.remote_dct_num = self.server.dct_qp.qp_num
self.server.remote_dct_num = self.client.dct_qp.qp_num
self.traffic_args = {'client': self.client, 'server': self.server,
'iters': self.iters, 'gid_idx': self.gid_index,
'port': self.ib_port}
def test_dv_cq_traffic(self):
"""
Run SEND traffic using DC CQ.
"""
self.create_players(Mlx5CQRes)
u.traffic(**self.traffic_args, is_cq_ex=True)
def test_dv_cq_compression_flags(self):
"""
Create DV CQ with different types of CQE compression formats. The test
also does bad flow and try to use more than one compression formats.
"""
# Create DV CQ with all legal compression flags.
for comp_type in [dve.MLX5DV_CQE_RES_FORMAT_CSUM_STRIDX,
dve.MLX5DV_CQE_RES_FORMAT_CSUM,
dve.MLX5DV_CQE_RES_FORMAT_HASH]:
self.create_players(Mlx5CQRes, cqe_comp_res_format=comp_type,
requested_dev_cap=dve.MLX5DV_CONTEXT_FLAGS_CQE_128B_COMP)
u.traffic(**self.traffic_args, is_cq_ex=True)
# Try to create DV CQ with more than one compression flags.
cqe_multi_format = dve.MLX5DV_CQE_RES_FORMAT_HASH | \
dve.MLX5DV_CQE_RES_FORMAT_CSUM
with self.assertRaises(PyverbsRDMAError) as ex:
self.create_players(Mlx5CQRes, cqe_comp_res_format=cqe_multi_format)
self.assertEqual(ex.exception.error_code, errno.EINVAL)
def test_dv_cq_padding(self):
"""
Create DV CQ with padding flag.
"""
self.create_players(Mlx5CQRes, cqe_size=128,
flags=dve.MLX5DV_CQ_INIT_ATTR_FLAGS_CQE_PAD,
requested_dev_cap=dve.MLX5DV_CONTEXT_FLAGS_CQE_128B_PAD)
u.traffic(**self.traffic_args, is_cq_ex=True)
def test_dv_cq_padding_not_aligned_cqe_size(self):
"""
Create DV CQ with padding flag when CQE size is not 128B. The creation
should fail because padding is supported only with CQE size of 128B.
"""
# Padding flag works only when the cqe size is 128.
with self.assertRaises(PyverbsRDMAError) as ex:
self.create_players(Mlx5CQRes, cqe_size=64,
flags=dve.MLX5DV_CQ_INIT_ATTR_FLAGS_CQE_PAD,
requested_dev_cap=dve.MLX5DV_CONTEXT_FLAGS_CQE_128B_PAD)
self.assertEqual(ex.exception.error_code, errno.EINVAL)
def test_dv_cq_cqe_size_128(self):
"""
Test multiple sizes of msg using CQE size of 128B.
"""
msg_sizes = [60, # Lower than 64B
70, # In range of 64B - 128B
140] # Bigger than 128B
for size in msg_sizes:
self.create_players(Mlx5CQRes, cqe_size=128, msg_size=size)
u.traffic(**self.traffic_args, is_cq_ex=True)
def test_dv_cq_cqe_size_64(self):
"""
Test multiple sizes of msg using CQE size of 64B.
"""
msg_sizes = [16, # Lower than 32B
60, # In range of 32B - 64B
70] # Bigger than 64B
for size in msg_sizes:
self.create_players(Mlx5CQRes, cqe_size=64, msg_size=size)
u.traffic(**self.traffic_args, is_cq_ex=True)
def test_dv_cq_cqe_size_with_bad_size(self):
"""
Create CQ with ilegal cqe_size value.
"""
# Set the CQE size in the CQE creation.
with self.assertRaises(PyverbsRDMAError) as ex:
self.create_players(Mlx5CQRes, cqe_size=100)
self.assertEqual(ex.exception.error_code, errno.EINVAL)
# Set the CQE size using the environment value.
self.set_env_variable('MLX5_CQE_SIZE', '100')
with self.assertRaises(PyverbsRDMAError) as ex:
self.create_players(Mlx5CQRes)
self.assertEqual(ex.exception.error_code, errno.EINVAL)
def test_dv_cq_cqe_size_environment_var(self):
"""
Create DV CQs with all the legal cqe_size values using the environment
variable mechanism.
"""
for cqe_size in ['64', '128']:
self.set_env_variable('MLX5_CQE_SIZE', cqe_size)
self.create_players(Mlx5CQRes)
def test_scatter_to_cqe_control_by_qp(self):
"""
Create QP with specific SCATTER_TO_CQE flags. The test set different
values in the scatter2cqe environment variable and create the QP with
enable/disable flags. The QP should ignore the environment variable
value and behave according to the specific creation flag.
"""
for s2c_env_val in ['0', '1']:
for qp_s2c_value in [dve.MLX5DV_QP_CREATE_DISABLE_SCATTER_TO_CQE,
dve.MLX5DV_QP_CREATE_ALLOW_SCATTER_TO_CQE]:
self.set_env_variable('MLX5_SCATTER_TO_CQE', s2c_env_val)
self.create_players(Mlx5DvCqDcRes, create_flags=qp_s2c_value)
u.traffic(**self.traffic_args, new_send=True,
send_op=e.IBV_QP_EX_WITH_SEND, is_cq_ex=True)