DPDK patches and discussions
 help / color / mirror / Atom feed
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


             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).