Skip to content

Commit

Permalink
Merge pull request #1560 from EdwardSro/pr-pyverbs-tests
Browse files Browse the repository at this point in the history
tests: Add QP basic test and enhance stability
  • Loading branch information
rleon authored Feb 16, 2025
2 parents 4414a12 + fede944 commit d9a2586
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 9 deletions.
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

0 comments on commit d9a2586

Please sign in to comment.