From patchwork Mon Aug 12 17:22:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeremy Spewock X-Patchwork-Id: 143101 X-Patchwork-Delegate: juraj.linkes@pantheon.tech Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id C88BA457A3; Mon, 12 Aug 2024 19:23:28 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 7C83B40BA5; Mon, 12 Aug 2024 19:23:27 +0200 (CEST) Received: from mail-pl1-f227.google.com (mail-pl1-f227.google.com [209.85.214.227]) by mails.dpdk.org (Postfix) with ESMTP id AAC7940BA5 for ; Mon, 12 Aug 2024 19:23:25 +0200 (CEST) Received: by mail-pl1-f227.google.com with SMTP id d9443c01a7336-1fd640a6454so34804375ad.3 for ; Mon, 12 Aug 2024 10:23:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=iol.unh.edu; s=unh-iol; t=1723483404; x=1724088204; 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=X1GxgMCwjUOSXJ6AzQeB2RUHJCsWsuAhXWemy9CNW3U=; b=RCGN5zS1szXQwR0EW85eUhYgnAvWowI37ftEzsVue3raUtLaT0ZzXbtmBuwLgnW5iH Os4Z+kdZsa1WgOqx28pFL2VR25M+CjlApSGnKuyjkRs9cscBKWrx9WmBSVJ7Hp8F95jN Qesel4/GTcPv0dqkVsr0sA9YwsSDWkMH7HNQ0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723483404; x=1724088204; 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=X1GxgMCwjUOSXJ6AzQeB2RUHJCsWsuAhXWemy9CNW3U=; b=krHNubUsc8MyTg5kFQG+luXKipbl00dk48hzH3DBnnX+syRnod7I0jGLgj0+AFwaY+ T2UaUa+bYaRGis4/Mzq9vDoVSCvrTnX6oR5Pms2/ZyVXFKrojezcHutWJn1i4h+JkP7p Yk1Kpj2j1On7VpD1onF0QODTpMlX2xjcllm5GFJlXoYWtAhYa+srHWilwlk8sT03/Zfa fk4n7H6Li+FAp+vZMISeUxpcB99CsThZa4afjEhFGeEQAXCuLYmthFr0u4p52DsBVlLc poDDbBBS/8h9irEdeAM74xYdbiTGywHR2vbjPrJchgFSjmCbMzD0EY2SY0OzDQpUa93e d50g== X-Gm-Message-State: AOJu0Yxcw04pm7QYGG2Ev+aLBE+jEh00RIPtm5kthlg6Bs5yKSZu6sIl PQ2nJ6+C09IuLEKycnc9L5RjJ5knJHyzu5OigyBA2DAMzRWsig9apN4/6ej0QFFqaqgGs1lZQCz TWJe63kXPYDM50KD4MYLdPJlGZNWOLcIp X-Google-Smtp-Source: AGHT+IH0z7Qrow4/qCTElgC2B6foO2aw+0MpvN1jxJlL8671i8WkI+i60Iw7oe//2qpAXZ0eXD1n8ZvClDmr X-Received: by 2002:a17:902:f54b:b0:200:69e8:7e3c with SMTP id d9443c01a7336-201ca1c86bfmr11136895ad.49.1723483404353; Mon, 12 Aug 2024 10:23:24 -0700 (PDT) Received: from postal.iol.unh.edu (postal.iol.unh.edu. [132.177.123.84]) by smtp-relay.gmail.com with ESMTPS id d9443c01a7336-200bb914059sm2847595ad.63.2024.08.12.10.23.24 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 12 Aug 2024 10:23:24 -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 B7E1F605C380; Mon, 12 Aug 2024 13:23:22 -0400 (EDT) From: jspewock@iol.unh.edu To: alex.chapman@arm.com, Luca.Vizzarro@arm.com, wathsala.vithanage@arm.com, Honnappa.Nagarahalli@arm.com, juraj.linkes@pantheon.tech, paul.szczepanek@arm.com, npratte@iol.unh.edu, thomas@monjalon.net, yoan.picchi@foss.arm.com, probb@iol.unh.edu Cc: dev@dpdk.org, Jeremy Spewock Subject: [PATCH 1/1] dts: add binding to different drivers to TG node Date: Mon, 12 Aug 2024 13:22:51 -0400 Message-ID: <20240812172251.41131-2-jspewock@iol.unh.edu> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240812172251.41131-1-jspewock@iol.unh.edu> References: <20240812172251.41131-1-jspewock@iol.unh.edu> MIME-Version: 1.0 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 steps to copy the DPDK tarball into the node class rather than the SUT node class, and calls this function on the TG node as well as the SUT. It also moves the driver binding step into the Node class and triggers the same pattern of binding to ports that existed on the SUT on the TG. Bugzilla ID: 1420 Signed-off-by: Jeremy Spewock Reviewed-by: Nicholas Pratte Reviewed-by: Patrick Robb --- dts/framework/runner.py | 2 + dts/framework/testbed_model/node.py | 106 +++++++++++++++++++++++- dts/framework/testbed_model/sut_node.py | 86 +------------------ 3 files changed, 109 insertions(+), 85 deletions(-) diff --git a/dts/framework/runner.py b/dts/framework/runner.py index 6b6f6a05f5..ed9e58b172 100644 --- a/dts/framework/runner.py +++ b/dts/framework/runner.py @@ -484,6 +484,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) @@ -498,6 +499,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..8e6181e424 100644 --- a/dts/framework/testbed_model/node.py +++ b/dts/framework/testbed_model/node.py @@ -13,11 +13,19 @@ The :func:`~Node.skip_setup` decorator can be used without subclassing. """ +import os +import tarfile from abc import ABC 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 +66,11 @@ class Node(ABC): lcores: list[LogicalCore] ports: list[Port] _logger: DTSLogger + _remote_tmp_dir: PurePath + __remote_dpdk_dir: PurePath | None _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 +99,9 @@ def __init__(self, node_config: NodeConfiguration): self._other_sessions = [] self._init_ports() + self._remote_tmp_dir = self.main_session.get_remote_tmp_dir() + self.__remote_dpdk_dir = None + 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 +109,34 @@ def _init_ports(self) -> None: for port in self.ports: self.configure_port_state(port) + def _guess_dpdk_remote_dir(self) -> PurePath: + return self.main_session.guess_dpdk_remote_dir(self._remote_tmp_dir) + + @property + def _remote_dpdk_dir(self) -> PurePath: + """The remote DPDK dir. + + This internal property should be set after extracting the DPDK tarball. If it's not set, + that implies the DPDK setup step has been skipped, in which case we can guess where + a previous build was located. + """ + if self.__remote_dpdk_dir is None: + self.__remote_dpdk_dir = self._guess_dpdk_remote_dir() + return self.__remote_dpdk_dir + + @_remote_dpdk_dir.setter + def _remote_dpdk_dir(self, value: PurePath) -> None: + self.__remote_dpdk_dir = value + + @property + def path_to_devbind_script(self) -> PurePath: + """The path to the dpdk-devbind.py script on the node.""" + 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" + ) + return self._path_to_devbind_script + def set_up_test_run(self, test_run_config: TestRunConfiguration) -> None: """Test run setup steps. @@ -114,6 +156,24 @@ 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: + """Set up DPDK the node and bind ports. + + 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. + + Args: + build_target_config: The build target test run configuration according to which + the setup steps will be taken. + """ + self._copy_dpdk_tarball() + self.bind_ports_to_driver() + + def tear_down_build_target(self) -> None: + """Reset DPDK variables and bind port driver to the OS driver.""" + self.__remote_dpdk_dir = None + 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 +288,50 @@ def skip_setup(func: Callable[..., Any]) -> Callable[..., Any]: else: return func + @skip_setup + def _copy_dpdk_tarball(self) -> None: + """Copy to and extract DPDK tarball on the node.""" + self._logger.info(f"Copying DPDK tarball to {self.name}.") + self.main_session.copy_to(SETTINGS.dpdk_tarball_path, self._remote_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) + ) + + # 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._logger.info( + f"Extracting DPDK tarball on {self.name}: " + f"'{remote_tarball_path}' into '{self._remote_dpdk_dir}'." + ) + # clean remote path where we're extracting + self.main_session.remove_remote_dir(self._remote_dpdk_dir) + + # then extract to remote path + self.main_session.extract_remote_tarball(remote_tarball_path, self._remote_dpdk_dir) + + 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..f3fd4e2304 100644 --- a/dts/framework/testbed_model/sut_node.py +++ b/dts/framework/testbed_model/sut_node.py @@ -13,7 +13,6 @@ import os -import tarfile import time from pathlib import PurePath @@ -26,7 +25,6 @@ ) from framework.params.eal import EalParams from framework.remote_session.remote_session import CommandResult -from framework.settings import SETTINGS from framework.utils import MesonArgs from .node import Node @@ -59,14 +57,11 @@ 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,8 +74,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 self.dpdk_timestamp = ( @@ -89,25 +82,8 @@ 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 - def _remote_dpdk_dir(self) -> PurePath: - """The remote DPDK dir. - - This internal property should be set after extracting the DPDK tarball. If it's not set, - that implies the DPDK setup step has been skipped, in which case we can guess where - a previous build was located. - """ - if self.__remote_dpdk_dir is None: - self.__remote_dpdk_dir = self._guess_dpdk_remote_dir() - return self.__remote_dpdk_dir - - @_remote_dpdk_dir.setter - def _remote_dpdk_dir(self, value: PurePath) -> None: - self.__remote_dpdk_dir = value - @property def remote_dpdk_build_dir(self) -> PurePath: """The remote DPDK build directory. @@ -151,15 +127,6 @@ def compiler_version(self) -> str: return "" return self._compiler_version - @property - def path_to_devbind_script(self) -> PurePath: - """The path to the dpdk-devbind.py script on the node.""" - 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" - ) - return self._path_to_devbind_script - def get_build_target_info(self) -> BuildTargetInfo: """Get additional build target information. @@ -170,9 +137,6 @@ def get_build_target_info(self) -> BuildTargetInfo: dpdk_version=self.dpdk_version, compiler_version=self.compiler_version ) - def _guess_dpdk_remote_dir(self) -> PurePath: - return self.main_session.guess_dpdk_remote_dir(self._remote_tmp_dir) - def set_up_test_run(self, test_run_config: TestRunConfiguration) -> None: """Extend the test run setup with vdev config. @@ -199,19 +163,17 @@ def set_up_build_target(self, build_target_config: BuildTargetConfiguration) -> build_target_config: The build target test run configuration according to which the setup steps will be taken. """ + super().set_up_build_target(build_target_config) self._configure_build_target(build_target_config) - self._copy_dpdk_tarball() 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.""" + super().tear_down_build_target() self._env_vars = {} self._build_target_config = None - self.__remote_dpdk_dir = 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.""" @@ -224,35 +186,6 @@ def _configure_build_target(self, build_target_config: BuildTargetConfiguration) f"'{build_target_config.compiler_wrapper} {build_target_config.compiler.name}'" ) # fmt: skip - @Node.skip_setup - 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) - - # 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) - ) - - # 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._logger.info( - f"Extracting DPDK tarball on SUT: " - f"'{remote_tarball_path}' into '{self._remote_dpdk_dir}'." - ) - # clean remote path where we're extracting - self.main_session.remove_remote_dir(self._remote_dpdk_dir) - - # then extract to remote path - self.main_session.extract_remote_tarball(remote_tarball_path, self._remote_dpdk_dir) - @Node.skip_setup def _build_dpdk(self) -> None: """Build DPDK. @@ -335,18 +268,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, - )