blob: b961865ba53312b76f1efe81159a8c75ffc8a5bf [file]
# SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB)
# Copyright (c) 2021 Nvidia, Inc. All rights reserved. See COPYING file
"""
Test module for pyverbs' mlx5_vfio module.
"""
from threading import Thread
import unittest
import select
import errno
from pyverbs.providers.mlx5.mlx5_vfio import Mlx5VfioAttr, Mlx5VfioContext
from tests.mlx5_base import Mlx5DevxRcResources, Mlx5DevxTrafficBase
from pyverbs.pyverbs_error import PyverbsRDMAError
class Mlx5VfioResources(Mlx5DevxRcResources):
def __init__(self, ib_port, pci_name, gid_index=None, ctx=None):
self.pci_name = pci_name
self.ctx = ctx
super().__init__(None, ib_port, gid_index)
def create_context(self):
"""
Opens an mlx5 VFIO context.
Since only one context is allowed to be opened on a VFIO, the user must
pass that context for the remaining resources, which in that case, the
same context would be used.
:return: None
"""
if self.ctx:
return
try:
vfio_attr = Mlx5VfioAttr(pci_name=self.pci_name)
vfio_attr.pci_name = self.pci_name
self.ctx = Mlx5VfioContext(attr=vfio_attr)
except PyverbsRDMAError as ex:
if ex.error_code == errno.EOPNOTSUPP:
raise unittest.SkipTest(f'Mlx5 VFIO is not supported ({ex})')
raise ex
def query_gid(self):
"""
Currently Mlx5VfioResources does not support Eth port type.
Query GID would just be skipped.
"""
pass
class Mlx5VfioTrafficTest(Mlx5DevxTrafficBase):
"""
Test various functionality of an mlx5-vfio device.
"""
def setUp(self):
"""
Verifies that the user has passed a PCI device name to work with.
"""
self.pci_dev = self.config['pci_dev']
if not self.pci_dev:
raise unittest.SkipTest('PCI device must be passed by the user')
def create_players(self):
self.server = Mlx5VfioResources(ib_port=self.ib_port, pci_name=self.pci_dev)
self.client = Mlx5VfioResources(ib_port=self.ib_port, pci_name=self.pci_dev,
ctx=self.server.ctx)
def vfio_processs_events(self):
"""
Processes mlx5 vfio device events.
This method should run from application thread to maintain the events.
"""
# Server and client use the same context
events_fd = self.server.ctx.get_events_fd()
with select.epoll() as epoll_events:
epoll_events.register(events_fd, select.EPOLLIN)
while self.proc_events:
for fd, event in epoll_events.poll(timeout=0.1):
if fd == events_fd:
if not (event & select.EPOLLIN):
self.event_ex.append(PyverbsRDMAError(f'Unexpected vfio event: {event}'))
self.server.ctx.process_events()
def test_mlx5vfio_rc_qp_send_imm_traffic(self):
"""
Opens one mlx5 vfio context, creates two DevX RC QPs on it, and modifies
them to RTS state.
Then does SEND_IMM traffic.
"""
self.create_players()
if self.server.is_eth():
raise unittest.SkipTest(f'{self.__class__.__name__} is currently supported over IB only')
self.event_ex = []
self.proc_events = True
proc_events = Thread(target=self.vfio_processs_events)
proc_events.start()
# Move the DevX QPs ro RTS state
self.pre_run()
try:
# Send traffic
self.send_imm_traffic()
finally:
# Stop listening to events
self.proc_events = False
proc_events.join()
if self.event_ex:
raise PyverbsRDMAError(f'Received unexpected vfio events: {self.event_ex}')