This patch adds the eventdev pipeline performance testsuite,
which launches the dpdk-test-eventdev application to measure
packet forwarding throughput performance across various frame
sizes and pipeline scheduling modes against expected baseline metrics.

Signed-off-by: Dillon Ladd <[email protected]>
---
 dts/tests/TestSuite_eventdev_pipeline_perf.py | 138 ++++++++++++++++++
 1 file changed, 138 insertions(+)
 create mode 100644 dts/tests/TestSuite_eventdev_pipeline_perf.py

diff --git a/dts/tests/TestSuite_eventdev_pipeline_perf.py 
b/dts/tests/TestSuite_eventdev_pipeline_perf.py
new file mode 100644
index 0000000000..a631a89990
--- /dev/null
+++ b/dts/tests/TestSuite_eventdev_pipeline_perf.py
@@ -0,0 +1,138 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2026 University of New Hampshire
+
+"""EventDev pipeline performance test suite.
+
+Measures packet forwarding throughput (MPPS) using dpdk-test-eventdev pipeline 
mode.
+"""
+
+from dataclasses import dataclass
+
+from scapy.layers.inet import IP
+from scapy.layers.l2 import Ether
+from scapy.packet import Raw
+
+from api.capabilities import (
+    LinkTopology,
+    requires_link_topology,
+)
+from api.packet import assess_performance_by_packet
+from api.test import verify, write_performance_json
+from framework.params import Option, Params, TextArgument
+from framework.remote_session.dpdk_shell import DPDKShell
+from framework.test_suite import BaseConfig, TestSuite, perf_test
+
+
+@dataclass(kw_only=True)
+class EventDevParams(Params):
+
+    test: str | None = TextArgument("--test")
+    prod_type_ethdev: bool = Option("--prod_type_ethdev")
+    stlist: str | None = TextArgument("--stlist")
+    wlcores: str | None = TextArgument("--wlcores")
+    pool_sz: int | None = TextArgument("--pool-sz")
+
+
+class Config(BaseConfig):
+
+    frame_sizes: list[int] = [64, 128, 256, 512, 1024, 1518]
+    num_descriptors: int = 1024
+    traffic_duration: int = 5
+    pool_size: int = 16384
+    delta_tolerance: float = 0.05
+    expected_mpps: dict[int, float] = {
+        64: 14.8,
+        128: 12.0,
+        256: 8.5,
+        512: 4.5,
+        1024: 2.3,
+        1518: 1.5,
+    }
+
+
+@requires_link_topology(LinkTopology.TWO_LINKS)
+class TestEventdevPipelinePerf(TestSuite):
+
+    config: Config
+
+    def set_up_suite(self) -> None:
+
+        self.delta_tolerance = self.config.delta_tolerance
+
+    def _transmit(self, frame_size: int, repetitions: int = 5) -> float:
+        padding = max(0, frame_size - len(Ether() / IP()))
+        packet = Ether() / IP() / Raw(b"X" * padding)
+
+        total_mpps = 0.0
+        for _ in range(repetitions):
+            stats = assess_performance_by_packet(
+                packet=packet,
+                duration=self.config.traffic_duration,
+            )
+            total_mpps += stats.rx_mpps
+
+        return total_mpps / repetitions
+
+    def _produce_stats_table(self, test_parameters: list[dict[str, int | 
float]]) -> None:
+    
+        header = f"{'Frame Size':>12} | {'TXD/RXD':>12} | {'Real MPPS':>12} | 
{'Expected MPPS':>14}"
+        print("-" * len(header))
+        print(header)
+        print("-" * len(header))
+        for params in test_parameters:
+
+            print(f"{params['frame_size']:>12} | 
{params['num_descriptors']:>12} | ", end="")
+            print(f"{params['measured_mpps']:>12} | 
{params['expected_mpps']:>14}")
+            print("-" * len(header))
+
+        write_performance_json({"results": test_parameters})
+
+    @perf_test
+    def test_perf_eventdev_pipeline_1ports_atomic_performance(self) -> None:
+        results = []
+
+        worker_core = str(self.sut_node.lcores[1].id)
+
+        eventdev_params = EventDevParams(
+
+            test="pipeline_atq",
+            prod_type_ethdev=True,
+            stlist="a",
+            wlcores=worker_core,
+            pool_sz=self.config.pool_size,
+        )
+
+        with self.sut_node.create_interactive_shell(
+
+            DPDKShell,
+            app_name="dpdk-test-eventdev",
+            app_params=eventdev_params,
+            eal_params=Params(vdev="event_sw0"),
+            privileged=True,
+        ) as eventdev_app:
+            for frame_size in self.config.frame_sizes:
+                
+                measured_mpps = round(self._transmit(frame_size=frame_size, 
repetitions=5), 2)
+                expected_mpps = self.config.expected_mpps.get(frame_size, 0.0)
+                passed = measured_mpps >= (expected_mpps * (1 - 
self.delta_tolerance))
+
+                results.append(
+                    {
+                        "frame_size": frame_size,
+                        "num_descriptors": self.config.num_descriptors,
+                        "measured_mpps": measured_mpps,
+                        "expected_mpps": expected_mpps,
+                        "pass": passed,
+                    }
+                )
+
+        self._produce_stats_table(results)
+
+        for result in results:
+
+            expected_baseline = result["expected_mpps"] * (1 - 
self.delta_tolerance)
+            verify(
+                result["pass"],
+                f"Measured MPPS ({result['measured_mpps']:.2f}) for frame size 
{result['frame_size']} "
+                f"is below expected baseline ({expected_baseline:.2f}).",
+            )
-- 
2.53.0

Reply via email to