From: Andrew Bailey <abailey@iol.unh.edu>
To: luca.vizzarro@arm.com
Cc: dev@dpdk.org, dmarx@iol.unh.edu, probb@iol.unh.edu,
Andrew Bailey <abailey@iol.unh.edu>
Subject: [PATCH 1/2] dts: introduce abstract class for TG and SUT DPDK runtime environments
Date: Fri, 8 Aug 2025 14:21:08 -0400 [thread overview]
Message-ID: <20250808182152.356879-1-abailey@iol.unh.edu> (raw)
DPDK runtime environment has logic in methods for two modes of use, one
for TG environments and one for SUT environments. TG nodes utilizing
these methods only require a single class attribute that DPDK runtime
environment holds. TG nodes using these methods do not require the
overhead of a new DPDK runtime evironment.
Lift shared methods into a new abstract class and split the existing
runtime class into SUT and TG specific runtime classes.
Signed-off-by: Andrew Bailey <abailey@iol.unh.edu>
---
dts/framework/context.py | 4 +-
dts/framework/remote_session/dpdk.py | 151 ++++++++++++++++++---------
dts/framework/test_run.py | 9 +-
3 files changed, 110 insertions(+), 54 deletions(-)
diff --git a/dts/framework/context.py b/dts/framework/context.py
index 4360bc8699..086f07e0e9 100644
--- a/dts/framework/context.py
+++ b/dts/framework/context.py
@@ -15,7 +15,7 @@
from framework.testbed_model.topology import Topology
if TYPE_CHECKING:
- from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
+ from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKSUTRuntimeEnvironment
from framework.testbed_model.traffic_generator.traffic_generator import TrafficGenerator
P = ParamSpec("P")
@@ -68,7 +68,7 @@ class Context:
tg_node: Node
topology: Topology
dpdk_build: "DPDKBuildEnvironment"
- dpdk: "DPDKRuntimeEnvironment"
+ dpdk: "DPDKSUTRuntimeEnvironment"
tg: "TrafficGenerator"
local: LocalContext = field(default_factory=LocalContext)
shell_pool: ShellPool = field(default_factory=ShellPool)
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index 606d6e22fe..8e45da4bd5 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -7,6 +7,7 @@
import os
import time
+from abc import ABC, abstractmethod
from collections.abc import Iterable
from dataclasses import dataclass
from functools import cached_property
@@ -302,14 +303,83 @@ def get_dpdk_build_info(self) -> DPDKBuildInfo:
return DPDKBuildInfo(dpdk_version=self.dpdk_version, compiler_version=self.compiler_version)
-class DPDKRuntimeEnvironment:
- """Class handling a DPDK runtime environment."""
+class DPDKRuntimeEnvironment(ABC):
+ """Shared methods between TG and SUT runtimes."""
- config: Final[DPDKRuntimeConfiguration]
- build: Final[DPDKBuildEnvironment | None]
_node: Final[Node]
+
+ def __init__(self, node: Node):
+ """DPDK runtime environment constructor.
+
+ Args:
+ node: The target node to manage a DPDK environment.
+ """
+ self._node = node
+
+ @abstractmethod
+ def _prepare_devbind_script(self):
+ """Prepare the devbind script.
+
+ This script is only available for Linux, if the detected session is not Linux then do
+ nothing.
+
+ Raises:
+ InternalError: If dpdk-devbind.py could not be found.
+ """
+
+ @abstractmethod
+ def setup(self) -> None:
+ """Set up the DPDK runtime on the target node."""
+
+
+class DPDKTGRuntimeEnvironment(DPDKRuntimeEnvironment):
+ """Class handling a DPDK runtime environment for a TG."""
+
+ def __init__(self, node: Node):
+ """DPDK TG environment constructor.
+
+ Args:
+ node: The target node to manage a DPDK environment.
+ """
+ super().__init__(node)
+
+ def setup(self) -> None:
+ """Set up the DPDK runtime on the target node."""
+ self._prepare_devbind_script()
+
+ def _prepare_devbind_script(self) -> None:
+ """Prepare the devbind script.
+
+ Copy the script build from the local repository.
+
+ This script is only available for Linux, if the detected session is not Linux then do
+ nothing.
+
+ Raises:
+ InternalError: If dpdk-devbind.py could not be found.
+ """
+ if not isinstance(self._node.main_session, LinuxSession):
+ return
+
+ local_script_path = Path("..", "usertools", "dpdk-devbind.py").resolve()
+ if not local_script_path.exists():
+ raise InternalError("Could not find dpdk-devbind.py locally.")
+
+ devbind_script_path = self._node.main_session.join_remote_path(
+ self._node.tmp_dir, local_script_path.name
+ )
+
+ self._node.main_session.copy_to(local_script_path, devbind_script_path)
+ self._node.main_session.devbind_script_path = devbind_script_path
+
+
+class DPDKSUTRuntimeEnvironment(DPDKRuntimeEnvironment):
+ """Class handling a DPDK runtime environment for a SUT."""
+
+ config: Final[DPDKRuntimeConfiguration]
_logger: Final[DTSLogger]
+ build: Final[DPDKBuildEnvironment]
timestamp: Final[str]
_virtual_devices: list[VirtualDevice]
_lcores: list[LogicalCore]
@@ -322,18 +392,18 @@ def __init__(
self,
config: DPDKRuntimeConfiguration,
node: Node,
- build_env: DPDKBuildEnvironment | None = None,
+ build_env: DPDKBuildEnvironment,
):
- """DPDK environment constructor.
+ """DPDK SUT environment constructor.
Args:
config: The configuration of DPDK.
node: The target node to manage a DPDK environment.
- build_env: The DPDK build environment, if any.
+ build_env: The DPDK build environment.
"""
- self.config = config
+ super().__init__(node)
self.build = build_env
- self._node = node
+ self.config = config
self._logger = get_dts_logger()
self.timestamp = f"{str(os.getpid())}_{time.strftime('%Y%m%d%H%M%S', time.localtime())}"
@@ -354,17 +424,11 @@ def __init__(
self._ports_bound_to_dpdk = False
self._kill_session = None
- def setup(self):
+ def setup(self) -> None:
"""Set up the DPDK runtime on the target node."""
- if self.build:
- self.build.setup()
+ self.build.setup()
self._prepare_devbind_script()
- def teardown(self) -> None:
- """Reset DPDK variables and bind port driver to the OS driver."""
- if self.build:
- self.build.teardown()
-
def run_dpdk_app(
self, app_path: PurePath, eal_params: EalParams, timeout: float = 30
) -> CommandResult:
@@ -385,38 +449,6 @@ def run_dpdk_app(
f"{app_path} {eal_params}", timeout, privileged=True, verify=True
)
- def _prepare_devbind_script(self) -> None:
- """Prepare the devbind script.
-
- If the environment has a build associated with it, then use the script within that build's
- tree. Otherwise, copy the script from the local repository.
-
- This script is only available for Linux, if the detected session is not Linux then do
- nothing.
-
- Raises:
- InternalError: If dpdk-devbind.py could not be found.
- """
- if not isinstance(self._node.main_session, LinuxSession):
- return
-
- if self.build:
- devbind_script_path = self._node.main_session.join_remote_path(
- self.build.remote_dpdk_tree_path, "usertools", "dpdk-devbind.py"
- )
- else:
- local_script_path = Path("..", "usertools", "dpdk-devbind.py").resolve()
- if not local_script_path.exists():
- raise InternalError("Could not find dpdk-devbind.py locally.")
-
- devbind_script_path = self._node.main_session.join_remote_path(
- self._node.tmp_dir, local_script_path.name
- )
-
- self._node.main_session.copy_to(local_script_path, devbind_script_path)
-
- self._node.main_session.devbind_script_path = devbind_script_path
-
def filter_lcores(
self,
filter_specifier: LogicalCoreCount | LogicalCoreList,
@@ -459,3 +491,24 @@ def kill_cleanup_dpdk_apps(self) -> None:
def get_virtual_devices(self) -> Iterable[VirtualDevice]:
"""The available DPDK virtual devices."""
return (v for v in self._virtual_devices)
+
+ def _prepare_devbind_script(self) -> None:
+ """Prepare the devbind script.
+
+ Use the script within the associated build's tree.
+
+ This script is only available for Linux, if the detected session is not Linux then do
+ nothing.
+ """
+ if not isinstance(self._node.main_session, LinuxSession):
+ return
+
+ devbind_script_path = self._node.main_session.join_remote_path(
+ self.build.remote_dpdk_tree_path, "usertools", "dpdk-devbind.py"
+ )
+
+ self._node.main_session.devbind_script_path = devbind_script_path
+
+ def teardown(self) -> None:
+ """Reset DPDK variables and bind port driver to the OS driver."""
+ self.build.teardown()
diff --git a/dts/framework/test_run.py b/dts/framework/test_run.py
index 4355aeeb4b..274dceebfd 100644
--- a/dts/framework/test_run.py
+++ b/dts/framework/test_run.py
@@ -111,7 +111,10 @@
from framework.context import Context, init_ctx
from framework.exception import InternalError, SkippedTestException, TestCaseVerifyError
from framework.logger import DTSLogger, get_dts_logger
-from framework.remote_session.dpdk import DPDKBuildEnvironment, DPDKRuntimeEnvironment
+from framework.remote_session.dpdk import (
+ DPDKBuildEnvironment,
+ DPDKSUTRuntimeEnvironment,
+)
from framework.settings import SETTINGS
from framework.test_result import Result, ResultNode, TestRunResult
from framework.test_suite import BaseConfig, TestCase, TestSuite
@@ -199,11 +202,11 @@ def __init__(
)
dpdk_build_env = DPDKBuildEnvironment(config.dpdk.build, sut_node)
- dpdk_runtime_env = DPDKRuntimeEnvironment(config.dpdk, sut_node, dpdk_build_env)
+ dpdk_sut_runtime_env = DPDKSUTRuntimeEnvironment(config.dpdk, sut_node, dpdk_build_env)
traffic_generator = create_traffic_generator(config.traffic_generator, tg_node)
self.ctx = Context(
- sut_node, tg_node, topology, dpdk_build_env, dpdk_runtime_env, traffic_generator
+ sut_node, tg_node, topology, dpdk_build_env, dpdk_sut_runtime_env, traffic_generator
)
self.result = result
self.selected_tests = list(self.config.filter_tests(tests_config))
--
2.50.1
next reply other threads:[~2025-08-08 18:22 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-08 18:21 Andrew Bailey [this message]
2025-08-08 18:21 ` [PATCH 2/2] dts: enable port binding on the TG Andrew Bailey
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250808182152.356879-1-abailey@iol.unh.edu \
--to=abailey@iol.unh.edu \
--cc=dev@dpdk.org \
--cc=dmarx@iol.unh.edu \
--cc=luca.vizzarro@arm.com \
--cc=probb@iol.unh.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).