DPDK patches and discussions
 help / color / mirror / Atom feed
From: Luca Vizzarro <luca.vizzarro@arm.com>
To: dev@dpdk.org
Cc: Nicholas Pratte <npratte@iol.unh.edu>,
	Luca Vizzarro <luca.vizzarro@arm.com>,
	Paul Szczepanek <paul.szczepanek@arm.com>,
	Patrick Robb <probb@iol.unh.edu>
Subject: [PATCH v3 4/7] dts: rework DPDK attributes in SUT node config
Date: Wed, 15 Jan 2025 14:18:06 +0000	[thread overview]
Message-ID: <20250115141809.3898708-5-luca.vizzarro@arm.com> (raw)
In-Reply-To: <20250115141809.3898708-1-luca.vizzarro@arm.com>

From: Nicholas Pratte <npratte@iol.unh.edu>

Rework 'lcores' and 'memory_channels' into a new 'dpdk_config'
subsection in an effort to make these attributes SUT specific; the
traffic generator, more often than not, does not need this information.
Ideally, if such information is needed, then it will be listed in the
'traffic_generator' component in TG Node configuration. Such logic is
not introduced in this patch, but the framework can be rewritten to do
so without any implications of extreme effort.

To make this work, use_first_core has been removed from the framework
entirely in favor of doing this within the LogicalCoreListFilter object.
Since use_first_core was only ever activated when logical core 0 was
explicitly defined, core 0 can be removed from the list of total logical
cores assuming that it was not listed within filter_specifier.

This patch also removes 'vdevs' from 'system_under_test_node' and moves
it into 'test_runs'.

Bugzilla ID: 1360

Signed-off-by: Nicholas Pratte <npratte@iol.unh.edu>
Signed-off-by: Luca Vizzarro <luca.vizzarro@arm.com>
Reviewed-by: Paul Szczepanek <paul.szczepanek@arm.com>
---
 dts/conf.yaml                                | 20 +++++-----
 dts/framework/config/__init__.py             | 39 ++++++++++----------
 dts/framework/runner.py                      |  6 +--
 dts/framework/testbed_model/cpu.py           |  6 ++-
 dts/framework/testbed_model/linux_session.py |  5 +--
 dts/framework/testbed_model/node.py          | 27 +-------------
 dts/framework/testbed_model/os_session.py    |  2 +-
 dts/framework/testbed_model/sut_node.py      | 14 ++++++-
 8 files changed, 54 insertions(+), 65 deletions(-)

diff --git a/dts/conf.yaml b/dts/conf.yaml
index c93eedbc94..bc78882d0d 100644
--- a/dts/conf.yaml
+++ b/dts/conf.yaml
@@ -26,12 +26,11 @@ test_runs:
     skip_smoke_tests: false # optional
     test_suites: # the following test suites will be run in their entirety
       - hello_world
+    vdevs: # optional; if removed, vdevs won't be used in the execution
+      - "crypto_openssl"
     # The machine running the DPDK test executable
-    system_under_test_node:
-      node_name: "SUT 1"
-      vdevs: # optional; if removed, vdevs won't be used in the test run
-        - "crypto_openssl"
-    # Traffic generator node to use for this test run
+    system_under_test_node: "SUT 1"
+    # Traffic generator node to use for this execution environment
     traffic_generator_node: "TG 1"
 nodes:
   # Define a system under test node, having two network ports physically
@@ -40,11 +39,6 @@ nodes:
     hostname: sut1.change.me.localhost
     user: dtsuser
     os: linux
-    lcores: "" # use all available logical cores (Skips first core)
-    memory_channels: 4 # tells DPDK to use 4 memory channels
-    hugepages_2mb: # optional; if removed, will use system hugepage configuration
-        number_of: 256
-        force_first_numa: false
     ports:
       # sets up the physical link between "SUT 1"@0000:00:08.0 and "TG 1"@0000:00:08.0
       - pci: "0000:00:08.0"
@@ -58,6 +52,12 @@ nodes:
         os_driver: i40e
         peer_node: "TG 1"
         peer_pci: "0000:00:08.1"
+    hugepages_2mb: # optional; if removed, will use system hugepage configuration
+        number_of: 256
+        force_first_numa: false
+    dpdk_config:
+        lcores: "" # use all available logical cores (Skips first core)
+        memory_channels: 4 # tells DPDK to use 4 memory channels
   # Define a Scapy traffic generator node, having two network ports
   # physically connected to the corresponding ports in SUT 1 (the peer node).
   - name: "TG 1"
diff --git a/dts/framework/config/__init__.py b/dts/framework/config/__init__.py
index 5dfa0cf0d4..2496f48e20 100644
--- a/dts/framework/config/__init__.py
+++ b/dts/framework/config/__init__.py
@@ -161,15 +161,23 @@ class NodeConfiguration(FrozenModel):
     password: str | None = None
     #: The operating system of the :class:`~framework.testbed_model.node.Node`.
     os: OS
-    #: A comma delimited list of logical cores to use when running DPDK. ```any```, an empty
-    #: string or omitting this field means use any core except for the first one. The first core
-    #: will only be used if explicitly set.
-    lcores: LogicalCores = ""
     #: An optional hugepage configuration.
     hugepages: HugepageConfiguration | None = Field(None, alias="hugepages_2mb")
     #: The ports that can be used in testing.
     ports: list[PortConfig] = Field(min_length=1)
 
+
+class DPDKConfiguration(FrozenModel):
+    """Configuration of the DPDK EAL parameters."""
+
+    #: A comma delimited list of logical cores to use when running DPDK. ```any```, an empty
+    #: string or omitting this field means use any core except for the first one. The first core
+    #: will only be used if explicitly set.
+    lcores: LogicalCores = ""
+
+    #: The number of memory channels to use when running DPDK.
+    memory_channels: int = 1
+
     @property
     def use_first_core(self) -> bool:
         """Returns :data:`True` if `lcores` explicitly selects the first core."""
@@ -179,8 +187,8 @@ def use_first_core(self) -> bool:
 class SutNodeConfiguration(NodeConfiguration):
     """:class:`~framework.testbed_model.sut_node.SutNode` specific configuration."""
 
-    #: The number of memory channels to use when running DPDK.
-    memory_channels: int = 1
+    #: The runtime configuration for DPDK.
+    dpdk_config: DPDKConfiguration
 
 
 class TGNodeConfiguration(NodeConfiguration):
@@ -405,15 +413,6 @@ def validate_names(self) -> Self:
         return self
 
 
-class TestRunSUTNodeConfiguration(FrozenModel):
-    """The SUT node configuration of a test run."""
-
-    #: The SUT node to use in this test run.
-    node_name: str
-    #: The names of virtual devices to test.
-    vdevs: list[str] = Field(default_factory=list)
-
-
 class TestRunConfiguration(FrozenModel):
     """The configuration of a test run.
 
@@ -431,10 +430,12 @@ class TestRunConfiguration(FrozenModel):
     skip_smoke_tests: bool = False
     #: The names of test suites and/or test cases to execute.
     test_suites: list[TestSuiteConfig] = Field(min_length=1)
-    #: The SUT node configuration to use in this test run.
-    system_under_test_node: TestRunSUTNodeConfiguration
+    #: The SUT node name to use in this test run.
+    system_under_test_node: str
     #: The TG node name to use in this test run.
     traffic_generator_node: str
+    #: The names of virtual devices to test.
+    vdevs: list[str] = Field(default_factory=list)
     #: The seed to use for pseudo-random generation.
     random_seed: int | None = None
 
@@ -464,12 +465,12 @@ def test_runs_with_nodes(self) -> list[TestRunWithNodesConfiguration]:
         test_runs_with_nodes = []
 
         for test_run_no, test_run in enumerate(self.test_runs):
-            sut_node_name = test_run.system_under_test_node.node_name
+            sut_node_name = test_run.system_under_test_node
             sut_node = next(filter(lambda n: n.name == sut_node_name, self.nodes), None)
 
             assert sut_node is not None, (
                 f"test_runs.{test_run_no}.sut_node_config.node_name "
-                f"({test_run.system_under_test_node.node_name}) is not a valid node name"
+                f"({test_run.system_under_test_node}) is not a valid node name"
             )
             assert isinstance(sut_node, SutNodeConfiguration), (
                 f"test_runs.{test_run_no}.sut_node_config.node_name is a valid node name, "
diff --git a/dts/framework/runner.py b/dts/framework/runner.py
index 510be1a870..0cdbb07e06 100644
--- a/dts/framework/runner.py
+++ b/dts/framework/runner.py
@@ -277,7 +277,7 @@ def _connect_nodes_and_run_test_run(
                 tg_node = TGNode(tg_node_config)
                 tg_nodes[tg_node.name] = tg_node
         except Exception as e:
-            failed_node = test_run_config.system_under_test_node.node_name
+            failed_node = test_run_config.system_under_test_node
             if sut_node:
                 failed_node = test_run_config.traffic_generator_node
             self._logger.exception(f"The Creation of node {failed_node} failed.")
@@ -315,9 +315,7 @@ def _run_test_run(
         Raises:
             ConfigurationError: If the DPDK sources or build is not set up from config or settings.
         """
-        self._logger.info(
-            f"Running test run with SUT '{test_run_config.system_under_test_node.node_name}'."
-        )
+        self._logger.info(f"Running test run with SUT '{test_run_config.system_under_test_node}'.")
         test_run_result.ports = sut_node.ports
         test_run_result.sut_info = sut_node.node_info
         try:
diff --git a/dts/framework/testbed_model/cpu.py b/dts/framework/testbed_model/cpu.py
index d19fa5d597..b8bc601c22 100644
--- a/dts/framework/testbed_model/cpu.py
+++ b/dts/framework/testbed_model/cpu.py
@@ -185,7 +185,6 @@ def __init__(
 
         # sorting by core is needed in case hyperthreading is enabled
         self._lcores_to_filter = sorted(lcore_list, key=lambda x: x.core, reverse=not ascending)
-        self.filter()
 
     @abstractmethod
     def filter(self) -> list[LogicalCore]:
@@ -228,6 +227,8 @@ def filter(self) -> list[LogicalCore]:
         Returns:
             The filtered cores.
         """
+        if 0 in self._lcores_to_filter:
+            self._lcores_to_filter = self._lcores_to_filter[1:]
         sockets_to_filter = self._filter_sockets(self._lcores_to_filter)
         filtered_lcores = []
         for socket_to_filter in sockets_to_filter:
@@ -356,6 +357,9 @@ def filter(self) -> list[LogicalCore]:
         Raises:
             ValueError: If the specified lcore filter specifier is invalid.
         """
+        if 0 not in self._filter_specifier.lcore_list:
+            self._lcores_to_filter = self._lcores_to_filter[1:]
+
         if not len(self._filter_specifier.lcore_list):
             return self._lcores_to_filter
 
diff --git a/dts/framework/testbed_model/linux_session.py b/dts/framework/testbed_model/linux_session.py
index bda2d448f7..396bdbd890 100644
--- a/dts/framework/testbed_model/linux_session.py
+++ b/dts/framework/testbed_model/linux_session.py
@@ -67,15 +67,12 @@ class LinuxSession(PosixSession):
     def _get_privileged_command(command: str) -> str:
         return f"sudo -- sh -c '{command}'"
 
-    def get_remote_cpus(self, use_first_core: bool) -> list[LogicalCore]:
+    def get_remote_cpus(self) -> list[LogicalCore]:
         """Overrides :meth:`~.os_session.OSSession.get_remote_cpus`."""
         cpu_info = self.send_command("lscpu -p=CPU,CORE,SOCKET,NODE|grep -v \\#").stdout
         lcores = []
         for cpu_line in cpu_info.splitlines():
             lcore, core, socket, node = map(int, cpu_line.split(","))
-            if core == 0 and socket == 0 and not use_first_core:
-                self._logger.info("Not using the first physical core.")
-                continue
             lcores.append(LogicalCore(lcore, core, socket, node))
         return lcores
 
diff --git a/dts/framework/testbed_model/node.py b/dts/framework/testbed_model/node.py
index b08b1cf14d..6c2dfd6185 100644
--- a/dts/framework/testbed_model/node.py
+++ b/dts/framework/testbed_model/node.py
@@ -24,14 +24,7 @@
 from framework.exception import ConfigurationError
 from framework.logger import DTSLogger, get_dts_logger
 
-from .cpu import (
-    Architecture,
-    LogicalCore,
-    LogicalCoreCount,
-    LogicalCoreList,
-    LogicalCoreListFilter,
-    lcore_filter,
-)
+from .cpu import Architecture, LogicalCore, LogicalCoreCount, LogicalCoreList, lcore_filter
 from .linux_session import LinuxSession
 from .os_session import OSSession
 from .port import Port
@@ -82,24 +75,8 @@ def __init__(self, node_config: NodeConfiguration):
         self._logger = get_dts_logger(self.name)
         self.main_session = create_session(self.config, self.name, self._logger)
         self.arch = Architecture(self.main_session.get_arch_info())
-
         self._logger.info(f"Connected to node: {self.name}")
-
         self._get_remote_cpus()
-        # filter the node lcores according to the test run configuration
-        self.lcores = LogicalCoreListFilter(
-            self.lcores, LogicalCoreList(self.config.lcores)
-        ).filter()
-
-        if LogicalCore(lcore=0, core=0, socket=0, node=0) in self.lcores:
-            self._logger.info(
-                """
-                WARNING: First core being used;
-                using the first core is considered risky and should only
-                be done by advanced users.
-                """
-            )
-
         self._other_sessions = []
         self._init_ports()
 
@@ -188,7 +165,7 @@ def filter_lcores(
     def _get_remote_cpus(self) -> None:
         """Scan CPUs in the remote OS and store a list of LogicalCores."""
         self._logger.info("Getting CPU information.")
-        self.lcores = self.main_session.get_remote_cpus(self.config.use_first_core)
+        self.lcores = self.main_session.get_remote_cpus()
 
     def _setup_hugepages(self) -> None:
         """Setup hugepages on the node.
diff --git a/dts/framework/testbed_model/os_session.py b/dts/framework/testbed_model/os_session.py
index fcda9b3de1..e436886692 100644
--- a/dts/framework/testbed_model/os_session.py
+++ b/dts/framework/testbed_model/os_session.py
@@ -445,7 +445,7 @@ def get_dpdk_version(self, version_path: str | PurePath) -> str:
         """
 
     @abstractmethod
-    def get_remote_cpus(self, use_first_core: bool) -> list[LogicalCore]:
+    def get_remote_cpus(self) -> list[LogicalCore]:
         r"""Get the list of :class:`~.cpu.LogicalCore`\s on the remote node.
 
         Args:
diff --git a/dts/framework/testbed_model/sut_node.py b/dts/framework/testbed_model/sut_node.py
index 11d4b22089..d8f1f9d452 100644
--- a/dts/framework/testbed_model/sut_node.py
+++ b/dts/framework/testbed_model/sut_node.py
@@ -33,6 +33,7 @@
 from framework.remote_session.remote_session import CommandResult
 from framework.utils import MesonArgs, TarCompressionFormat
 
+from .cpu import LogicalCore, LogicalCoreList
 from .node import Node
 from .os_session import OSSession, OSSessionInfo
 from .virtual_device import VirtualDevice
@@ -92,6 +93,17 @@ def __init__(self, node_config: SutNodeConfiguration):
             node_config: The SUT node's test run configuration.
         """
         super().__init__(node_config)
+        self.lcores = self.filter_lcores(LogicalCoreList(self.config.dpdk_config.lcores))
+        if LogicalCore(lcore=0, core=0, socket=0, node=0) in self.lcores:
+            self._logger.info(
+                """
+                WARNING: First core being used;
+                using the first core is considered risky and should only
+                be done by advanced users.
+                """
+            )
+        else:
+            self._logger.info("Not using first core")
         self.virtual_devices = []
         self.dpdk_prefix_list = []
         self._env_vars = {}
@@ -198,7 +210,7 @@ def set_up_test_run(
             dpdk_build_config: The build configuration of DPDK.
         """
         super().set_up_test_run(test_run_config, dpdk_build_config)
-        for vdev in test_run_config.system_under_test_node.vdevs:
+        for vdev in test_run_config.vdevs:
             self.virtual_devices.append(VirtualDevice(vdev))
         self._set_up_dpdk(dpdk_build_config)
 
-- 
2.43.0


  parent reply	other threads:[~2025-01-15 14:19 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-13 20:18 [PATCH 0/4] dts: Remove Excess Attributes From User Config Nicholas Pratte
2024-06-13 20:18 ` [PATCH 1/4] dts: Remove build target config and list of devices Nicholas Pratte
2024-06-14 18:07   ` Jeremy Spewock
2024-06-13 20:18 ` [PATCH 2/4] dts: Use First Core Logic Change Nicholas Pratte
2024-06-14 18:09   ` Jeremy Spewock
2024-06-20 13:41     ` Nicholas Pratte
2024-06-13 20:18 ` [PATCH 3/4] dts: Self-Discovering Architecture Change Nicholas Pratte
2024-06-14 18:09   ` Jeremy Spewock
2024-06-13 20:18 ` [PATCH 4/4] dts: Rework DPDK Attributes In SUT Node Config Nicholas Pratte
2024-06-14 18:11   ` Jeremy Spewock
2024-07-05 17:13 ` [PATCH v2 0/6] dts: Remove Excess Attributes From User Config Nicholas Pratte
2024-07-05 18:29   ` [PATCH v2 1/6] dts: Remove build target config and list of devices Nicholas Pratte
2024-11-06 19:29     ` Dean Marx
2024-07-05 18:31   ` [PATCH v2 2/6] dts: Use First Core Logic Change Nicholas Pratte
2024-11-06 19:48     ` Dean Marx
2024-07-05 18:32   ` [PATCH v2 3/6] dts: Self-Discovering Architecture Change Nicholas Pratte
2024-11-06 20:13     ` Dean Marx
2024-07-05 18:32   ` [PATCH v2 4/6] dts: Rework DPDK Attributes In SUT Node Config Nicholas Pratte
2024-11-06 20:32     ` Dean Marx
2024-07-05 18:33   ` [PATCH v2 5/6] dts: add conditional behavior for test suite Nicholas Pratte
2024-07-05 18:33   ` [PATCH v2 6/6] doc: dpdk documentation changes for new dts config Nicholas Pratte
2025-01-15 14:18   ` [PATCH v3 0/7] dts: refactor configuration Luca Vizzarro
2025-01-15 14:18     ` [PATCH v3 1/7] dts: enable arch self-discovery Luca Vizzarro
2025-01-15 14:18     ` [PATCH v3 2/7] dts: simplify build options config Luca Vizzarro
2025-01-15 14:18     ` [PATCH v3 3/7] dts: infer use first core without config Luca Vizzarro
2025-01-15 14:18     ` Luca Vizzarro [this message]
2025-01-15 14:18     ` [PATCH v3 5/7] dts: handle CLI overrides in the configuration Luca Vizzarro
2025-01-15 14:18     ` [PATCH v3 6/7] dts: split configuration file Luca Vizzarro
2025-01-15 14:18     ` [PATCH v3 7/7] dts: run all test suites by default Luca Vizzarro
2024-07-05 17:13 ` [PATCH v2 1/6] dts: Remove build target config and list of devices Nicholas Pratte
2024-07-16 15:07   ` Jeremy Spewock
2024-09-12 20:33     ` Nicholas Pratte
2024-09-10 11:30   ` Juraj Linkeš
2024-09-12 20:31     ` Nicholas Pratte
2024-11-18 16:51   ` Luca Vizzarro
2024-07-05 17:13 ` [PATCH v2 2/6] dts: Use First Core Logic Change Nicholas Pratte
2024-09-10 13:34   ` Juraj Linkeš
2024-11-18 16:54   ` Luca Vizzarro
2024-07-05 17:13 ` [PATCH v2 3/6] dts: Self-Discovering Architecture Change Nicholas Pratte
2024-09-10 13:41   ` Juraj Linkeš
2024-11-18 17:14   ` Luca Vizzarro
2024-07-05 17:13 ` [PATCH v2 4/6] dts: Rework DPDK Attributes In SUT Node Config Nicholas Pratte
2024-09-10 14:04   ` Juraj Linkeš
2024-11-18 17:16   ` Luca Vizzarro
2024-07-05 17:13 ` [PATCH v2 5/6] dts: add conditional behavior for test suite Nicholas Pratte
2024-07-16 14:59   ` Jeremy Spewock
2024-09-10 14:12   ` Juraj Linkeš
2024-11-06 20:52   ` Dean Marx
2024-11-18 17:21   ` Luca Vizzarro
2024-07-05 17:13 ` [PATCH v2 6/6] doc: dpdk documentation changes for new dts config Nicholas Pratte
2024-09-10 14:17   ` Juraj Linkeš
2024-11-06 20:57   ` Dean Marx
2024-11-18 17:21   ` Luca Vizzarro
2024-07-05 18:24 ` [PATCH v2 1/6] dts: Remove build target config and list of devices Nicholas Pratte

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=20250115141809.3898708-5-luca.vizzarro@arm.com \
    --to=luca.vizzarro@arm.com \
    --cc=dev@dpdk.org \
    --cc=npratte@iol.unh.edu \
    --cc=paul.szczepanek@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).