/
githubmirror
/
rdma-core
Обзор
Документация
Войти
/
githubmirror
/
rdma-core
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
tests/test_mlx5_dc.py
163 строки
8 KB
Daniel Hayon
tests: Add timeout to DC stream QP recovery test
06 май 2026, 08:37
06 май 2026, 08:37
343d7de
Код
Авторство
О чём код?
# SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB) # Copyright (c) 2020 NVIDIA Corporation . All rights reserved. See COPYING file import unittest import errno import time from tests.mlx5_base import Mlx5DcResources, Mlx5RDMATestCase, Mlx5DcStreamsRes from pyverbs.pyverbs_error import PyverbsRDMAError from pyverbs.providers.mlx5.mlx5dv import Mlx5QP from pyverbs.libibverbs_enums import ibv_access_flags, ibv_qp_create_send_ops_flags, ibv_wr_opcode, \ ibv_odp_transport_cap_bits, ibv_qp_attr_mask, ibv_qp_state import tests.utils as u class OdpDc(Mlx5DcResources): def create_mr(self): try: self.mr = u.create_custom_mr(self, ibv_access_flags.IBV_ACCESS_ON_DEMAND) except PyverbsRDMAError as ex: if ex.error_code == errno.EOPNOTSUPP: raise unittest.SkipTest('Reg ODP MR is not supported') raise ex class DCTest(Mlx5RDMATestCase): def setUp(self): super().setUp() self.iters = 10 self.server = None self.client = None self.traffic_args = None def sync_remote_attr(self): """ Exchange the remote attributes between the server and the client. """ super().sync_remote_attr() self.client.remote_dct_num = self.server.dct_qp.qp_num self.server.remote_dct_num = self.client.dct_qp.qp_num def test_dc_rdma_write(self): self.create_players(Mlx5DcResources, qp_count=2, send_ops_flags=ibv_qp_create_send_ops_flags.IBV_QP_EX_WITH_RDMA_WRITE) u.rdma_traffic(**self.traffic_args, new_send=True, send_op=ibv_wr_opcode.IBV_WR_RDMA_WRITE) def test_dc_send(self): self.create_players(Mlx5DcResources, qp_count=2, send_ops_flags=ibv_qp_create_send_ops_flags.IBV_QP_EX_WITH_SEND) u.traffic(**self.traffic_args, new_send=True, send_op=ibv_wr_opcode.IBV_WR_SEND) def test_dc_atomic(self): self.create_players(Mlx5DcResources, qp_count=2, send_ops_flags=ibv_qp_create_send_ops_flags.IBV_QP_EX_WITH_ATOMIC_FETCH_AND_ADD) client_max_log = self.client.ctx.query_mlx5_device().max_dc_rd_atom server_max_log = self.server.ctx.query_mlx5_device().max_dc_rd_atom u.atomic_traffic(**self.traffic_args, new_send=True, send_op=ibv_wr_opcode.IBV_WR_ATOMIC_FETCH_AND_ADD, client_wr=client_max_log, server_wr=server_max_log) def test_dc_ah_to_qp_mapping(self): self.create_players(Mlx5DcResources, qp_count=2, send_ops_flags=ibv_qp_create_send_ops_flags.IBV_QP_EX_WITH_SEND) client_ah = u.get_global_ah(self.client, self.gid_index, self.ib_port) try: Mlx5QP.map_ah_to_qp(client_ah, self.server.qps[0].qp_num) except PyverbsRDMAError as ex: if ex.error_code == errno.EOPNOTSUPP: raise unittest.SkipTest('Mapping AH to QP is not supported') raise ex u.traffic(**self.traffic_args, new_send=True, send_op=ibv_wr_opcode.IBV_WR_SEND) def check_odp_dc_support(self): """ Check if the device supports ODP with DC. :raises SkipTest: In case ODP is not supported with DC """ dc_odp_caps = self.server.ctx.query_mlx5_device().dc_odp_caps required_odp_caps = ibv_odp_transport_cap_bits.IBV_ODP_SUPPORT_SEND | \ ibv_odp_transport_cap_bits.IBV_ODP_SUPPORT_SRQ_RECV if required_odp_caps & dc_odp_caps != required_odp_caps: raise unittest.SkipTest('ODP is not supported using DC') def test_odp_dc_traffic(self): send_ops_flag = ibv_qp_create_send_ops_flags.IBV_QP_EX_WITH_SEND self.create_players(OdpDc, qp_count=2, send_ops_flags=send_ops_flag) self.check_odp_dc_support() u.traffic(**self.traffic_args, new_send=True, send_op=ibv_wr_opcode.IBV_WR_SEND) def test_dc_rdma_write_stream(self): """ Check good flow of DCS. Calculate stream_id for DCS test by setting same stream id twice for WR and after increase it. Setting goes by loop and after stream_id is more than number of concurrent streams + 1 then stream_id returns to 1. :raises SkipTest: In case DCI is not supported with HW """ self.create_players(Mlx5DcStreamsRes, qp_count=2, send_ops_flags=ibv_qp_create_send_ops_flags.IBV_QP_EX_WITH_RDMA_WRITE) u.rdma_traffic(**self.traffic_args, new_send=True, send_op=ibv_wr_opcode.IBV_WR_RDMA_WRITE) def test_dc_stream_qp_recovery(self): """ Test DC QP error state transition with stream channel error accumulation. Creates DC QPs with restricted MR access and generates remote access errors via RDMA_WRITE operations. Verifies QP transitions to ERR state after enough channels entered error mode. Validates QP recovery after reset. """ self.create_players(Mlx5DcStreamsRes, qp_count=2, send_ops_flags=ibv_qp_create_send_ops_flags.IBV_QP_EX_WITH_RDMA_WRITE, mr_access=ibv_access_flags.IBV_ACCESS_LOCAL_WRITE) qp_idx = 0 error_threshold = self.client.dcis[qp_idx]['errored'] u.traffic(**self.traffic_args, new_send=True, send_op=ibv_wr_opcode.IBV_WR_SEND) for _ in range(error_threshold): with self.assertRaisesRegex(PyverbsRDMAError, r'Remote access error'): u.rdma_traffic(**self.traffic_args, new_send=True, send_op=ibv_wr_opcode.IBV_WR_RDMA_WRITE) # Poll QP state with timeout: it takes time to transition QP to ERR after errors qp_in_err_state = False start = time.perf_counter() while time.perf_counter() - start < 1.0: qp_attr, _ = self.client.qps[qp_idx].query(ibv_qp_attr_mask.IBV_QP_STATE) if qp_attr.cur_qp_state == ibv_qp_state.IBV_QPS_ERR: qp_in_err_state = True break if not qp_in_err_state: raise PyverbsRDMAError(f'QP is not in ERR state after {error_threshold} errors') for qp_idx in range(self.client.qp_count): self.client.reset_qp(qp_idx) for qp_idx in range(self.server.qp_count): self.server.reset_qp(qp_idx) u.traffic(**self.traffic_args, new_send=True, send_op=ibv_wr_opcode.IBV_WR_SEND) def test_dc_stream_ids_recovery(self): """ Test DC stream ID reset functionality after remote access errors. Creates DC QPs with restricted MR access and generates remote access errors via RDMA_WRITE operations. After each error, resets the stream ID and verifies QP remains functional. Validates normal SEND traffic continues to work after stream resets. """ self.create_players(Mlx5DcStreamsRes, qp_count=2, send_ops_flags=ibv_qp_create_send_ops_flags.IBV_QP_EX_WITH_RDMA_WRITE, mr_access=ibv_access_flags.IBV_ACCESS_LOCAL_WRITE) qp_idx = 0 error_threshold = self.client.dcis[qp_idx]['errored'] u.traffic(**self.traffic_args, new_send=True, send_op=ibv_wr_opcode.IBV_WR_SEND) for _ in range(error_threshold): with self.assertRaisesRegex(PyverbsRDMAError, r'Remote access error'): u.rdma_traffic(**self.traffic_args, new_send=True, send_op=ibv_wr_opcode.IBV_WR_RDMA_WRITE) self.client.dci_reset_stream_id(qp_idx) qp_attr, _ = self.client.qps[qp_idx].query(ibv_qp_attr_mask.IBV_QP_STATE) if qp_attr.cur_qp_state == ibv_qp_state.IBV_QPS_ERR: raise PyverbsRDMAError('QP is in ERR state after reset stream id') u.traffic(**self.traffic_args, new_send=True, send_op=ibv_wr_opcode.IBV_WR_SEND)