From: Jeremy Spewock <jspew...@iol.unh.edu> Adds a new test suite that tests the support of scattered packets in poll mode drivers. It is a rewrite of the existing scatter test suite in the DTS repository of the DPDK project.
Signed-off-by: Jeremy Spewock <jspew...@iol.unh.edu> --- .../remote_session/remote/testpmd_shell.py | 30 ++++++++- dts/framework/testbed_model/__init__.py | 2 + dts/framework/testbed_model/hw/__init__.py | 1 + dts/framework/testbed_model/hw/port.py | 9 +++ dts/framework/testbed_model/sut_node.py | 5 +- dts/tests/TestSuite_scatter.py | 62 +++++++++++++++++++ 6 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 dts/tests/TestSuite_scatter.py diff --git a/dts/framework/remote_session/remote/testpmd_shell.py b/dts/framework/remote_session/remote/testpmd_shell.py index 1455b5a199..4feed3bdb8 100644 --- a/dts/framework/remote_session/remote/testpmd_shell.py +++ b/dts/framework/remote_session/remote/testpmd_shell.py @@ -3,6 +3,8 @@ from pathlib import PurePath from typing import Callable +from framework.settings import SETTINGS +import time from .interactive_shell import InteractiveShell @@ -29,7 +31,7 @@ def _start_application( self, get_privileged_command: Callable[[str], str] | None ) -> None: """See "_start_application" in InteractiveShell.""" - self._app_args += " -- -i" + self._app_args += " -i" super()._start_application(get_privileged_command) def get_devices(self) -> list[TestPmdDevice]: @@ -47,3 +49,29 @@ def get_devices(self) -> list[TestPmdDevice]: if "device name:" in line.lower(): dev_list.append(TestPmdDevice(line)) return dev_list + + def wait_link_status_up(self, port_id: int, timeout=SETTINGS.timeout) -> bool: + """Wait until the link status on the given port is "up". + + Arguments: + port_id: Port to check the link status on. + timeout: time to wait for the link to come up. + + Returns: + If the link came up in time or not. + """ + time_to_stop = time.time() + timeout + while time.time() < time_to_stop: + port_info = self.send_command(f"show port info {port_id}") + if "Link status: up" in port_info: + break + time.sleep(0.5) + else: + self._logger.error( + f"The link for port {port_id} did not come up in the given timeout." + ) + return "Link status: up" in port_info + + def close(self) -> None: + self.send_command("exit", "") + return super().close() diff --git a/dts/framework/testbed_model/__init__.py b/dts/framework/testbed_model/__init__.py index 5cbb859e47..ead25aea8e 100644 --- a/dts/framework/testbed_model/__init__.py +++ b/dts/framework/testbed_model/__init__.py @@ -17,6 +17,8 @@ LogicalCoreListFilter, VirtualDevice, lcore_filter, + Port, + PortLink ) from .node import Node from .sut_node import SutNode diff --git a/dts/framework/testbed_model/hw/__init__.py b/dts/framework/testbed_model/hw/__init__.py index 88ccac0b0e..5719af2017 100644 --- a/dts/framework/testbed_model/hw/__init__.py +++ b/dts/framework/testbed_model/hw/__init__.py @@ -12,6 +12,7 @@ LogicalCoreListFilter, ) from .virtual_device import VirtualDevice +from .port import Port, PortLink def lcore_filter( diff --git a/dts/framework/testbed_model/hw/port.py b/dts/framework/testbed_model/hw/port.py index 680c29bfe3..97cfd01b6b 100644 --- a/dts/framework/testbed_model/hw/port.py +++ b/dts/framework/testbed_model/hw/port.py @@ -27,6 +27,7 @@ class Port: Example: mlx5_core peer: The identifier of a port this port is connected with. + logical_name: The logical name of the port (e.g. ens162) """ identifier: PortIdentifier @@ -35,6 +36,7 @@ class Port: peer: PortIdentifier mac_address: str = "" logical_name: str = "" + _id: int | None def __init__(self, node_name: str, config: PortConfig): self.identifier = PortIdentifier( @@ -44,6 +46,7 @@ def __init__(self, node_name: str, config: PortConfig): self.os_driver = config.os_driver self.os_driver_for_dpdk = config.os_driver_for_dpdk self.peer = PortIdentifier(node=config.peer_node, pci=config.peer_pci) + self._id = None @property def node(self) -> str: @@ -53,6 +56,12 @@ def node(self) -> str: def pci(self) -> str: return self.identifier.pci + @property + def id(self) -> int: + if self._id is None: + self._id = self.pci.split(".")[-1] + return self._id + @dataclass(slots=True, frozen=True) class PortLink: diff --git a/dts/framework/testbed_model/sut_node.py b/dts/framework/testbed_model/sut_node.py index 202aebfd06..8779c1e1b0 100644 --- a/dts/framework/testbed_model/sut_node.py +++ b/dts/framework/testbed_model/sut_node.py @@ -360,6 +360,7 @@ def create_interactive_shell( timeout: float = SETTINGS.timeout, privileged: bool = False, eal_parameters: EalParameters | str | None = None, + app_parameters: str | None = None ) -> InteractiveShellType: """Factory method for creating a handler for an interactive session. @@ -374,6 +375,8 @@ def create_interactive_shell( eal_parameters: List of EAL parameters to use to launch the app. If this isn't provided or an empty string is passed, it will default to calling create_eal_parameters(). + app_parameters: Additional arguments to pass into the application on the + command-line. Returns: Instance of the desired interactive application. """ @@ -387,5 +390,5 @@ def create_interactive_shell( ) return super().create_interactive_shell( - shell_cls, timeout, privileged, str(eal_parameters) + shell_cls, timeout, privileged, f"{eal_parameters} -- {app_parameters}" ) diff --git a/dts/tests/TestSuite_scatter.py b/dts/tests/TestSuite_scatter.py new file mode 100644 index 0000000000..898d56e288 --- /dev/null +++ b/dts/tests/TestSuite_scatter.py @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2023 University of New Hampshire + +from framework.test_suite import TestSuite +from framework.testbed_model import PortLink +from framework.remote_session import TestPmdShell + + +class Scatter(TestSuite): + port_link_for_testing: PortLink + mbsize: int + + def set_up_suite(self) -> None: + self.verify( + len(self._port_links) > 0, + "Must have at least one port link to run scatter" + ) + self.port_link_for_testing = self._port_links[0] + self.mbsize = 1024 # TODO: make this 2048 for some NICs like in old DTS + self.tg_node.main_session.send_command( + f"ifconfig {self.port_link_for_testing.tg_port.logical_name} mtu 9000" + ) + + def scatter_pktgen_send_packet(self, pktsize: int) -> None: + """Generate and send packet to the SUT. + + Functional test for scatter packets. + + Args: + pktsize: Size of the packet to generate and send. + """ + dest_mac = self.port_link_for_testing.sut_port.mac_address + # TODO: Need to create the packet and then send it and receive + + def test_scatter_mbuf_2048(self) -> None: + """ + Test: + Start testpmd and run functional test with preset mbsize. + """ + testpmd = self.sut_node.create_interactive_shell( + TestPmdShell, + app_parameters=f"--mbcache=200 \ + --mbuf-size={self.mbsize} \ + --portmask=0x1 \ + --max-pkt-len=9000 \ + --port-topology=loop \ + --tx-offloads=0x00008000" + ) + testpmd.send_command("set fwd mac") + testpmd.send_command("start") + link_is_up = testpmd.wait_link_status_up(self.port_link_for_testing.sut_port.id) + self.verify(link_is_up, "Link never came up in TestPMD.") + + for offset in [-1, 0, 1, 4, 5]: + self.scatter_pktgen_send_packet(self.mbsize + offset) + + testpmd.send_command("stop") + + def tear_down_suite(self) -> None: + self.tg_node.main_session.send_command( + f"ifconfig {self.port_link_for_testing.tg_port.logical_name} mtu 1500" + ) -- 2.41.0