Add an API for the dpdk-test-eventdev application, run as a blocking app with the topology's Ethernet ports as event producers. Only the event_sw virtual device is currently supported, with its scheduler on a dedicated service core. Eventdev testing existed on old-dts but not new-dts. This API was written so the eventdev performance testsuite from old dts can be ported over.
Signed-off-by: Dillon Ladd <[email protected]> --- dts/api/eventdev/__init__.py | 95 ++++++++++++++++++++++++++++++++++++ dts/api/eventdev/config.py | 41 ++++++++++++++++ dts/api/params/types.py | 11 +++++ 3 files changed, 147 insertions(+) create mode 100644 dts/api/eventdev/__init__.py create mode 100644 dts/api/eventdev/config.py diff --git a/dts/api/eventdev/__init__.py b/dts/api/eventdev/__init__.py new file mode 100644 index 0000000000..202ddcb77c --- /dev/null +++ b/dts/api/eventdev/__init__.py @@ -0,0 +1,95 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2026 University of New Hampshire + +"""dpdk-test-eventdev application. + +Typical usage example in a TestSuite:: + + with Eventdev(num_workers=2, stlist="a"): + stats = assess_performance_by_packet(packet=packet, duration=5) +""" + +from typing import TYPE_CHECKING + +from typing_extensions import Self, Unpack + +from api.context import get_ctx +from api.eventdev.config import EventdevParams +from api.exception import ( + InteractiveCommandExecutionError, + SkippedTestException, +) +from api.params import Params +from api.testbed_model.cpu import LogicalCoreCount, LogicalCoreList +from api.testbed_model.virtual_device import VirtualDevice +from framework.remote_session.blocking_app import BlockingApp +from framework.remote_session.dpdk_shell import compute_eal_params + +if TYPE_CHECKING: + from api.params.types import EventdevParamsDict + + +class Eventdev(BlockingApp[EventdevParams]): + """Blocking dpdk-test-eventdev application. + + Attributes: + _app_params: app parameters to pass to dpdk-test-eventdev application + """ + + _app_params: EventdevParams + + def __init__(self, num_workers: int = 1, **app_params: Unpack["EventdevParamsDict"]) -> None: + """Initialize the eventdev application. + + Args: + num_workers: number of worker cores to run the application with. + app_params: The application parameters as keyword arguments. + + Raises: + ValueError: if the build environment is `None` + SkippedTestException: if there are not enough cores on one socket + """ + ctx = get_ctx() + dpdk = ctx.dpdk.build + if dpdk is None: + raise ValueError("No DPDK build environment exists.") + self._app_path = dpdk.get_app("test-eventdev") + + # One main lcore, one service lcore for the software event scheduler, and the workers. + num_lcores = num_workers + 2 + try: + lcores = ctx.dpdk.filter_lcores( + LogicalCoreCount(cores_per_socket=num_lcores), ctx.local.ascending_cores + ) + except ValueError as e: + raise SkippedTestException( + f"dpdk-test-eventdev needs {num_lcores} cores on one socket: {e}" + ) + + main, service, *workers = lcores + app_params.setdefault("other_eal_param", Params.from_str(f"-S {service.lcore}")) + app_params.setdefault("vdevs", [VirtualDevice("event_sw0")]) + app_params.setdefault("lcore_list", LogicalCoreList(lcores)) + app_params.setdefault("wlcores", str(LogicalCoreList(workers))) + app_params.setdefault("prod_type_ethdev", True) + params = EventdevParams(**app_params) + compute_eal_params(params) + self._num_eth_ports = len(params.allowed_ports or []) + super().__init__(ctx.sut_node, self._app_path, app_params=params, privileged=True) + + def __enter__(self) -> Self: + """Start the application and wait until ready. + + Raises: + InteractiveCommandExecutionError: If there is an error starting the application. + + Returns: + The started application. + """ + last_port = self._num_eth_ports - 1 + try: + return self.wait_until_ready( + f"Port[{last_port}] using Tx adapter[{last_port}] Configured\x1b[0m" + ) + except InteractiveCommandExecutionError as e: + raise e diff --git a/dts/api/eventdev/config.py b/dts/api/eventdev/config.py new file mode 100644 index 0000000000..acdbc88743 --- /dev/null +++ b/dts/api/eventdev/config.py @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2026 University of New Hampshire + +"""Module containing types and parameter classes for the dpdk-test-eventdev application.""" + +from dataclasses import dataclass, field + +from api.params import Params, Switch +from api.params.eal import EalParams + + +@dataclass(slots=True, kw_only=True) +class EventdevParams(EalParams): + """Parameters for the dpdk-test-eventdev application. + + Attributes: + test: Name of the test to run. + wlcores: List of worker lcores. + stlist: List of scheduled types of the pipeline stages. + pool_sz: Size of the mbuf mempool. + nb_eth_queues: Number of Ethernet Rx queues. + prod_type_ethdev: Use an Ethernet device as the event producer. + """ + + test: str = field(default="pipeline_queue", metadata=Params.long("test")) + wlcores: str | None = field(default=None, metadata=Params.long("wlcores")) + stlist: str | None = field(default=None, metadata=Params.long("stlist")) + pool_sz: int | None = field(default=None, metadata=Params.long("pool_sz")) + nb_eth_queues: int | None = field(default=None, metadata=Params.long("nb_eth_queues")) + prod_type_ethdev: Switch = field(default=None, metadata=Params.long("prod_type_ethdev")) + + def __str__(self) -> str: + """Convert the parameters to a command line string. + + Returns: + The command line arguments, with underscored option names as the application expects. + """ + params = Params.__str__(self) + for name in ("pool_sz", "nb_eth_queues", "prod_type_ethdev"): + params = params.replace(f"--{name.replace('_', '-')}", f"--{name}") + return params diff --git a/dts/api/params/types.py b/dts/api/params/types.py index c4b718eebe..1ba7e9bf52 100644 --- a/dts/api/params/types.py +++ b/dts/api/params/types.py @@ -203,3 +203,14 @@ class TestPmdParamsDict(EalParamsDict, total=False): mempool_allocation_mode: SimpleMempoolAllocationMode | AnonMempoolAllocationMode | None record_core_cycles: Switch record_burst_status: Switch + + +class EventdevParamsDict(EalParamsDict, total=False): + """:class:`TypedDict` equivalent of :class:`~.eventdev.config.EventdevParams`.""" + + test: str + wlcores: str | None + stlist: str | None + pool_sz: int | None + nb_eth_queues: int | None + prod_type_ethdev: Switch -- 2.53.0

