<div dir="ltr"><span class="gmail-il">Recheck</span>-<span class="gmail-il">request</span>: <span style="color:rgb(51,51,51);font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px">iol-unit-arm64-testing</span></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Tue, Sep 1, 2026 at 2:59 PM Koushik Bhargav Nimoji <<a href="mailto:knimoji@iol.unh.edu">knimoji@iol.unh.edu</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">This patch adds the pvp multi paths vhost single core forward<br>
performance testsuite, which launches testpmd using the vhost<br>
and virtio virtual devices with one and two cores respectively,<br>
and tests the vhost single core throughput performance.<br>
<br>
Signed-off-by: Koushik Bhargav Nimoji <<a href="mailto:knimoji@iol.unh.edu" target="_blank">knimoji@iol.unh.edu</a>><br>
---<br>
...lti_paths_vhost_single_core_performance.py | 445 ++++++++++++++++++<br>
1 file changed, 445 insertions(+)<br>
create mode 100644 dts/tests/TestSuite_pvp_multi_paths_vhost_single_core_performance.py<br>
<br>
diff --git a/dts/tests/TestSuite_pvp_multi_paths_vhost_single_core_performance.py b/dts/tests/TestSuite_pvp_multi_paths_vhost_single_core_performance.py<br>
new file mode 100644<br>
index 0000000000..111cb4df12<br>
--- /dev/null<br>
+++ b/dts/tests/TestSuite_pvp_multi_paths_vhost_single_core_performance.py<br>
@@ -0,0 +1,445 @@<br>
+# SPDX-License-Identifier: BSD-3-Clause<br>
+# Copyright(c) 2025 University of New Hampshire<br>
+<br>
+"""Vhost-user single-core forwarding performance test suite.<br>
+<br>
+This suite measures the packet forwarding performance of DPDK's vhost-user PMD running on a<br>
+single CPU core in a Physical-Virtual-Physical (PVP) topology. Performance is evaluated across<br>
+multiple virtio-user backend options, including packed versus split ring formats, in-order packet<br>
+processing, mergeable buffers, and SIMD vectorization. Test cases are parameterized using<br>
+combinations of frame sizes, descriptor ring sizes, and target MPPS baselines specified in the<br>
+test configuration. High-speed traffic is injected from an external generator through SUT physical<br>
+interfaces, routed through Vhost and Virtio loops, and returned to the generator to measure<br>
+aggregate MPPS.<br>
+"""<br>
+<br>
+from scapy.layers.inet import IP<br>
+from scapy.layers.l2 import Ether<br>
+from scapy.packet import Raw<br>
+<br>
+from api.capabilities import (<br>
+ LinkTopology,<br>
+ requires_link_topology,<br>
+)<br>
+from api.packet import assess_performance_by_packet<br>
+from api.test import verify, write_performance_json<br>
+from api.testpmd import TestPmd<br>
+from api.testpmd.config import PortTopology, RXRingParams, SimpleForwardingModes, TXRingParams<br>
+from framework.params.eal import VirtualDevice<br>
+from framework.params.types import LogicalCoreList, RSSSetting, TestPmdParamsDict<br>
+from framework.test_suite import BaseConfig, TestSuite, perf_test<br>
+<br>
+<br>
+class Config(BaseConfig):<br>
+ """Performance test metrics."""<br>
+<br>
+ test_parameters: list[dict[str, int | float]] = [<br>
+ {"frame_size": 64, "num_descriptors": 1024, "expected_mpps": 1.00},<br>
+ {"frame_size": 128, "num_descriptors": 1024, "expected_mpps": 1.00},<br>
+ {"frame_size": 256, "num_descriptors": 1024, "expected_mpps": 1.00},<br>
+ {"frame_size": 512, "num_descriptors": 1024, "expected_mpps": 1.00},<br>
+ {"frame_size": 1024, "num_descriptors": 1024, "expected_mpps": 1.00},<br>
+ {"frame_size": 1518, "num_descriptors": 1024, "expected_mpps": 1.00},<br>
+ ]<br>
+ delta_tolerance: float = 0.05<br>
+<br>
+<br>
+@requires_link_topology(LinkTopology.TWO_LINKS)<br>
+class TestPvpMultiPathsVhostSingleCorePerformance(TestSuite):<br>
+ """pvp multi paths vhost single core performance test suite."""<br>
+<br>
+ config: Config<br>
+<br>
+ def set_up_suite(self):<br>
+ """Assign test parameters."""<br>
+ self.test_parameters = self.config.test_parameters<br>
+ self.delta_tolerance = self.config.delta_tolerance<br>
+<br>
+ def set_up_test_case(self):<br>
+ """Delete stale vhost-user Unix domain socket files."""<br>
+ self._ctx.sut_node.main_session.send_command("rm -rf /tmp/vhost-net*", privileged=True)<br>
+<br>
+ def _transmit(<br>
+ self, vhost: TestPmd, virtio: TestPmd, frame_size: int, repetitions: int = 1<br>
+ ) -> float:<br>
+ """Create a testpmd session with every rule in the given list, verify jump behavior.<br>
+<br>
+ Args:<br>
+ vhost: the running vhost testpmd shell.<br>
+ virtio: the running virtio testpmd shell.<br>
+ testpmd: The testpmd shell to use for forwarding packets.<br>
+ frame_size: The size of the frame to transmit.<br>
+ repetitions: The number of times to rerun the transmission.<br>
+<br>
+ Returns:<br>
+ The MPPS (millions of packets per second) forwarded by the SUT.<br>
+ """<br>
+ assert repetitions > 0, "Invalid number of repetitions given."<br>
+ # Build packet with dummy values, and account for the 14B and 20B Ether and IP headers<br>
+ packet = (<br>
+ Ether(src="52:00:00:00:00:00")<br>
+ / IP(src="1.2.3.4", dst="192.18.1.0")<br>
+ / Raw(load="x" * (frame_size - 14 - 20))<br>
+ )<br>
+<br>
+ vhost.start()<br>
+ virtio.start()<br>
+ rx_avg = 0.0<br>
+<br>
+ for _ in range(repetitions):<br>
+ # Transmit for 5 seconds.<br>
+ stats = assess_performance_by_packet(packet=packet, duration=5)<br>
+ rx_avg += stats.rx_pps<br>
+ return rx_avg / (repetitions * 1_000_000)<br>
+<br>
+ def _create_and_transmit(<br>
+ self,<br>
+ ring_format: int,<br>
+ in_order: int,<br>
+ buffers: int,<br>
+ vectorized: int,<br>
+ extra_args: TestPmdParamsDict,<br>
+ ):<br>
+ """Create testpmd instance with specified params and send traffic."""<br>
+ sut_dpdk_driver = self._ctx.sut_node.config.ports[0].os_driver_for_dpdk<br>
+ vhost_user_vdev = VirtualDevice("net_vhost0,iface=/tmp/vhost-net,queues=1")<br>
+ virtio_user_vdev = VirtualDevice(<br>
+ "net_virtio_user0,"<br>
+ "mac=00:11:22:33:44:10,"<br>
+ "path=/tmp/vhost-net,"<br>
+ "queues=1,"<br>
+ f"packed_vq={ring_format},"<br>
+ f"mrg_rxbuf={buffers},"<br>
+ f"in_order={in_order},"<br>
+ f"vectorized={vectorized}"<br>
+ )<br>
+<br>
+ for params in self.test_parameters:<br>
+ frame_size = params["frame_size"]<br>
+ num_descriptors = params["num_descriptors"]<br>
+<br>
+ default_args = {<br>
+ "tx_ring": TXRingParams(descriptors=num_descriptors),<br>
+ "rx_ring": RXRingParams(descriptors=num_descriptors),<br>
+ }<br>
+<br>
+ # extra_args["tx_ring"] = TXRingParams(descriptors=num_descriptors)<br>
+ # extra_args["rx_ring"] = RXRingParams(descriptors=num_descriptors)<br>
+<br>
+ if sut_dpdk_driver == "mlx5_core":<br>
+ default_args["burst"] = 64<br>
+ default_args["mbcache"] = 512<br>
+ elif sut_dpdk_driver == "i40e":<br>
+ default_args["rx_queues"] = 1<br>
+ default_args["tx_queues"] = 1<br>
+<br>
+ with (<br>
+ TestPmd(<br>
+ prefix="vhost",<br>
+ allowed_ports=[],<br>
+ memory_channels=4,<br>
+ port_topology=PortTopology.chained,<br>
+ vdevs=[vhost_user_vdev],<br>
+ lcore_list=LogicalCoreList([1, 2]),<br>
+ nb_cores=1,<br>
+ **default_args,<br>
+ ) as vhost,<br>
+ TestPmd(<br>
+ prefix="virtio",<br>
+ no_pci=True,<br>
+ memory_channels=4,<br>
+ allowed_ports=[],<br>
+ vdevs=[virtio_user_vdev],<br>
+ lcore_list=LogicalCoreList([3, 4, 5]),<br>
+ nb_cores=2,<br>
+ **extra_args,<br>
+ **default_args,<br>
+ ) as virtio,<br>
+ ):<br>
+ vhost.set_forward_mode(SimpleForwardingModes.mac)<br>
+ virtio.set_forward_mode(SimpleForwardingModes.io)<br>
+ vhost.set_portlist([0, 2, 1])<br>
+<br>
+ params["measured_mpps"] = round(<br>
+ self._transmit(vhost, virtio, frame_size, repetitions=5), 3<br>
+ )<br>
+ params["performance_delta"] = round(<br>
+ (float(params["measured_mpps"]) - float(params["expected_mpps"]))<br>
+ / float(params["expected_mpps"]),<br>
+ 3,<br>
+ )<br>
+ params["pass"] = float(params["performance_delta"]) >= -self.delta_tolerance<br>
+<br>
+ self._produce_stats_table(self.test_parameters)<br>
+ for params in self.test_parameters:<br>
+ verify(<br>
+ params["pass"] is True,<br>
+ f"""Packets forwarded is less than {(1 - self.delta_tolerance) * 100}%<br>
+ of the expected baseline.<br>
+ Measured MPPS = {params["measured_mpps"]}<br>
+ Expected MPPS = {params["expected_mpps"]}""",<br>
+ )<br>
+<br>
+ def _produce_stats_table(self, test_parameters: list[dict[str, int | float]]) -> None:<br>
+ """Display performance results in table format and write to structured JSON file.<br>
+<br>
+ Args:<br>
+ test_parameters: The expected and real stats per set of test parameters.<br>
+ """<br>
+ header = f"{'Frame Size':>12} | {'TXD/RXD':>12} | {'Real MPPS':>12} | {'Expected MPPS':>14}"<br>
+ print("-" * len(header))<br>
+ print(header)<br>
+ print("-" * len(header))<br>
+ for params in test_parameters:<br>
+ print(f"{params['frame_size']:>12} | {params['num_descriptors']:>12} | ", end="")<br>
+ print(f"{params['measured_mpps']:>12} | {params['expected_mpps']:>14}")<br>
+ print("-" * len(header))<br>
+<br>
+ write_performance_json({"results": test_parameters})<br>
+<br>
+ @perf_test<br>
+ def test_perf_vhost_single_core_virtio11_mergeable(self):<br>
+ """Validate expected single core forwarding performance.<br>
+<br>
+ Steps:<br>
+ * Set TestPMD virtio parameters: ring_format=1, buffers=1.<br>
+ * Create a packet according to the frame size specified in the test config.<br>
+ * Transmit from the traffic generator's ports 0 and 1 at above the expect.<br>
+ * Forward on TestPMD's interfaces 0 and 1 with 1 core.<br>
+<br>
+ Verify:<br>
+ * The resulting MPPS forwarded is greater than expected_mpps*(1-delta_tolerance).<br>
+ """<br>
+ extra_args: TestPmdParamsDict = {<br>
+ "tx_offloads": 0,<br>
+ "enable_hw_vlan_strip": True,<br>
+ "rss": RSSSetting.SetIPOnly(),<br>
+ }<br>
+ self._create_and_transmit(<br>
+ ring_format=1,<br>
+ buffers=1,<br>
+ in_order=0,<br>
+ vectorized=0,<br>
+ extra_args=extra_args,<br>
+ )<br>
+<br>
+ @perf_test<br>
+ def test_perf_vhost_single_core_virtio11_non_mergeable(self):<br>
+ """Validate expected single core forwarding performance.<br>
+<br>
+ Steps:<br>
+ * Set TestPMD virtio parameters: ring_format=1.<br>
+ * Create a packet according to the frame size specified in the test config.<br>
+ * Transmit from the traffic generator's ports 0 and 1 at above the expect.<br>
+ * Forward on TestPMD's interfaces 0 and 1 with 1 core.<br>
+<br>
+ Verify:<br>
+ * The resulting MPPS forwarded is greater than expected_mpps*(1-delta_tolerance).<br>
+ """<br>
+ extra_args: TestPmdParamsDict = {<br>
+ "tx_offloads": 0,<br>
+ "enable_hw_vlan_strip": True,<br>
+ "rss": RSSSetting.SetIPOnly(),<br>
+ }<br>
+ self._create_and_transmit(<br>
+ ring_format=1,<br>
+ buffers=0,<br>
+ in_order=0,<br>
+ vectorized=0,<br>
+ extra_args=extra_args,<br>
+ )<br>
+<br>
+ @perf_test<br>
+ def test_perf_vhost_single_core_virtio_inorder_mergeable(self):<br>
+ """Validate expected single core forwarding performance.<br>
+<br>
+ Steps:<br>
+ * Set TestPMD virtio parameters: buffers=1, in_order=1.<br>
+ * Create a packet according to the frame size specified in the test config.<br>
+ * Transmit from the traffic generator's ports 0 and 1 at above the expect.<br>
+ * Forward on TestPMD's interfaces 0 and 1 with 1 core.<br>
+<br>
+ Verify:<br>
+ * The resulting MPPS forwarded is greater than expected_mpps*(1-delta_tolerance).<br>
+ """<br>
+ extra_args: TestPmdParamsDict = {<br>
+ "tx_offloads": 0,<br>
+ "enable_hw_vlan_strip": True,<br>
+ "rss": RSSSetting.SetIPOnly(),<br>
+ }<br>
+ self._create_and_transmit(<br>
+ ring_format=0,<br>
+ buffers=1,<br>
+ in_order=1,<br>
+ vectorized=0,<br>
+ extra_args=extra_args,<br>
+ )<br>
+<br>
+ @perf_test<br>
+ def test_perf_vhost_single_core_virtio_inorder_nonmergeable(self):<br>
+ """Validate expected single core forwarding performance.<br>
+<br>
+ Steps:<br>
+ * Set TestPMD virtio parameters: in_order=1.<br>
+ * Create a packet according to the frame size specified in the test config.<br>
+ * Transmit from the traffic generator's ports 0 and 1 at above the expect.<br>
+ * Forward on TestPMD's interfaces 0 and 1 with 1 core.<br>
+<br>
+ Verify:<br>
+ * The resulting MPPS forwarded is greater than expected_mpps*(1-delta_tolerance).<br>
+ """<br>
+ extra_args: TestPmdParamsDict = {<br>
+ "tx_offloads": 0,<br>
+ "enable_hw_vlan_strip": True,<br>
+ "rss": RSSSetting.SetIPOnly(),<br>
+ }<br>
+ self._create_and_transmit(<br>
+ ring_format=0,<br>
+ buffers=0,<br>
+ in_order=1,<br>
+ vectorized=0,<br>
+ extra_args=extra_args,<br>
+ )<br>
+<br>
+ @perf_test<br>
+ def test_perf_vhost_single_core_virtio_mergeable(self):<br>
+ """Validate expected single core forwarding performance.<br>
+<br>
+ Steps:<br>
+ * Set TestPMD virtio parameters: buffers=1.<br>
+ * Create a packet according to the frame size specified in the test config.<br>
+ * Transmit from the traffic generator's ports 0 and 1 at above the expect.<br>
+ * Forward on TestPMD's interfaces 0 and 1 with 1 core.<br>
+<br>
+ Verify:<br>
+ * The resulting MPPS forwarded is greater than expected_mpps*(1-delta_tolerance).<br>
+ """<br>
+ extra_args: TestPmdParamsDict = {<br>
+ "tx_offloads": 0,<br>
+ "enable_hw_vlan_strip": True,<br>
+ "rss": RSSSetting.SetIPOnly(),<br>
+ }<br>
+ self._create_and_transmit(<br>
+ ring_format=0,<br>
+ buffers=1,<br>
+ in_order=0,<br>
+ vectorized=0,<br>
+ extra_args=extra_args,<br>
+ )<br>
+<br>
+ @perf_test<br>
+ def test_perf_vhost_single_core_virtio_nonmergeable(self):<br>
+ """Validate expected single core forwarding performance.<br>
+<br>
+ Steps:<br>
+ * Set TestPMD virtio parameters: vectorized=1.<br>
+ * Create a packet according to the frame size specified in the test config.<br>
+ * Transmit from the traffic generator's ports 0 and 1 at above the expect.<br>
+ * Forward on TestPMD's interfaces 0 and 1 with 1 core.<br>
+<br>
+ Verify:<br>
+ * The resulting MPPS forwarded is greater than expected_mpps*(1-delta_tolerance).<br>
+ """<br>
+ extra_args: TestPmdParamsDict = {<br>
+ "tx_offloads": 0,<br>
+ "enable_hw_vlan_strip": True,<br>
+ "rss": RSSSetting.SetIPOnly(),<br>
+ }<br>
+ self._create_and_transmit(<br>
+ ring_format=0,<br>
+ buffers=0,<br>
+ in_order=0,<br>
+ vectorized=1,<br>
+ extra_args=extra_args,<br>
+ )<br>
+<br>
+ @perf_test<br>
+ def test_perf_vhost_single_core_virtio_vectorized(self):<br>
+ """Validate expected single core forwarding performance.<br>
+<br>
+ Steps:<br>
+ * Set TestPMD virtio parameters: buffers=1.<br>
+ * Create a packet according to the frame size specified in the test config.<br>
+ * Transmit from the traffic generator's ports 0 and 1 at above the expect.<br>
+ * Forward on TestPMD's interfaces 0 and 1 with 1 core.<br>
+<br>
+ Verify:<br>
+ * The resulting MPPS forwarded is greater than expected_mpps*(1-delta_tolerance).<br>
+ """<br>
+ self._create_and_transmit(<br>
+ ring_format=0,<br>
+ buffers=1,<br>
+ in_order=0,<br>
+ vectorized=0,<br>
+ extra_args={},<br>
+ )<br>
+<br>
+ @perf_test<br>
+ def test_perf_vhost_single_core_virtio11_inorder_mergeable(self):<br>
+ """Validate expected single core forwarding performance.<br>
+<br>
+ Steps:<br>
+ * Set TestPMD virtio parameters: ring_format=1, buffers=1, in_order=1.<br>
+ * Create a packet according to the frame size specified in the test config.<br>
+ * Transmit from the traffic generator's ports 0 and 1 at above the expect.<br>
+ * Forward on TestPMD's interfaces 0 and 1 with 1 core.<br>
+<br>
+ Verify:<br>
+ * The resulting MPPS forwarded is greater than expected_mpps*(1-delta_tolerance).<br>
+ """<br>
+ extra_args: TestPmdParamsDict = {<br>
+ "tx_offloads": 0,<br>
+ "enable_hw_vlan_strip": True,<br>
+ "rss": RSSSetting.SetIPOnly(),<br>
+ }<br>
+ self._create_and_transmit(<br>
+ ring_format=1,<br>
+ buffers=1,<br>
+ in_order=1,<br>
+ vectorized=0,<br>
+ extra_args=extra_args,<br>
+ )<br>
+<br>
+ @perf_test<br>
+ def test_perf_vhost_single_core_virtio11_inorder_nonmergeable(self):<br>
+ """Validate expected single core forwarding performance.<br>
+<br>
+ Steps:<br>
+ * Set TestPMD virtio parameters: ring_format=1, in_order=1.<br>
+ * Create a packet according to the frame size specified in the test config.<br>
+ * Transmit from the traffic generator's ports 0 and 1 at above the expect.<br>
+ * Forward on TestPMD's interfaces 0 and 1 with 1 core.<br>
+<br>
+ Verify:<br>
+ * The resulting MPPS forwarded is greater than expected_mpps*(1-delta_tolerance).<br>
+ """<br>
+ extra_args: TestPmdParamsDict = {"rss": RSSSetting.SetIPOnly()}<br>
+ self._create_and_transmit(<br>
+ ring_format=1,<br>
+ buffers=0,<br>
+ in_order=1,<br>
+ vectorized=0,<br>
+ extra_args=extra_args,<br>
+ )<br>
+<br>
+ @perf_test<br>
+ def test_perf_vhost_single_core_virtio11_vectorized(self):<br>
+ """Validate expected single core forwarding performance.<br>
+<br>
+ Steps:<br>
+ * Set TestPMD virtio parameters: ring_format=1, in_order=1, vectorized=1.<br>
+ * Create a packet according to the frame size specified in the test config.<br>
+ * Transmit from the traffic generator's ports 0 and 1 at above the expect.<br>
+ * Forward on TestPMD's interfaces 0 and 1 with 1 core.<br>
+<br>
+ Verify:<br>
+ * The resulting MPPS forwarded is greater than expected_mpps*(1-delta_tolerance).<br>
+ """<br>
+ extra_args: TestPmdParamsDict = {"rss": RSSSetting.SetIPOnly()}<br>
+ self._create_and_transmit(<br>
+ ring_format=1,<br>
+ buffers=0,<br>
+ in_order=1,<br>
+ vectorized=1,<br>
+ extra_args=extra_args,<br>
+ )<br>
-- <br>
2.55.0<br>
<br>
</blockquote></div>