From patchwork Thu Apr 20 09:31:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Juraj_Linke=C5=A1?= X-Patchwork-Id: 126318 X-Patchwork-Delegate: thomas@monjalon.net 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 3289442995; Thu, 20 Apr 2023 11:51:19 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 9327342C76; Thu, 20 Apr 2023 11:51:10 +0200 (CEST) Received: from mail-ej1-f44.google.com (mail-ej1-f44.google.com [209.85.218.44]) by mails.dpdk.org (Postfix) with ESMTP id 72C9B40EE3 for ; Thu, 20 Apr 2023 11:51:08 +0200 (CEST) Received: by mail-ej1-f44.google.com with SMTP id a640c23a62f3a-94a34d3812dso59246666b.3 for ; Thu, 20 Apr 2023 02:51:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pantheon-tech.20221208.gappssmtp.com; s=20221208; t=1681984268; x=1684576268; 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=qZto+FhOCTbkf7MCEx+fHxuEVFXw5qOIqWEGXHqqNlA=; b=zHHPpkSw8JWfx6FQKflklf18gP0A0idI5Im/NL6xPurtsooqHuqKRmgVOp1ogpnYEk lrNb9zN/mw5mwXk6jMpOSYV1otq/IJV5HFS8PDmUeL5emoqja9h+xuDB5ScH79AY2oYf M3UgCQ/mRSJvvP2MwBeP6BtFyBdFlhB5B0BeEK3Hk2RWuLztFPbHJiReFMT2hPdPy3wT aVXP+/t57TT7Jv5W3S4IWu/kX3Bhv7eLJbWwep3Svvn3nnnM3ZzubK/EJ73GqFIPxAbd 6TIOw++ZZFsvop70kmzEfxnYl/56zVN8r31vL9g1XSPihH8sTci5u2pOgQMAHCgP+RDz wn0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681984268; x=1684576268; 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=qZto+FhOCTbkf7MCEx+fHxuEVFXw5qOIqWEGXHqqNlA=; b=UBxcwQGs728VqyZ7rM8EWgY3pkMs4oO1q1YfbYgtyCjxzxznGWAPBGA1/QZU66BoFH hUyoIaQQ7bQBdWRXeilWC78SOTUQ6+vkjk6VC+Gd99YPUt27YvwUjvtUCklfHe8NYA0p KxBPH+USx5gcY6tQ2/C6hOyIAkl6C4H9DHVX0BotsF9yyssgkWLJaNrfwOs3MvQfHHfH mfcyhNUJ9CGxRfe5tw5FzZb1R/cYPA4Q20TFqKVp5b6J6Cc1pX2sYNEWJCuWV8LNmIrQ iXm2jk8VwxzvK9Im1zxYPsz+IWUYIkMNaLE104Xlgqb8x52KhpWyan5e8GqvdmL0AFuM 8D2w== X-Gm-Message-State: AAQBX9c+IsGiVRuTosVzBAhJivO9oXcucCEdeCZ2U1LxkVDb7zyJXE1c CSudZKaDpSHEBAJWDaIrNt1PzMh4CZeHbUyX0xQtevflrKfwzKuEv6i25bBVXOEuJmsJ8tDi2w= = X-Google-Smtp-Source: AKy350bRP+iqP3w9o3q6WNdnG45KPurfqU/tqr/s9iHJcOyyPz+8vC9cMDseENx7J7wAPiEV1kwFrQ== X-Received: by 2002:aa7:dc1a:0:b0:505:abcd:d2cc with SMTP id b26-20020aa7dc1a000000b00505abcdd2ccmr1299878edu.30.1681984267962; Thu, 20 Apr 2023 02:51:07 -0700 (PDT) Received: from jlinkes.pantheon.local (81.89.53.154.host.vnet.sk. [81.89.53.154]) by smtp.gmail.com with ESMTPSA id v2-20020aa7d802000000b004ad601533a3sm580801edq.55.2023.04.20.02.51.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Apr 2023 02:51:07 -0700 (PDT) From: =?utf-8?q?Juraj_Linke=C5=A1?= To: thomas@monjalon.net, Honnappa.Nagarahalli@arm.com, lijuan.tu@intel.com, wathsala.vithanage@arm.com, jspewock@iol.unh.edu, probb@iol.unh.edu Cc: dev@dpdk.org, =?utf-8?q?Juraj_Linke=C5=A1?= Subject: [RFC PATCH v1 2/5] dts: add traffic generator config Date: Thu, 20 Apr 2023 11:31:06 +0200 Message-Id: <20230420093109.594704-3-juraj.linkes@pantheon.tech> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230420093109.594704-1-juraj.linkes@pantheon.tech> References: <20230420093109.594704-1-juraj.linkes@pantheon.tech> 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 Node configuration - where to connect, what ports to use and what TG to use. Signed-off-by: Juraj Linkeš --- dts/conf.yaml | 25 +++ dts/framework/config/__init__.py | 107 +++++++++++-- dts/framework/config/conf_yaml_schema.json | 172 ++++++++++++++++++++- 3 files changed, 287 insertions(+), 17 deletions(-) diff --git a/dts/conf.yaml b/dts/conf.yaml index a9bd8a3ecf..4e5fd3560f 100644 --- a/dts/conf.yaml +++ b/dts/conf.yaml @@ -13,6 +13,7 @@ executions: test_suites: - hello_world system_under_test: "SUT 1" + traffic_generator_system: "TG 1" nodes: - name: "SUT 1" hostname: sut1.change.me.localhost @@ -25,3 +26,27 @@ nodes: hugepages: # optional; if removed, will use system hugepage configuration amount: 256 force_first_numa: false + ports: + - pci: "0000:00:08.0" + dpdk_os_driver: vfio-pci + os_driver: i40e + peer_node: "TG 1" + peer_pci: "0000:00:08.0" + - name: "TG 1" + hostname: tg1.change.me.localhost + user: root + arch: x86_64 + os: linux + lcores: "" + use_first_core: false + hugepages: # optional; if removed, will use system hugepage configuration + amount: 256 + force_first_numa: false + ports: + - pci: "0000:00:08.0" + dpdk_os_driver: rdma + os_driver: rdma + peer_node: "SUT 1" + peer_pci: "0000:00:08.0" + traffic_generator: + type: SCAPY diff --git a/dts/framework/config/__init__.py b/dts/framework/config/__init__.py index ebb0823ff5..6b1c3159f7 100644 --- a/dts/framework/config/__init__.py +++ b/dts/framework/config/__init__.py @@ -12,7 +12,7 @@ import pathlib from dataclasses import dataclass from enum import Enum, auto, unique -from typing import Any, TypedDict +from typing import Any, TypedDict, Union import warlock # type: ignore import yaml @@ -61,6 +61,18 @@ class Compiler(StrEnum): msvc = auto() +@unique +class NodeType(StrEnum): + physical = auto() + virtual = auto() + + +@unique +class TrafficGeneratorType(StrEnum): + NONE = auto() + SCAPY = auto() + + # Slots enables some optimizations, by pre-allocating space for the defined # attributes in the underlying data structure. # @@ -72,6 +84,41 @@ class HugepageConfiguration: force_first_numa: bool +@dataclass(slots=True, frozen=True) +class PortConfig: + id: int + node: str + pci: str + dpdk_os_driver: str + os_driver: str + peer_node: str + peer_pci: str + + @staticmethod + def from_dict(id: int, node: str, d: dict) -> "PortConfig": + return PortConfig(id=id, node=node, **d) + + +@dataclass(slots=True, frozen=True) +class TrafficGeneratorConfig: + traffic_generator_type: TrafficGeneratorType + + @staticmethod + def from_dict(d: dict): + # This looks useless now, but is designed to allow expansion to traffic + # generators that require more configuration later. + match TrafficGeneratorType(d["type"]): + case TrafficGeneratorType.SCAPY: + return ScapyTrafficGeneratorConfig( + traffic_generator_type=TrafficGeneratorType.SCAPY + ) + + +@dataclass(slots=True, frozen=True) +class ScapyTrafficGeneratorConfig(TrafficGeneratorConfig): + pass + + @dataclass(slots=True, frozen=True) class NodeConfiguration: name: str @@ -82,29 +129,52 @@ class NodeConfiguration: os: OS lcores: str use_first_core: bool - memory_channels: int hugepages: HugepageConfiguration | None + ports: list[PortConfig] @staticmethod - def from_dict(d: dict) -> "NodeConfiguration": + def from_dict(d: dict) -> Union["SUTConfiguration", "TGConfiguration"]: hugepage_config = d.get("hugepages") if hugepage_config: if "force_first_numa" not in hugepage_config: hugepage_config["force_first_numa"] = False hugepage_config = HugepageConfiguration(**hugepage_config) - return NodeConfiguration( - name=d["name"], - hostname=d["hostname"], - user=d["user"], - password=d.get("password"), - arch=Architecture(d["arch"]), - os=OS(d["os"]), - lcores=d.get("lcores", "1"), - use_first_core=d.get("use_first_core", False), - memory_channels=d.get("memory_channels", 1), - hugepages=hugepage_config, - ) + common_config = {"name": d["name"], + "hostname": d["hostname"], + "user": d["user"], + "password": d.get("password"), + "arch": Architecture(d["arch"]), + "os": OS(d["os"]), + "lcores": d.get("lcores", "1"), + "use_first_core": d.get("use_first_core", False), + "hugepages": hugepage_config, + "ports": [ + PortConfig.from_dict(i, d["name"], port) + for i, port in enumerate(d["ports"]) + ]} + + if "traffic_generator" in d: + return TGConfiguration( + traffic_generator=TrafficGeneratorConfig.from_dict( + d["traffic_generator"]), + **common_config + ) + else: + return SUTConfiguration( + memory_channels=d.get("memory_channels", 1), + **common_config + ) + + +@dataclass(slots=True, frozen=True) +class SUTConfiguration(NodeConfiguration): + memory_channels: int + + +@dataclass(slots=True, frozen=True) +class TGConfiguration(NodeConfiguration): + traffic_generator: TrafficGeneratorConfig @dataclass(slots=True, frozen=True) @@ -156,7 +226,8 @@ class ExecutionConfiguration: perf: bool func: bool test_suites: list[TestSuiteConfig] - system_under_test: NodeConfiguration + system_under_test: SUTConfiguration + traffic_generator_system: TGConfiguration @staticmethod def from_dict(d: dict, node_map: dict) -> "ExecutionConfiguration": @@ -169,12 +240,16 @@ def from_dict(d: dict, node_map: dict) -> "ExecutionConfiguration": sut_name = d["system_under_test"] assert sut_name in node_map, f"Unknown SUT {sut_name} in execution {d}" + tg_name = d["traffic_generator_system"] + assert tg_name in node_map, f"Unknown TG {tg_name} in execution {d}" + return ExecutionConfiguration( build_targets=build_targets, perf=d["perf"], func=d["func"], test_suites=test_suites, system_under_test=node_map[sut_name], + traffic_generator_system=node_map[tg_name], ) diff --git a/dts/framework/config/conf_yaml_schema.json b/dts/framework/config/conf_yaml_schema.json index ca2d4a1ef2..af1d071368 100644 --- a/dts/framework/config/conf_yaml_schema.json +++ b/dts/framework/config/conf_yaml_schema.json @@ -6,6 +6,76 @@ "type": "string", "description": "A unique identifier for a node" }, + "NIC": { + "type": "string", + "enum": [ + "ALL", + "ConnectX3_MT4103", + "ConnectX4_LX_MT4117", + "ConnectX4_MT4115", + "ConnectX5_MT4119", + "ConnectX5_MT4121", + "I40E_10G-10G_BASE_T_BC", + "I40E_10G-10G_BASE_T_X722", + "I40E_10G-SFP_X722", + "I40E_10G-SFP_XL710", + "I40E_10G-X722_A0", + "I40E_1G-1G_BASE_T_X722", + "I40E_25G-25G_SFP28", + "I40E_40G-QSFP_A", + "I40E_40G-QSFP_B", + "IAVF-ADAPTIVE_VF", + "IAVF-VF", + "IAVF_10G-X722_VF", + "ICE_100G-E810C_QSFP", + "ICE_25G-E810C_SFP", + "ICE_25G-E810_XXV_SFP", + "IGB-I350_VF", + "IGB_1G-82540EM", + "IGB_1G-82545EM_COPPER", + "IGB_1G-82571EB_COPPER", + "IGB_1G-82574L", + "IGB_1G-82576", + "IGB_1G-82576_QUAD_COPPER", + "IGB_1G-82576_QUAD_COPPER_ET2", + "IGB_1G-82580_COPPER", + "IGB_1G-I210_COPPER", + "IGB_1G-I350_COPPER", + "IGB_1G-I354_SGMII", + "IGB_1G-PCH_LPTLP_I218_LM", + "IGB_1G-PCH_LPTLP_I218_V", + "IGB_1G-PCH_LPT_I217_LM", + "IGB_1G-PCH_LPT_I217_V", + "IGB_2.5G-I354_BACKPLANE_2_5GBPS", + "IGC-I225_LM", + "IGC-I226_LM", + "IXGBE_10G-82599_SFP", + "IXGBE_10G-82599_SFP_SF_QP", + "IXGBE_10G-82599_T3_LOM", + "IXGBE_10G-82599_VF", + "IXGBE_10G-X540T", + "IXGBE_10G-X540_VF", + "IXGBE_10G-X550EM_A_SFP", + "IXGBE_10G-X550EM_X_10G_T", + "IXGBE_10G-X550EM_X_SFP", + "IXGBE_10G-X550EM_X_VF", + "IXGBE_10G-X550T", + "IXGBE_10G-X550_VF", + "brcm_57414", + "brcm_P2100G", + "cavium_0011", + "cavium_a034", + "cavium_a063", + "cavium_a064", + "fastlinq_ql41000", + "fastlinq_ql41000_vf", + "fastlinq_ql45000", + "fastlinq_ql45000_vf", + "hi1822", + "virtio" + ] + }, + "ARCH": { "type": "string", "enum": [ @@ -20,6 +90,20 @@ "linux" ] }, + "OS_WITH_OPTIONS": { + "oneOf": [ + { + "$ref": "#/definitions/OS" + }, + { + "type": "string", + "enum": [ + "ALL", + "OTHER" + ] + } + ] + }, "cpu": { "type": "string", "description": "Native should be the default on x86", @@ -94,6 +178,34 @@ "amount" ] }, + "mac_address": { + "type": "string", + "description": "A MAC address", + "pattern": "^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$" + }, + "pktgen_type": { + "type": "string", + "enum": [ + "IXIA", + "IXIA_NETWORK", + "TREX", + "SCAPY", + "NONE" + ] + }, + "pci_address": { + "type": "string", + "pattern": "^[\\da-fA-F]{4}:[\\da-fA-F]{2}:[\\da-fA-F]{2}.\\d:?\\w*$" + }, + "port_peer_address": { + "description": "Peer is a TRex port, and IXIA port or a PCI address", + "oneOf": [ + { + "description": "PCI peer port", + "$ref": "#/definitions/pci_address" + } + ] + }, "test_suite": { "type": "string", "enum": [ @@ -165,6 +277,60 @@ }, "hugepages": { "$ref": "#/definitions/hugepages" + }, + "ports": { + "type": "array", + "items": { + "type": "object", + "description": "Each port should be described on both sides of the connection. This makes configuration slightly more verbose but greatly simplifies implementation. If there are an inconsistencies, then DTS will not run until that issue is fixed. An example inconsistency would be port 1, node 1 says it is connected to port 1, node 2, but port 1, node 2 says it is connected to port 2, node 1.", + "properties": { + "pci": { + "$ref": "#/definitions/pci_address", + "description": "The local PCI address of the port" + }, + "dpdk_os_driver": { + "type": "string", + "description": "The driver that the kernel should bind this device to for DPDK to use it. (ex: vfio-pci)" + }, + "os_driver": { + "type": "string", + "description": "The driver normally used by this port (ex: i40e)" + }, + "peer_node": { + "type": "string", + "description": "The name of the node the peer port is on" + }, + "peer_pci": { + "$ref": "#/definitions/pci_address", + "description": "The PCI address of the peer port" + } + }, + "additionalProperties": false, + "required": [ + "pci", + "dpdk_os_driver", + "os_driver", + "peer_node", + "peer_pci" + ] + }, + "minimum": 1 + }, + "traffic_generator": { + "oneOf": [ + { + "type": "object", + "description": "Scapy traffic generator", + "properties": { + "type": { + "type": "string", + "enum": [ + "SCAPY" + ] + } + } + } + ] } }, "additionalProperties": false, @@ -213,6 +379,9 @@ }, "system_under_test": { "$ref": "#/definitions/node_name" + }, + "traffic_generator_system": { + "$ref": "#/definitions/node_name" } }, "additionalProperties": false, @@ -221,7 +390,8 @@ "perf", "func", "test_suites", - "system_under_test" + "system_under_test", + "traffic_generator_system" ] }, "minimum": 1