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

