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 438E445830; Wed, 21 Aug 2024 16:53:57 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 05E8A4114B; Wed, 21 Aug 2024 16:53:28 +0200 (CEST) Received: from mail-lj1-f182.google.com (mail-lj1-f182.google.com [209.85.208.182]) by mails.dpdk.org (Postfix) with ESMTP id 459CB41143 for ; Wed, 21 Aug 2024 16:53:24 +0200 (CEST) Received: by mail-lj1-f182.google.com with SMTP id 38308e7fff4ca-2f3f163e379so27539581fa.3 for ; Wed, 21 Aug 2024 07:53:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pantheon.tech; s=google; t=1724252004; x=1724856804; 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=hYJEbeWbSMr0BoQOmMotFUlNe9bt88+mvzsiHxqUkAs=; b=b0FdxZIiIp/LpMHt/YNb6po8RHqGz+jexFpA5Jzl2ukb8C8gf3VCwvGydm8SJCmwtN O7tf7Ylv3VGj9NcaGZig83F77lViI6n8sGIQKMAaEDJK4QIDhCvmP5aJWZ+NDqackVsb JCAutCjmIAfBvjIu6sfO61HlT85cgMZ0GCGZCEFpA70JrG0HvigOpnJBMhRJP7CZYtni SW8wY9Swgs/p4OMcBri9ngR+FzW8OYONkQYHlEPI/SNhuE8kTrak3AYA281lGMS/psCm q//g/HqVuYR832W180LOgFqIjidbg1wgwpFzP8VewZsjxMtUT+EaKkTWu19ZLzWujJ3X DI+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1724252004; x=1724856804; 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=hYJEbeWbSMr0BoQOmMotFUlNe9bt88+mvzsiHxqUkAs=; b=cWrKd3WOlwjzRGHQhlDMj0XrvuoBSi3nt+KUjcUPn7orvhCnA07k4ZqMNnWA7HlDeF V7pQf6WMserFU/58deIM//rbEiW0XhfrUbDNMm6KT/VKr7TLEjXMc2kx4q6FNTb+kmCo wVzxvrDzRX5tj8SbrP3z2ZzRATJjFIlgDtJAZwAGTzWSl6ZUgdgX4HsHnminewX5OhV8 SD5GvqC0cieWkR742vflkoRLmiwcBQuvawySyF2OHe4GUQD+RVgImOHUtwac6KahLKIm +EhLK5Wn64hNu6fiXXd7L9NqQcgejixgjigFqIvGpqrPXG8KZ3JMLZ9H1srWKGPIcDZM 6N2w== X-Gm-Message-State: AOJu0YzO2eVH6H2TKqgwH3E1Y85uiH3wlkwsT+QwZmzp+NQnHpx5EMEZ I2hwT1pqdJWpSRWLkPHLfrNDr4Q+pN7a20MuxoLiNltTnAUs7yMD84hNhuRWvWk= X-Google-Smtp-Source: AGHT+IH5ICBRkJ99Dlk/YFNtu//ILV/B1oo98U/yaMpF360lmpjmvErjUi9hA/zzlpNU+Bh132G7og== X-Received: by 2002:a2e:7019:0:b0:2ec:5685:f061 with SMTP id 38308e7fff4ca-2f3f887b324mr17096561fa.21.1724252003456; Wed, 21 Aug 2024 07:53:23 -0700 (PDT) Received: from localhost.localdomain ([84.245.121.236]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a8680c4725csm52434866b.91.2024.08.21.07.53.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Aug 2024 07:53:23 -0700 (PDT) From: =?UTF-8?q?Juraj=20Linke=C5=A1?= To: thomas@monjalon.net, Honnappa.Nagarahalli@arm.com, jspewock@iol.unh.edu, probb@iol.unh.edu, paul.szczepanek@arm.com, Luca.Vizzarro@arm.com, npratte@iol.unh.edu, dmarx@iol.unh.edu, alex.chapman@arm.com Cc: dev@dpdk.org, =?UTF-8?q?Juraj=20Linke=C5=A1?= Subject: [PATCH v3 05/12] dts: add support for simpler topologies Date: Wed, 21 Aug 2024 16:53:08 +0200 Message-Id: <20240821145315.97974-6-juraj.linkes@pantheon.tech> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240821145315.97974-1-juraj.linkes@pantheon.tech> References: <20240301155416.96960-1-juraj.linkes@pantheon.tech> <20240821145315.97974-1-juraj.linkes@pantheon.tech> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 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 We currently assume there are two links between the SUT and TG nodes, but that's too strict, even for some of the already existing test cases. Add support for topologies with less than two links. For topologies with no links, dummy ports are used. The expectation is that test suites or cases that don't require any links won't be using methods that use ports. Any test suites or cases requiring links will be skipped in topologies with no links, but this feature is not implemented in this commit. Signed-off-by: Juraj Linkeš --- dts/framework/runner.py | 6 +- dts/framework/test_suite.py | 32 +++---- dts/framework/testbed_model/node.py | 2 +- dts/framework/testbed_model/port.py | 4 +- dts/framework/testbed_model/topology.py | 101 ++++++++++++++++++++++ dts/tests/TestSuite_pmd_buffer_scatter.py | 2 +- 6 files changed, 120 insertions(+), 27 deletions(-) create mode 100644 dts/framework/testbed_model/topology.py diff --git a/dts/framework/runner.py b/dts/framework/runner.py index 55357ea1fe..48ae9cc215 100644 --- a/dts/framework/runner.py +++ b/dts/framework/runner.py @@ -53,6 +53,7 @@ TestSuiteWithCases, ) from .test_suite import TestCase, TestSuite +from .testbed_model.topology import Topology class DTSRunner: @@ -474,6 +475,7 @@ def _run_test_suites( test_suites_with_cases: The test suites with test cases to run. """ end_build_target = False + topology = Topology(sut_node.ports, tg_node.ports) for test_suite_with_cases in test_suites_with_cases: test_suite_result = build_target_result.add_test_suite(test_suite_with_cases) try: @@ -481,6 +483,7 @@ def _run_test_suites( self._run_test_suite( sut_node, tg_node, + topology, test_suite_result, test_suite_with_cases, ) @@ -506,6 +509,7 @@ def _run_test_suite( self, sut_node: SutNode, tg_node: TGNode, + topology: Topology, test_suite_result: TestSuiteResult, test_suite_with_cases: TestSuiteWithCases, ) -> None: @@ -533,7 +537,7 @@ def _run_test_suite( self._logger.set_stage( DtsStage.test_suite_setup, Path(SETTINGS.output_dir, test_suite_name) ) - test_suite = test_suite_with_cases.test_suite_class(sut_node, tg_node) + test_suite = test_suite_with_cases.test_suite_class(sut_node, tg_node, topology) try: self._logger.info(f"Starting test suite setup: {test_suite_name}") test_suite.set_up_suite() diff --git a/dts/framework/test_suite.py b/dts/framework/test_suite.py index c59fc9c6e6..56f153bda6 100644 --- a/dts/framework/test_suite.py +++ b/dts/framework/test_suite.py @@ -24,9 +24,10 @@ from scapy.packet import Packet, Padding # type: ignore[import-untyped] from framework.testbed_model.capability import TestProtocol -from framework.testbed_model.port import Port, PortLink +from framework.testbed_model.port import Port from framework.testbed_model.sut_node import SutNode from framework.testbed_model.tg_node import TGNode +from framework.testbed_model.topology import Topology, TopologyType from framework.testbed_model.traffic_generator.capturing_traffic_generator import ( PacketFilteringConfig, ) @@ -72,7 +73,7 @@ class TestSuite(TestProtocol): #: will block the execution of all subsequent test suites in the current build target. is_blocking: ClassVar[bool] = False _logger: DTSLogger - _port_links: list[PortLink] + _topology_type: TopologyType _sut_port_ingress: Port _sut_port_egress: Port _sut_ip_address_ingress: Union[IPv4Interface, IPv6Interface] @@ -86,6 +87,7 @@ def __init__( self, sut_node: SutNode, tg_node: TGNode, + topology: Topology, ): """Initialize the test suite testbed information and basic configuration. @@ -95,35 +97,21 @@ def __init__( Args: sut_node: The SUT node where the test suite will run. tg_node: The TG node where the test suite will run. + topology: The topology where the test suite will run. """ self.sut_node = sut_node self.tg_node = tg_node self._logger = get_dts_logger(self.__class__.__name__) - self._port_links = [] - self._process_links() - self._sut_port_ingress, self._tg_port_egress = ( - self._port_links[0].sut_port, - self._port_links[0].tg_port, - ) - self._sut_port_egress, self._tg_port_ingress = ( - self._port_links[1].sut_port, - self._port_links[1].tg_port, - ) + self._topology_type = topology.type + self._tg_port_egress = topology.tg_port_egress + self._sut_port_ingress = topology.sut_port_ingress + self._sut_port_egress = topology.sut_port_egress + self._tg_port_ingress = topology.tg_port_ingress self._sut_ip_address_ingress = ip_interface("192.168.100.2/24") self._sut_ip_address_egress = ip_interface("192.168.101.2/24") self._tg_ip_address_egress = ip_interface("192.168.100.3/24") self._tg_ip_address_ingress = ip_interface("192.168.101.3/24") - def _process_links(self) -> None: - """Construct links between SUT and TG ports.""" - for sut_port in self.sut_node.ports: - for tg_port in self.tg_node.ports: - if (sut_port.identifier, sut_port.peer) == ( - tg_port.peer, - tg_port.identifier, - ): - self._port_links.append(PortLink(sut_port=sut_port, tg_port=tg_port)) - @classmethod def get_test_cases( cls, test_case_sublist: Sequence[str] | None = None diff --git a/dts/framework/testbed_model/node.py b/dts/framework/testbed_model/node.py index 12a40170ac..51443cd71f 100644 --- a/dts/framework/testbed_model/node.py +++ b/dts/framework/testbed_model/node.py @@ -90,7 +90,7 @@ def __init__(self, node_config: NodeConfiguration): self._init_ports() def _init_ports(self) -> None: - self.ports = [Port(self.name, port_config) for port_config in self.config.ports] + self.ports = [Port(port_config) for port_config in self.config.ports] self.main_session.update_ports(self.ports) for port in self.ports: self.configure_port_state(port) diff --git a/dts/framework/testbed_model/port.py b/dts/framework/testbed_model/port.py index 817405bea4..82c84cf4f8 100644 --- a/dts/framework/testbed_model/port.py +++ b/dts/framework/testbed_model/port.py @@ -54,7 +54,7 @@ class Port: mac_address: str = "" logical_name: str = "" - def __init__(self, node_name: str, config: PortConfig): + def __init__(self, config: PortConfig): """Initialize the port from `node_name` and `config`. Args: @@ -62,7 +62,7 @@ def __init__(self, node_name: str, config: PortConfig): config: The test run configuration of the port. """ self.identifier = PortIdentifier( - node=node_name, + node=config.node, pci=config.pci, ) self.os_driver = config.os_driver diff --git a/dts/framework/testbed_model/topology.py b/dts/framework/testbed_model/topology.py new file mode 100644 index 0000000000..19632ee890 --- /dev/null +++ b/dts/framework/testbed_model/topology.py @@ -0,0 +1,101 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2024 PANTHEON.tech s.r.o. + +"""Testbed topology representation. + +A topology of a testbed captures what links are available between the testbed's nodes. +The link information then implies what type of topology is available. +""" + +from dataclasses import dataclass +from enum import IntEnum +from typing import Iterable + +from framework.config import PortConfig + +from .port import Port + + +class TopologyType(IntEnum): + """Supported topology types.""" + + #: A topology with no Traffic Generator. + no_link = 0 + #: A topology with one physical link between the SUT node and the TG node. + one_link = 1 + #: A topology with two physical links between the Sut node and the TG node. + two_links = 2 + + +class Topology: + """Testbed topology. + + The topology contains ports processed into ingress and egress ports. + It's assumed that port0 of the SUT node is connected to port0 of the TG node and so on. + If there are no ports on a node, dummy ports (ports with no actual values) are stored. + If there is only one link available, the ports of this link are stored + as both ingress and egress ports. + + The dummy ports shouldn't be used. It's up to :class:`~framework.runner.DTSRunner` + to ensure no test case or suite requiring actual links is executed + when the topology prohibits it and up to the developers to make sure that test cases + not requiring any links don't use any ports. Otherwise, the underlying methods + using the ports will fail. + + Attributes: + type: The type of the topology. + tg_port_egress: The egress port of the TG node. + sut_port_ingress: The ingress port of the SUT node. + sut_port_egress: The egress port of the SUT node. + tg_port_ingress: The ingress port of the TG node. + """ + + type: TopologyType + tg_port_egress: Port + sut_port_ingress: Port + sut_port_egress: Port + tg_port_ingress: Port + + def __init__(self, sut_ports: Iterable[Port], tg_ports: Iterable[Port]): + """Create the topology from `sut_ports` and `tg_ports`. + + Args: + sut_ports: The SUT node's ports. + tg_ports: The TG node's ports. + """ + port_links = [] + for sut_port in sut_ports: + for tg_port in tg_ports: + if (sut_port.identifier, sut_port.peer) == ( + tg_port.peer, + tg_port.identifier, + ): + port_links.append(PortLink(sut_port=sut_port, tg_port=tg_port)) + + self.type = TopologyType(len(port_links)) + dummy_port = Port(PortConfig("", "", "", "", "", "")) + self.tg_port_egress = dummy_port + self.sut_port_ingress = dummy_port + self.sut_port_egress = dummy_port + self.tg_port_ingress = dummy_port + if self.type > TopologyType.no_link: + self.tg_port_egress = port_links[0].tg_port + self.sut_port_ingress = port_links[0].sut_port + self.sut_port_egress = self.sut_port_ingress + self.tg_port_ingress = self.tg_port_egress + if self.type > TopologyType.one_link: + self.sut_port_egress = port_links[1].sut_port + self.tg_port_ingress = port_links[1].tg_port + + +@dataclass(slots=True, frozen=True) +class PortLink: + """The physical, cabled connection between the ports. + + Attributes: + sut_port: The port on the SUT node connected to `tg_port`. + tg_port: The port on the TG node connected to `sut_port`. + """ + + sut_port: Port + tg_port: Port diff --git a/dts/tests/TestSuite_pmd_buffer_scatter.py b/dts/tests/TestSuite_pmd_buffer_scatter.py index 020fb0ab62..178a40385e 100644 --- a/dts/tests/TestSuite_pmd_buffer_scatter.py +++ b/dts/tests/TestSuite_pmd_buffer_scatter.py @@ -58,7 +58,7 @@ def set_up_suite(self) -> None: to support larger packet sizes. """ self.verify( - len(self._port_links) > 1, + self._topology_type > 1, "There must be at least two port links to run the scatter test suite", ) -- 2.34.1