diff options
| author | Luca Vizzarro <[email protected]> | 2024-09-09 12:01:57 +0100 |
|---|---|---|
| committer | Juraj Linkeš <[email protected]> | 2024-09-09 17:43:41 +0200 |
| commit | 2ecfd1267a070ccf13c3f43841e14e62289acc1e (patch) | |
| tree | 01130b6ee71f8237ef0de314e348aab327ffc6a0 /dts/framework/remote_session/testpmd_shell.py | |
| parent | f51557fb27115ffa4487c5807ebca77023c3f484 (diff) | |
dts: add ability to start/stop testpmd ports
Add testpmd commands to start and stop all the ports, so that they can
be configured. Because there is a distinction of commands that require
the ports to be stopped and started, also add decorators for commands
that require a specific state, removing this logic from the test
writer's duty.
Signed-off-by: Luca Vizzarro <[email protected]>
Reviewed-by: Paul Szczepanek <[email protected]>
Reviewed-by: Juraj Linkeš <[email protected]>
Reviewed-by: Jeremy Spewock <[email protected]>
Diffstat (limited to 'dts/framework/remote_session/testpmd_shell.py')
| -rw-r--r-- | dts/framework/remote_session/testpmd_shell.py | 94 |
1 files changed, 92 insertions, 2 deletions
diff --git a/dts/framework/remote_session/testpmd_shell.py b/dts/framework/remote_session/testpmd_shell.py index 43e9f56517..fa818d7181 100644 --- a/dts/framework/remote_session/testpmd_shell.py +++ b/dts/framework/remote_session/testpmd_shell.py @@ -14,16 +14,17 @@ Typical usage example in a TestSuite:: testpmd_shell.close() """ +import functools import re import time from dataclasses import dataclass, field from enum import Flag, auto from pathlib import PurePath -from typing import ClassVar +from typing import Any, Callable, ClassVar, Concatenate, ParamSpec from typing_extensions import Self, Unpack -from framework.exception import InteractiveCommandExecutionError +from framework.exception import InteractiveCommandExecutionError, InternalError from framework.params.testpmd import SimpleForwardingModes, TestPmdParams from framework.params.types import TestPmdParamsDict from framework.parser import ParserFn, TextParser @@ -33,6 +34,9 @@ from framework.testbed_model.cpu import LogicalCoreCount, LogicalCoreList from framework.testbed_model.sut_node import SutNode from framework.utils import StrEnum +P = ParamSpec("P") +TestPmdShellMethod = Callable[Concatenate["TestPmdShell", P], Any] + class TestPmdDevice: """The data of a device that testpmd can recognize. @@ -577,12 +581,57 @@ class TestPmdPortStats(TextParser): tx_bps: int = field(metadata=TextParser.find_int(r"Tx-bps:\s+(\d+)")) +def requires_stopped_ports(func: TestPmdShellMethod) -> TestPmdShellMethod: + """Decorator for :class:`TestPmdShell` commands methods that require stopped ports. + + If the decorated method is called while the ports are started, then these are stopped before + continuing. + + Args: + func: The :class:`TestPmdShell` method to decorate. + """ + + @functools.wraps(func) + def _wrapper(self: "TestPmdShell", *args: P.args, **kwargs: P.kwargs): + if self.ports_started: + self._logger.debug("Ports need to be stopped to continue.") + self.stop_all_ports() + + return func(self, *args, **kwargs) + + return _wrapper + + +def requires_started_ports(func: TestPmdShellMethod) -> TestPmdShellMethod: + """Decorator for :class:`TestPmdShell` commands methods that require started ports. + + If the decorated method is called while the ports are stopped, then these are started before + continuing. + + Args: + func: The :class:`TestPmdShell` method to decorate. + """ + + @functools.wraps(func) + def _wrapper(self: "TestPmdShell", *args: P.args, **kwargs: P.kwargs): + if not self.ports_started: + self._logger.debug("Ports need to be started to continue.") + self.start_all_ports() + + return func(self, *args, **kwargs) + + return _wrapper + + class TestPmdShell(DPDKShell): """Testpmd interactive shell. The testpmd shell users should never use the :meth:`~.interactive_shell.InteractiveShell.send_command` method directly, but rather call specialized methods. If there isn't one that satisfies a need, it should be added. + + Attributes: + ports_started: Indicates whether the ports are started. """ _app_params: TestPmdParams @@ -596,6 +645,8 @@ class TestPmdShell(DPDKShell): #: This forces the prompt to appear after sending a command. _command_extra_chars: ClassVar[str] = "\n" + ports_started: bool + def __init__( self, node: SutNode, @@ -619,6 +670,9 @@ class TestPmdShell(DPDKShell): name, ) + self.ports_started = not self._app_params.disable_device_start + + @requires_started_ports def start(self, verify: bool = True) -> None: """Start packet forwarding with the current configuration. @@ -723,6 +777,42 @@ class TestPmdShell(DPDKShell): f"Test pmd failed to set fwd mode to {mode.value}" ) + def stop_all_ports(self, verify: bool = True) -> None: + """Stops all the ports. + + Args: + verify: If :data:`True`, the output of the command will be checked for a successful + execution. + + Raises: + InteractiveCommandExecutionError: If `verify` is :data:`True` and the ports were not + stopped successfully. + """ + self._logger.debug("Stopping all the ports...") + output = self.send_command("port stop all") + if verify and not output.strip().endswith("Done"): + raise InteractiveCommandExecutionError("Ports were not stopped successfully.") + + self.ports_started = False + + def start_all_ports(self, verify: bool = True) -> None: + """Starts all the ports. + + Args: + verify: If :data:`True`, the output of the command will be checked for a successful + execution. + + Raises: + InteractiveCommandExecutionError: If `verify` is :data:`True` and the ports were not + started successfully. + """ + self._logger.debug("Starting all the ports...") + output = self.send_command("port start all") + if verify and not output.strip().endswith("Done"): + raise InteractiveCommandExecutionError("Ports were not started successfully.") + + self.ports_started = True + def show_port_info_all(self) -> list[TestPmdPort]: """Returns the information of all the ports. |
