From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id B155645A1C; Tue, 24 Sep 2024 18:29:17 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id E4BB9402ED; Tue, 24 Sep 2024 18:29:12 +0200 (CEST) Received: from mail-pj1-f99.google.com (mail-pj1-f99.google.com [209.85.216.99]) by mails.dpdk.org (Postfix) with ESMTP id 4339A402EC for ; Tue, 24 Sep 2024 18:29:11 +0200 (CEST) Received: by mail-pj1-f99.google.com with SMTP id 98e67ed59e1d1-2d877e9054eso4013593a91.3 for ; Tue, 24 Sep 2024 09:29:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iol.unh.edu; s=unh-iol; t=1727195350; x=1727800150; darn=dpdk.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=uLPoVgF42BmnLEr5qhYw+dPApWL9wOAHp/vTUMzXSK8=; b=FjJI2kpq8YDvivwKfE0JG//O/8H9bDEXA5zLFycl04L5kiMs81E7mB482S1Ln8yEFO a5WwyJsLVdb4wGRBsUWyTzzbsop+V6/S2zzlGxwey7JlcqxA1st4pQOcRrQbgGs7NnQp cz+59CsrP/5DkrZ/oWfd1fOeM4QwMAbmZVJLE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727195350; x=1727800150; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=uLPoVgF42BmnLEr5qhYw+dPApWL9wOAHp/vTUMzXSK8=; b=FMaL5tnKFACWMYhEh0/yclQRjc4G9tXowJcji8KsX3GtD/EI6v2VzAlqQyrBSp1sTp Ak77a7NuwOVwpEuMPyeodDZCuczRCdwSsCSJ3Mlh8bq1WbfZLkkzj6uLMcCZtC+adfih XUsqhx4bZS/r9PQdieS9/jQzd+ZxWGkOJgIIjbEvinM5dxSToLg3fFmgzSjvhyN4l+2K tVyAizuchvjkI70YDOPMCE4o1FqEIgQHM2YuL0JqR9n2+5EZ9cQK6dgqf5aG9f3rM+VM ilKDe9kc8dMP0gJ41GusRZ0wBon45ZBCVwGytLZjUjPkGdEQqpGXRlb6GaU8z2aVMepI FxUw== X-Gm-Message-State: AOJu0YyHXZ+gllMR9C4QSA4Bc9ZAmLgNigopCl78mJ6t9j9fh+ECP14P nzkUD+9ldjPVePfIxtzdvVeo/u3waJxzZWmScD9RgDOiTxzz3kxU6lbi7D0hDZ09OblvDHmDJ9/ 0+ZqYsA5MnPEP7Ie5uICqqBtqwmnPpc6KeFWGpGra2WkMpzCe X-Google-Smtp-Source: AGHT+IEHlotmvCq0aR/cfP7tDfvUMuFV9yBKhKHN/4MfphecS1e6HN9W4uAQqKp8kGIks4kq7696/IvPiX1P X-Received: by 2002:a17:90a:e58a:b0:2da:da85:b705 with SMTP id 98e67ed59e1d1-2dd7f3e4cf1mr17904065a91.14.1727195350326; Tue, 24 Sep 2024 09:29:10 -0700 (PDT) Received: from postal.iol.unh.edu (postal.iol.unh.edu. [2606:4100:3880:1234::84]) by smtp-relay.gmail.com with ESMTPS id 98e67ed59e1d1-2dd6ef6b0cfsm696623a91.16.2024.09.24.09.29.09 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 24 Sep 2024 09:29:10 -0700 (PDT) X-Relaying-Domain: iol.unh.edu Received: from iol.unh.edu (unknown [IPv6:2606:4100:3880:1257::1083]) by postal.iol.unh.edu (Postfix) with ESMTP id 784DA605C352; Tue, 24 Sep 2024 12:29:08 -0400 (EDT) From: jspewock@iol.unh.edu To: paul.szczepanek@arm.com, probb@iol.unh.edu, thomas@monjalon.net, alex.chapman@arm.com, Honnappa.Nagarahalli@arm.com, wathsala.vithanage@arm.com, yoan.picchi@foss.arm.com, Luca.Vizzarro@arm.com, juraj.linkes@pantheon.tech, npratte@iol.unh.edu Cc: dev@dpdk.org, Jeremy Spewock Subject: [PATCH v3 2/2] dts: add binding to different drivers to TG node Date: Tue, 24 Sep 2024 12:28:42 -0400 Message-ID: <20240924162842.11714-3-jspewock@iol.unh.edu> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20240924162842.11714-1-jspewock@iol.unh.edu> References: <20240812172251.41131-1-jspewock@iol.unh.edu> <20240924162842.11714-1-jspewock@iol.unh.edu> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Jeremy Spewock The DTS framework in its current state supports binding ports to different drivers on the SUT node but not the TG node. The TG node already has the information that it needs about the different drivers that it has available in the configuration file, but it did not previously have access to the devbind script, so it did not use that information for anything. This patch moves the location of the tmp directory as well as the method for binding ports into the node class rather than the SUT node class and adds an abstract method for getting the path to the devbind script into the node class. Then, binding ports to the correct drivers is moved into the build target setup and run on both nodes. Bugzilla ID: 1420 Signed-off-by: Jeremy Spewock --- dts/framework/runner.py | 2 + dts/framework/testbed_model/node.py | 49 ++++++++++++++++++++++++- dts/framework/testbed_model/sut_node.py | 49 ++++++++----------------- dts/framework/testbed_model/tg_node.py | 21 +++++++++++ dts/framework/utils.py | 2 + 5 files changed, 88 insertions(+), 35 deletions(-) diff --git a/dts/framework/runner.py b/dts/framework/runner.py index ab98de8353..4c884fbcd4 100644 --- a/dts/framework/runner.py +++ b/dts/framework/runner.py @@ -486,6 +486,7 @@ def _run_build_target( try: sut_node.set_up_build_target(build_target_config) + tg_node.set_up_build_target(build_target_config) self._result.dpdk_version = sut_node.dpdk_version build_target_result.add_build_target_info(sut_node.get_build_target_info()) build_target_result.update_setup(Result.PASS) @@ -500,6 +501,7 @@ def _run_build_target( try: self._logger.set_stage(DtsStage.build_target_teardown) sut_node.tear_down_build_target() + tg_node.tear_down_build_target() build_target_result.update_teardown(Result.PASS) except Exception as e: self._logger.exception("Build target teardown failed.") diff --git a/dts/framework/testbed_model/node.py b/dts/framework/testbed_model/node.py index 12a40170ac..aa26f2a2a7 100644 --- a/dts/framework/testbed_model/node.py +++ b/dts/framework/testbed_model/node.py @@ -13,11 +13,18 @@ The :func:`~Node.skip_setup` decorator can be used without subclassing. """ -from abc import ABC + +from abc import ABC, abstractmethod from ipaddress import IPv4Interface, IPv6Interface +from pathlib import PurePath from typing import Any, Callable, Union -from framework.config import OS, NodeConfiguration, TestRunConfiguration +from framework.config import ( + OS, + BuildTargetConfiguration, + NodeConfiguration, + TestRunConfiguration, +) from framework.exception import ConfigurationError from framework.logger import DTSLogger, get_dts_logger from framework.settings import SETTINGS @@ -58,8 +65,10 @@ class Node(ABC): lcores: list[LogicalCore] ports: list[Port] _logger: DTSLogger + _tmp_dir: PurePath _other_sessions: list[OSSession] _test_run_config: TestRunConfiguration + _path_to_devbind_script: PurePath | None def __init__(self, node_config: NodeConfiguration): """Connect to the node and gather info during initialization. @@ -88,6 +97,8 @@ def __init__(self, node_config: NodeConfiguration): self._other_sessions = [] self._init_ports() + self._tmp_dir = self.main_session.get_remote_tmp_dir() + self._path_to_devbind_script = None def _init_ports(self) -> None: self.ports = [Port(self.name, port_config) for port_config in self.config.ports] @@ -95,6 +106,11 @@ def _init_ports(self) -> None: for port in self.ports: self.configure_port_state(port) + @property + @abstractmethod + def path_to_devbind_script(self) -> PurePath: + """The path to the dpdk-devbind.py script on the node.""" + def set_up_test_run(self, test_run_config: TestRunConfiguration) -> None: """Test run setup steps. @@ -114,6 +130,20 @@ def tear_down_test_run(self) -> None: Additional steps can be added by extending the method in subclasses with the use of super(). """ + def set_up_build_target(self, build_target_config: BuildTargetConfiguration) -> None: + """Bind ports to their DPDK drivers. + + Args: + build_target_config: The build target test run configuration according to which + the setup steps will be taken. This is unused in this method, but subclasses that + extend this method may need it. + """ + self.bind_ports_to_driver() + + def tear_down_build_target(self) -> None: + """Bind ports to their OS drivers.""" + self.bind_ports_to_driver(for_dpdk=False) + def create_session(self, name: str) -> OSSession: """Create and return a new OS-aware remote session. @@ -228,6 +258,21 @@ def skip_setup(func: Callable[..., Any]) -> Callable[..., Any]: else: return func + def bind_ports_to_driver(self, for_dpdk: bool = True) -> None: + """Bind all ports on the node to a driver. + + Args: + for_dpdk: If :data:`True`, binds ports to os_driver_for_dpdk. + If :data:`False`, binds to os_driver. + """ + for port in self.ports: + driver = port.os_driver_for_dpdk if for_dpdk else port.os_driver + self.main_session.send_command( + f"{self.path_to_devbind_script} -b {driver} --force {port.pci}", + privileged=True, + verify=True, + ) + def create_session(node_config: NodeConfiguration, name: str, logger: DTSLogger) -> OSSession: """Factory for OS-aware sessions. diff --git a/dts/framework/testbed_model/sut_node.py b/dts/framework/testbed_model/sut_node.py index 2855fe0276..8bd5c03f12 100644 --- a/dts/framework/testbed_model/sut_node.py +++ b/dts/framework/testbed_model/sut_node.py @@ -59,14 +59,12 @@ class SutNode(Node): dpdk_timestamp: str _build_target_config: BuildTargetConfiguration | None _env_vars: dict - _remote_tmp_dir: PurePath __remote_dpdk_dir: PurePath | None _app_compile_timeout: float _dpdk_kill_session: OSSession | None _dpdk_version: str | None _node_info: NodeInfo | None _compiler_version: str | None - _path_to_devbind_script: PurePath | None def __init__(self, node_config: SutNodeConfiguration): """Extend the constructor with SUT node specifics. @@ -79,7 +77,6 @@ def __init__(self, node_config: SutNodeConfiguration): self.dpdk_prefix_list = [] self._build_target_config = None self._env_vars = {} - self._remote_tmp_dir = self.main_session.get_remote_tmp_dir() self.__remote_dpdk_dir = None self._app_compile_timeout = 90 self._dpdk_kill_session = None @@ -89,7 +86,6 @@ def __init__(self, node_config: SutNodeConfiguration): self._dpdk_version = None self._node_info = None self._compiler_version = None - self._path_to_devbind_script = None self._logger.info(f"Created node: {self.name}") @property @@ -153,7 +149,11 @@ def compiler_version(self) -> str: @property def path_to_devbind_script(self) -> PurePath: - """The path to the dpdk-devbind.py script on the node.""" + """Implements :meth:`Node.path_to_devbind_script` on the SUT node. + + It is expected that the DPDK directory will be available on this host before this property + is accessed. + """ if self._path_to_devbind_script is None: self._path_to_devbind_script = self.main_session.join_remote_path( self._remote_dpdk_dir, "usertools", "dpdk-devbind.py" @@ -171,7 +171,7 @@ def get_build_target_info(self) -> BuildTargetInfo: ) def _guess_dpdk_remote_dir(self) -> PurePath: - return self.main_session.guess_dpdk_remote_dir(self._remote_tmp_dir) + return self.main_session.guess_dpdk_remote_dir(self._tmp_dir) def set_up_test_run(self, test_run_config: TestRunConfiguration) -> None: """Extend the test run setup with vdev config. @@ -190,28 +190,28 @@ def tear_down_test_run(self) -> None: self.virtual_devices = [] def set_up_build_target(self, build_target_config: BuildTargetConfiguration) -> None: - """Set up DPDK the SUT node and bind ports. + """Extend :meth:`Node.set_up_build_target` with DPDK setup steps. DPDK setup includes setting all internals needed for the build, the copying of DPDK tarball - and then building DPDK. The drivers are bound to those that DPDK needs. + and then building DPDK. Args: build_target_config: The build target test run configuration according to which the setup steps will be taken. """ - self._configure_build_target(build_target_config) self._copy_dpdk_tarball() + super().set_up_build_target(build_target_config) + self._configure_build_target(build_target_config) self._build_dpdk() - self.bind_ports_to_driver() def tear_down_build_target(self) -> None: - """Reset DPDK variables and bind port driver to the OS driver.""" + """Extend :meth:`Node.tear_down_build_target` with the resetting of DPDK variables.""" + super().tear_down_build_target() self._env_vars = {} - self._build_target_config = None self.__remote_dpdk_dir = None + self._build_target_config = None self._dpdk_version = None self._compiler_version = None - self.bind_ports_to_driver(for_dpdk=False) def _configure_build_target(self, build_target_config: BuildTargetConfiguration) -> None: """Populate common environment variables and set build target config.""" @@ -228,20 +228,18 @@ def _configure_build_target(self, build_target_config: BuildTargetConfiguration) def _copy_dpdk_tarball(self) -> None: """Copy to and extract DPDK tarball on the SUT node.""" self._logger.info("Copying DPDK tarball to SUT.") - self.main_session.copy_to(SETTINGS.dpdk_tarball_path, self._remote_tmp_dir) + self.main_session.copy_to(SETTINGS.dpdk_tarball_path, self._tmp_dir) # construct remote tarball path # the basename is the same on local host and on remote Node remote_tarball_path = self.main_session.join_remote_path( - self._remote_tmp_dir, os.path.basename(SETTINGS.dpdk_tarball_path) + self._tmp_dir, os.path.basename(SETTINGS.dpdk_tarball_path) ) # construct remote path after extracting with tarfile.open(SETTINGS.dpdk_tarball_path) as dpdk_tar: dpdk_top_dir = dpdk_tar.getnames()[0] - self._remote_dpdk_dir = self.main_session.join_remote_path( - self._remote_tmp_dir, dpdk_top_dir - ) + self._remote_dpdk_dir = self.main_session.join_remote_path(self._tmp_dir, dpdk_top_dir) self._logger.info( f"Extracting DPDK tarball on SUT: " @@ -335,18 +333,3 @@ def configure_ipv4_forwarding(self, enable: bool) -> None: enable: If :data:`True`, enable the forwarding, otherwise disable it. """ self.main_session.configure_ipv4_forwarding(enable) - - def bind_ports_to_driver(self, for_dpdk: bool = True) -> None: - """Bind all ports on the SUT to a driver. - - Args: - for_dpdk: If :data:`True`, binds ports to os_driver_for_dpdk. - If :data:`False`, binds to os_driver. - """ - for port in self.ports: - driver = port.os_driver_for_dpdk if for_dpdk else port.os_driver - self.main_session.send_command( - f"{self.path_to_devbind_script} -b {driver} --force {port.pci}", - privileged=True, - verify=True, - ) diff --git a/dts/framework/testbed_model/tg_node.py b/dts/framework/testbed_model/tg_node.py index 19b5b6e74c..45873b359f 100644 --- a/dts/framework/testbed_model/tg_node.py +++ b/dts/framework/testbed_model/tg_node.py @@ -9,12 +9,15 @@ A TG node is where the TG runs. """ +from pathlib import Path, PurePath + from scapy.packet import Packet # type: ignore[import-untyped] from framework.config import TGNodeConfiguration from framework.testbed_model.traffic_generator.capturing_traffic_generator import ( PacketFilteringConfig, ) +from framework.utils import LOCAL_DTS_DIR from .node import Node from .port import Port @@ -51,6 +54,24 @@ def __init__(self, node_config: TGNodeConfiguration): self.traffic_generator = create_traffic_generator(self, node_config.traffic_generator) self._logger.info(f"Created node: {self.name}") + @property + def path_to_devbind_script(self) -> PurePath: + """Implements :meth:`Node.path_to_devbind_script` on the TG node. + + For traffic generators this script is only copied onto the host when needed by the + framework. + """ + if self._path_to_devbind_script is None: + self._logger.info(f"Copying dpdk-devbind script into {self._tmp_dir}") + self.main_session.copy_to( + Path(LOCAL_DTS_DIR, "dpdk-devbind.py"), + PurePath(self._tmp_dir, "dpdk-devbind.py"), + ) + self._path_to_devbind_script = self.main_session.join_remote_path( + self._tmp_dir, "dpdk-devbind.py" + ) + return self._path_to_devbind_script + def send_packets_and_capture( self, packets: list[Packet], diff --git a/dts/framework/utils.py b/dts/framework/utils.py index c768dd0c99..9056b2245f 100644 --- a/dts/framework/utils.py +++ b/dts/framework/utils.py @@ -29,6 +29,8 @@ from .exception import ConfigurationError, InternalError REGEX_FOR_PCI_ADDRESS: str = "/[0-9a-fA-F]{4}:[0-9a-fA-F]{2}:[0-9a-fA-F]{2}.[0-9]{1}/" +#: Path to the DTS directory on the host where DTS is being run. +LOCAL_DTS_DIR: Path = Path(__file__).parents[1] def expand_range(range_str: str) -> list[int]: -- 2.46.0