Skip to content

Commit

Permalink
tests: Cover ODP over DevX
Browse files Browse the repository at this point in the history
Add a test that runs DevX traffic with a ODP enabled MR.
Force memory page-outs to make sure that the test goes through the
ODP page fault flow.
Add ODP caps to ensure ODPv2 is supported.

Signed-off-by: Maxim Chicherin <maximc@nvidia.com>
Signed-off-by: Edward Srouji <edwards@nvidia.com>
  • Loading branch information
Maxim Chicherin authored and EdwardSro committed Oct 1, 2024
1 parent a4a7d80 commit 092cf78
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 1 deletion.
10 changes: 10 additions & 0 deletions tests/mlx5_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,8 @@ def __init__(self, dev_name, ib_port, gid_index, msg_size=1024, activate_port_st
self.rmac = None
self.devx_objs = []
self.qattr = QueueAttrs()
self.with_odp = False
self.user_addr = None
if activate_port_state:
start_state_t = time.perf_counter()
self.change_port_state_with_registers(PortStatus.MLX5_PORT_UP)
Expand Down Expand Up @@ -953,10 +955,18 @@ def pre_run(self):
self.client.pre_run(self.server.psn, self.server.qpn, self.server.gid,
self.server.lid, self.mac_addr)

def invalidate_mr_pages(self):
if self.client.with_odp:
mem.madvise(self.client.mr.buf, self.client.msg_size)
self.client.mem_write('c' * self.client.msg_size, self.client.msg_size)
if self.server.with_odp:
mem.madvise(self.server.mr.buf, self.server.msg_size)

def send_imm_traffic(self):
self.client.mem_write('c' * self.client.msg_size, self.client.msg_size)
for _ in range(self.client.num_msgs):
cons_idx = self.client.qattr.cq.cons_idx
self.invalidate_mr_pages()
self.server.post_recv()
self.client.post_send()
# Poll client and verify received cqe opcode
Expand Down
60 changes: 60 additions & 0 deletions tests/mlx5_prm_structs.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class DevxOps:
MLX5_QPC_PM_STATE_MIGRATED = 0x3
MLX5_CMD_OP_QUERY_HCA_CAP = 0x100
MLX5_CMD_OP_QUERY_QOS_CAP = 0xc
MLX5_CMD_OP_QUERY_ODP_CAP = 0x2
MLX5_CMD_OP_ALLOC_FLOW_COUNTER = 0x939
MLX5_CMD_OP_DEALLOC_FLOW_COUNTER = 0x93a
MLX5_CMD_OP_QUERY_FLOW_COUNTER = 0x93b
Expand Down Expand Up @@ -1976,6 +1977,65 @@ class QueryQosCapOut(PRMPacket):
]


class OdpPerTransportServiceCap(PRMPacket):
fields_desc = [
BitField('send', 0, 1),
BitField('receive', 0, 1),
BitField('write', 0, 1),
BitField('read', 0, 1),
BitField('atomic', 0, 1),
BitField('rmp', 0, 1),
BitField('tag_matching', 0, 1),
BitField('reserved1', 0, 25),
]


class OdpSchemeCap(PRMPacket):
fields_desc = [
StrFixedLenField('reserved1', None, length=8),
BitField('sig', 0, 1),
BitField('cross_vhca_mkey', 0, 1),
BitField('klm_null_mkey', 0, 1),
BitField('dpa_process_win', 0, 1),
BitField('reserved2', 0, 3),
BitField('mmo_wqe', 0, 1),
BitField('local_mmo_wqe', 0, 1),
BitField('aso_wqe', 0, 1),
BitField('umr_wqe', 0, 1),
BitField('get_psv_wqe', 0, 1),
BitField('rget_psv_wqe', 0, 1),
BitField('reserved3', 0, 19),
StrFixedLenField('reserved4', None, length=4),
PacketField('rc_odp_caps', OdpPerTransportServiceCap(), OdpPerTransportServiceCap),
PacketField('uc_odp_caps', OdpPerTransportServiceCap(), OdpPerTransportServiceCap),
PacketField('ud_odp_caps', OdpPerTransportServiceCap(), OdpPerTransportServiceCap),
PacketField('xrc_odp_caps', OdpPerTransportServiceCap(), OdpPerTransportServiceCap),
PacketField('dc_odp_caps', OdpPerTransportServiceCap(), OdpPerTransportServiceCap),
StrFixedLenField('reserved5', None, length=28),
]


class OdpCap(PRMPacket):
fields_desc = [
PacketField('transport_page_fault_scheme_cap', OdpSchemeCap(), OdpSchemeCap),
PacketField('memory_page_fault_scheme_cap', OdpSchemeCap(), OdpSchemeCap),
StrFixedLenField('reserved1', None, length=64),
BitField('mem_page_fault', 0, 1),
BitField('reserved2', 0, 31),
StrFixedLenField('reserved3', None, length=60),
]


class QueryOdpCapOut(PRMPacket):
fields_desc = [
ByteField('status', 0),
BitField('reserved1', 0, 24),
IntField('syndrome', 0),
StrFixedLenField('reserved2', None, length=8),
PadField(PacketField('capability', OdpCap(), OdpCap), 4096, padwith=b"\x00"),
]


class FlowTableFieldsSupported2(PRMPacket):
fields_desc = [
BitField('reserved1', 0, 10),
Expand Down
25 changes: 25 additions & 0 deletions tests/test_mlx5_devx.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@
"""

from tests.mlx5_base import Mlx5DevxRcResources, Mlx5DevxTrafficBase
import pyverbs.mem_alloc as mem
from pyverbs.mr import MR
import pyverbs.enums as e
import tests.utils as u


class Mlx5DevxRcOdpRes(Mlx5DevxRcResources):
@u.requires_odpv2
def create_mr(self):
self.with_odp = True
self.user_addr = mem.mmap(length=self.msg_size,
flags=mem.MAP_ANONYMOUS_ | mem.MAP_PRIVATE_)
access = e.IBV_ACCESS_LOCAL_WRITE | e.IBV_ACCESS_REMOTE_READ | \
e.IBV_ACCESS_ON_DEMAND
self.mr = MR(self.pd, self.msg_size, access, self.user_addr)


class Mlx5DevxRcTrafficTest(Mlx5DevxTrafficBase):
Expand All @@ -32,3 +47,13 @@ def test_devx_rc_qp_send_imm_doorbell_less_traffic(self):
self.create_players(Mlx5DevxRcResources, send_dbr_mode=SendDbrMode.NO_DBR_EXT)
# Send traffic
self.send_imm_traffic()

@u.requires_odp('rc', e.IBV_ODP_SUPPORT_SEND | e.IBV_ODP_SUPPORT_RECV)
def test_devx_rc_qp_odp_traffic(self):
"""
Creates two DevX RC QPs using ODP enabled MKeys.
Then does SEND_IMM traffic.
"""
self.create_players(Mlx5DevxRcOdpRes)
# Send traffic
self.send_imm_traffic()
27 changes: 26 additions & 1 deletion tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1377,7 +1377,8 @@ def xrc_traffic(client, server, is_cq_ex=False, send_op=None, force_page_faults=
def requires_odp(qp_type, required_odp_caps):
def outer(func):
def inner(instance):
odp_supported(instance.ctx, qp_type, required_odp_caps)
ctx = getattr(instance, 'ctx', d.Context(name=instance.dev_name))
odp_supported(ctx, qp_type, required_odp_caps)
if getattr(instance, 'is_implicit', False):
odp_implicit_supported(instance.ctx)
return func(instance)
Expand Down Expand Up @@ -1438,6 +1439,30 @@ def odp_implicit_supported(ctx):
raise unittest.SkipTest('ODP implicit is not supported')


def odp_v2_supported(ctx):
"""
ODPv2 check
:return: True/False if ODPv2 supported
"""
from tests.mlx5_prm_structs import QueryHcaCapIn, QueryOdpCapOut, DevxOps, QueryHcaCapMod
query_cap_in = QueryHcaCapIn(op_mod=DevxOps.MLX5_CMD_OP_QUERY_ODP_CAP << 1 | \
QueryHcaCapMod.CURRENT)
cmd_res = ctx.devx_general_cmd(query_cap_in, len(QueryOdpCapOut()))
query_cap_out = QueryOdpCapOut(cmd_res)
if query_cap_out.status:
raise PyverbsRDMAError(f'QUERY_HCA_CAP has failed with status ({query_cap_out.status}) '
f'and syndrome ({query_cap_out.syndrome})')
return query_cap_out.capability.mem_page_fault == 1


def requires_odpv2(func):
def inner(instance):
if not odp_v2_supported(instance.ctx):
raise unittest.SkipTest('ODPv2 is not supported')
return func(instance)
return inner


def get_pci_name(dev_name):
pci_name = glob.glob(f'/sys/bus/pci/devices/*/infiniband/{dev_name}')
if not pci_name:
Expand Down

0 comments on commit 092cf78

Please sign in to comment.