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 04815459D8; Thu, 19 Sep 2024 20:16:28 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id DBAB5433C8; Thu, 19 Sep 2024 20:16:23 +0200 (CEST) Received: from mail-il1-f225.google.com (mail-il1-f225.google.com [209.85.166.225]) by mails.dpdk.org (Postfix) with ESMTP id E733A433C5 for ; Thu, 19 Sep 2024 20:16:21 +0200 (CEST) Received: by mail-il1-f225.google.com with SMTP id e9e14a558f8ab-3a07bd770e2so5400045ab.0 for ; Thu, 19 Sep 2024 11:16:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iol.unh.edu; s=unh-iol; t=1726769781; x=1727374581; darn=dpdk.org; h=mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:from:to:cc:subject:date:message-id:reply-to; bh=jA0US20cEP99p9KmBuy//g8oVIKBwAhbViEVg0pgYwI=; b=iIeM5M/Ha6QckY0l+hNGBD17nJEZtZjvmvxA8F5XTCrAmUob3iU82ztkNuzbYRjaKS 1fySlCIdD7PVbd0gbs2FlEBLGgWFyp30MkZ4s6EAb8cI5ef1NHmbMH03MWa6bG45A8cZ 6yXW9vnkBEZmOAliOS4IOtNs0N+FEbvV/HFUM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1726769781; x=1727374581; h=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=jA0US20cEP99p9KmBuy//g8oVIKBwAhbViEVg0pgYwI=; b=Nth4KAEbxkdbKvdfZykjX8rW2AU6nsy89YQVcIS1ERAQPgUmdvhbCqt5v8GeoYtRDs eKcrrt7//5JlwS0Uf0FP74EaRH+e/pq7nmDs4O3Iuia7eZDCrMtSkXynW0WXy9kaPFRw u+sOgbUFtg/bEv5odhs78IrWIeziX5pUGOoCK9YKox5uvKGlj35Y7Yw432LVz9hi2Zx6 jtY6XrSYHF4heH/ZP+YPV3gWWMT+XOY6vJG3C/ge+7Pvb6sp6YuUNNG5Bsip7z5EuAE7 OY/IV4PDeOrLk6DbBBQpZ1nrpVfiGSe6dN6I8fuLw2m3x1ju3ElemM3Re7I4J7iKJii8 o6fA== X-Gm-Message-State: AOJu0Yxb+toLFfA6AG6o1gr99WsPy6cie3kVTeHxUpTaJae/P3MdCfwC ueX7OEpCmeD7xFK2DYDUrAAuAmUkOJufSxUqY0hG7CQRi/O3YCr+UHdd9CZZjWR8y3yxjLiuVxi cwqqDoSx7FssOoKaJ3VQicAGPj3DiX0O+zRIfMEt5r+BwDZ+lfdb5vUePKAAzojokC8BPKNQHsZ A8Ujc= X-Google-Smtp-Source: AGHT+IE15Lscxxn0UsSiVtAf9Q7o69onTDgZX9NDn2H+VN3BaSf+3GzK00J9SGrezzMn6uW8tJwY4gcX+bDz X-Received: by 2002:a05:6e02:152a:b0:3a0:9b56:a69 with SMTP id e9e14a558f8ab-3a0c8c8e78fmr5333365ab.7.1726769781160; Thu, 19 Sep 2024 11:16:21 -0700 (PDT) Received: from postal.iol.unh.edu (postal.iol.unh.edu. [132.177.123.84]) by smtp-relay.gmail.com with ESMTPS id e9e14a558f8ab-3a0b6529be6sm1653485ab.4.2024.09.19.11.16.20 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Thu, 19 Sep 2024 11:16:21 -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 DD4D2605C352; Thu, 19 Sep 2024 14:16:19 -0400 (EDT) From: jspewock@iol.unh.edu To: alex.chapman@arm.com, npratte@iol.unh.edu, thomas@monjalon.net, Honnappa.Nagarahalli@arm.com, juraj.linkes@pantheon.tech, probb@iol.unh.edu, yoan.picchi@foss.arm.com, Luca.Vizzarro@arm.com, paul.szczepanek@arm.com, wathsala.vithanage@arm.com Cc: dev@dpdk.org, Jeremy Spewock Subject: [PATCH v2 1/1] dts: add binding to different drivers to TG node Date: Thu, 19 Sep 2024 14:16:11 -0400 Message-ID: <20240919181611.20289-2-jspewock@iol.unh.edu> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20240919181611.20289-1-jspewock@iol.unh.edu> References: <20240812172251.41131-1-jspewock@iol.unh.edu> <20240919181611.20289-1-jspewock@iol.unh.edu> MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" 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 | 39 ++++++-------------- dts/framework/testbed_model/tg_node.py | 21 +++++++++++ dts/framework/utils.py | 4 +- 5 files changed, 85 insertions(+), 30 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..6484e16a0f 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 + _remote_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._remote_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..d68270eee1 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" @@ -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.""" @@ -335,18 +335,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..25facb5e67 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 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_DPDK_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._remote_tmp_dir}") + self.main_session.copy_to( + PurePath(LOCAL_DPDK_DIR, "usertools", "dpdk-devbind.py"), + PurePath(self._remote_tmp_dir, "dpdk-devbind.py"), + ) + self._path_to_devbind_script = self.main_session.join_remote_path( + self._remote_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..fcc178e600 100644 --- a/dts/framework/utils.py +++ b/dts/framework/utils.py @@ -20,7 +20,7 @@ import random import subprocess from enum import Enum, Flag -from pathlib import Path +from pathlib import Path, PurePath from subprocess import SubprocessError from scapy.layers.inet import IP, TCP, UDP, Ether # type: ignore[import-untyped] @@ -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 DPDK directory on the host where DTS is being run. +LOCAL_DPDK_DIR: PurePath = PurePath(__file__).parents[2] def expand_range(range_str: str) -> list[int]: -- 2.46.0 -- *Let's Connect!* ... *October Webinars* Ask Us Anything: IOL Services Open Q&A Your questions. Our answers. Let's get started. Oct 3rd Live Tour of INTACT(R) for IPv6 Testing and Validation Open tour. Open Q&A. See why we think you'll love INTACT. Oct 9th How to Prep for Our NVMe(R) Plugfest #21 Checklists. Conversation. Let's get ready to plugin! Oct 15th ... * Newsletter* * * Get the IOL Connector for our latest news and event info. .