Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests: Add QP basic test and enhance stability #1560

Merged
merged 5 commits into from
Feb 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions pyverbs/wr.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,6 @@ cdef class RecvWR(PyverbsCM):
"""
super().__init__()
cdef v.ibv_sge *dst
if num_sge < 1 or sg is None:
raise PyverbsUserError('A WR needs at least one SGE')
self.recv_wr.sg_list = <v.ibv_sge*>malloc(num_sge * sizeof(v.ibv_sge))
if self.recv_wr.sg_list == NULL:
raise PyverbsRDMAErrno('Failed to malloc SG buffer')
Expand Down
19 changes: 17 additions & 2 deletions tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,21 @@ def __init__(self, dev_name, ib_port, gid_index, **kwargs):


class RCResources(RoCETrafficResources):
def __init__(self, dev_name, ib_port, gid_index,
max_dest_rd_atomic=MAX_DEST_RD_ATOMIC, max_rd_atomic=MAX_RD_ATOMIC, **kwargs):
"""
Initializes a TrafficResources object with the given values and creates
basic RDMA resources.
: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 max_dest_rd_atomic: Number of responder incoming rd_atomic operations that can
be handled
:param max_rd_atomic: Number of outstanding destination rd_atomic operations
"""
self.max_dest_rd_atomic = max_dest_rd_atomic
self.max_rd_atomic = max_rd_atomic
super().__init__(dev_name, ib_port, gid_index, **kwargs)

def to_rts(self):
"""
Expand All @@ -714,9 +729,9 @@ def to_rts(self):
"""
attr = self.create_qp_attr()
attr.path_mtu = PATH_MTU
attr.max_dest_rd_atomic = MAX_DEST_RD_ATOMIC
attr.max_dest_rd_atomic = self.max_dest_rd_atomic
set_rnr_attributes(attr)
attr.max_rd_atomic = MAX_RD_ATOMIC
attr.max_rd_atomic = self.max_rd_atomic
gr = GlobalRoute(dgid=self.ctx.query_gid(self.ib_port, self.gid_index),
sgid_index=self.gid_index)
ah_attr = AHAttr(port_num=self.ib_port, is_global=1, gr=gr,
Expand Down
14 changes: 13 additions & 1 deletion tests/test_mlx5_dr.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,17 @@ def func_wrapper(instance):
return func_wrapper


def requires_flow_counter_support(func):
def func_wrapper(instance):
nic_tbl_caps = u.query_nic_flow_table_caps(instance)
rx_counter_support = nic_tbl_caps.flow_table_properties_nic_receive.flow_counter
tx_counter_support = nic_tbl_caps.flow_table_properties_nic_transmit.flow_counter
if not (rx_counter_support and tx_counter_support):
raise unittest.SkipTest('NIC flow tables do not support counter action')
return func(instance)
return func_wrapper


class Mlx5DrResources(RawResources):
"""
Test various functionalities of the mlx5 direct rules class.
Expand Down Expand Up @@ -142,7 +153,7 @@ def get_first_flow_meter_reg_id(self):
f'and syndrome ({query_cap_out.syndrome})')
bit_regs = query_cap_out.capability.flow_meter_reg_id
if bit_regs == 0:
raise PyverbsRDMAError(f'Reg C is not supported)')
raise unittest.SkipTest('Reg C is not supported')
return int(math.log2(bit_regs & -bit_regs))


Expand Down Expand Up @@ -1368,6 +1379,7 @@ def reuse_action_and_matcher(self, root_only=False):
self.assertEqual(matched_packets_rx, self.iters, 'Reuse action or matcher failed on RX')

@skip_unsupported
@requires_flow_counter_support
def test_root_reuse_action_and_matcher(self):
"""
Create root rules on TX and RX that use the same matcher and actions
Expand Down
15 changes: 13 additions & 2 deletions tests/test_mlx5_vfio.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
import pyverbs.mem_alloc as mem
import pyverbs.dma_util as dma

EVENT_TIMEOUT = 2 # In seconds
EVENT_REGISTRATION_TIMEOUT = 3 # In seconds


class Mlx5VfioResources(Mlx5DevxRcResources):
def __init__(self, ib_port, pci_name, gid_index=None, ctx=None, activate_port_state=False):
Expand Down Expand Up @@ -204,6 +207,7 @@ def vfio_process_async_events(self):
events_fd = self.server.msi_vector.fd
with select.epoll() as epoll_events:
epoll_events.register(events_fd, select.EPOLLIN)
self.reg_async_events = True
while self.proc_events:
for fd, event in epoll_events.poll(timeout=0.1):
if fd == events_fd:
Expand Down Expand Up @@ -248,13 +252,18 @@ def test_mlx5vfio_async_event(self):
self.event_ex = []
self.proc_events = True
self.caught_event = False
self.reg_async_events = False
proc_events = Thread(target=self.vfio_process_events)
proc_async_events = Thread(target=self.vfio_process_async_events)
proc_events.start()
proc_async_events.start()
# Move the DevX QPs to RTS state
self.pre_run()
try:
start_reg_t = time.perf_counter()
while not self.reg_async_events:
if time.perf_counter() - start_reg_t >= EVENT_REGISTRATION_TIMEOUT:
raise PyverbsRDMAError('Could not register async events')
# Change port state
self.server.change_port_state_with_registers(PortStatus.MLX5_PORT_UP)
admin_status, oper_status = self.server.query_port_state_with_registers()
Expand All @@ -270,10 +279,12 @@ def test_mlx5vfio_async_event(self):
time.sleep(1)
finally:
# Stop listening to events
start_event_t = time.perf_counter()
while not self.caught_event:
if time.perf_counter() - start_event_t >= EVENT_TIMEOUT:
raise PyverbsRDMAError('Failed to catch an async event')
self.proc_events = False
proc_events.join()
proc_async_events.join()
if self.event_ex:
raise PyverbsRDMAError(f'Received unexpected vfio events: {self.event_ex}')
if not self.caught_event:
raise PyverbsRDMAError('Failed to catch an async event')
27 changes: 25 additions & 2 deletions tests/test_qp.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
import os

from pyverbs.pyverbs_error import PyverbsRDMAError
from pyverbs.qp import QPInitAttr, QPAttr, QP
from tests.base import PyverbsAPITestCase
from pyverbs.qp import QPAttr, QP
from tests.base import PyverbsAPITestCase, RDMATestCase, RCResources
import pyverbs.utils as pu
import pyverbs.device as d
import pyverbs.enums as e
Expand Down Expand Up @@ -366,6 +366,29 @@ def test_modify_ud_qp(self):
assert qp.qp_state == e.IBV_QPS_RESET, 'Extended QP, QP state is not as expected'


class RCQPTest(RDMATestCase):
"""
Test various functionalities of the RC QP class.
"""
def test_modify_rc_qp_rd_atomic(self):
"""
This test verifies that the values of rd_atomic fields are
at least the requested value.
"""
self.max_rd_atomic = 12
self.max_dest_rd_atomic = 12

self.create_players(RCResources, max_rd_atomic=self.max_rd_atomic,
max_dest_rd_atomic=self.max_dest_rd_atomic)

qp_attr, _ = self.server.qp.query(e.IBV_QP_MAX_QP_RD_ATOMIC | e.IBV_QP_MAX_DEST_RD_ATOMIC)

self.assertGreaterEqual(qp_attr.max_rd_atomic, self.max_rd_atomic,
'Max RD Atomic value is less than requested.')
self.assertGreaterEqual(qp_attr.max_dest_rd_atomic, self.max_dest_rd_atomic,
'Max Dest RD Atomic is less than requested.')


def get_qp_init_attr_ex(cq, pd, attr, attr_ex, qpt):
"""
Creates a QPInitAttrEx object with a QP type of the provided <qpts> array
Expand Down