1840b1e01SJuraj Linkeš# SPDX-License-Identifier: BSD-3-Clause 2840b1e01SJuraj Linkeš# Copyright(c) 2023 University of New Hampshire 36ef07151SJuraj Linkeš# Copyright(c) 2023 PANTHEON.tech s.r.o. 461d5bc9bSLuca Vizzarro# Copyright(c) 2024 Arm Limited 56ef07151SJuraj Linkeš 66ef07151SJuraj Linkeš"""Testpmd interactive shell. 76ef07151SJuraj Linkeš 86ef07151SJuraj LinkešTypical usage example in a TestSuite:: 96ef07151SJuraj Linkeš 10bfad0948SLuca Vizzarro testpmd_shell = TestPmdShell(self.sut_node) 116ef07151SJuraj Linkeš devices = testpmd_shell.get_devices() 126ef07151SJuraj Linkeš for device in devices: 136ef07151SJuraj Linkeš print(device) 146ef07151SJuraj Linkeš testpmd_shell.close() 156ef07151SJuraj Linkeš""" 16840b1e01SJuraj Linkeš 172ecfd126SLuca Vizzarroimport functools 1861d5bc9bSLuca Vizzarroimport re 19369d34b8SJeremy Spewockimport time 20c89d0038SJuraj Linkešfrom collections.abc import Callable, MutableSet 2161d5bc9bSLuca Vizzarrofrom dataclasses import dataclass, field 2261d5bc9bSLuca Vizzarrofrom enum import Flag, auto 23949d1488SLuca Vizzarrofrom os import environ 24840b1e01SJuraj Linkešfrom pathlib import PurePath 25c89d0038SJuraj Linkešfrom typing import TYPE_CHECKING, Any, ClassVar, Concatenate, ParamSpec, TypeAlias 26c89d0038SJuraj Linkeš 27949d1488SLuca Vizzarroif TYPE_CHECKING or environ.get("DTS_DOC_BUILD"): 28c89d0038SJuraj Linkeš from enum import Enum as NoAliasEnum 29c89d0038SJuraj Linkešelse: 30c89d0038SJuraj Linkeš from aenum import NoAliasEnum 31840b1e01SJuraj Linkeš 3287ba4cdcSLuca Vizzarrofrom typing_extensions import Self, Unpack 3361d5bc9bSLuca Vizzarro 342ecfd126SLuca Vizzarrofrom framework.exception import InteractiveCommandExecutionError, InternalError 35fc0f7dc4SLuca Vizzarrofrom framework.params.testpmd import SimpleForwardingModes, TestPmdParams 3687ba4cdcSLuca Vizzarrofrom framework.params.types import TestPmdParamsDict 3761d5bc9bSLuca Vizzarrofrom framework.parser import ParserFn, TextParser 38bfad0948SLuca Vizzarrofrom framework.remote_session.dpdk_shell import DPDKShell 39369d34b8SJeremy Spewockfrom framework.settings import SETTINGS 40bfad0948SLuca Vizzarrofrom framework.testbed_model.cpu import LogicalCoreCount, LogicalCoreList 41bfad0948SLuca Vizzarrofrom framework.testbed_model.sut_node import SutNode 42a91d5f47SJeremy Spewockfrom framework.utils import REGEX_FOR_MAC_ADDRESS, StrEnum 43369d34b8SJeremy Spewock 442ecfd126SLuca VizzarroP = ParamSpec("P") 452ecfd126SLuca VizzarroTestPmdShellMethod = Callable[Concatenate["TestPmdShell", P], Any] 462ecfd126SLuca Vizzarro 47c89d0038SJuraj LinkešTestPmdShellCapabilityMethod: TypeAlias = Callable[ 48c89d0038SJuraj Linkeš ["TestPmdShell", MutableSet["NicCapability"], MutableSet["NicCapability"]], None 49c89d0038SJuraj Linkeš] 50c89d0038SJuraj Linkeš 51c89d0038SJuraj LinkešTestPmdShellDecorator: TypeAlias = Callable[[TestPmdShellMethod], TestPmdShellMethod] 52c89d0038SJuraj Linkeš 53c0119400SJuraj LinkešTestPmdShellNicCapability = ( 54c0119400SJuraj Linkeš TestPmdShellCapabilityMethod | tuple[TestPmdShellCapabilityMethod, TestPmdShellDecorator] 55c0119400SJuraj Linkeš) 56c0119400SJuraj Linkeš 57840b1e01SJuraj Linkeš 583e967643SJuraj Linkešclass TestPmdDevice: 596ef07151SJuraj Linkeš """The data of a device that testpmd can recognize. 606ef07151SJuraj Linkeš 616ef07151SJuraj Linkeš Attributes: 626ef07151SJuraj Linkeš pci_address: The PCI address of the device. 636ef07151SJuraj Linkeš """ 646ef07151SJuraj Linkeš 65840b1e01SJuraj Linkeš pci_address: str 66840b1e01SJuraj Linkeš 67840b1e01SJuraj Linkeš def __init__(self, pci_address_line: str): 686ef07151SJuraj Linkeš """Initialize the device from the testpmd output line string. 696ef07151SJuraj Linkeš 706ef07151SJuraj Linkeš Args: 716ef07151SJuraj Linkeš pci_address_line: A line of testpmd output that contains a device. 726ef07151SJuraj Linkeš """ 73840b1e01SJuraj Linkeš self.pci_address = pci_address_line.strip().split(": ")[1].strip() 74840b1e01SJuraj Linkeš 75840b1e01SJuraj Linkeš def __str__(self) -> str: 766ef07151SJuraj Linkeš """The PCI address captures what the device is.""" 77840b1e01SJuraj Linkeš return self.pci_address 78840b1e01SJuraj Linkeš 79840b1e01SJuraj Linkeš 8061d5bc9bSLuca Vizzarroclass VLANOffloadFlag(Flag): 8161d5bc9bSLuca Vizzarro """Flag representing the VLAN offload settings of a NIC port.""" 8261d5bc9bSLuca Vizzarro 8361d5bc9bSLuca Vizzarro #: 8461d5bc9bSLuca Vizzarro STRIP = auto() 8561d5bc9bSLuca Vizzarro #: 8661d5bc9bSLuca Vizzarro FILTER = auto() 8761d5bc9bSLuca Vizzarro #: 8861d5bc9bSLuca Vizzarro EXTEND = auto() 8961d5bc9bSLuca Vizzarro #: 9061d5bc9bSLuca Vizzarro QINQ_STRIP = auto() 9161d5bc9bSLuca Vizzarro 9261d5bc9bSLuca Vizzarro @classmethod 9361d5bc9bSLuca Vizzarro def from_str_dict(cls, d): 9461d5bc9bSLuca Vizzarro """Makes an instance from a dict containing the flag member names with an "on" value. 9561d5bc9bSLuca Vizzarro 9661d5bc9bSLuca Vizzarro Args: 9761d5bc9bSLuca Vizzarro d: A dictionary containing the flag members as keys and any string value. 9861d5bc9bSLuca Vizzarro 9961d5bc9bSLuca Vizzarro Returns: 10061d5bc9bSLuca Vizzarro A new instance of the flag. 10161d5bc9bSLuca Vizzarro """ 10261d5bc9bSLuca Vizzarro flag = cls(0) 10361d5bc9bSLuca Vizzarro for name in cls.__members__: 10461d5bc9bSLuca Vizzarro if d.get(name) == "on": 10561d5bc9bSLuca Vizzarro flag |= cls[name] 10661d5bc9bSLuca Vizzarro return flag 10761d5bc9bSLuca Vizzarro 10861d5bc9bSLuca Vizzarro @classmethod 10961d5bc9bSLuca Vizzarro def make_parser(cls) -> ParserFn: 11061d5bc9bSLuca Vizzarro """Makes a parser function. 11161d5bc9bSLuca Vizzarro 11261d5bc9bSLuca Vizzarro Returns: 11361d5bc9bSLuca Vizzarro ParserFn: A dictionary for the `dataclasses.field` metadata argument containing a 11461d5bc9bSLuca Vizzarro parser function that makes an instance of this flag from text. 11561d5bc9bSLuca Vizzarro """ 11661d5bc9bSLuca Vizzarro return TextParser.wrap( 11761d5bc9bSLuca Vizzarro TextParser.find( 11861d5bc9bSLuca Vizzarro r"VLAN offload:\s+" 11961d5bc9bSLuca Vizzarro r"strip (?P<STRIP>on|off), " 12061d5bc9bSLuca Vizzarro r"filter (?P<FILTER>on|off), " 12161d5bc9bSLuca Vizzarro r"extend (?P<EXTEND>on|off), " 1221a7520a1SDean Marx r"qinq strip (?P<QINQ_STRIP>on|off)", 12361d5bc9bSLuca Vizzarro re.MULTILINE, 12461d5bc9bSLuca Vizzarro named=True, 12561d5bc9bSLuca Vizzarro ), 12661d5bc9bSLuca Vizzarro cls.from_str_dict, 12761d5bc9bSLuca Vizzarro ) 12861d5bc9bSLuca Vizzarro 12961d5bc9bSLuca Vizzarro 13061d5bc9bSLuca Vizzarroclass RSSOffloadTypesFlag(Flag): 13161d5bc9bSLuca Vizzarro """Flag representing the RSS offload flow types supported by the NIC port.""" 13261d5bc9bSLuca Vizzarro 13361d5bc9bSLuca Vizzarro #: 13461d5bc9bSLuca Vizzarro ipv4 = auto() 13561d5bc9bSLuca Vizzarro #: 13661d5bc9bSLuca Vizzarro ipv4_frag = auto() 13761d5bc9bSLuca Vizzarro #: 13861d5bc9bSLuca Vizzarro ipv4_tcp = auto() 13961d5bc9bSLuca Vizzarro #: 14061d5bc9bSLuca Vizzarro ipv4_udp = auto() 14161d5bc9bSLuca Vizzarro #: 14261d5bc9bSLuca Vizzarro ipv4_sctp = auto() 14361d5bc9bSLuca Vizzarro #: 14461d5bc9bSLuca Vizzarro ipv4_other = auto() 14561d5bc9bSLuca Vizzarro #: 14661d5bc9bSLuca Vizzarro ipv6 = auto() 14761d5bc9bSLuca Vizzarro #: 14861d5bc9bSLuca Vizzarro ipv6_frag = auto() 14961d5bc9bSLuca Vizzarro #: 15061d5bc9bSLuca Vizzarro ipv6_tcp = auto() 15161d5bc9bSLuca Vizzarro #: 15261d5bc9bSLuca Vizzarro ipv6_udp = auto() 15361d5bc9bSLuca Vizzarro #: 15461d5bc9bSLuca Vizzarro ipv6_sctp = auto() 15561d5bc9bSLuca Vizzarro #: 15661d5bc9bSLuca Vizzarro ipv6_other = auto() 15761d5bc9bSLuca Vizzarro #: 15861d5bc9bSLuca Vizzarro l2_payload = auto() 15961d5bc9bSLuca Vizzarro #: 16061d5bc9bSLuca Vizzarro ipv6_ex = auto() 16161d5bc9bSLuca Vizzarro #: 16261d5bc9bSLuca Vizzarro ipv6_tcp_ex = auto() 16361d5bc9bSLuca Vizzarro #: 16461d5bc9bSLuca Vizzarro ipv6_udp_ex = auto() 16561d5bc9bSLuca Vizzarro #: 16661d5bc9bSLuca Vizzarro port = auto() 16761d5bc9bSLuca Vizzarro #: 16861d5bc9bSLuca Vizzarro vxlan = auto() 16961d5bc9bSLuca Vizzarro #: 17061d5bc9bSLuca Vizzarro geneve = auto() 17161d5bc9bSLuca Vizzarro #: 17261d5bc9bSLuca Vizzarro nvgre = auto() 17361d5bc9bSLuca Vizzarro #: 17461d5bc9bSLuca Vizzarro user_defined_22 = auto() 17561d5bc9bSLuca Vizzarro #: 17661d5bc9bSLuca Vizzarro gtpu = auto() 17761d5bc9bSLuca Vizzarro #: 17861d5bc9bSLuca Vizzarro eth = auto() 17961d5bc9bSLuca Vizzarro #: 18061d5bc9bSLuca Vizzarro s_vlan = auto() 18161d5bc9bSLuca Vizzarro #: 18261d5bc9bSLuca Vizzarro c_vlan = auto() 18361d5bc9bSLuca Vizzarro #: 18461d5bc9bSLuca Vizzarro esp = auto() 18561d5bc9bSLuca Vizzarro #: 18661d5bc9bSLuca Vizzarro ah = auto() 18761d5bc9bSLuca Vizzarro #: 18861d5bc9bSLuca Vizzarro l2tpv3 = auto() 18961d5bc9bSLuca Vizzarro #: 19061d5bc9bSLuca Vizzarro pfcp = auto() 19161d5bc9bSLuca Vizzarro #: 19261d5bc9bSLuca Vizzarro pppoe = auto() 19361d5bc9bSLuca Vizzarro #: 19461d5bc9bSLuca Vizzarro ecpri = auto() 19561d5bc9bSLuca Vizzarro #: 19661d5bc9bSLuca Vizzarro mpls = auto() 19761d5bc9bSLuca Vizzarro #: 19861d5bc9bSLuca Vizzarro ipv4_chksum = auto() 19961d5bc9bSLuca Vizzarro #: 20061d5bc9bSLuca Vizzarro l4_chksum = auto() 20161d5bc9bSLuca Vizzarro #: 20261d5bc9bSLuca Vizzarro l2tpv2 = auto() 20361d5bc9bSLuca Vizzarro #: 20461d5bc9bSLuca Vizzarro ipv6_flow_label = auto() 20561d5bc9bSLuca Vizzarro #: 20661d5bc9bSLuca Vizzarro user_defined_38 = auto() 20761d5bc9bSLuca Vizzarro #: 20861d5bc9bSLuca Vizzarro user_defined_39 = auto() 20961d5bc9bSLuca Vizzarro #: 21061d5bc9bSLuca Vizzarro user_defined_40 = auto() 21161d5bc9bSLuca Vizzarro #: 21261d5bc9bSLuca Vizzarro user_defined_41 = auto() 21361d5bc9bSLuca Vizzarro #: 21461d5bc9bSLuca Vizzarro user_defined_42 = auto() 21561d5bc9bSLuca Vizzarro #: 21661d5bc9bSLuca Vizzarro user_defined_43 = auto() 21761d5bc9bSLuca Vizzarro #: 21861d5bc9bSLuca Vizzarro user_defined_44 = auto() 21961d5bc9bSLuca Vizzarro #: 22061d5bc9bSLuca Vizzarro user_defined_45 = auto() 22161d5bc9bSLuca Vizzarro #: 22261d5bc9bSLuca Vizzarro user_defined_46 = auto() 22361d5bc9bSLuca Vizzarro #: 22461d5bc9bSLuca Vizzarro user_defined_47 = auto() 22561d5bc9bSLuca Vizzarro #: 22661d5bc9bSLuca Vizzarro user_defined_48 = auto() 22761d5bc9bSLuca Vizzarro #: 22861d5bc9bSLuca Vizzarro user_defined_49 = auto() 22961d5bc9bSLuca Vizzarro #: 23061d5bc9bSLuca Vizzarro user_defined_50 = auto() 23161d5bc9bSLuca Vizzarro #: 23261d5bc9bSLuca Vizzarro user_defined_51 = auto() 23361d5bc9bSLuca Vizzarro #: 23461d5bc9bSLuca Vizzarro l3_pre96 = auto() 23561d5bc9bSLuca Vizzarro #: 23661d5bc9bSLuca Vizzarro l3_pre64 = auto() 23761d5bc9bSLuca Vizzarro #: 23861d5bc9bSLuca Vizzarro l3_pre56 = auto() 23961d5bc9bSLuca Vizzarro #: 24061d5bc9bSLuca Vizzarro l3_pre48 = auto() 24161d5bc9bSLuca Vizzarro #: 24261d5bc9bSLuca Vizzarro l3_pre40 = auto() 24361d5bc9bSLuca Vizzarro #: 24461d5bc9bSLuca Vizzarro l3_pre32 = auto() 24561d5bc9bSLuca Vizzarro #: 24661d5bc9bSLuca Vizzarro l2_dst_only = auto() 24761d5bc9bSLuca Vizzarro #: 24861d5bc9bSLuca Vizzarro l2_src_only = auto() 24961d5bc9bSLuca Vizzarro #: 25061d5bc9bSLuca Vizzarro l4_dst_only = auto() 25161d5bc9bSLuca Vizzarro #: 25261d5bc9bSLuca Vizzarro l4_src_only = auto() 25361d5bc9bSLuca Vizzarro #: 25461d5bc9bSLuca Vizzarro l3_dst_only = auto() 25561d5bc9bSLuca Vizzarro #: 25661d5bc9bSLuca Vizzarro l3_src_only = auto() 25761d5bc9bSLuca Vizzarro 25861d5bc9bSLuca Vizzarro #: 25961d5bc9bSLuca Vizzarro ip = ipv4 | ipv4_frag | ipv4_other | ipv6 | ipv6_frag | ipv6_other | ipv6_ex 26061d5bc9bSLuca Vizzarro #: 26161d5bc9bSLuca Vizzarro udp = ipv4_udp | ipv6_udp | ipv6_udp_ex 26261d5bc9bSLuca Vizzarro #: 26361d5bc9bSLuca Vizzarro tcp = ipv4_tcp | ipv6_tcp | ipv6_tcp_ex 26461d5bc9bSLuca Vizzarro #: 26561d5bc9bSLuca Vizzarro sctp = ipv4_sctp | ipv6_sctp 26661d5bc9bSLuca Vizzarro #: 26761d5bc9bSLuca Vizzarro tunnel = vxlan | geneve | nvgre 26861d5bc9bSLuca Vizzarro #: 26961d5bc9bSLuca Vizzarro vlan = s_vlan | c_vlan 27061d5bc9bSLuca Vizzarro #: 27161d5bc9bSLuca Vizzarro all = ( 27261d5bc9bSLuca Vizzarro eth 27361d5bc9bSLuca Vizzarro | vlan 27461d5bc9bSLuca Vizzarro | ip 27561d5bc9bSLuca Vizzarro | tcp 27661d5bc9bSLuca Vizzarro | udp 27761d5bc9bSLuca Vizzarro | sctp 27861d5bc9bSLuca Vizzarro | l2_payload 27961d5bc9bSLuca Vizzarro | l2tpv3 28061d5bc9bSLuca Vizzarro | esp 28161d5bc9bSLuca Vizzarro | ah 28261d5bc9bSLuca Vizzarro | pfcp 28361d5bc9bSLuca Vizzarro | gtpu 28461d5bc9bSLuca Vizzarro | ecpri 28561d5bc9bSLuca Vizzarro | mpls 28661d5bc9bSLuca Vizzarro | l2tpv2 28761d5bc9bSLuca Vizzarro ) 28861d5bc9bSLuca Vizzarro 28961d5bc9bSLuca Vizzarro @classmethod 29061d5bc9bSLuca Vizzarro def from_list_string(cls, names: str) -> Self: 29161d5bc9bSLuca Vizzarro """Makes a flag from a whitespace-separated list of names. 29261d5bc9bSLuca Vizzarro 29361d5bc9bSLuca Vizzarro Args: 29461d5bc9bSLuca Vizzarro names: a whitespace-separated list containing the members of this flag. 29561d5bc9bSLuca Vizzarro 29661d5bc9bSLuca Vizzarro Returns: 29761d5bc9bSLuca Vizzarro An instance of this flag. 29861d5bc9bSLuca Vizzarro """ 29961d5bc9bSLuca Vizzarro flag = cls(0) 30061d5bc9bSLuca Vizzarro for name in names.split(): 30161d5bc9bSLuca Vizzarro flag |= cls.from_str(name) 30261d5bc9bSLuca Vizzarro return flag 30361d5bc9bSLuca Vizzarro 30461d5bc9bSLuca Vizzarro @classmethod 30561d5bc9bSLuca Vizzarro def from_str(cls, name: str) -> Self: 30661d5bc9bSLuca Vizzarro """Makes a flag matching the supplied name. 30761d5bc9bSLuca Vizzarro 30861d5bc9bSLuca Vizzarro Args: 30961d5bc9bSLuca Vizzarro name: a valid member of this flag in text 31061d5bc9bSLuca Vizzarro Returns: 31161d5bc9bSLuca Vizzarro An instance of this flag. 31261d5bc9bSLuca Vizzarro """ 31361d5bc9bSLuca Vizzarro member_name = name.strip().replace("-", "_") 31461d5bc9bSLuca Vizzarro return cls[member_name] 31561d5bc9bSLuca Vizzarro 31661d5bc9bSLuca Vizzarro @classmethod 31761d5bc9bSLuca Vizzarro def make_parser(cls) -> ParserFn: 31861d5bc9bSLuca Vizzarro """Makes a parser function. 31961d5bc9bSLuca Vizzarro 32061d5bc9bSLuca Vizzarro Returns: 32161d5bc9bSLuca Vizzarro ParserFn: A dictionary for the `dataclasses.field` metadata argument containing a 32261d5bc9bSLuca Vizzarro parser function that makes an instance of this flag from text. 32361d5bc9bSLuca Vizzarro """ 32461d5bc9bSLuca Vizzarro return TextParser.wrap( 32561d5bc9bSLuca Vizzarro TextParser.find(r"Supported RSS offload flow types:((?:\r?\n? \S+)+)", re.MULTILINE), 32661d5bc9bSLuca Vizzarro RSSOffloadTypesFlag.from_list_string, 32761d5bc9bSLuca Vizzarro ) 32861d5bc9bSLuca Vizzarro 32961d5bc9bSLuca Vizzarro 33061d5bc9bSLuca Vizzarroclass DeviceCapabilitiesFlag(Flag): 33161d5bc9bSLuca Vizzarro """Flag representing the device capabilities.""" 33261d5bc9bSLuca Vizzarro 33361d5bc9bSLuca Vizzarro #: Device supports Rx queue setup after device started. 33461d5bc9bSLuca Vizzarro RUNTIME_RX_QUEUE_SETUP = auto() 33561d5bc9bSLuca Vizzarro #: Device supports Tx queue setup after device started. 33661d5bc9bSLuca Vizzarro RUNTIME_TX_QUEUE_SETUP = auto() 33761d5bc9bSLuca Vizzarro #: Device supports shared Rx queue among ports within Rx domain and switch domain. 33861d5bc9bSLuca Vizzarro RXQ_SHARE = auto() 33961d5bc9bSLuca Vizzarro #: Device supports keeping flow rules across restart. 34061d5bc9bSLuca Vizzarro FLOW_RULE_KEEP = auto() 34161d5bc9bSLuca Vizzarro #: Device supports keeping shared flow objects across restart. 34261d5bc9bSLuca Vizzarro FLOW_SHARED_OBJECT_KEEP = auto() 34361d5bc9bSLuca Vizzarro 34461d5bc9bSLuca Vizzarro @classmethod 34561d5bc9bSLuca Vizzarro def make_parser(cls) -> ParserFn: 34661d5bc9bSLuca Vizzarro """Makes a parser function. 34761d5bc9bSLuca Vizzarro 34861d5bc9bSLuca Vizzarro Returns: 34961d5bc9bSLuca Vizzarro ParserFn: A dictionary for the `dataclasses.field` metadata argument containing a 35061d5bc9bSLuca Vizzarro parser function that makes an instance of this flag from text. 35161d5bc9bSLuca Vizzarro """ 35261d5bc9bSLuca Vizzarro return TextParser.wrap( 35361d5bc9bSLuca Vizzarro TextParser.find_int(r"Device capabilities: (0x[A-Fa-f\d]+)"), 35461d5bc9bSLuca Vizzarro cls, 35561d5bc9bSLuca Vizzarro ) 35661d5bc9bSLuca Vizzarro 35761d5bc9bSLuca Vizzarro 35861d5bc9bSLuca Vizzarroclass DeviceErrorHandlingMode(StrEnum): 35961d5bc9bSLuca Vizzarro """Enum representing the device error handling mode.""" 36061d5bc9bSLuca Vizzarro 36161d5bc9bSLuca Vizzarro #: 36261d5bc9bSLuca Vizzarro none = auto() 36361d5bc9bSLuca Vizzarro #: 36461d5bc9bSLuca Vizzarro passive = auto() 36561d5bc9bSLuca Vizzarro #: 36661d5bc9bSLuca Vizzarro proactive = auto() 36761d5bc9bSLuca Vizzarro #: 36861d5bc9bSLuca Vizzarro unknown = auto() 36961d5bc9bSLuca Vizzarro 37061d5bc9bSLuca Vizzarro @classmethod 37161d5bc9bSLuca Vizzarro def make_parser(cls) -> ParserFn: 37261d5bc9bSLuca Vizzarro """Makes a parser function. 37361d5bc9bSLuca Vizzarro 37461d5bc9bSLuca Vizzarro Returns: 37561d5bc9bSLuca Vizzarro ParserFn: A dictionary for the `dataclasses.field` metadata argument containing a 37661d5bc9bSLuca Vizzarro parser function that makes an instance of this enum from text. 37761d5bc9bSLuca Vizzarro """ 37861d5bc9bSLuca Vizzarro return TextParser.wrap(TextParser.find(r"Device error handling mode: (\w+)"), cls) 37961d5bc9bSLuca Vizzarro 38061d5bc9bSLuca Vizzarro 38161d5bc9bSLuca Vizzarrodef make_device_private_info_parser() -> ParserFn: 38261d5bc9bSLuca Vizzarro """Device private information parser. 38361d5bc9bSLuca Vizzarro 38461d5bc9bSLuca Vizzarro Ensures that we are not parsing invalid device private info output. 38561d5bc9bSLuca Vizzarro 38661d5bc9bSLuca Vizzarro Returns: 38761d5bc9bSLuca Vizzarro ParserFn: A dictionary for the `dataclasses.field` metadata argument containing a parser 38861d5bc9bSLuca Vizzarro function that parses the device private info from the TestPmd port info output. 38961d5bc9bSLuca Vizzarro """ 39061d5bc9bSLuca Vizzarro 39161d5bc9bSLuca Vizzarro def _validate(info: str): 39261d5bc9bSLuca Vizzarro info = info.strip() 39361d5bc9bSLuca Vizzarro if info == "none" or info.startswith("Invalid file") or info.startswith("Failed to dump"): 39461d5bc9bSLuca Vizzarro return None 39561d5bc9bSLuca Vizzarro return info 39661d5bc9bSLuca Vizzarro 39761d5bc9bSLuca Vizzarro return TextParser.wrap(TextParser.find(r"Device private info:\s+([\s\S]+)"), _validate) 39861d5bc9bSLuca Vizzarro 39961d5bc9bSLuca Vizzarro 400c0119400SJuraj Linkešclass RxQueueState(StrEnum): 401c0119400SJuraj Linkeš """RX queue states. 402c0119400SJuraj Linkeš 403c0119400SJuraj Linkeš References: 404c0119400SJuraj Linkeš DPDK lib: ``lib/ethdev/rte_ethdev.h`` 405c0119400SJuraj Linkeš testpmd display function: ``app/test-pmd/config.c:get_queue_state_name()`` 406c0119400SJuraj Linkeš """ 407c0119400SJuraj Linkeš 408c0119400SJuraj Linkeš #: 409c0119400SJuraj Linkeš stopped = auto() 410c0119400SJuraj Linkeš #: 411c0119400SJuraj Linkeš started = auto() 412c0119400SJuraj Linkeš #: 413c0119400SJuraj Linkeš hairpin = auto() 414c0119400SJuraj Linkeš #: 415c0119400SJuraj Linkeš unknown = auto() 416c0119400SJuraj Linkeš 417c0119400SJuraj Linkeš @classmethod 418c0119400SJuraj Linkeš def make_parser(cls) -> ParserFn: 419c0119400SJuraj Linkeš """Makes a parser function. 420c0119400SJuraj Linkeš 421c0119400SJuraj Linkeš Returns: 422c0119400SJuraj Linkeš ParserFn: A dictionary for the `dataclasses.field` metadata argument containing a 423c0119400SJuraj Linkeš parser function that makes an instance of this enum from text. 424c0119400SJuraj Linkeš """ 425c0119400SJuraj Linkeš return TextParser.wrap(TextParser.find(r"Rx queue state: ([^\r\n]+)"), cls) 426c0119400SJuraj Linkeš 427c0119400SJuraj Linkeš 428c0119400SJuraj Linkeš@dataclass 429*c986c339SDean Marxclass TestPmdQueueInfo(TextParser): 430*c986c339SDean Marx """Dataclass representation of the common parts of the testpmd `show rxq/txq info` commands.""" 431*c986c339SDean Marx 432*c986c339SDean Marx #: 433*c986c339SDean Marx prefetch_threshold: int = field(metadata=TextParser.find_int(r"prefetch threshold: (\d+)")) 434*c986c339SDean Marx #: 435*c986c339SDean Marx host_threshold: int = field(metadata=TextParser.find_int(r"host threshold: (\d+)")) 436*c986c339SDean Marx #: 437*c986c339SDean Marx writeback_threshold: int = field(metadata=TextParser.find_int(r"writeback threshold: (\d+)")) 438*c986c339SDean Marx #: 439*c986c339SDean Marx free_threshold: int = field(metadata=TextParser.find_int(r"free threshold: (\d+)")) 440*c986c339SDean Marx #: 441*c986c339SDean Marx deferred_start: bool = field(metadata=TextParser.find("deferred start: on")) 442*c986c339SDean Marx #: The number of RXD/TXDs is just the ring size of the queue. 443*c986c339SDean Marx ring_size: int = field(metadata=TextParser.find_int(r"Number of (?:RXDs|TXDs): (\d+)")) 444*c986c339SDean Marx #: 445*c986c339SDean Marx is_queue_started: bool = field(metadata=TextParser.find("queue state: started")) 446*c986c339SDean Marx #: 447*c986c339SDean Marx burst_mode: str | None = field( 448*c986c339SDean Marx default=None, metadata=TextParser.find(r"Burst mode: ([^\r\n]+)") 449*c986c339SDean Marx ) 450*c986c339SDean Marx 451*c986c339SDean Marx 452*c986c339SDean Marx@dataclass 453*c986c339SDean Marxclass TestPmdTxqInfo(TestPmdQueueInfo): 454*c986c339SDean Marx """Representation of testpmd's ``show txq info <port_id> <queue_id>`` command. 455*c986c339SDean Marx 456*c986c339SDean Marx References: 457*c986c339SDean Marx testpmd command function: ``app/test-pmd/cmdline.c:cmd_showqueue()`` 458*c986c339SDean Marx testpmd display function: ``app/test-pmd/config.c:rx_queue_infos_display()`` 459*c986c339SDean Marx """ 460*c986c339SDean Marx 461*c986c339SDean Marx #: Ring size threshold 462*c986c339SDean Marx rs_threshold: int | None = field( 463*c986c339SDean Marx default=None, metadata=TextParser.find_int(r"TX RS threshold: (\d+)\b") 464*c986c339SDean Marx ) 465*c986c339SDean Marx 466*c986c339SDean Marx 467*c986c339SDean Marx@dataclass 468*c986c339SDean Marxclass TestPmdRxqInfo(TestPmdQueueInfo): 469c0119400SJuraj Linkeš """Representation of testpmd's ``show rxq info <port_id> <queue_id>`` command. 470c0119400SJuraj Linkeš 471c0119400SJuraj Linkeš References: 472c0119400SJuraj Linkeš testpmd command function: ``app/test-pmd/cmdline.c:cmd_showqueue()`` 473c0119400SJuraj Linkeš testpmd display function: ``app/test-pmd/config.c:rx_queue_infos_display()`` 474c0119400SJuraj Linkeš """ 475c0119400SJuraj Linkeš 476c0119400SJuraj Linkeš #: Mempool used by that queue 477*c986c339SDean Marx mempool: str | None = field(default=None, metadata=TextParser.find(r"Mempool: ([^\r\n]+)")) 478c0119400SJuraj Linkeš #: Drop packets if no descriptors are available 479*c986c339SDean Marx drop_packets: bool | None = field( 480*c986c339SDean Marx default=None, metadata=TextParser.find(r"RX drop packets: on") 481*c986c339SDean Marx ) 482c0119400SJuraj Linkeš #: Scattered packets Rx enabled 483*c986c339SDean Marx scattered_packets: bool | None = field( 484*c986c339SDean Marx default=None, metadata=TextParser.find(r"RX scattered packets: on") 485*c986c339SDean Marx ) 486c0119400SJuraj Linkeš #: The state of the queue 487*c986c339SDean Marx queue_state: str | None = field(default=None, metadata=RxQueueState.make_parser()) 488c0119400SJuraj Linkeš 489c0119400SJuraj Linkeš 49061d5bc9bSLuca Vizzarro@dataclass 49161d5bc9bSLuca Vizzarroclass TestPmdPort(TextParser): 49261d5bc9bSLuca Vizzarro """Dataclass representing the result of testpmd's ``show port info`` command.""" 49361d5bc9bSLuca Vizzarro 49461d5bc9bSLuca Vizzarro #: 49561d5bc9bSLuca Vizzarro id: int = field(metadata=TextParser.find_int(r"Infos for port (\d+)\b")) 49661d5bc9bSLuca Vizzarro #: 49761d5bc9bSLuca Vizzarro device_name: str = field(metadata=TextParser.find(r"Device name: ([^\r\n]+)")) 49861d5bc9bSLuca Vizzarro #: 49961d5bc9bSLuca Vizzarro driver_name: str = field(metadata=TextParser.find(r"Driver name: ([^\r\n]+)")) 50061d5bc9bSLuca Vizzarro #: 50161d5bc9bSLuca Vizzarro socket_id: int = field(metadata=TextParser.find_int(r"Connect to socket: (\d+)")) 50261d5bc9bSLuca Vizzarro #: 50361d5bc9bSLuca Vizzarro is_link_up: bool = field(metadata=TextParser.find("Link status: up")) 50461d5bc9bSLuca Vizzarro #: 50561d5bc9bSLuca Vizzarro link_speed: str = field(metadata=TextParser.find(r"Link speed: ([^\r\n]+)")) 50661d5bc9bSLuca Vizzarro #: 50761d5bc9bSLuca Vizzarro is_link_full_duplex: bool = field(metadata=TextParser.find("Link duplex: full-duplex")) 50861d5bc9bSLuca Vizzarro #: 50961d5bc9bSLuca Vizzarro is_link_autonegotiated: bool = field(metadata=TextParser.find("Autoneg status: On")) 51061d5bc9bSLuca Vizzarro #: 51161d5bc9bSLuca Vizzarro is_promiscuous_mode_enabled: bool = field(metadata=TextParser.find("Promiscuous mode: enabled")) 51261d5bc9bSLuca Vizzarro #: 51361d5bc9bSLuca Vizzarro is_allmulticast_mode_enabled: bool = field( 51461d5bc9bSLuca Vizzarro metadata=TextParser.find("Allmulticast mode: enabled") 51561d5bc9bSLuca Vizzarro ) 51661d5bc9bSLuca Vizzarro #: Maximum number of MAC addresses 51761d5bc9bSLuca Vizzarro max_mac_addresses_num: int = field( 51861d5bc9bSLuca Vizzarro metadata=TextParser.find_int(r"Maximum number of MAC addresses: (\d+)") 51961d5bc9bSLuca Vizzarro ) 52061d5bc9bSLuca Vizzarro #: Maximum configurable length of RX packet 52161d5bc9bSLuca Vizzarro max_hash_mac_addresses_num: int = field( 52261d5bc9bSLuca Vizzarro metadata=TextParser.find_int(r"Maximum number of MAC addresses of hash filtering: (\d+)") 52361d5bc9bSLuca Vizzarro ) 52461d5bc9bSLuca Vizzarro #: Minimum size of RX buffer 52561d5bc9bSLuca Vizzarro min_rx_bufsize: int = field(metadata=TextParser.find_int(r"Minimum size of RX buffer: (\d+)")) 52661d5bc9bSLuca Vizzarro #: Maximum configurable length of RX packet 52761d5bc9bSLuca Vizzarro max_rx_packet_length: int = field( 52861d5bc9bSLuca Vizzarro metadata=TextParser.find_int(r"Maximum configurable length of RX packet: (\d+)") 52961d5bc9bSLuca Vizzarro ) 53061d5bc9bSLuca Vizzarro #: Maximum configurable size of LRO aggregated packet 53161d5bc9bSLuca Vizzarro max_lro_packet_size: int = field( 53261d5bc9bSLuca Vizzarro metadata=TextParser.find_int(r"Maximum configurable size of LRO aggregated packet: (\d+)") 53361d5bc9bSLuca Vizzarro ) 53461d5bc9bSLuca Vizzarro 53561d5bc9bSLuca Vizzarro #: Current number of RX queues 53661d5bc9bSLuca Vizzarro rx_queues_num: int = field(metadata=TextParser.find_int(r"Current number of RX queues: (\d+)")) 53761d5bc9bSLuca Vizzarro #: Max possible RX queues 53861d5bc9bSLuca Vizzarro max_rx_queues_num: int = field(metadata=TextParser.find_int(r"Max possible RX queues: (\d+)")) 53961d5bc9bSLuca Vizzarro #: Max possible number of RXDs per queue 54061d5bc9bSLuca Vizzarro max_queue_rxd_num: int = field( 54161d5bc9bSLuca Vizzarro metadata=TextParser.find_int(r"Max possible number of RXDs per queue: (\d+)") 54261d5bc9bSLuca Vizzarro ) 54361d5bc9bSLuca Vizzarro #: Min possible number of RXDs per queue 54461d5bc9bSLuca Vizzarro min_queue_rxd_num: int = field( 54561d5bc9bSLuca Vizzarro metadata=TextParser.find_int(r"Min possible number of RXDs per queue: (\d+)") 54661d5bc9bSLuca Vizzarro ) 54761d5bc9bSLuca Vizzarro #: RXDs number alignment 54861d5bc9bSLuca Vizzarro rxd_alignment_num: int = field(metadata=TextParser.find_int(r"RXDs number alignment: (\d+)")) 54961d5bc9bSLuca Vizzarro 55061d5bc9bSLuca Vizzarro #: Current number of TX queues 55161d5bc9bSLuca Vizzarro tx_queues_num: int = field(metadata=TextParser.find_int(r"Current number of TX queues: (\d+)")) 55261d5bc9bSLuca Vizzarro #: Max possible TX queues 55361d5bc9bSLuca Vizzarro max_tx_queues_num: int = field(metadata=TextParser.find_int(r"Max possible TX queues: (\d+)")) 55461d5bc9bSLuca Vizzarro #: Max possible number of TXDs per queue 55561d5bc9bSLuca Vizzarro max_queue_txd_num: int = field( 55661d5bc9bSLuca Vizzarro metadata=TextParser.find_int(r"Max possible number of TXDs per queue: (\d+)") 55761d5bc9bSLuca Vizzarro ) 55861d5bc9bSLuca Vizzarro #: Min possible number of TXDs per queue 55961d5bc9bSLuca Vizzarro min_queue_txd_num: int = field( 56061d5bc9bSLuca Vizzarro metadata=TextParser.find_int(r"Min possible number of TXDs per queue: (\d+)") 56161d5bc9bSLuca Vizzarro ) 56261d5bc9bSLuca Vizzarro #: TXDs number alignment 56361d5bc9bSLuca Vizzarro txd_alignment_num: int = field(metadata=TextParser.find_int(r"TXDs number alignment: (\d+)")) 56461d5bc9bSLuca Vizzarro #: Max segment number per packet 56561d5bc9bSLuca Vizzarro max_packet_segment_num: int = field( 56661d5bc9bSLuca Vizzarro metadata=TextParser.find_int(r"Max segment number per packet: (\d+)") 56761d5bc9bSLuca Vizzarro ) 56861d5bc9bSLuca Vizzarro #: Max segment number per MTU/TSO 56961d5bc9bSLuca Vizzarro max_mtu_segment_num: int = field( 57061d5bc9bSLuca Vizzarro metadata=TextParser.find_int(r"Max segment number per MTU\/TSO: (\d+)") 57161d5bc9bSLuca Vizzarro ) 57261d5bc9bSLuca Vizzarro 57361d5bc9bSLuca Vizzarro #: 57461d5bc9bSLuca Vizzarro device_capabilities: DeviceCapabilitiesFlag = field( 57561d5bc9bSLuca Vizzarro metadata=DeviceCapabilitiesFlag.make_parser(), 57661d5bc9bSLuca Vizzarro ) 57761d5bc9bSLuca Vizzarro #: 578618d9140SJuraj Linkeš device_error_handling_mode: DeviceErrorHandlingMode | None = field( 579618d9140SJuraj Linkeš default=None, metadata=DeviceErrorHandlingMode.make_parser() 58061d5bc9bSLuca Vizzarro ) 58161d5bc9bSLuca Vizzarro #: 58261d5bc9bSLuca Vizzarro device_private_info: str | None = field( 58361d5bc9bSLuca Vizzarro default=None, 58461d5bc9bSLuca Vizzarro metadata=make_device_private_info_parser(), 58561d5bc9bSLuca Vizzarro ) 58661d5bc9bSLuca Vizzarro 58761d5bc9bSLuca Vizzarro #: 58861d5bc9bSLuca Vizzarro hash_key_size: int | None = field( 58961d5bc9bSLuca Vizzarro default=None, metadata=TextParser.find_int(r"Hash key size in bytes: (\d+)") 59061d5bc9bSLuca Vizzarro ) 59161d5bc9bSLuca Vizzarro #: 59261d5bc9bSLuca Vizzarro redirection_table_size: int | None = field( 59361d5bc9bSLuca Vizzarro default=None, metadata=TextParser.find_int(r"Redirection table size: (\d+)") 59461d5bc9bSLuca Vizzarro ) 59561d5bc9bSLuca Vizzarro #: 59661d5bc9bSLuca Vizzarro supported_rss_offload_flow_types: RSSOffloadTypesFlag = field( 59761d5bc9bSLuca Vizzarro default=RSSOffloadTypesFlag(0), metadata=RSSOffloadTypesFlag.make_parser() 59861d5bc9bSLuca Vizzarro ) 59961d5bc9bSLuca Vizzarro 60061d5bc9bSLuca Vizzarro #: 60161d5bc9bSLuca Vizzarro mac_address: str | None = field( 60261d5bc9bSLuca Vizzarro default=None, metadata=TextParser.find(r"MAC address: ([A-Fa-f0-9:]+)") 60361d5bc9bSLuca Vizzarro ) 60461d5bc9bSLuca Vizzarro #: 60561d5bc9bSLuca Vizzarro fw_version: str | None = field( 60661d5bc9bSLuca Vizzarro default=None, metadata=TextParser.find(r"Firmware-version: ([^\r\n]+)") 60761d5bc9bSLuca Vizzarro ) 60861d5bc9bSLuca Vizzarro #: 60961d5bc9bSLuca Vizzarro dev_args: str | None = field(default=None, metadata=TextParser.find(r"Devargs: ([^\r\n]+)")) 61061d5bc9bSLuca Vizzarro #: Socket id of the memory allocation 61161d5bc9bSLuca Vizzarro mem_alloc_socket_id: int | None = field( 61261d5bc9bSLuca Vizzarro default=None, 61361d5bc9bSLuca Vizzarro metadata=TextParser.find_int(r"memory allocation on the socket: (\d+)"), 61461d5bc9bSLuca Vizzarro ) 61561d5bc9bSLuca Vizzarro #: 61661d5bc9bSLuca Vizzarro mtu: int | None = field(default=None, metadata=TextParser.find_int(r"MTU: (\d+)")) 61761d5bc9bSLuca Vizzarro 61861d5bc9bSLuca Vizzarro #: 61961d5bc9bSLuca Vizzarro vlan_offload: VLANOffloadFlag | None = field( 62061d5bc9bSLuca Vizzarro default=None, 62161d5bc9bSLuca Vizzarro metadata=VLANOffloadFlag.make_parser(), 62261d5bc9bSLuca Vizzarro ) 62361d5bc9bSLuca Vizzarro 62461d5bc9bSLuca Vizzarro #: Maximum size of RX buffer 62561d5bc9bSLuca Vizzarro max_rx_bufsize: int | None = field( 62661d5bc9bSLuca Vizzarro default=None, metadata=TextParser.find_int(r"Maximum size of RX buffer: (\d+)") 62761d5bc9bSLuca Vizzarro ) 62861d5bc9bSLuca Vizzarro #: Maximum number of VFs 62961d5bc9bSLuca Vizzarro max_vfs_num: int | None = field( 63061d5bc9bSLuca Vizzarro default=None, metadata=TextParser.find_int(r"Maximum number of VFs: (\d+)") 63161d5bc9bSLuca Vizzarro ) 63261d5bc9bSLuca Vizzarro #: Maximum number of VMDq pools 63361d5bc9bSLuca Vizzarro max_vmdq_pools_num: int | None = field( 63461d5bc9bSLuca Vizzarro default=None, metadata=TextParser.find_int(r"Maximum number of VMDq pools: (\d+)") 63561d5bc9bSLuca Vizzarro ) 63661d5bc9bSLuca Vizzarro 63761d5bc9bSLuca Vizzarro #: 63861d5bc9bSLuca Vizzarro switch_name: str | None = field( 63961d5bc9bSLuca Vizzarro default=None, metadata=TextParser.find(r"Switch name: ([\r\n]+)") 64061d5bc9bSLuca Vizzarro ) 64161d5bc9bSLuca Vizzarro #: 64261d5bc9bSLuca Vizzarro switch_domain_id: int | None = field( 64361d5bc9bSLuca Vizzarro default=None, metadata=TextParser.find_int(r"Switch domain Id: (\d+)") 64461d5bc9bSLuca Vizzarro ) 64561d5bc9bSLuca Vizzarro #: 64661d5bc9bSLuca Vizzarro switch_port_id: int | None = field( 64761d5bc9bSLuca Vizzarro default=None, metadata=TextParser.find_int(r"Switch Port Id: (\d+)") 64861d5bc9bSLuca Vizzarro ) 64961d5bc9bSLuca Vizzarro #: 65061d5bc9bSLuca Vizzarro switch_rx_domain: int | None = field( 65161d5bc9bSLuca Vizzarro default=None, metadata=TextParser.find_int(r"Switch Rx domain: (\d+)") 65261d5bc9bSLuca Vizzarro ) 65361d5bc9bSLuca Vizzarro 65461d5bc9bSLuca Vizzarro 65553eacf3dSLuca Vizzarro@dataclass 65653eacf3dSLuca Vizzarroclass TestPmdPortStats(TextParser): 65753eacf3dSLuca Vizzarro """Port statistics.""" 65853eacf3dSLuca Vizzarro 65953eacf3dSLuca Vizzarro #: 66053eacf3dSLuca Vizzarro port_id: int = field(metadata=TextParser.find_int(r"NIC statistics for port (\d+)")) 66153eacf3dSLuca Vizzarro 66253eacf3dSLuca Vizzarro #: 66353eacf3dSLuca Vizzarro rx_packets: int = field(metadata=TextParser.find_int(r"RX-packets:\s+(\d+)")) 66453eacf3dSLuca Vizzarro #: 66553eacf3dSLuca Vizzarro rx_missed: int = field(metadata=TextParser.find_int(r"RX-missed:\s+(\d+)")) 66653eacf3dSLuca Vizzarro #: 66753eacf3dSLuca Vizzarro rx_bytes: int = field(metadata=TextParser.find_int(r"RX-bytes:\s+(\d+)")) 66853eacf3dSLuca Vizzarro #: 66953eacf3dSLuca Vizzarro rx_errors: int = field(metadata=TextParser.find_int(r"RX-errors:\s+(\d+)")) 67053eacf3dSLuca Vizzarro #: 67153eacf3dSLuca Vizzarro rx_nombuf: int = field(metadata=TextParser.find_int(r"RX-nombuf:\s+(\d+)")) 67253eacf3dSLuca Vizzarro 67353eacf3dSLuca Vizzarro #: 67453eacf3dSLuca Vizzarro tx_packets: int = field(metadata=TextParser.find_int(r"TX-packets:\s+(\d+)")) 67553eacf3dSLuca Vizzarro #: 67653eacf3dSLuca Vizzarro tx_errors: int = field(metadata=TextParser.find_int(r"TX-errors:\s+(\d+)")) 67753eacf3dSLuca Vizzarro #: 67853eacf3dSLuca Vizzarro tx_bytes: int = field(metadata=TextParser.find_int(r"TX-bytes:\s+(\d+)")) 67953eacf3dSLuca Vizzarro 68053eacf3dSLuca Vizzarro #: 68153eacf3dSLuca Vizzarro rx_pps: int = field(metadata=TextParser.find_int(r"Rx-pps:\s+(\d+)")) 68253eacf3dSLuca Vizzarro #: 68353eacf3dSLuca Vizzarro rx_bps: int = field(metadata=TextParser.find_int(r"Rx-bps:\s+(\d+)")) 68453eacf3dSLuca Vizzarro 68553eacf3dSLuca Vizzarro #: 68653eacf3dSLuca Vizzarro tx_pps: int = field(metadata=TextParser.find_int(r"Tx-pps:\s+(\d+)")) 68753eacf3dSLuca Vizzarro #: 68853eacf3dSLuca Vizzarro tx_bps: int = field(metadata=TextParser.find_int(r"Tx-bps:\s+(\d+)")) 68953eacf3dSLuca Vizzarro 69053eacf3dSLuca Vizzarro 691a91d5f47SJeremy Spewockclass PacketOffloadFlag(Flag): 692a91d5f47SJeremy Spewock """Flag representing the Packet Offload Features Flags in DPDK. 693a91d5f47SJeremy Spewock 694a91d5f47SJeremy Spewock Values in this class are taken from the definitions in the RTE MBUF core library in DPDK 695a91d5f47SJeremy Spewock located in ``lib/mbuf/rte_mbuf_core.h``. It is expected that flag values in this class will 696a91d5f47SJeremy Spewock match the values they are set to in said DPDK library with one exception; all values must be 697a91d5f47SJeremy Spewock unique. For example, the definitions for unknown checksum flags in ``rte_mbuf_core.h`` are all 698a91d5f47SJeremy Spewock set to :data:`0`, but it is valuable to distinguish between them in this framework. For this 699a91d5f47SJeremy Spewock reason flags that are not unique in the DPDK library are set either to values within the 700a91d5f47SJeremy Spewock RTE_MBUF_F_FIRST_FREE-RTE_MBUF_F_LAST_FREE range for Rx or shifted 61+ bits for Tx. 701a91d5f47SJeremy Spewock 702a91d5f47SJeremy Spewock References: 703a91d5f47SJeremy Spewock DPDK lib: ``lib/mbuf/rte_mbuf_core.h`` 704a91d5f47SJeremy Spewock """ 705a91d5f47SJeremy Spewock 706a91d5f47SJeremy Spewock # RX flags 707a91d5f47SJeremy Spewock 708a91d5f47SJeremy Spewock #: The RX packet is a 802.1q VLAN packet, and the tci has been saved in mbuf->vlan_tci. If the 709a91d5f47SJeremy Spewock #: flag RTE_MBUF_F_RX_VLAN_STRIPPED is also present, the VLAN header has been stripped from 710a91d5f47SJeremy Spewock #: mbuf data, else it is still present. 711a91d5f47SJeremy Spewock RTE_MBUF_F_RX_VLAN = auto() 712a91d5f47SJeremy Spewock 713a91d5f47SJeremy Spewock #: RX packet with RSS hash result. 714a91d5f47SJeremy Spewock RTE_MBUF_F_RX_RSS_HASH = auto() 715a91d5f47SJeremy Spewock 716a91d5f47SJeremy Spewock #: RX packet with FDIR match indicate. 717a91d5f47SJeremy Spewock RTE_MBUF_F_RX_FDIR = auto() 718a91d5f47SJeremy Spewock 719a91d5f47SJeremy Spewock #: This flag is set when the outermost IP header checksum is detected as wrong by the hardware. 720a91d5f47SJeremy Spewock RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD = 1 << 5 721a91d5f47SJeremy Spewock 722a91d5f47SJeremy Spewock #: A vlan has been stripped by the hardware and its tci is saved in mbuf->vlan_tci. This can 723a91d5f47SJeremy Spewock #: only happen if vlan stripping is enabled in the RX configuration of the PMD. When 724a91d5f47SJeremy Spewock #: RTE_MBUF_F_RX_VLAN_STRIPPED is set, RTE_MBUF_F_RX_VLAN must also be set. 725a91d5f47SJeremy Spewock RTE_MBUF_F_RX_VLAN_STRIPPED = auto() 726a91d5f47SJeremy Spewock 727a91d5f47SJeremy Spewock #: No information about the RX IP checksum. Value is 0 in the DPDK library. 728a91d5f47SJeremy Spewock RTE_MBUF_F_RX_IP_CKSUM_UNKNOWN = 1 << 23 729a91d5f47SJeremy Spewock #: The IP checksum in the packet is wrong. 730a91d5f47SJeremy Spewock RTE_MBUF_F_RX_IP_CKSUM_BAD = 1 << 4 731a91d5f47SJeremy Spewock #: The IP checksum in the packet is valid. 732a91d5f47SJeremy Spewock RTE_MBUF_F_RX_IP_CKSUM_GOOD = 1 << 7 733a91d5f47SJeremy Spewock #: The IP checksum is not correct in the packet data, but the integrity of the IP header is 734a91d5f47SJeremy Spewock #: verified. Value is RTE_MBUF_F_RX_IP_CKSUM_BAD | RTE_MBUF_F_RX_IP_CKSUM_GOOD in the DPDK 735a91d5f47SJeremy Spewock #: library. 736a91d5f47SJeremy Spewock RTE_MBUF_F_RX_IP_CKSUM_NONE = 1 << 24 737a91d5f47SJeremy Spewock 738a91d5f47SJeremy Spewock #: No information about the RX L4 checksum. Value is 0 in the DPDK library. 739a91d5f47SJeremy Spewock RTE_MBUF_F_RX_L4_CKSUM_UNKNOWN = 1 << 25 740a91d5f47SJeremy Spewock #: The L4 checksum in the packet is wrong. 741a91d5f47SJeremy Spewock RTE_MBUF_F_RX_L4_CKSUM_BAD = 1 << 3 742a91d5f47SJeremy Spewock #: The L4 checksum in the packet is valid. 743a91d5f47SJeremy Spewock RTE_MBUF_F_RX_L4_CKSUM_GOOD = 1 << 8 744a91d5f47SJeremy Spewock #: The L4 checksum is not correct in the packet data, but the integrity of the L4 data is 745a91d5f47SJeremy Spewock #: verified. Value is RTE_MBUF_F_RX_L4_CKSUM_BAD | RTE_MBUF_F_RX_L4_CKSUM_GOOD in the DPDK 746a91d5f47SJeremy Spewock #: library. 747a91d5f47SJeremy Spewock RTE_MBUF_F_RX_L4_CKSUM_NONE = 1 << 26 748a91d5f47SJeremy Spewock 749a91d5f47SJeremy Spewock #: RX IEEE1588 L2 Ethernet PT Packet. 750a91d5f47SJeremy Spewock RTE_MBUF_F_RX_IEEE1588_PTP = 1 << 9 751a91d5f47SJeremy Spewock #: RX IEEE1588 L2/L4 timestamped packet. 752a91d5f47SJeremy Spewock RTE_MBUF_F_RX_IEEE1588_TMST = 1 << 10 753a91d5f47SJeremy Spewock 754a91d5f47SJeremy Spewock #: FD id reported if FDIR match. 755a91d5f47SJeremy Spewock RTE_MBUF_F_RX_FDIR_ID = 1 << 13 756a91d5f47SJeremy Spewock #: Flexible bytes reported if FDIR match. 757a91d5f47SJeremy Spewock RTE_MBUF_F_RX_FDIR_FLX = 1 << 14 758a91d5f47SJeremy Spewock 759a91d5f47SJeremy Spewock #: If both RTE_MBUF_F_RX_QINQ_STRIPPED and RTE_MBUF_F_RX_VLAN_STRIPPED are set, the 2 VLANs 760a91d5f47SJeremy Spewock #: have been stripped by the hardware. If RTE_MBUF_F_RX_QINQ_STRIPPED is set and 761a91d5f47SJeremy Spewock #: RTE_MBUF_F_RX_VLAN_STRIPPED is unset, only the outer VLAN is removed from packet data. 762a91d5f47SJeremy Spewock RTE_MBUF_F_RX_QINQ_STRIPPED = auto() 763a91d5f47SJeremy Spewock 764a91d5f47SJeremy Spewock #: When packets are coalesced by a hardware or virtual driver, this flag can be set in the RX 765a91d5f47SJeremy Spewock #: mbuf, meaning that the m->tso_segsz field is valid and is set to the segment size of 766a91d5f47SJeremy Spewock #: original packets. 767a91d5f47SJeremy Spewock RTE_MBUF_F_RX_LRO = auto() 768a91d5f47SJeremy Spewock 769a91d5f47SJeremy Spewock #: Indicate that security offload processing was applied on the RX packet. 770a91d5f47SJeremy Spewock RTE_MBUF_F_RX_SEC_OFFLOAD = 1 << 18 771a91d5f47SJeremy Spewock #: Indicate that security offload processing failed on the RX packet. 772a91d5f47SJeremy Spewock RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED = auto() 773a91d5f47SJeremy Spewock 774a91d5f47SJeremy Spewock #: The RX packet is a double VLAN. If this flag is set, RTE_MBUF_F_RX_VLAN must also be set. If 775a91d5f47SJeremy Spewock #: the flag RTE_MBUF_F_RX_QINQ_STRIPPED is also present, both VLANs headers have been stripped 776a91d5f47SJeremy Spewock #: from mbuf data, else they are still present. 777a91d5f47SJeremy Spewock RTE_MBUF_F_RX_QINQ = auto() 778a91d5f47SJeremy Spewock 779a91d5f47SJeremy Spewock #: No info about the outer RX L4 checksum. Value is 0 in the DPDK library. 780a91d5f47SJeremy Spewock RTE_MBUF_F_RX_OUTER_L4_CKSUM_UNKNOWN = 1 << 27 781a91d5f47SJeremy Spewock #: The outer L4 checksum in the packet is wrong 782a91d5f47SJeremy Spewock RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD = 1 << 21 783a91d5f47SJeremy Spewock #: The outer L4 checksum in the packet is valid 784a91d5f47SJeremy Spewock RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD = 1 << 22 785a91d5f47SJeremy Spewock #: Invalid outer L4 checksum state. Value is 786a91d5f47SJeremy Spewock #: RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD | RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD in the DPDK library. 787a91d5f47SJeremy Spewock RTE_MBUF_F_RX_OUTER_L4_CKSUM_INVALID = 1 << 28 788a91d5f47SJeremy Spewock 789a91d5f47SJeremy Spewock # TX flags 790a91d5f47SJeremy Spewock 791a91d5f47SJeremy Spewock #: Outer UDP checksum offload flag. This flag is used for enabling outer UDP checksum in PMD. 792a91d5f47SJeremy Spewock #: To use outer UDP checksum, the user either needs to enable the following in mbuf: 793a91d5f47SJeremy Spewock #: 794a91d5f47SJeremy Spewock #: a) Fill outer_l2_len and outer_l3_len in mbuf. 795a91d5f47SJeremy Spewock #: b) Set the RTE_MBUF_F_TX_OUTER_UDP_CKSUM flag. 796a91d5f47SJeremy Spewock #: c) Set the RTE_MBUF_F_TX_OUTER_IPV4 or RTE_MBUF_F_TX_OUTER_IPV6 flag. 797a91d5f47SJeremy Spewock #: 798a91d5f47SJeremy Spewock #: Or configure RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM offload flag. 799a91d5f47SJeremy Spewock RTE_MBUF_F_TX_OUTER_UDP_CKSUM = 1 << 41 800a91d5f47SJeremy Spewock 801a91d5f47SJeremy Spewock #: UDP Fragmentation Offload flag. This flag is used for enabling UDP fragmentation in SW or in 802a91d5f47SJeremy Spewock #: HW. 803a91d5f47SJeremy Spewock RTE_MBUF_F_TX_UDP_SEG = auto() 804a91d5f47SJeremy Spewock 805a91d5f47SJeremy Spewock #: Request security offload processing on the TX packet. To use Tx security offload, the user 806a91d5f47SJeremy Spewock #: needs to fill l2_len in mbuf indicating L2 header size and where L3 header starts. 807a91d5f47SJeremy Spewock #: Similarly, l3_len should also be filled along with ol_flags reflecting current L3 type. 808a91d5f47SJeremy Spewock RTE_MBUF_F_TX_SEC_OFFLOAD = auto() 809a91d5f47SJeremy Spewock 810a91d5f47SJeremy Spewock #: Offload the MACsec. This flag must be set by the application to enable this offload feature 811a91d5f47SJeremy Spewock #: for a packet to be transmitted. 812a91d5f47SJeremy Spewock RTE_MBUF_F_TX_MACSEC = auto() 813a91d5f47SJeremy Spewock 814a91d5f47SJeremy Spewock # Bits 45:48 are used for the tunnel type in ``lib/mbuf/rte_mbuf_core.h``, but some are modified 815a91d5f47SJeremy Spewock # in this Flag to maintain uniqueness. The tunnel type must be specified for TSO or checksum on 816a91d5f47SJeremy Spewock # the inner part of tunnel packets. These flags can be used with RTE_MBUF_F_TX_TCP_SEG for TSO, 817a91d5f47SJeremy Spewock # or RTE_MBUF_F_TX_xxx_CKSUM. The mbuf fields for inner and outer header lengths are required: 818a91d5f47SJeremy Spewock # outer_l2_len, outer_l3_len, l2_len, l3_len, l4_len and tso_segsz for TSO. 819a91d5f47SJeremy Spewock 820a91d5f47SJeremy Spewock #: 821a91d5f47SJeremy Spewock RTE_MBUF_F_TX_TUNNEL_VXLAN = 1 << 45 822a91d5f47SJeremy Spewock #: 823a91d5f47SJeremy Spewock RTE_MBUF_F_TX_TUNNEL_GRE = 1 << 46 824a91d5f47SJeremy Spewock #: Value is 3 << 45 in the DPDK library. 825a91d5f47SJeremy Spewock RTE_MBUF_F_TX_TUNNEL_IPIP = 1 << 61 826a91d5f47SJeremy Spewock #: 827a91d5f47SJeremy Spewock RTE_MBUF_F_TX_TUNNEL_GENEVE = 1 << 47 828a91d5f47SJeremy Spewock #: TX packet with MPLS-in-UDP RFC 7510 header. Value is 5 << 45 in the DPDK library. 829a91d5f47SJeremy Spewock RTE_MBUF_F_TX_TUNNEL_MPLSINUDP = 1 << 62 830a91d5f47SJeremy Spewock #: Value is 6 << 45 in the DPDK library. 831a91d5f47SJeremy Spewock RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE = 1 << 63 832a91d5f47SJeremy Spewock #: Value is 7 << 45 in the DPDK library. 833a91d5f47SJeremy Spewock RTE_MBUF_F_TX_TUNNEL_GTP = 1 << 64 834a91d5f47SJeremy Spewock #: 835a91d5f47SJeremy Spewock RTE_MBUF_F_TX_TUNNEL_ESP = 1 << 48 836a91d5f47SJeremy Spewock #: Generic IP encapsulated tunnel type, used for TSO and checksum offload. This can be used for 837a91d5f47SJeremy Spewock #: tunnels which are not standards or listed above. It is preferred to use specific tunnel 838a91d5f47SJeremy Spewock #: flags like RTE_MBUF_F_TX_TUNNEL_GRE or RTE_MBUF_F_TX_TUNNEL_IPIP if possible. The ethdev 839a91d5f47SJeremy Spewock #: must be configured with RTE_ETH_TX_OFFLOAD_IP_TNL_TSO. Outer and inner checksums are done 840a91d5f47SJeremy Spewock #: according to the existing flags like RTE_MBUF_F_TX_xxx_CKSUM. Specific tunnel headers that 841a91d5f47SJeremy Spewock #: contain payload length, sequence id or checksum are not expected to be updated. Value is 842a91d5f47SJeremy Spewock #: 0xD << 45 in the DPDK library. 843a91d5f47SJeremy Spewock RTE_MBUF_F_TX_TUNNEL_IP = 1 << 65 844a91d5f47SJeremy Spewock #: Generic UDP encapsulated tunnel type, used for TSO and checksum offload. UDP tunnel type 845a91d5f47SJeremy Spewock #: implies outer IP layer. It can be used for tunnels which are not standards or listed above. 846a91d5f47SJeremy Spewock #: It is preferred to use specific tunnel flags like RTE_MBUF_F_TX_TUNNEL_VXLAN if possible. 847a91d5f47SJeremy Spewock #: The ethdev must be configured with RTE_ETH_TX_OFFLOAD_UDP_TNL_TSO. Outer and inner checksums 848a91d5f47SJeremy Spewock #: are done according to the existing flags like RTE_MBUF_F_TX_xxx_CKSUM. Specific tunnel 849a91d5f47SJeremy Spewock #: headers that contain payload length, sequence id or checksum are not expected to be updated. 850a91d5f47SJeremy Spewock #: value is 0xE << 45 in the DPDK library. 851a91d5f47SJeremy Spewock RTE_MBUF_F_TX_TUNNEL_UDP = 1 << 66 852a91d5f47SJeremy Spewock 853a91d5f47SJeremy Spewock #: Double VLAN insertion (QinQ) request to driver, driver may offload the insertion based on 854a91d5f47SJeremy Spewock #: device capability. Mbuf 'vlan_tci' & 'vlan_tci_outer' must be valid when this flag is set. 855a91d5f47SJeremy Spewock RTE_MBUF_F_TX_QINQ = 1 << 49 856a91d5f47SJeremy Spewock 857a91d5f47SJeremy Spewock #: TCP segmentation offload. To enable this offload feature for a packet to be transmitted on 858a91d5f47SJeremy Spewock #: hardware supporting TSO: 859a91d5f47SJeremy Spewock #: 860a91d5f47SJeremy Spewock #: - set the RTE_MBUF_F_TX_TCP_SEG flag in mbuf->ol_flags (this flag implies 861a91d5f47SJeremy Spewock #: RTE_MBUF_F_TX_TCP_CKSUM) 862a91d5f47SJeremy Spewock #: - set the flag RTE_MBUF_F_TX_IPV4 or RTE_MBUF_F_TX_IPV6 863a91d5f47SJeremy Spewock #: * if it's IPv4, set the RTE_MBUF_F_TX_IP_CKSUM flag 864a91d5f47SJeremy Spewock #: - fill the mbuf offload information: l2_len, l3_len, l4_len, tso_segsz 865a91d5f47SJeremy Spewock RTE_MBUF_F_TX_TCP_SEG = auto() 866a91d5f47SJeremy Spewock 867a91d5f47SJeremy Spewock #: TX IEEE1588 packet to timestamp. 868a91d5f47SJeremy Spewock RTE_MBUF_F_TX_IEEE1588_TMST = auto() 869a91d5f47SJeremy Spewock 870a91d5f47SJeremy Spewock # Bits 52+53 used for L4 packet type with checksum enabled in ``lib/mbuf/rte_mbuf_core.h`` but 871a91d5f47SJeremy Spewock # some values must be modified in this framework to maintain uniqueness. To use hardware 872a91d5f47SJeremy Spewock # L4 checksum offload, the user needs to: 873a91d5f47SJeremy Spewock # 874a91d5f47SJeremy Spewock # - fill l2_len and l3_len in mbuf 875a91d5f47SJeremy Spewock # - set the flags RTE_MBUF_F_TX_TCP_CKSUM, RTE_MBUF_F_TX_SCTP_CKSUM or 876a91d5f47SJeremy Spewock # RTE_MBUF_F_TX_UDP_CKSUM 877a91d5f47SJeremy Spewock # - set the flag RTE_MBUF_F_TX_IPV4 or RTE_MBUF_F_TX_IPV6 878a91d5f47SJeremy Spewock 879a91d5f47SJeremy Spewock #: Disable L4 cksum of TX pkt. Value is 0 in the DPDK library. 880a91d5f47SJeremy Spewock RTE_MBUF_F_TX_L4_NO_CKSUM = 1 << 67 881a91d5f47SJeremy Spewock #: TCP cksum of TX pkt. Computed by NIC. 882a91d5f47SJeremy Spewock RTE_MBUF_F_TX_TCP_CKSUM = 1 << 52 883a91d5f47SJeremy Spewock #: SCTP cksum of TX pkt. Computed by NIC. 884a91d5f47SJeremy Spewock RTE_MBUF_F_TX_SCTP_CKSUM = 1 << 53 885a91d5f47SJeremy Spewock #: UDP cksum of TX pkt. Computed by NIC. Value is 3 << 52 in the DPDK library. 886a91d5f47SJeremy Spewock RTE_MBUF_F_TX_UDP_CKSUM = 1 << 68 887a91d5f47SJeremy Spewock 888a91d5f47SJeremy Spewock #: Offload the IP checksum in the hardware. The flag RTE_MBUF_F_TX_IPV4 should also be set by 889a91d5f47SJeremy Spewock #: the application, although a PMD will only check RTE_MBUF_F_TX_IP_CKSUM. 890a91d5f47SJeremy Spewock RTE_MBUF_F_TX_IP_CKSUM = 1 << 54 891a91d5f47SJeremy Spewock 892a91d5f47SJeremy Spewock #: Packet is IPv4. This flag must be set when using any offload feature (TSO, L3 or L4 893a91d5f47SJeremy Spewock #: checksum) to tell the NIC that the packet is an IPv4 packet. If the packet is a tunneled 894a91d5f47SJeremy Spewock #: packet, this flag is related to the inner headers. 895a91d5f47SJeremy Spewock RTE_MBUF_F_TX_IPV4 = auto() 896a91d5f47SJeremy Spewock #: Packet is IPv6. This flag must be set when using an offload feature (TSO or L4 checksum) to 897a91d5f47SJeremy Spewock #: tell the NIC that the packet is an IPv6 packet. If the packet is a tunneled packet, this 898a91d5f47SJeremy Spewock #: flag is related to the inner headers. 899a91d5f47SJeremy Spewock RTE_MBUF_F_TX_IPV6 = auto() 900a91d5f47SJeremy Spewock #: VLAN tag insertion request to driver, driver may offload the insertion based on the device 901a91d5f47SJeremy Spewock #: capability. mbuf 'vlan_tci' field must be valid when this flag is set. 902a91d5f47SJeremy Spewock RTE_MBUF_F_TX_VLAN = auto() 903a91d5f47SJeremy Spewock 904a91d5f47SJeremy Spewock #: Offload the IP checksum of an external header in the hardware. The flag 905a91d5f47SJeremy Spewock #: RTE_MBUF_F_TX_OUTER_IPV4 should also be set by the application, although a PMD will only 906a91d5f47SJeremy Spewock #: check RTE_MBUF_F_TX_OUTER_IP_CKSUM. 907a91d5f47SJeremy Spewock RTE_MBUF_F_TX_OUTER_IP_CKSUM = auto() 908a91d5f47SJeremy Spewock #: Packet outer header is IPv4. This flag must be set when using any outer offload feature (L3 909a91d5f47SJeremy Spewock #: or L4 checksum) to tell the NIC that the outer header of the tunneled packet is an IPv4 910a91d5f47SJeremy Spewock #: packet. 911a91d5f47SJeremy Spewock RTE_MBUF_F_TX_OUTER_IPV4 = auto() 912a91d5f47SJeremy Spewock #: Packet outer header is IPv6. This flag must be set when using any outer offload feature (L4 913a91d5f47SJeremy Spewock #: checksum) to tell the NIC that the outer header of the tunneled packet is an IPv6 packet. 914a91d5f47SJeremy Spewock RTE_MBUF_F_TX_OUTER_IPV6 = auto() 915a91d5f47SJeremy Spewock 916a91d5f47SJeremy Spewock @classmethod 917a91d5f47SJeremy Spewock def from_list_string(cls, names: str) -> Self: 918a91d5f47SJeremy Spewock """Makes a flag from a whitespace-separated list of names. 919a91d5f47SJeremy Spewock 920a91d5f47SJeremy Spewock Args: 921a91d5f47SJeremy Spewock names: a whitespace-separated list containing the members of this flag. 922a91d5f47SJeremy Spewock 923a91d5f47SJeremy Spewock Returns: 924a91d5f47SJeremy Spewock An instance of this flag. 925a91d5f47SJeremy Spewock """ 926a91d5f47SJeremy Spewock flag = cls(0) 927a91d5f47SJeremy Spewock for name in names.split(): 928a91d5f47SJeremy Spewock flag |= cls.from_str(name) 929a91d5f47SJeremy Spewock return flag 930a91d5f47SJeremy Spewock 931a91d5f47SJeremy Spewock @classmethod 932a91d5f47SJeremy Spewock def from_str(cls, name: str) -> Self: 933a91d5f47SJeremy Spewock """Makes a flag matching the supplied name. 934a91d5f47SJeremy Spewock 935a91d5f47SJeremy Spewock Args: 936a91d5f47SJeremy Spewock name: a valid member of this flag in text 937a91d5f47SJeremy Spewock Returns: 938a91d5f47SJeremy Spewock An instance of this flag. 939a91d5f47SJeremy Spewock """ 940a91d5f47SJeremy Spewock member_name = name.strip().replace("-", "_") 941a91d5f47SJeremy Spewock return cls[member_name] 942a91d5f47SJeremy Spewock 943a91d5f47SJeremy Spewock @classmethod 944a91d5f47SJeremy Spewock def make_parser(cls) -> ParserFn: 945a91d5f47SJeremy Spewock """Makes a parser function. 946a91d5f47SJeremy Spewock 947a91d5f47SJeremy Spewock Returns: 948a91d5f47SJeremy Spewock ParserFn: A dictionary for the `dataclasses.field` metadata argument containing a 949a91d5f47SJeremy Spewock parser function that makes an instance of this flag from text. 950a91d5f47SJeremy Spewock """ 951a91d5f47SJeremy Spewock return TextParser.wrap( 952a91d5f47SJeremy Spewock TextParser.find(r"ol_flags: ([^\n]+)"), 953a91d5f47SJeremy Spewock cls.from_list_string, 954a91d5f47SJeremy Spewock ) 955a91d5f47SJeremy Spewock 956a91d5f47SJeremy Spewock 957a91d5f47SJeremy Spewockclass RtePTypes(Flag): 958a91d5f47SJeremy Spewock """Flag representing possible packet types in DPDK verbose output. 959a91d5f47SJeremy Spewock 960a91d5f47SJeremy Spewock Values in this class are derived from definitions in the RTE MBUF ptype library in DPDK located 961a91d5f47SJeremy Spewock in ``lib/mbuf/rte_mbuf_ptype.h``. Specifically, the names of values in this class should match 962a91d5f47SJeremy Spewock the possible return options from the functions ``rte_get_ptype_*_name`` in ``rte_mbuf_ptype.c``. 963a91d5f47SJeremy Spewock 964a91d5f47SJeremy Spewock References: 965a91d5f47SJeremy Spewock DPDK lib: ``lib/mbuf/rte_mbuf_ptype.h`` 966a91d5f47SJeremy Spewock DPDK ptype name formatting functions: ``lib/mbuf/rte_mbuf_ptype.c:rte_get_ptype_*_name()`` 967a91d5f47SJeremy Spewock """ 968a91d5f47SJeremy Spewock 969a91d5f47SJeremy Spewock # L2 970a91d5f47SJeremy Spewock #: Ethernet packet type. This is used for outer packet for tunneling cases. 971a91d5f47SJeremy Spewock L2_ETHER = auto() 972a91d5f47SJeremy Spewock #: Ethernet packet type for time sync. 973a91d5f47SJeremy Spewock L2_ETHER_TIMESYNC = auto() 974a91d5f47SJeremy Spewock #: ARP (Address Resolution Protocol) packet type. 975a91d5f47SJeremy Spewock L2_ETHER_ARP = auto() 976a91d5f47SJeremy Spewock #: LLDP (Link Layer Discovery Protocol) packet type. 977a91d5f47SJeremy Spewock L2_ETHER_LLDP = auto() 978a91d5f47SJeremy Spewock #: NSH (Network Service Header) packet type. 979a91d5f47SJeremy Spewock L2_ETHER_NSH = auto() 980a91d5f47SJeremy Spewock #: VLAN packet type. 981a91d5f47SJeremy Spewock L2_ETHER_VLAN = auto() 982a91d5f47SJeremy Spewock #: QinQ packet type. 983a91d5f47SJeremy Spewock L2_ETHER_QINQ = auto() 984a91d5f47SJeremy Spewock #: PPPOE packet type. 985a91d5f47SJeremy Spewock L2_ETHER_PPPOE = auto() 986a91d5f47SJeremy Spewock #: FCoE packet type.. 987a91d5f47SJeremy Spewock L2_ETHER_FCOE = auto() 988a91d5f47SJeremy Spewock #: MPLS packet type. 989a91d5f47SJeremy Spewock L2_ETHER_MPLS = auto() 990a91d5f47SJeremy Spewock #: No L2 packet information. 991a91d5f47SJeremy Spewock L2_UNKNOWN = auto() 992a91d5f47SJeremy Spewock 993a91d5f47SJeremy Spewock # L3 994a91d5f47SJeremy Spewock #: IP (Internet Protocol) version 4 packet type. This is used for outer packet for tunneling 995a91d5f47SJeremy Spewock #: cases, and does not contain any header option. 996a91d5f47SJeremy Spewock L3_IPV4 = auto() 997a91d5f47SJeremy Spewock #: IP (Internet Protocol) version 4 packet type. This is used for outer packet for tunneling 998a91d5f47SJeremy Spewock #: cases, and contains header options. 999a91d5f47SJeremy Spewock L3_IPV4_EXT = auto() 1000a91d5f47SJeremy Spewock #: IP (Internet Protocol) version 6 packet type. This is used for outer packet for tunneling 1001a91d5f47SJeremy Spewock #: cases, and does not contain any extension header. 1002a91d5f47SJeremy Spewock L3_IPV6 = auto() 1003a91d5f47SJeremy Spewock #: IP (Internet Protocol) version 4 packet type. This is used for outer packet for tunneling 1004a91d5f47SJeremy Spewock #: cases, and may or maynot contain header options. 1005a91d5f47SJeremy Spewock L3_IPV4_EXT_UNKNOWN = auto() 1006a91d5f47SJeremy Spewock #: IP (Internet Protocol) version 6 packet type. This is used for outer packet for tunneling 1007a91d5f47SJeremy Spewock #: cases, and contains extension headers. 1008a91d5f47SJeremy Spewock L3_IPV6_EXT = auto() 1009a91d5f47SJeremy Spewock #: IP (Internet Protocol) version 6 packet type. This is used for outer packet for tunneling 1010a91d5f47SJeremy Spewock #: cases, and may or maynot contain extension headers. 1011a91d5f47SJeremy Spewock L3_IPV6_EXT_UNKNOWN = auto() 1012a91d5f47SJeremy Spewock #: No L3 packet information. 1013a91d5f47SJeremy Spewock L3_UNKNOWN = auto() 1014a91d5f47SJeremy Spewock 1015a91d5f47SJeremy Spewock # L4 1016a91d5f47SJeremy Spewock #: TCP (Transmission Control Protocol) packet type. This is used for outer packet for tunneling 1017a91d5f47SJeremy Spewock #: cases. 1018a91d5f47SJeremy Spewock L4_TCP = auto() 1019a91d5f47SJeremy Spewock #: UDP (User Datagram Protocol) packet type. This is used for outer packet for tunneling cases. 1020a91d5f47SJeremy Spewock L4_UDP = auto() 1021a91d5f47SJeremy Spewock #: Fragmented IP (Internet Protocol) packet type. This is used for outer packet for tunneling 1022a91d5f47SJeremy Spewock #: cases and refers to those packets of any IP types which can be recognized as fragmented. A 1023a91d5f47SJeremy Spewock #: fragmented packet cannot be recognized as any other L4 types (RTE_PTYPE_L4_TCP, 1024a91d5f47SJeremy Spewock #: RTE_PTYPE_L4_UDP, RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP, RTE_PTYPE_L4_NONFRAG). 1025a91d5f47SJeremy Spewock L4_FRAG = auto() 1026a91d5f47SJeremy Spewock #: SCTP (Stream Control Transmission Protocol) packet type. This is used for outer packet for 1027a91d5f47SJeremy Spewock #: tunneling cases. 1028a91d5f47SJeremy Spewock L4_SCTP = auto() 1029a91d5f47SJeremy Spewock #: ICMP (Internet Control Message Protocol) packet type. This is used for outer packet for 1030a91d5f47SJeremy Spewock #: tunneling cases. 1031a91d5f47SJeremy Spewock L4_ICMP = auto() 1032a91d5f47SJeremy Spewock #: Non-fragmented IP (Internet Protocol) packet type. This is used for outer packet for 1033a91d5f47SJeremy Spewock #: tunneling cases and refers to those packets of any IP types, that cannot be recognized as 1034a91d5f47SJeremy Spewock #: any of the above L4 types (RTE_PTYPE_L4_TCP, RTE_PTYPE_L4_UDP, RTE_PTYPE_L4_FRAG, 1035a91d5f47SJeremy Spewock #: RTE_PTYPE_L4_SCTP, RTE_PTYPE_L4_ICMP). 1036a91d5f47SJeremy Spewock L4_NONFRAG = auto() 1037a91d5f47SJeremy Spewock #: IGMP (Internet Group Management Protocol) packet type. 1038a91d5f47SJeremy Spewock L4_IGMP = auto() 1039a91d5f47SJeremy Spewock #: No L4 packet information. 1040a91d5f47SJeremy Spewock L4_UNKNOWN = auto() 1041a91d5f47SJeremy Spewock 1042a91d5f47SJeremy Spewock # Tunnel 1043a91d5f47SJeremy Spewock #: IP (Internet Protocol) in IP (Internet Protocol) tunneling packet type. 1044a91d5f47SJeremy Spewock TUNNEL_IP = auto() 1045a91d5f47SJeremy Spewock #: GRE (Generic Routing Encapsulation) tunneling packet type. 1046a91d5f47SJeremy Spewock TUNNEL_GRE = auto() 1047a91d5f47SJeremy Spewock #: VXLAN (Virtual eXtensible Local Area Network) tunneling packet type. 1048a91d5f47SJeremy Spewock TUNNEL_VXLAN = auto() 1049a91d5f47SJeremy Spewock #: NVGRE (Network Virtualization using Generic Routing Encapsulation) tunneling packet type. 1050a91d5f47SJeremy Spewock TUNNEL_NVGRE = auto() 1051a91d5f47SJeremy Spewock #: GENEVE (Generic Network Virtualization Encapsulation) tunneling packet type. 1052a91d5f47SJeremy Spewock TUNNEL_GENEVE = auto() 1053a91d5f47SJeremy Spewock #: Tunneling packet type of Teredo, VXLAN (Virtual eXtensible Local Area Network) or GRE 1054a91d5f47SJeremy Spewock #: (Generic Routing Encapsulation) could be recognized as this packet type, if they can not be 1055a91d5f47SJeremy Spewock #: recognized independently as of hardware capability. 1056a91d5f47SJeremy Spewock TUNNEL_GRENAT = auto() 1057a91d5f47SJeremy Spewock #: GTP-C (GPRS Tunnelling Protocol) control tunneling packet type. 1058a91d5f47SJeremy Spewock TUNNEL_GTPC = auto() 1059a91d5f47SJeremy Spewock #: GTP-U (GPRS Tunnelling Protocol) user data tunneling packet type. 1060a91d5f47SJeremy Spewock TUNNEL_GTPU = auto() 1061a91d5f47SJeremy Spewock #: ESP (IP Encapsulating Security Payload) tunneling packet type. 1062a91d5f47SJeremy Spewock TUNNEL_ESP = auto() 1063a91d5f47SJeremy Spewock #: L2TP (Layer 2 Tunneling Protocol) tunneling packet type. 1064a91d5f47SJeremy Spewock TUNNEL_L2TP = auto() 1065a91d5f47SJeremy Spewock #: VXLAN-GPE (VXLAN Generic Protocol Extension) tunneling packet type. 1066a91d5f47SJeremy Spewock TUNNEL_VXLAN_GPE = auto() 1067a91d5f47SJeremy Spewock #: MPLS-in-UDP tunneling packet type (RFC 7510). 1068a91d5f47SJeremy Spewock TUNNEL_MPLS_IN_UDP = auto() 1069a91d5f47SJeremy Spewock #: MPLS-in-GRE tunneling packet type (RFC 4023). 1070a91d5f47SJeremy Spewock TUNNEL_MPLS_IN_GRE = auto() 1071a91d5f47SJeremy Spewock #: No tunnel information found on the packet. 1072a91d5f47SJeremy Spewock TUNNEL_UNKNOWN = auto() 1073a91d5f47SJeremy Spewock 1074a91d5f47SJeremy Spewock # Inner L2 1075a91d5f47SJeremy Spewock #: Ethernet packet type. This is used for inner packet type only. 1076a91d5f47SJeremy Spewock INNER_L2_ETHER = auto() 1077a91d5f47SJeremy Spewock #: Ethernet packet type with VLAN (Virtual Local Area Network) tag. 1078a91d5f47SJeremy Spewock INNER_L2_ETHER_VLAN = auto() 1079a91d5f47SJeremy Spewock #: QinQ packet type. 1080a91d5f47SJeremy Spewock INNER_L2_ETHER_QINQ = auto() 1081a91d5f47SJeremy Spewock #: No inner L2 information found on the packet. 1082a91d5f47SJeremy Spewock INNER_L2_UNKNOWN = auto() 1083a91d5f47SJeremy Spewock 1084a91d5f47SJeremy Spewock # Inner L3 1085a91d5f47SJeremy Spewock #: IP (Internet Protocol) version 4 packet type. This is used for inner packet only, and does 1086a91d5f47SJeremy Spewock #: not contain any header option. 1087a91d5f47SJeremy Spewock INNER_L3_IPV4 = auto() 1088a91d5f47SJeremy Spewock #: IP (Internet Protocol) version 4 packet type. This is used for inner packet only, and 1089a91d5f47SJeremy Spewock #: contains header options. 1090a91d5f47SJeremy Spewock INNER_L3_IPV4_EXT = auto() 1091a91d5f47SJeremy Spewock #: IP (Internet Protocol) version 6 packet type. This is used for inner packet only, and does 1092a91d5f47SJeremy Spewock #: not contain any extension header. 1093a91d5f47SJeremy Spewock INNER_L3_IPV6 = auto() 1094a91d5f47SJeremy Spewock #: IP (Internet Protocol) version 4 packet type. This is used for inner packet only, and may or 1095a91d5f47SJeremy Spewock #: may not contain header options. 1096a91d5f47SJeremy Spewock INNER_L3_IPV4_EXT_UNKNOWN = auto() 1097a91d5f47SJeremy Spewock #: IP (Internet Protocol) version 6 packet type. This is used for inner packet only, and 1098a91d5f47SJeremy Spewock #: contains extension headers. 1099a91d5f47SJeremy Spewock INNER_L3_IPV6_EXT = auto() 1100a91d5f47SJeremy Spewock #: IP (Internet Protocol) version 6 packet type. This is used for inner packet only, and may or 1101a91d5f47SJeremy Spewock #: may not contain extension headers. 1102a91d5f47SJeremy Spewock INNER_L3_IPV6_EXT_UNKNOWN = auto() 1103a91d5f47SJeremy Spewock #: No inner L3 information found on the packet. 1104a91d5f47SJeremy Spewock INNER_L3_UNKNOWN = auto() 1105a91d5f47SJeremy Spewock 1106a91d5f47SJeremy Spewock # Inner L4 1107a91d5f47SJeremy Spewock #: TCP (Transmission Control Protocol) packet type. This is used for inner packet only. 1108a91d5f47SJeremy Spewock INNER_L4_TCP = auto() 1109a91d5f47SJeremy Spewock #: UDP (User Datagram Protocol) packet type. This is used for inner packet only. 1110a91d5f47SJeremy Spewock INNER_L4_UDP = auto() 1111a91d5f47SJeremy Spewock #: Fragmented IP (Internet Protocol) packet type. This is used for inner packet only, and may 1112a91d5f47SJeremy Spewock #: or maynot have a layer 4 packet. 1113a91d5f47SJeremy Spewock INNER_L4_FRAG = auto() 1114a91d5f47SJeremy Spewock #: SCTP (Stream Control Transmission Protocol) packet type. This is used for inner packet only. 1115a91d5f47SJeremy Spewock INNER_L4_SCTP = auto() 1116a91d5f47SJeremy Spewock #: ICMP (Internet Control Message Protocol) packet type. This is used for inner packet only. 1117a91d5f47SJeremy Spewock INNER_L4_ICMP = auto() 1118a91d5f47SJeremy Spewock #: Non-fragmented IP (Internet Protocol) packet type. It is used for inner packet only, and may 1119a91d5f47SJeremy Spewock #: or may not have other unknown layer 4 packet types. 1120a91d5f47SJeremy Spewock INNER_L4_NONFRAG = auto() 1121a91d5f47SJeremy Spewock #: No inner L4 information found on the packet. 1122a91d5f47SJeremy Spewock INNER_L4_UNKNOWN = auto() 1123a91d5f47SJeremy Spewock 1124a91d5f47SJeremy Spewock @classmethod 1125a91d5f47SJeremy Spewock def from_list_string(cls, names: str) -> Self: 1126a91d5f47SJeremy Spewock """Makes a flag from a whitespace-separated list of names. 1127a91d5f47SJeremy Spewock 1128a91d5f47SJeremy Spewock Args: 1129a91d5f47SJeremy Spewock names: a whitespace-separated list containing the members of this flag. 1130a91d5f47SJeremy Spewock 1131a91d5f47SJeremy Spewock Returns: 1132a91d5f47SJeremy Spewock An instance of this flag. 1133a91d5f47SJeremy Spewock """ 1134a91d5f47SJeremy Spewock flag = cls(0) 1135a91d5f47SJeremy Spewock for name in names.split(): 1136a91d5f47SJeremy Spewock flag |= cls.from_str(name) 1137a91d5f47SJeremy Spewock return flag 1138a91d5f47SJeremy Spewock 1139a91d5f47SJeremy Spewock @classmethod 1140a91d5f47SJeremy Spewock def from_str(cls, name: str) -> Self: 1141a91d5f47SJeremy Spewock """Makes a flag matching the supplied name. 1142a91d5f47SJeremy Spewock 1143a91d5f47SJeremy Spewock Args: 1144a91d5f47SJeremy Spewock name: a valid member of this flag in text 1145a91d5f47SJeremy Spewock Returns: 1146a91d5f47SJeremy Spewock An instance of this flag. 1147a91d5f47SJeremy Spewock """ 1148a91d5f47SJeremy Spewock member_name = name.strip().replace("-", "_") 1149a91d5f47SJeremy Spewock return cls[member_name] 1150a91d5f47SJeremy Spewock 1151a91d5f47SJeremy Spewock @classmethod 1152a91d5f47SJeremy Spewock def make_parser(cls, hw: bool) -> ParserFn: 1153a91d5f47SJeremy Spewock """Makes a parser function. 1154a91d5f47SJeremy Spewock 1155a91d5f47SJeremy Spewock Args: 1156a91d5f47SJeremy Spewock hw: Whether to make a parser for hardware ptypes or software ptypes. If :data:`True`, 1157a91d5f47SJeremy Spewock hardware ptypes will be collected, otherwise software pytpes will. 1158a91d5f47SJeremy Spewock 1159a91d5f47SJeremy Spewock Returns: 1160a91d5f47SJeremy Spewock ParserFn: A dictionary for the `dataclasses.field` metadata argument containing a 1161a91d5f47SJeremy Spewock parser function that makes an instance of this flag from text. 1162a91d5f47SJeremy Spewock """ 1163a91d5f47SJeremy Spewock return TextParser.wrap( 1164a91d5f47SJeremy Spewock TextParser.find(f"{'hw' if hw else 'sw'} ptype: ([^-]+)"), 1165a91d5f47SJeremy Spewock cls.from_list_string, 1166a91d5f47SJeremy Spewock ) 1167a91d5f47SJeremy Spewock 1168a91d5f47SJeremy Spewock 1169a91d5f47SJeremy Spewock@dataclass 1170a91d5f47SJeremy Spewockclass TestPmdVerbosePacket(TextParser): 1171a91d5f47SJeremy Spewock """Packet information provided by verbose output in Testpmd. 1172a91d5f47SJeremy Spewock 1173a91d5f47SJeremy Spewock This dataclass expects that packet information be prepended with the starting line of packet 1174a91d5f47SJeremy Spewock bursts. Specifically, the line that reads "port X/queue Y: sent/received Z packets". 1175a91d5f47SJeremy Spewock """ 1176a91d5f47SJeremy Spewock 1177a91d5f47SJeremy Spewock #: ID of the port that handled the packet. 1178a91d5f47SJeremy Spewock port_id: int = field(metadata=TextParser.find_int(r"port (\d+)/queue \d+")) 1179a91d5f47SJeremy Spewock #: ID of the queue that handled the packet. 1180a91d5f47SJeremy Spewock queue_id: int = field(metadata=TextParser.find_int(r"port \d+/queue (\d+)")) 1181a91d5f47SJeremy Spewock #: Whether the packet was received or sent by the queue/port. 1182a91d5f47SJeremy Spewock was_received: bool = field(metadata=TextParser.find(r"received \d+ packets")) 1183a91d5f47SJeremy Spewock #: 1184a91d5f47SJeremy Spewock src_mac: str = field(metadata=TextParser.find(f"src=({REGEX_FOR_MAC_ADDRESS})")) 1185a91d5f47SJeremy Spewock #: 1186a91d5f47SJeremy Spewock dst_mac: str = field(metadata=TextParser.find(f"dst=({REGEX_FOR_MAC_ADDRESS})")) 1187a91d5f47SJeremy Spewock #: Memory pool the packet was handled on. 1188a91d5f47SJeremy Spewock pool: str = field(metadata=TextParser.find(r"pool=(\S+)")) 1189a91d5f47SJeremy Spewock #: Packet type in hex. 1190a91d5f47SJeremy Spewock p_type: int = field(metadata=TextParser.find_int(r"type=(0x[a-fA-F\d]+)")) 1191a91d5f47SJeremy Spewock #: 1192a91d5f47SJeremy Spewock length: int = field(metadata=TextParser.find_int(r"length=(\d+)")) 1193a91d5f47SJeremy Spewock #: Number of segments in the packet. 1194a91d5f47SJeremy Spewock nb_segs: int = field(metadata=TextParser.find_int(r"nb_segs=(\d+)")) 1195a91d5f47SJeremy Spewock #: Hardware packet type. 1196a91d5f47SJeremy Spewock hw_ptype: RtePTypes = field(metadata=RtePTypes.make_parser(hw=True)) 1197a91d5f47SJeremy Spewock #: Software packet type. 1198a91d5f47SJeremy Spewock sw_ptype: RtePTypes = field(metadata=RtePTypes.make_parser(hw=False)) 1199a91d5f47SJeremy Spewock #: 1200a91d5f47SJeremy Spewock l2_len: int = field(metadata=TextParser.find_int(r"l2_len=(\d+)")) 1201a91d5f47SJeremy Spewock #: 1202a91d5f47SJeremy Spewock ol_flags: PacketOffloadFlag = field(metadata=PacketOffloadFlag.make_parser()) 1203a91d5f47SJeremy Spewock #: RSS hash of the packet in hex. 1204a91d5f47SJeremy Spewock rss_hash: int | None = field( 1205a91d5f47SJeremy Spewock default=None, metadata=TextParser.find_int(r"RSS hash=(0x[a-fA-F\d]+)") 1206a91d5f47SJeremy Spewock ) 1207a91d5f47SJeremy Spewock #: RSS queue that handled the packet in hex. 1208a91d5f47SJeremy Spewock rss_queue: int | None = field( 1209a91d5f47SJeremy Spewock default=None, metadata=TextParser.find_int(r"RSS queue=(0x[a-fA-F\d]+)") 1210a91d5f47SJeremy Spewock ) 1211a91d5f47SJeremy Spewock #: 1212a91d5f47SJeremy Spewock l3_len: int | None = field(default=None, metadata=TextParser.find_int(r"l3_len=(\d+)")) 1213a91d5f47SJeremy Spewock #: 1214a91d5f47SJeremy Spewock l4_len: int | None = field(default=None, metadata=TextParser.find_int(r"l4_len=(\d+)")) 1215a91d5f47SJeremy Spewock 1216a91d5f47SJeremy Spewock 1217a79884f9SJuraj Linkešclass RxOffloadCapability(Flag): 1218a79884f9SJuraj Linkeš """Rx offload capabilities of a device. 1219a79884f9SJuraj Linkeš 1220a79884f9SJuraj Linkeš The flags are taken from ``lib/ethdev/rte_ethdev.h``. 1221a79884f9SJuraj Linkeš They're prefixed with ``RTE_ETH_RX_OFFLOAD`` in ``lib/ethdev/rte_ethdev.h`` 1222a79884f9SJuraj Linkeš instead of ``RX_OFFLOAD``, which is what testpmd changes the prefix to. 1223a79884f9SJuraj Linkeš The values are not contiguous, so the correspondence is preserved 1224a79884f9SJuraj Linkeš by specifying concrete values interspersed between auto() values. 1225a79884f9SJuraj Linkeš 1226a79884f9SJuraj Linkeš The ``RX_OFFLOAD`` prefix has been preserved so that the same flag names can be used 1227a79884f9SJuraj Linkeš in :class:`NicCapability`. The prefix is needed in :class:`NicCapability` since there's 1228a79884f9SJuraj Linkeš no other qualifier which would sufficiently distinguish it from other capabilities. 1229a79884f9SJuraj Linkeš 1230a79884f9SJuraj Linkeš References: 1231a79884f9SJuraj Linkeš DPDK lib: ``lib/ethdev/rte_ethdev.h`` 1232a79884f9SJuraj Linkeš testpmd display function: ``app/test-pmd/cmdline.c:print_rx_offloads()`` 1233a79884f9SJuraj Linkeš """ 1234a79884f9SJuraj Linkeš 1235a79884f9SJuraj Linkeš #: 1236a79884f9SJuraj Linkeš RX_OFFLOAD_VLAN_STRIP = auto() 1237a79884f9SJuraj Linkeš #: Device supports L3 checksum offload. 1238a79884f9SJuraj Linkeš RX_OFFLOAD_IPV4_CKSUM = auto() 1239a79884f9SJuraj Linkeš #: Device supports L4 checksum offload. 1240a79884f9SJuraj Linkeš RX_OFFLOAD_UDP_CKSUM = auto() 1241a79884f9SJuraj Linkeš #: Device supports L4 checksum offload. 1242a79884f9SJuraj Linkeš RX_OFFLOAD_TCP_CKSUM = auto() 1243a79884f9SJuraj Linkeš #: Device supports Large Receive Offload. 1244a79884f9SJuraj Linkeš RX_OFFLOAD_TCP_LRO = auto() 1245a79884f9SJuraj Linkeš #: Device supports QinQ (queue in queue) offload. 1246a79884f9SJuraj Linkeš RX_OFFLOAD_QINQ_STRIP = auto() 1247a79884f9SJuraj Linkeš #: Device supports inner packet L3 checksum. 1248a79884f9SJuraj Linkeš RX_OFFLOAD_OUTER_IPV4_CKSUM = auto() 1249a79884f9SJuraj Linkeš #: Device supports MACsec. 1250a79884f9SJuraj Linkeš RX_OFFLOAD_MACSEC_STRIP = auto() 1251a79884f9SJuraj Linkeš #: Device supports filtering of a VLAN Tag identifier. 1252a79884f9SJuraj Linkeš RX_OFFLOAD_VLAN_FILTER = 1 << 9 1253a79884f9SJuraj Linkeš #: Device supports VLAN offload. 1254a79884f9SJuraj Linkeš RX_OFFLOAD_VLAN_EXTEND = auto() 1255a79884f9SJuraj Linkeš #: Device supports receiving segmented mbufs. 1256a79884f9SJuraj Linkeš RX_OFFLOAD_SCATTER = 1 << 13 1257a79884f9SJuraj Linkeš #: Device supports Timestamp. 1258a79884f9SJuraj Linkeš RX_OFFLOAD_TIMESTAMP = auto() 1259a79884f9SJuraj Linkeš #: Device supports crypto processing while packet is received in NIC. 1260a79884f9SJuraj Linkeš RX_OFFLOAD_SECURITY = auto() 1261a79884f9SJuraj Linkeš #: Device supports CRC stripping. 1262a79884f9SJuraj Linkeš RX_OFFLOAD_KEEP_CRC = auto() 1263a79884f9SJuraj Linkeš #: Device supports L4 checksum offload. 1264a79884f9SJuraj Linkeš RX_OFFLOAD_SCTP_CKSUM = auto() 1265a79884f9SJuraj Linkeš #: Device supports inner packet L4 checksum. 1266a79884f9SJuraj Linkeš RX_OFFLOAD_OUTER_UDP_CKSUM = auto() 1267a79884f9SJuraj Linkeš #: Device supports RSS hashing. 1268a79884f9SJuraj Linkeš RX_OFFLOAD_RSS_HASH = auto() 1269a79884f9SJuraj Linkeš #: Device supports 1270a79884f9SJuraj Linkeš RX_OFFLOAD_BUFFER_SPLIT = auto() 1271a79884f9SJuraj Linkeš #: Device supports all checksum capabilities. 1272a79884f9SJuraj Linkeš RX_OFFLOAD_CHECKSUM = RX_OFFLOAD_IPV4_CKSUM | RX_OFFLOAD_UDP_CKSUM | RX_OFFLOAD_TCP_CKSUM 1273a79884f9SJuraj Linkeš #: Device supports all VLAN capabilities. 1274a79884f9SJuraj Linkeš RX_OFFLOAD_VLAN = ( 1275a79884f9SJuraj Linkeš RX_OFFLOAD_VLAN_STRIP 1276a79884f9SJuraj Linkeš | RX_OFFLOAD_VLAN_FILTER 1277a79884f9SJuraj Linkeš | RX_OFFLOAD_VLAN_EXTEND 1278a79884f9SJuraj Linkeš | RX_OFFLOAD_QINQ_STRIP 1279a79884f9SJuraj Linkeš ) 1280a79884f9SJuraj Linkeš 1281a79884f9SJuraj Linkeš @classmethod 1282a79884f9SJuraj Linkeš def from_string(cls, line: str) -> Self: 1283a79884f9SJuraj Linkeš """Make an instance from a string containing the flag names separated with a space. 1284a79884f9SJuraj Linkeš 1285a79884f9SJuraj Linkeš Args: 1286a79884f9SJuraj Linkeš line: The line to parse. 1287a79884f9SJuraj Linkeš 1288a79884f9SJuraj Linkeš Returns: 1289a79884f9SJuraj Linkeš A new instance containing all found flags. 1290a79884f9SJuraj Linkeš """ 1291a79884f9SJuraj Linkeš flag = cls(0) 1292a79884f9SJuraj Linkeš for flag_name in line.split(): 1293a79884f9SJuraj Linkeš flag |= cls[f"RX_OFFLOAD_{flag_name}"] 1294a79884f9SJuraj Linkeš return flag 1295a79884f9SJuraj Linkeš 1296a79884f9SJuraj Linkeš @classmethod 1297a79884f9SJuraj Linkeš def make_parser(cls, per_port: bool) -> ParserFn: 1298a79884f9SJuraj Linkeš """Make a parser function. 1299a79884f9SJuraj Linkeš 1300a79884f9SJuraj Linkeš Args: 1301a79884f9SJuraj Linkeš per_port: If :data:`True`, will return capabilities per port. If :data:`False`, 1302a79884f9SJuraj Linkeš will return capabilities per queue. 1303a79884f9SJuraj Linkeš 1304a79884f9SJuraj Linkeš Returns: 1305a79884f9SJuraj Linkeš ParserFn: A dictionary for the `dataclasses.field` metadata argument containing a 1306a79884f9SJuraj Linkeš parser function that makes an instance of this flag from text. 1307a79884f9SJuraj Linkeš """ 1308a79884f9SJuraj Linkeš granularity = "Port" if per_port else "Queue" 1309a79884f9SJuraj Linkeš return TextParser.wrap( 1310a79884f9SJuraj Linkeš TextParser.find(rf"Per {granularity}\s+:(.*)$", re.MULTILINE), 1311a79884f9SJuraj Linkeš cls.from_string, 1312a79884f9SJuraj Linkeš ) 1313a79884f9SJuraj Linkeš 1314a79884f9SJuraj Linkeš 1315a79884f9SJuraj Linkeš@dataclass 1316a79884f9SJuraj Linkešclass RxOffloadCapabilities(TextParser): 1317a79884f9SJuraj Linkeš """The result of testpmd's ``show port <port_id> rx_offload capabilities`` command. 1318a79884f9SJuraj Linkeš 1319a79884f9SJuraj Linkeš References: 1320a79884f9SJuraj Linkeš testpmd command function: ``app/test-pmd/cmdline.c:cmd_rx_offload_get_capa()`` 1321a79884f9SJuraj Linkeš testpmd display function: ``app/test-pmd/cmdline.c:cmd_rx_offload_get_capa_parsed()`` 1322a79884f9SJuraj Linkeš """ 1323a79884f9SJuraj Linkeš 1324a79884f9SJuraj Linkeš #: 1325a79884f9SJuraj Linkeš port_id: int = field( 1326a79884f9SJuraj Linkeš metadata=TextParser.find_int(r"Rx Offloading Capabilities of port (\d+) :") 1327a79884f9SJuraj Linkeš ) 1328a79884f9SJuraj Linkeš #: Per-queue Rx offload capabilities. 1329a79884f9SJuraj Linkeš per_queue: RxOffloadCapability = field(metadata=RxOffloadCapability.make_parser(False)) 1330a79884f9SJuraj Linkeš #: Capabilities other than per-queue Rx offload capabilities. 1331a79884f9SJuraj Linkeš per_port: RxOffloadCapability = field(metadata=RxOffloadCapability.make_parser(True)) 1332a79884f9SJuraj Linkeš 1333a79884f9SJuraj Linkeš 13342ecfd126SLuca Vizzarrodef requires_stopped_ports(func: TestPmdShellMethod) -> TestPmdShellMethod: 13352ecfd126SLuca Vizzarro """Decorator for :class:`TestPmdShell` commands methods that require stopped ports. 13362ecfd126SLuca Vizzarro 13372ecfd126SLuca Vizzarro If the decorated method is called while the ports are started, then these are stopped before 13382ecfd126SLuca Vizzarro continuing. 13392ecfd126SLuca Vizzarro 13402ecfd126SLuca Vizzarro Args: 13412ecfd126SLuca Vizzarro func: The :class:`TestPmdShell` method to decorate. 13422ecfd126SLuca Vizzarro """ 13432ecfd126SLuca Vizzarro 13442ecfd126SLuca Vizzarro @functools.wraps(func) 13452ecfd126SLuca Vizzarro def _wrapper(self: "TestPmdShell", *args: P.args, **kwargs: P.kwargs): 13462ecfd126SLuca Vizzarro if self.ports_started: 13472ecfd126SLuca Vizzarro self._logger.debug("Ports need to be stopped to continue.") 13482ecfd126SLuca Vizzarro self.stop_all_ports() 13492ecfd126SLuca Vizzarro 13502ecfd126SLuca Vizzarro return func(self, *args, **kwargs) 13512ecfd126SLuca Vizzarro 13522ecfd126SLuca Vizzarro return _wrapper 13532ecfd126SLuca Vizzarro 13542ecfd126SLuca Vizzarro 13552ecfd126SLuca Vizzarrodef requires_started_ports(func: TestPmdShellMethod) -> TestPmdShellMethod: 13562ecfd126SLuca Vizzarro """Decorator for :class:`TestPmdShell` commands methods that require started ports. 13572ecfd126SLuca Vizzarro 13582ecfd126SLuca Vizzarro If the decorated method is called while the ports are stopped, then these are started before 13592ecfd126SLuca Vizzarro continuing. 13602ecfd126SLuca Vizzarro 13612ecfd126SLuca Vizzarro Args: 13622ecfd126SLuca Vizzarro func: The :class:`TestPmdShell` method to decorate. 13632ecfd126SLuca Vizzarro """ 13642ecfd126SLuca Vizzarro 13652ecfd126SLuca Vizzarro @functools.wraps(func) 13662ecfd126SLuca Vizzarro def _wrapper(self: "TestPmdShell", *args: P.args, **kwargs: P.kwargs): 13672ecfd126SLuca Vizzarro if not self.ports_started: 13682ecfd126SLuca Vizzarro self._logger.debug("Ports need to be started to continue.") 13692ecfd126SLuca Vizzarro self.start_all_ports() 13702ecfd126SLuca Vizzarro 13712ecfd126SLuca Vizzarro return func(self, *args, **kwargs) 13722ecfd126SLuca Vizzarro 13732ecfd126SLuca Vizzarro return _wrapper 13742ecfd126SLuca Vizzarro 13752ecfd126SLuca Vizzarro 1376c0119400SJuraj Linkešdef add_remove_mtu(mtu: int = 1500) -> Callable[[TestPmdShellMethod], TestPmdShellMethod]: 1377c0119400SJuraj Linkeš """Configure MTU to `mtu` on all ports, run the decorated function, then revert. 1378c0119400SJuraj Linkeš 1379c0119400SJuraj Linkeš Args: 1380c0119400SJuraj Linkeš mtu: The MTU to configure all ports on. 1381c0119400SJuraj Linkeš 1382c0119400SJuraj Linkeš Returns: 1383c0119400SJuraj Linkeš The method decorated with setting and reverting MTU. 1384c0119400SJuraj Linkeš """ 1385c0119400SJuraj Linkeš 1386c0119400SJuraj Linkeš def decorator(func: TestPmdShellMethod) -> TestPmdShellMethod: 1387c0119400SJuraj Linkeš @functools.wraps(func) 1388c0119400SJuraj Linkeš def wrapper(self: "TestPmdShell", *args: P.args, **kwargs: P.kwargs): 1389c0119400SJuraj Linkeš original_mtu = self.ports[0].mtu 1390c0119400SJuraj Linkeš self.set_port_mtu_all(mtu=mtu, verify=False) 1391c0119400SJuraj Linkeš retval = func(self, *args, **kwargs) 1392c0119400SJuraj Linkeš self.set_port_mtu_all(original_mtu if original_mtu else 1500, verify=False) 1393c0119400SJuraj Linkeš return retval 1394c0119400SJuraj Linkeš 1395c0119400SJuraj Linkeš return wrapper 1396c0119400SJuraj Linkeš 1397c0119400SJuraj Linkeš return decorator 1398c0119400SJuraj Linkeš 1399c0119400SJuraj Linkeš 1400bfad0948SLuca Vizzarroclass TestPmdShell(DPDKShell): 14016ef07151SJuraj Linkeš """Testpmd interactive shell. 14026ef07151SJuraj Linkeš 14036ef07151SJuraj Linkeš The testpmd shell users should never use 14046ef07151SJuraj Linkeš the :meth:`~.interactive_shell.InteractiveShell.send_command` method directly, but rather 14056ef07151SJuraj Linkeš call specialized methods. If there isn't one that satisfies a need, it should be added. 14062ecfd126SLuca Vizzarro 14072ecfd126SLuca Vizzarro Attributes: 14082ecfd126SLuca Vizzarro ports_started: Indicates whether the ports are started. 14096ef07151SJuraj Linkeš """ 14106ef07151SJuraj Linkeš 1411bfad0948SLuca Vizzarro _app_params: TestPmdParams 141285d15c7cSJuraj Linkeš _ports: list[TestPmdPort] | None 1413369d34b8SJeremy Spewock 14146ef07151SJuraj Linkeš #: The path to the testpmd executable. 14156ef07151SJuraj Linkeš path: ClassVar[PurePath] = PurePath("app", "dpdk-testpmd") 14166ef07151SJuraj Linkeš 14176ef07151SJuraj Linkeš #: The testpmd's prompt. 14186ef07151SJuraj Linkeš _default_prompt: ClassVar[str] = "testpmd>" 14196ef07151SJuraj Linkeš 14206ef07151SJuraj Linkeš #: This forces the prompt to appear after sending a command. 14216ef07151SJuraj Linkeš _command_extra_chars: ClassVar[str] = "\n" 1422840b1e01SJuraj Linkeš 14232ecfd126SLuca Vizzarro ports_started: bool 14242ecfd126SLuca Vizzarro 1425bfad0948SLuca Vizzarro def __init__( 1426bfad0948SLuca Vizzarro self, 1427bfad0948SLuca Vizzarro node: SutNode, 1428bfad0948SLuca Vizzarro privileged: bool = True, 1429bfad0948SLuca Vizzarro timeout: float = SETTINGS.timeout, 1430bfad0948SLuca Vizzarro lcore_filter_specifier: LogicalCoreCount | LogicalCoreList = LogicalCoreCount(), 1431bfad0948SLuca Vizzarro ascending_cores: bool = True, 1432bfad0948SLuca Vizzarro append_prefix_timestamp: bool = True, 143365a1b4e8SJeremy Spewock name: str | None = None, 143487ba4cdcSLuca Vizzarro **app_params: Unpack[TestPmdParamsDict], 1435bfad0948SLuca Vizzarro ) -> None: 1436bfad0948SLuca Vizzarro """Overrides :meth:`~.dpdk_shell.DPDKShell.__init__`. Changes app_params to kwargs.""" 1437bfad0948SLuca Vizzarro super().__init__( 1438bfad0948SLuca Vizzarro node, 1439bfad0948SLuca Vizzarro privileged, 1440bfad0948SLuca Vizzarro timeout, 1441bfad0948SLuca Vizzarro lcore_filter_specifier, 1442bfad0948SLuca Vizzarro ascending_cores, 1443bfad0948SLuca Vizzarro append_prefix_timestamp, 1444bfad0948SLuca Vizzarro TestPmdParams(**app_params), 144565a1b4e8SJeremy Spewock name, 1446fd8cd8eeSLuca Vizzarro ) 14472ecfd126SLuca Vizzarro self.ports_started = not self._app_params.disable_device_start 144885d15c7cSJuraj Linkeš self._ports = None 144985d15c7cSJuraj Linkeš 145085d15c7cSJuraj Linkeš @property 145185d15c7cSJuraj Linkeš def ports(self) -> list[TestPmdPort]: 145285d15c7cSJuraj Linkeš """The ports of the instance. 145385d15c7cSJuraj Linkeš 145485d15c7cSJuraj Linkeš This caches the ports returned by :meth:`show_port_info_all`. 145585d15c7cSJuraj Linkeš To force an update of port information, execute :meth:`show_port_info_all` or 145685d15c7cSJuraj Linkeš :meth:`show_port_info`. 145785d15c7cSJuraj Linkeš 145885d15c7cSJuraj Linkeš Returns: The list of known testpmd ports. 145985d15c7cSJuraj Linkeš """ 146085d15c7cSJuraj Linkeš if self._ports is None: 146185d15c7cSJuraj Linkeš return self.show_port_info_all() 146285d15c7cSJuraj Linkeš return self._ports 14632ecfd126SLuca Vizzarro 14642ecfd126SLuca Vizzarro @requires_started_ports 1465369d34b8SJeremy Spewock def start(self, verify: bool = True) -> None: 1466369d34b8SJeremy Spewock """Start packet forwarding with the current configuration. 1467369d34b8SJeremy Spewock 1468369d34b8SJeremy Spewock Args: 1469369d34b8SJeremy Spewock verify: If :data:`True` , a second start command will be sent in an attempt to verify 1470369d34b8SJeremy Spewock packet forwarding started as expected. 1471369d34b8SJeremy Spewock 1472369d34b8SJeremy Spewock Raises: 1473369d34b8SJeremy Spewock InteractiveCommandExecutionError: If `verify` is :data:`True` and forwarding fails to 1474369d34b8SJeremy Spewock start or ports fail to come up. 1475369d34b8SJeremy Spewock """ 1476369d34b8SJeremy Spewock self.send_command("start") 1477369d34b8SJeremy Spewock if verify: 1478369d34b8SJeremy Spewock # If forwarding was already started, sending "start" again should tell us 1479369d34b8SJeremy Spewock start_cmd_output = self.send_command("start") 1480369d34b8SJeremy Spewock if "Packet forwarding already started" not in start_cmd_output: 1481369d34b8SJeremy Spewock self._logger.debug(f"Failed to start packet forwarding: \n{start_cmd_output}") 1482369d34b8SJeremy Spewock raise InteractiveCommandExecutionError("Testpmd failed to start packet forwarding.") 1483369d34b8SJeremy Spewock 14840264e408SLuca Vizzarro number_of_ports = len(self._app_params.allowed_ports or []) 1485bfad0948SLuca Vizzarro for port_id in range(number_of_ports): 1486369d34b8SJeremy Spewock if not self.wait_link_status_up(port_id): 1487369d34b8SJeremy Spewock raise InteractiveCommandExecutionError( 1488369d34b8SJeremy Spewock "Not all ports came up after starting packet forwarding in testpmd." 1489369d34b8SJeremy Spewock ) 1490369d34b8SJeremy Spewock 1491a91d5f47SJeremy Spewock def stop(self, verify: bool = True) -> str: 1492369d34b8SJeremy Spewock """Stop packet forwarding. 1493369d34b8SJeremy Spewock 1494369d34b8SJeremy Spewock Args: 1495369d34b8SJeremy Spewock verify: If :data:`True` , the output of the stop command is scanned to verify that 1496369d34b8SJeremy Spewock forwarding was stopped successfully or not started. If neither is found, it is 1497369d34b8SJeremy Spewock considered an error. 1498369d34b8SJeremy Spewock 1499369d34b8SJeremy Spewock Raises: 1500369d34b8SJeremy Spewock InteractiveCommandExecutionError: If `verify` is :data:`True` and the command to stop 1501369d34b8SJeremy Spewock forwarding results in an error. 1502a91d5f47SJeremy Spewock 1503a91d5f47SJeremy Spewock Returns: 1504a91d5f47SJeremy Spewock Output gathered from the stop command and all other preceding logs in the buffer. This 1505a91d5f47SJeremy Spewock output is most often used to view forwarding statistics that are displayed when this 1506a91d5f47SJeremy Spewock command is sent as well as any verbose packet information that hasn't been consumed 1507a91d5f47SJeremy Spewock prior to calling this method. 1508369d34b8SJeremy Spewock """ 1509369d34b8SJeremy Spewock stop_cmd_output = self.send_command("stop") 1510369d34b8SJeremy Spewock if verify: 1511369d34b8SJeremy Spewock if ( 1512369d34b8SJeremy Spewock "Done." not in stop_cmd_output 1513369d34b8SJeremy Spewock and "Packet forwarding not started" not in stop_cmd_output 1514369d34b8SJeremy Spewock ): 1515369d34b8SJeremy Spewock self._logger.debug(f"Failed to stop packet forwarding: \n{stop_cmd_output}") 1516369d34b8SJeremy Spewock raise InteractiveCommandExecutionError("Testpmd failed to stop packet forwarding.") 1517a91d5f47SJeremy Spewock return stop_cmd_output 1518369d34b8SJeremy Spewock 1519840b1e01SJuraj Linkeš def get_devices(self) -> list[TestPmdDevice]: 15206ef07151SJuraj Linkeš """Get a list of device names that are known to testpmd. 1521840b1e01SJuraj Linkeš 15226ef07151SJuraj Linkeš Uses the device info listed in testpmd and then parses the output. 1523840b1e01SJuraj Linkeš 1524840b1e01SJuraj Linkeš Returns: 15256ef07151SJuraj Linkeš A list of devices. 1526840b1e01SJuraj Linkeš """ 1527840b1e01SJuraj Linkeš dev_info: str = self.send_command("show device info all") 1528840b1e01SJuraj Linkeš dev_list: list[TestPmdDevice] = [] 1529840b1e01SJuraj Linkeš for line in dev_info.split("\n"): 1530840b1e01SJuraj Linkeš if "device name:" in line.lower(): 1531840b1e01SJuraj Linkeš dev_list.append(TestPmdDevice(line)) 1532840b1e01SJuraj Linkeš return dev_list 1533369d34b8SJeremy Spewock 1534369d34b8SJeremy Spewock def wait_link_status_up(self, port_id: int, timeout=SETTINGS.timeout) -> bool: 1535369d34b8SJeremy Spewock """Wait until the link status on the given port is "up". 1536369d34b8SJeremy Spewock 1537369d34b8SJeremy Spewock Arguments: 1538369d34b8SJeremy Spewock port_id: Port to check the link status on. 1539369d34b8SJeremy Spewock timeout: Time to wait for the link to come up. The default value for this 1540369d34b8SJeremy Spewock argument may be modified using the :option:`--timeout` command-line argument 1541369d34b8SJeremy Spewock or the :envvar:`DTS_TIMEOUT` environment variable. 1542369d34b8SJeremy Spewock 1543369d34b8SJeremy Spewock Returns: 1544369d34b8SJeremy Spewock Whether the link came up in time or not. 1545369d34b8SJeremy Spewock """ 1546369d34b8SJeremy Spewock time_to_stop = time.time() + timeout 1547369d34b8SJeremy Spewock port_info: str = "" 1548369d34b8SJeremy Spewock while time.time() < time_to_stop: 1549369d34b8SJeremy Spewock port_info = self.send_command(f"show port info {port_id}") 1550369d34b8SJeremy Spewock if "Link status: up" in port_info: 1551369d34b8SJeremy Spewock break 1552369d34b8SJeremy Spewock time.sleep(0.5) 1553369d34b8SJeremy Spewock else: 1554369d34b8SJeremy Spewock self._logger.error(f"The link for port {port_id} did not come up in the given timeout.") 1555369d34b8SJeremy Spewock return "Link status: up" in port_info 1556369d34b8SJeremy Spewock 1557fc0f7dc4SLuca Vizzarro def set_forward_mode(self, mode: SimpleForwardingModes, verify: bool = True): 1558369d34b8SJeremy Spewock """Set packet forwarding mode. 1559369d34b8SJeremy Spewock 1560369d34b8SJeremy Spewock Args: 1561369d34b8SJeremy Spewock mode: The forwarding mode to use. 1562369d34b8SJeremy Spewock verify: If :data:`True` the output of the command will be scanned in an attempt to 1563369d34b8SJeremy Spewock verify that the forwarding mode was set to `mode` properly. 1564369d34b8SJeremy Spewock 1565369d34b8SJeremy Spewock Raises: 1566369d34b8SJeremy Spewock InteractiveCommandExecutionError: If `verify` is :data:`True` and the forwarding mode 1567369d34b8SJeremy Spewock fails to update. 1568369d34b8SJeremy Spewock """ 1569369d34b8SJeremy Spewock set_fwd_output = self.send_command(f"set fwd {mode.value}") 1570d7181426SDean Marx if verify: 1571369d34b8SJeremy Spewock if f"Set {mode.value} packet forwarding mode" not in set_fwd_output: 1572369d34b8SJeremy Spewock self._logger.debug(f"Failed to set fwd mode to {mode.value}:\n{set_fwd_output}") 1573369d34b8SJeremy Spewock raise InteractiveCommandExecutionError( 1574369d34b8SJeremy Spewock f"Test pmd failed to set fwd mode to {mode.value}" 1575369d34b8SJeremy Spewock ) 1576369d34b8SJeremy Spewock 15772ecfd126SLuca Vizzarro def stop_all_ports(self, verify: bool = True) -> None: 15782ecfd126SLuca Vizzarro """Stops all the ports. 15792ecfd126SLuca Vizzarro 15802ecfd126SLuca Vizzarro Args: 15812ecfd126SLuca Vizzarro verify: If :data:`True`, the output of the command will be checked for a successful 15822ecfd126SLuca Vizzarro execution. 15832ecfd126SLuca Vizzarro 15842ecfd126SLuca Vizzarro Raises: 15852ecfd126SLuca Vizzarro InteractiveCommandExecutionError: If `verify` is :data:`True` and the ports were not 15862ecfd126SLuca Vizzarro stopped successfully. 15872ecfd126SLuca Vizzarro """ 15882ecfd126SLuca Vizzarro self._logger.debug("Stopping all the ports...") 15892ecfd126SLuca Vizzarro output = self.send_command("port stop all") 15902ecfd126SLuca Vizzarro if verify and not output.strip().endswith("Done"): 15912ecfd126SLuca Vizzarro raise InteractiveCommandExecutionError("Ports were not stopped successfully.") 15922ecfd126SLuca Vizzarro 15932ecfd126SLuca Vizzarro self.ports_started = False 15942ecfd126SLuca Vizzarro 15952ecfd126SLuca Vizzarro def start_all_ports(self, verify: bool = True) -> None: 15962ecfd126SLuca Vizzarro """Starts all the ports. 15972ecfd126SLuca Vizzarro 15982ecfd126SLuca Vizzarro Args: 15992ecfd126SLuca Vizzarro verify: If :data:`True`, the output of the command will be checked for a successful 16002ecfd126SLuca Vizzarro execution. 16012ecfd126SLuca Vizzarro 16022ecfd126SLuca Vizzarro Raises: 16032ecfd126SLuca Vizzarro InteractiveCommandExecutionError: If `verify` is :data:`True` and the ports were not 16042ecfd126SLuca Vizzarro started successfully. 16052ecfd126SLuca Vizzarro """ 16062ecfd126SLuca Vizzarro self._logger.debug("Starting all the ports...") 16072ecfd126SLuca Vizzarro output = self.send_command("port start all") 16082ecfd126SLuca Vizzarro if verify and not output.strip().endswith("Done"): 16092ecfd126SLuca Vizzarro raise InteractiveCommandExecutionError("Ports were not started successfully.") 16102ecfd126SLuca Vizzarro 16112ecfd126SLuca Vizzarro self.ports_started = True 16122ecfd126SLuca Vizzarro 161307816eadSLuca Vizzarro @requires_stopped_ports 161407816eadSLuca Vizzarro def set_ports_queues(self, number_of: int) -> None: 161507816eadSLuca Vizzarro """Sets the number of queues per port. 161607816eadSLuca Vizzarro 161707816eadSLuca Vizzarro Args: 161807816eadSLuca Vizzarro number_of: The number of RX/TX queues to create per port. 161907816eadSLuca Vizzarro 162007816eadSLuca Vizzarro Raises: 162107816eadSLuca Vizzarro InternalError: If `number_of` is invalid. 162207816eadSLuca Vizzarro """ 162307816eadSLuca Vizzarro if number_of < 1: 162407816eadSLuca Vizzarro raise InternalError("The number of queues must be positive and non-zero.") 162507816eadSLuca Vizzarro 162607816eadSLuca Vizzarro self.send_command(f"port config all rxq {number_of}") 162707816eadSLuca Vizzarro self.send_command(f"port config all txq {number_of}") 162807816eadSLuca Vizzarro 162961d5bc9bSLuca Vizzarro def show_port_info_all(self) -> list[TestPmdPort]: 163061d5bc9bSLuca Vizzarro """Returns the information of all the ports. 163161d5bc9bSLuca Vizzarro 163261d5bc9bSLuca Vizzarro Returns: 163361d5bc9bSLuca Vizzarro list[TestPmdPort]: A list containing all the ports information as `TestPmdPort`. 163461d5bc9bSLuca Vizzarro """ 163561d5bc9bSLuca Vizzarro output = self.send_command("show port info all") 163661d5bc9bSLuca Vizzarro 163761d5bc9bSLuca Vizzarro # Sample output of the "all" command looks like: 163861d5bc9bSLuca Vizzarro # 163961d5bc9bSLuca Vizzarro # <start> 164061d5bc9bSLuca Vizzarro # 164161d5bc9bSLuca Vizzarro # ********************* Infos for port 0 ********************* 164261d5bc9bSLuca Vizzarro # Key: value 164361d5bc9bSLuca Vizzarro # 164461d5bc9bSLuca Vizzarro # ********************* Infos for port 1 ********************* 164561d5bc9bSLuca Vizzarro # Key: value 164661d5bc9bSLuca Vizzarro # <end> 164761d5bc9bSLuca Vizzarro # 164861d5bc9bSLuca Vizzarro # Takes advantage of the double new line in between ports as end delimiter. But we need to 164961d5bc9bSLuca Vizzarro # artificially add a new line at the end to pick up the last port. Because commands are 165061d5bc9bSLuca Vizzarro # executed on a pseudo-terminal created by paramiko on the remote node, lines end with CRLF. 165161d5bc9bSLuca Vizzarro # Therefore we also need to take the carriage return into account. 165261d5bc9bSLuca Vizzarro iter = re.finditer(r"\*{21}.*?[\r\n]{4}", output + "\r\n", re.S) 165385d15c7cSJuraj Linkeš self._ports = [TestPmdPort.parse(block.group(0)) for block in iter] 165485d15c7cSJuraj Linkeš return self._ports 165561d5bc9bSLuca Vizzarro 165661d5bc9bSLuca Vizzarro def show_port_info(self, port_id: int) -> TestPmdPort: 165761d5bc9bSLuca Vizzarro """Returns the given port information. 165861d5bc9bSLuca Vizzarro 165961d5bc9bSLuca Vizzarro Args: 166061d5bc9bSLuca Vizzarro port_id: The port ID to gather information for. 166161d5bc9bSLuca Vizzarro 166261d5bc9bSLuca Vizzarro Raises: 166361d5bc9bSLuca Vizzarro InteractiveCommandExecutionError: If `port_id` is invalid. 166461d5bc9bSLuca Vizzarro 166561d5bc9bSLuca Vizzarro Returns: 166661d5bc9bSLuca Vizzarro TestPmdPort: An instance of `TestPmdPort` containing the given port's information. 166761d5bc9bSLuca Vizzarro """ 166861d5bc9bSLuca Vizzarro output = self.send_command(f"show port info {port_id}", skip_first_line=True) 166961d5bc9bSLuca Vizzarro if output.startswith("Invalid port"): 167061d5bc9bSLuca Vizzarro raise InteractiveCommandExecutionError("invalid port given") 167161d5bc9bSLuca Vizzarro 167285d15c7cSJuraj Linkeš port = TestPmdPort.parse(output) 167385d15c7cSJuraj Linkeš self._update_port(port) 167485d15c7cSJuraj Linkeš return port 167585d15c7cSJuraj Linkeš 167685d15c7cSJuraj Linkeš def _update_port(self, port: TestPmdPort) -> None: 167785d15c7cSJuraj Linkeš if self._ports: 167885d15c7cSJuraj Linkeš self._ports = [ 167985d15c7cSJuraj Linkeš existing_port if port.id != existing_port.id else port 168085d15c7cSJuraj Linkeš for existing_port in self._ports 168185d15c7cSJuraj Linkeš ] 168261d5bc9bSLuca Vizzarro 1683e3b16f45SNicholas Pratte def set_mac_addr(self, port_id: int, mac_address: str, add: bool, verify: bool = True) -> None: 1684e3b16f45SNicholas Pratte """Add or remove a mac address on a given port's Allowlist. 1685e3b16f45SNicholas Pratte 1686e3b16f45SNicholas Pratte Args: 1687e3b16f45SNicholas Pratte port_id: The port ID the mac address is set on. 1688e3b16f45SNicholas Pratte mac_address: The mac address to be added to or removed from the specified port. 1689e3b16f45SNicholas Pratte add: If :data:`True`, add the specified mac address. If :data:`False`, remove specified 1690e3b16f45SNicholas Pratte mac address. 1691e3b16f45SNicholas Pratte verify: If :data:'True', assert that the 'mac_addr' operation was successful. If 1692e3b16f45SNicholas Pratte :data:'False', run the command and skip this assertion. 1693e3b16f45SNicholas Pratte 1694e3b16f45SNicholas Pratte Raises: 1695e3b16f45SNicholas Pratte InteractiveCommandExecutionError: If the set mac address operation fails. 1696e3b16f45SNicholas Pratte """ 1697e3b16f45SNicholas Pratte mac_cmd = "add" if add else "remove" 1698e3b16f45SNicholas Pratte output = self.send_command(f"mac_addr {mac_cmd} {port_id} {mac_address}") 1699e3b16f45SNicholas Pratte if "Bad arguments" in output: 1700e3b16f45SNicholas Pratte self._logger.debug("Invalid argument provided to mac_addr") 1701e3b16f45SNicholas Pratte raise InteractiveCommandExecutionError("Invalid argument provided") 1702e3b16f45SNicholas Pratte 1703e3b16f45SNicholas Pratte if verify: 1704e3b16f45SNicholas Pratte if "mac_addr_cmd error:" in output: 1705e3b16f45SNicholas Pratte self._logger.debug(f"Failed to {mac_cmd} {mac_address} on port {port_id}") 1706e3b16f45SNicholas Pratte raise InteractiveCommandExecutionError( 1707e3b16f45SNicholas Pratte f"Failed to {mac_cmd} {mac_address} on port {port_id} \n{output}" 1708e3b16f45SNicholas Pratte ) 1709e3b16f45SNicholas Pratte 1710e3b16f45SNicholas Pratte def set_multicast_mac_addr( 1711e3b16f45SNicholas Pratte self, port_id: int, multi_addr: str, add: bool, verify: bool = True 1712e3b16f45SNicholas Pratte ) -> None: 1713e3b16f45SNicholas Pratte """Add or remove multicast mac address to a specified port's allow list. 1714e3b16f45SNicholas Pratte 1715e3b16f45SNicholas Pratte Args: 1716e3b16f45SNicholas Pratte port_id: The port ID the multicast address is set on. 1717e3b16f45SNicholas Pratte multi_addr: The multicast address to be added or removed from the filter. 1718e3b16f45SNicholas Pratte add: If :data:'True', add the specified multicast address to the port filter. 1719e3b16f45SNicholas Pratte If :data:'False', remove the specified multicast address from the port filter. 1720e3b16f45SNicholas Pratte verify: If :data:'True', assert that the 'mcast_addr' operations was successful. 1721e3b16f45SNicholas Pratte If :data:'False', execute the 'mcast_addr' operation and skip the assertion. 1722e3b16f45SNicholas Pratte 1723e3b16f45SNicholas Pratte Raises: 1724e3b16f45SNicholas Pratte InteractiveCommandExecutionError: If either the 'add' or 'remove' operations fails. 1725e3b16f45SNicholas Pratte """ 1726e3b16f45SNicholas Pratte mcast_cmd = "add" if add else "remove" 1727e3b16f45SNicholas Pratte output = self.send_command(f"mcast_addr {mcast_cmd} {port_id} {multi_addr}") 1728e3b16f45SNicholas Pratte if "Bad arguments" in output: 1729e3b16f45SNicholas Pratte self._logger.debug("Invalid arguments provided to mcast_addr") 1730e3b16f45SNicholas Pratte raise InteractiveCommandExecutionError("Invalid argument provided") 1731e3b16f45SNicholas Pratte 1732e3b16f45SNicholas Pratte if verify: 1733e3b16f45SNicholas Pratte if ( 1734e3b16f45SNicholas Pratte "Invalid multicast_addr" in output 1735e3b16f45SNicholas Pratte or f'multicast address {"already" if add else "not"} filtered by port' in output 1736e3b16f45SNicholas Pratte ): 1737e3b16f45SNicholas Pratte self._logger.debug(f"Failed to {mcast_cmd} {multi_addr} on port {port_id}") 1738e3b16f45SNicholas Pratte raise InteractiveCommandExecutionError( 1739e3b16f45SNicholas Pratte f"Failed to {mcast_cmd} {multi_addr} on port {port_id} \n{output}" 1740e3b16f45SNicholas Pratte ) 1741e3b16f45SNicholas Pratte 174253eacf3dSLuca Vizzarro def show_port_stats_all(self) -> list[TestPmdPortStats]: 174353eacf3dSLuca Vizzarro """Returns the statistics of all the ports. 174453eacf3dSLuca Vizzarro 174553eacf3dSLuca Vizzarro Returns: 174653eacf3dSLuca Vizzarro list[TestPmdPortStats]: A list containing all the ports stats as `TestPmdPortStats`. 174753eacf3dSLuca Vizzarro """ 174853eacf3dSLuca Vizzarro output = self.send_command("show port stats all") 174953eacf3dSLuca Vizzarro 175053eacf3dSLuca Vizzarro # Sample output of the "all" command looks like: 175153eacf3dSLuca Vizzarro # 175253eacf3dSLuca Vizzarro # ########### NIC statistics for port 0 ########### 175353eacf3dSLuca Vizzarro # values... 175453eacf3dSLuca Vizzarro # ################################################# 175553eacf3dSLuca Vizzarro # 175653eacf3dSLuca Vizzarro # ########### NIC statistics for port 1 ########### 175753eacf3dSLuca Vizzarro # values... 175853eacf3dSLuca Vizzarro # ################################################# 175953eacf3dSLuca Vizzarro # 176053eacf3dSLuca Vizzarro iter = re.finditer(r"(^ #*.+#*$[^#]+)^ #*\r$", output, re.MULTILINE) 176153eacf3dSLuca Vizzarro return [TestPmdPortStats.parse(block.group(1)) for block in iter] 176253eacf3dSLuca Vizzarro 176353eacf3dSLuca Vizzarro def show_port_stats(self, port_id: int) -> TestPmdPortStats: 176453eacf3dSLuca Vizzarro """Returns the given port statistics. 176553eacf3dSLuca Vizzarro 176653eacf3dSLuca Vizzarro Args: 176753eacf3dSLuca Vizzarro port_id: The port ID to gather information for. 176853eacf3dSLuca Vizzarro 176953eacf3dSLuca Vizzarro Raises: 177053eacf3dSLuca Vizzarro InteractiveCommandExecutionError: If `port_id` is invalid. 177153eacf3dSLuca Vizzarro 177253eacf3dSLuca Vizzarro Returns: 177353eacf3dSLuca Vizzarro TestPmdPortStats: An instance of `TestPmdPortStats` containing the given port's stats. 177453eacf3dSLuca Vizzarro """ 177553eacf3dSLuca Vizzarro output = self.send_command(f"show port stats {port_id}", skip_first_line=True) 177653eacf3dSLuca Vizzarro if output.startswith("Invalid port"): 177753eacf3dSLuca Vizzarro raise InteractiveCommandExecutionError("invalid port given") 177853eacf3dSLuca Vizzarro 177953eacf3dSLuca Vizzarro return TestPmdPortStats.parse(output) 178053eacf3dSLuca Vizzarro 17819910db35SJeremy Spewock @requires_stopped_ports 17829910db35SJeremy Spewock def set_port_mtu(self, port_id: int, mtu: int, verify: bool = True) -> None: 17839910db35SJeremy Spewock """Change the MTU of a port using testpmd. 17849910db35SJeremy Spewock 17859910db35SJeremy Spewock Some PMDs require that the port be stopped before changing the MTU, and it does no harm to 17869910db35SJeremy Spewock stop the port before configuring in cases where it isn't required, so ports are stopped 17879910db35SJeremy Spewock prior to changing their MTU. 17889910db35SJeremy Spewock 17899910db35SJeremy Spewock Args: 17909910db35SJeremy Spewock port_id: ID of the port to adjust the MTU on. 17919910db35SJeremy Spewock mtu: Desired value for the MTU to be set to. 17929910db35SJeremy Spewock verify: If `verify` is :data:`True` then the output will be scanned in an attempt to 17939910db35SJeremy Spewock verify that the mtu was properly set on the port. Defaults to :data:`True`. 17949910db35SJeremy Spewock 17959910db35SJeremy Spewock Raises: 17969910db35SJeremy Spewock InteractiveCommandExecutionError: If `verify` is :data:`True` and the MTU was not 17979910db35SJeremy Spewock properly updated on the port matching `port_id`. 17989910db35SJeremy Spewock """ 17999910db35SJeremy Spewock set_mtu_output = self.send_command(f"port config mtu {port_id} {mtu}") 18009910db35SJeremy Spewock if verify and (f"MTU: {mtu}" not in self.send_command(f"show port info {port_id}")): 18019910db35SJeremy Spewock self._logger.debug( 18029910db35SJeremy Spewock f"Failed to set mtu to {mtu} on port {port_id}." f" Output was:\n{set_mtu_output}" 18039910db35SJeremy Spewock ) 18049910db35SJeremy Spewock raise InteractiveCommandExecutionError( 18059910db35SJeremy Spewock f"Test pmd failed to update mtu of port {port_id} to {mtu}" 18069910db35SJeremy Spewock ) 18079910db35SJeremy Spewock 18089910db35SJeremy Spewock def set_port_mtu_all(self, mtu: int, verify: bool = True) -> None: 18099910db35SJeremy Spewock """Change the MTU of all ports using testpmd. 18109910db35SJeremy Spewock 18119910db35SJeremy Spewock Runs :meth:`set_port_mtu` for every port that testpmd is aware of. 18129910db35SJeremy Spewock 18139910db35SJeremy Spewock Args: 18149910db35SJeremy Spewock mtu: Desired value for the MTU to be set to. 18159910db35SJeremy Spewock verify: Whether to verify that setting the MTU on each port was successful or not. 18169910db35SJeremy Spewock Defaults to :data:`True`. 18179910db35SJeremy Spewock 18189910db35SJeremy Spewock Raises: 18199910db35SJeremy Spewock InteractiveCommandExecutionError: If `verify` is :data:`True` and the MTU was not 18209910db35SJeremy Spewock properly updated on at least one port. 18219910db35SJeremy Spewock """ 18229910db35SJeremy Spewock for port in self.ports: 18239910db35SJeremy Spewock self.set_port_mtu(port.id, mtu, verify) 18249910db35SJeremy Spewock 1825a91d5f47SJeremy Spewock @staticmethod 1826a91d5f47SJeremy Spewock def extract_verbose_output(output: str) -> list[TestPmdVerbosePacket]: 1827a91d5f47SJeremy Spewock """Extract the verbose information present in given testpmd output. 1828a91d5f47SJeremy Spewock 1829a91d5f47SJeremy Spewock This method extracts sections of verbose output that begin with the line 1830a91d5f47SJeremy Spewock "port X/queue Y: sent/received Z packets" and end with the ol_flags of a packet. 1831a91d5f47SJeremy Spewock 1832a91d5f47SJeremy Spewock Args: 1833a91d5f47SJeremy Spewock output: Testpmd output that contains verbose information 1834a91d5f47SJeremy Spewock 1835a91d5f47SJeremy Spewock Returns: 1836a91d5f47SJeremy Spewock List of parsed packet information gathered from verbose information in `output`. 1837a91d5f47SJeremy Spewock """ 1838a91d5f47SJeremy Spewock out: list[TestPmdVerbosePacket] = [] 1839a91d5f47SJeremy Spewock prev_header: str = "" 1840a91d5f47SJeremy Spewock iter = re.finditer( 1841a91d5f47SJeremy Spewock r"(?P<HEADER>(?:port \d+/queue \d+: (?:received|sent) \d+ packets)?)\s*" 1842a91d5f47SJeremy Spewock r"(?P<PACKET>src=[\w\s=:-]+?ol_flags: [\w ]+)", 1843a91d5f47SJeremy Spewock output, 1844a91d5f47SJeremy Spewock ) 1845a91d5f47SJeremy Spewock for match in iter: 1846a91d5f47SJeremy Spewock if match.group("HEADER"): 1847a91d5f47SJeremy Spewock prev_header = match.group("HEADER") 1848a91d5f47SJeremy Spewock out.append(TestPmdVerbosePacket.parse(f"{prev_header}\n{match.group('PACKET')}")) 1849a91d5f47SJeremy Spewock return out 1850a91d5f47SJeremy Spewock 18511a7520a1SDean Marx def set_vlan_filter(self, port: int, enable: bool, verify: bool = True) -> None: 18521a7520a1SDean Marx """Set vlan filter on. 18531a7520a1SDean Marx 18541a7520a1SDean Marx Args: 18551a7520a1SDean Marx port: The port number to enable VLAN filter on. 18561a7520a1SDean Marx enable: Enable the filter on `port` if :data:`True`, otherwise disable it. 18571a7520a1SDean Marx verify: If :data:`True`, the output of the command and show port info 18581a7520a1SDean Marx is scanned to verify that vlan filtering was set successfully. 18591a7520a1SDean Marx 18601a7520a1SDean Marx Raises: 18611a7520a1SDean Marx InteractiveCommandExecutionError: If `verify` is :data:`True` and the filter 18621a7520a1SDean Marx fails to update. 18631a7520a1SDean Marx """ 18641a7520a1SDean Marx filter_cmd_output = self.send_command(f"vlan set filter {'on' if enable else 'off'} {port}") 18651a7520a1SDean Marx if verify: 18661a7520a1SDean Marx vlan_settings = self.show_port_info(port_id=port).vlan_offload 18671a7520a1SDean Marx if enable ^ (vlan_settings is not None and VLANOffloadFlag.FILTER in vlan_settings): 18681a7520a1SDean Marx self._logger.debug( 18691a7520a1SDean Marx f"""Failed to {'enable' if enable else 'disable'} 18701a7520a1SDean Marx filter on port {port}: \n{filter_cmd_output}""" 18711a7520a1SDean Marx ) 18721a7520a1SDean Marx raise InteractiveCommandExecutionError( 18731a7520a1SDean Marx f"""Failed to {'enable' if enable else 'disable'} 18741a7520a1SDean Marx filter on port {port}""" 18751a7520a1SDean Marx ) 18761a7520a1SDean Marx 18771a7520a1SDean Marx def rx_vlan(self, vlan: int, port: int, add: bool, verify: bool = True) -> None: 18781a7520a1SDean Marx """Add specified vlan tag to the filter list on a port. Requires vlan filter to be on. 18791a7520a1SDean Marx 18801a7520a1SDean Marx Args: 18811a7520a1SDean Marx vlan: The vlan tag to add, should be within 1-1005. 18821a7520a1SDean Marx port: The port number to add the tag on. 18831a7520a1SDean Marx add: Adds the tag if :data:`True`, otherwise removes the tag. 18841a7520a1SDean Marx verify: If :data:`True`, the output of the command is scanned to verify that 18851a7520a1SDean Marx the vlan tag was added to the filter list on the specified port. 18861a7520a1SDean Marx 18871a7520a1SDean Marx Raises: 18881a7520a1SDean Marx InteractiveCommandExecutionError: If `verify` is :data:`True` and the tag 18891a7520a1SDean Marx is not added. 18901a7520a1SDean Marx """ 18911a7520a1SDean Marx rx_cmd_output = self.send_command(f"rx_vlan {'add' if add else 'rm'} {vlan} {port}") 18921a7520a1SDean Marx if verify: 18931a7520a1SDean Marx if ( 18941a7520a1SDean Marx "VLAN-filtering disabled" in rx_cmd_output 18951a7520a1SDean Marx or "Invalid vlan_id" in rx_cmd_output 18961a7520a1SDean Marx or "Bad arguments" in rx_cmd_output 18971a7520a1SDean Marx ): 18981a7520a1SDean Marx self._logger.debug( 18991a7520a1SDean Marx f"""Failed to {'add' if add else 'remove'} tag {vlan} 19001a7520a1SDean Marx port {port}: \n{rx_cmd_output}""" 19011a7520a1SDean Marx ) 19021a7520a1SDean Marx raise InteractiveCommandExecutionError( 19031a7520a1SDean Marx f"Testpmd failed to {'add' if add else 'remove'} tag {vlan} on port {port}." 19041a7520a1SDean Marx ) 19051a7520a1SDean Marx 19061a7520a1SDean Marx def set_vlan_strip(self, port: int, enable: bool, verify: bool = True) -> None: 19071a7520a1SDean Marx """Enable or disable vlan stripping on the specified port. 19081a7520a1SDean Marx 19091a7520a1SDean Marx Args: 19101a7520a1SDean Marx port: The port number to use. 19111a7520a1SDean Marx enable: If :data:`True`, will turn vlan stripping on, otherwise will turn off. 19121a7520a1SDean Marx verify: If :data:`True`, the output of the command and show port info 19131a7520a1SDean Marx is scanned to verify that vlan stripping was enabled on the specified port. 19141a7520a1SDean Marx 19151a7520a1SDean Marx Raises: 19161a7520a1SDean Marx InteractiveCommandExecutionError: If `verify` is :data:`True` and stripping 19171a7520a1SDean Marx fails to update. 19181a7520a1SDean Marx """ 19191a7520a1SDean Marx strip_cmd_output = self.send_command(f"vlan set strip {'on' if enable else 'off'} {port}") 19201a7520a1SDean Marx if verify: 19211a7520a1SDean Marx vlan_settings = self.show_port_info(port_id=port).vlan_offload 19221a7520a1SDean Marx if enable ^ (vlan_settings is not None and VLANOffloadFlag.STRIP in vlan_settings): 19231a7520a1SDean Marx self._logger.debug( 19241a7520a1SDean Marx f"""Failed to set strip {'on' if enable else 'off'} 19251a7520a1SDean Marx port {port}: \n{strip_cmd_output}""" 19261a7520a1SDean Marx ) 19271a7520a1SDean Marx raise InteractiveCommandExecutionError( 19281a7520a1SDean Marx f"Testpmd failed to set strip {'on' if enable else 'off'} port {port}." 19291a7520a1SDean Marx ) 19301a7520a1SDean Marx 19311a7520a1SDean Marx @requires_stopped_ports 19321a7520a1SDean Marx def tx_vlan_set( 19331a7520a1SDean Marx self, port: int, enable: bool, vlan: int | None = None, verify: bool = True 19341a7520a1SDean Marx ) -> None: 19351a7520a1SDean Marx """Set hardware insertion of vlan tags in packets sent on a port. 19361a7520a1SDean Marx 19371a7520a1SDean Marx Args: 19381a7520a1SDean Marx port: The port number to use. 19391a7520a1SDean Marx enable: Sets vlan tag insertion if :data:`True`, and resets if :data:`False`. 19401a7520a1SDean Marx vlan: The vlan tag to insert if enable is :data:`True`. 19411a7520a1SDean Marx verify: If :data:`True`, the output of the command is scanned to verify that 19421a7520a1SDean Marx vlan insertion was enabled on the specified port. 19431a7520a1SDean Marx 19441a7520a1SDean Marx Raises: 19451a7520a1SDean Marx InteractiveCommandExecutionError: If `verify` is :data:`True` and the insertion 19461a7520a1SDean Marx tag is not set. 19471a7520a1SDean Marx """ 19481a7520a1SDean Marx if enable: 19491a7520a1SDean Marx tx_vlan_cmd_output = self.send_command(f"tx_vlan set {port} {vlan}") 19501a7520a1SDean Marx if verify: 19511a7520a1SDean Marx if ( 19521a7520a1SDean Marx "Please stop port" in tx_vlan_cmd_output 19531a7520a1SDean Marx or "Invalid vlan_id" in tx_vlan_cmd_output 19541a7520a1SDean Marx or "Invalid port" in tx_vlan_cmd_output 19551a7520a1SDean Marx ): 19561a7520a1SDean Marx self._logger.debug( 19571a7520a1SDean Marx f"Failed to set vlan tag {vlan} on port {port}:\n{tx_vlan_cmd_output}" 19581a7520a1SDean Marx ) 19591a7520a1SDean Marx raise InteractiveCommandExecutionError( 19601a7520a1SDean Marx f"Testpmd failed to set vlan insertion tag {vlan} on port {port}." 19611a7520a1SDean Marx ) 19621a7520a1SDean Marx else: 19631a7520a1SDean Marx tx_vlan_cmd_output = self.send_command(f"tx_vlan reset {port}") 19641a7520a1SDean Marx if verify: 19651a7520a1SDean Marx if "Please stop port" in tx_vlan_cmd_output or "Invalid port" in tx_vlan_cmd_output: 19661a7520a1SDean Marx self._logger.debug( 19671a7520a1SDean Marx f"Failed to reset vlan insertion on port {port}: \n{tx_vlan_cmd_output}" 19681a7520a1SDean Marx ) 19691a7520a1SDean Marx raise InteractiveCommandExecutionError( 19701a7520a1SDean Marx f"Testpmd failed to reset vlan insertion on port {port}." 19711a7520a1SDean Marx ) 19721a7520a1SDean Marx 19731a7520a1SDean Marx def set_promisc(self, port: int, enable: bool, verify: bool = True) -> None: 19741a7520a1SDean Marx """Enable or disable promiscuous mode for the specified port. 19751a7520a1SDean Marx 19761a7520a1SDean Marx Args: 19771a7520a1SDean Marx port: Port number to use. 19781a7520a1SDean Marx enable: If :data:`True`, turn promiscuous mode on, otherwise turn off. 19791a7520a1SDean Marx verify: If :data:`True` an additional command will be sent to verify that 19801a7520a1SDean Marx promiscuous mode is properly set. Defaults to :data:`True`. 19811a7520a1SDean Marx 19821a7520a1SDean Marx Raises: 19831a7520a1SDean Marx InteractiveCommandExecutionError: If `verify` is :data:`True` and promiscuous mode 19841a7520a1SDean Marx is not correctly set. 19851a7520a1SDean Marx """ 19861a7520a1SDean Marx promisc_cmd_output = self.send_command(f"set promisc {port} {'on' if enable else 'off'}") 19871a7520a1SDean Marx if verify: 19881a7520a1SDean Marx stats = self.show_port_info(port_id=port) 19891a7520a1SDean Marx if enable ^ stats.is_promiscuous_mode_enabled: 19901a7520a1SDean Marx self._logger.debug( 19911a7520a1SDean Marx f"Failed to set promiscuous mode on port {port}: \n{promisc_cmd_output}" 19921a7520a1SDean Marx ) 19931a7520a1SDean Marx raise InteractiveCommandExecutionError( 19941a7520a1SDean Marx f"Testpmd failed to set promiscuous mode on port {port}." 19951a7520a1SDean Marx ) 19961a7520a1SDean Marx 19971a7520a1SDean Marx def set_verbose(self, level: int, verify: bool = True) -> None: 19981a7520a1SDean Marx """Set debug verbosity level. 19991a7520a1SDean Marx 20001a7520a1SDean Marx Args: 20011a7520a1SDean Marx level: 0 - silent except for error 20021a7520a1SDean Marx 1 - fully verbose except for Tx packets 20031a7520a1SDean Marx 2 - fully verbose except for Rx packets 20041a7520a1SDean Marx >2 - fully verbose 20051a7520a1SDean Marx verify: If :data:`True` the command output will be scanned to verify that verbose level 20061a7520a1SDean Marx is properly set. Defaults to :data:`True`. 20071a7520a1SDean Marx 20081a7520a1SDean Marx Raises: 20091a7520a1SDean Marx InteractiveCommandExecutionError: If `verify` is :data:`True` and verbose level 20101a7520a1SDean Marx is not correctly set. 20111a7520a1SDean Marx """ 20121a7520a1SDean Marx verbose_cmd_output = self.send_command(f"set verbose {level}") 20131a7520a1SDean Marx if verify: 20141a7520a1SDean Marx if "Change verbose level" not in verbose_cmd_output: 20151a7520a1SDean Marx self._logger.debug( 20161a7520a1SDean Marx f"Failed to set verbose level to {level}: \n{verbose_cmd_output}" 20171a7520a1SDean Marx ) 20181a7520a1SDean Marx raise InteractiveCommandExecutionError( 20191a7520a1SDean Marx f"Testpmd failed to set verbose level to {level}." 20201a7520a1SDean Marx ) 20211a7520a1SDean Marx 20222b648cd4SJeremy Spewock def _close(self) -> None: 2023369d34b8SJeremy Spewock """Overrides :meth:`~.interactive_shell.close`.""" 20242b648cd4SJeremy Spewock self.stop() 202592439dc9SJeremy Spewock self.send_command("quit", "Bye...") 20262b648cd4SJeremy Spewock return super()._close() 2027c89d0038SJuraj Linkeš 2028c0119400SJuraj Linkeš """ 2029c0119400SJuraj Linkeš ====== Capability retrieval methods ====== 2030c0119400SJuraj Linkeš """ 2031c0119400SJuraj Linkeš 2032a79884f9SJuraj Linkeš def get_capabilities_rx_offload( 2033a79884f9SJuraj Linkeš self, 2034a79884f9SJuraj Linkeš supported_capabilities: MutableSet["NicCapability"], 2035a79884f9SJuraj Linkeš unsupported_capabilities: MutableSet["NicCapability"], 2036a79884f9SJuraj Linkeš ) -> None: 2037a79884f9SJuraj Linkeš """Get all rx offload capabilities and divide them into supported and unsupported. 2038a79884f9SJuraj Linkeš 2039a79884f9SJuraj Linkeš Args: 2040a79884f9SJuraj Linkeš supported_capabilities: Supported capabilities will be added to this set. 2041a79884f9SJuraj Linkeš unsupported_capabilities: Unsupported capabilities will be added to this set. 2042a79884f9SJuraj Linkeš """ 2043a79884f9SJuraj Linkeš self._logger.debug("Getting rx offload capabilities.") 2044a79884f9SJuraj Linkeš command = f"show port {self.ports[0].id} rx_offload capabilities" 2045a79884f9SJuraj Linkeš rx_offload_capabilities_out = self.send_command(command) 2046a79884f9SJuraj Linkeš rx_offload_capabilities = RxOffloadCapabilities.parse(rx_offload_capabilities_out) 2047a79884f9SJuraj Linkeš self._update_capabilities_from_flag( 2048a79884f9SJuraj Linkeš supported_capabilities, 2049a79884f9SJuraj Linkeš unsupported_capabilities, 2050a79884f9SJuraj Linkeš RxOffloadCapability, 2051a79884f9SJuraj Linkeš rx_offload_capabilities.per_port | rx_offload_capabilities.per_queue, 2052a79884f9SJuraj Linkeš ) 2053a79884f9SJuraj Linkeš 2054*c986c339SDean Marx def get_port_queue_info( 2055*c986c339SDean Marx self, port_id: int, queue_id: int, is_rx_queue: bool 2056*c986c339SDean Marx ) -> TestPmdQueueInfo: 2057*c986c339SDean Marx """Returns the current state of the specified queue.""" 2058*c986c339SDean Marx command = f"show {'rxq' if is_rx_queue else 'txq'} info {port_id} {queue_id}" 2059*c986c339SDean Marx queue_info = TestPmdQueueInfo.parse(self.send_command(command)) 2060*c986c339SDean Marx return queue_info 2061*c986c339SDean Marx 2062*c986c339SDean Marx def setup_port_queue(self, port_id: int, queue_id: int, is_rx_queue: bool) -> None: 2063*c986c339SDean Marx """Setup a given queue on a port. 2064*c986c339SDean Marx 2065*c986c339SDean Marx This functionality cannot be verified because the setup action only takes effect when the 2066*c986c339SDean Marx queue is started. 2067*c986c339SDean Marx 2068*c986c339SDean Marx Args: 2069*c986c339SDean Marx port_id: ID of the port where the queue resides. 2070*c986c339SDean Marx queue_id: ID of the queue to setup. 2071*c986c339SDean Marx is_rx_queue: Type of queue to setup. If :data:`True` an RX queue will be setup, 2072*c986c339SDean Marx otherwise a TX queue will be setup. 2073*c986c339SDean Marx """ 2074*c986c339SDean Marx self.send_command(f"port {port_id} {'rxq' if is_rx_queue else 'txq'} {queue_id} setup") 2075*c986c339SDean Marx 2076*c986c339SDean Marx def stop_port_queue( 2077*c986c339SDean Marx self, port_id: int, queue_id: int, is_rx_queue: bool, verify: bool = True 2078*c986c339SDean Marx ) -> None: 2079*c986c339SDean Marx """Stops a given queue on a port. 2080*c986c339SDean Marx 2081*c986c339SDean Marx Args: 2082*c986c339SDean Marx port_id: ID of the port that the queue belongs to. 2083*c986c339SDean Marx queue_id: ID of the queue to stop. 2084*c986c339SDean Marx is_rx_queue: Type of queue to stop. If :data:`True` an RX queue will be stopped, 2085*c986c339SDean Marx otherwise a TX queue will be stopped. 2086*c986c339SDean Marx verify: If :data:`True` an additional command will be sent to verify the queue stopped. 2087*c986c339SDean Marx Defaults to :data:`True`. 2088*c986c339SDean Marx 2089*c986c339SDean Marx Raises: 2090*c986c339SDean Marx InteractiveCommandExecutionError: If `verify` is :data:`True` and the queue fails to 2091*c986c339SDean Marx stop. 2092*c986c339SDean Marx """ 2093*c986c339SDean Marx port_type = "rxq" if is_rx_queue else "txq" 2094*c986c339SDean Marx stop_cmd_output = self.send_command(f"port {port_id} {port_type} {queue_id} stop") 2095*c986c339SDean Marx if verify: 2096*c986c339SDean Marx queue_started = self.get_port_queue_info( 2097*c986c339SDean Marx port_id, queue_id, is_rx_queue 2098*c986c339SDean Marx ).is_queue_started 2099*c986c339SDean Marx if queue_started: 2100*c986c339SDean Marx self._logger.debug( 2101*c986c339SDean Marx f"Failed to stop {port_type} {queue_id} on port {port_id}:\n{stop_cmd_output}" 2102*c986c339SDean Marx ) 2103*c986c339SDean Marx raise InteractiveCommandExecutionError( 2104*c986c339SDean Marx f"Test pmd failed to stop {port_type} {queue_id} on port {port_id}" 2105*c986c339SDean Marx ) 2106*c986c339SDean Marx 2107*c986c339SDean Marx def start_port_queue( 2108*c986c339SDean Marx self, port_id: int, queue_id: int, is_rx_queue: bool, verify: bool = True 2109*c986c339SDean Marx ) -> None: 2110*c986c339SDean Marx """Starts a given queue on a port. 2111*c986c339SDean Marx 2112*c986c339SDean Marx First sets up the port queue, then starts it. 2113*c986c339SDean Marx 2114*c986c339SDean Marx Args: 2115*c986c339SDean Marx port_id: ID of the port that the queue belongs to. 2116*c986c339SDean Marx queue_id: ID of the queue to start. 2117*c986c339SDean Marx is_rx_queue: Type of queue to start. If :data:`True` an RX queue will be started, 2118*c986c339SDean Marx otherwise a TX queue will be started. 2119*c986c339SDean Marx verify: if :data:`True` an additional command will be sent to verify that the queue was 2120*c986c339SDean Marx started. Defaults to :data:`True`. 2121*c986c339SDean Marx 2122*c986c339SDean Marx Raises: 2123*c986c339SDean Marx InteractiveCommandExecutionError: If `verify` is :data:`True` and the queue fails to 2124*c986c339SDean Marx start. 2125*c986c339SDean Marx """ 2126*c986c339SDean Marx port_type = "rxq" if is_rx_queue else "txq" 2127*c986c339SDean Marx self.setup_port_queue(port_id, queue_id, is_rx_queue) 2128*c986c339SDean Marx start_cmd_output = self.send_command(f"port {port_id} {port_type} {queue_id} start") 2129*c986c339SDean Marx if verify: 2130*c986c339SDean Marx queue_started = self.get_port_queue_info( 2131*c986c339SDean Marx port_id, queue_id, is_rx_queue 2132*c986c339SDean Marx ).is_queue_started 2133*c986c339SDean Marx if not queue_started: 2134*c986c339SDean Marx self._logger.debug( 2135*c986c339SDean Marx f"Failed to start {port_type} {queue_id} on port {port_id}:\n{start_cmd_output}" 2136*c986c339SDean Marx ) 2137*c986c339SDean Marx raise InteractiveCommandExecutionError( 2138*c986c339SDean Marx f"Test pmd failed to start {port_type} {queue_id} on port {port_id}" 2139*c986c339SDean Marx ) 2140*c986c339SDean Marx 2141*c986c339SDean Marx def get_queue_ring_size(self, port_id: int, queue_id: int, is_rx_queue: bool) -> int: 2142*c986c339SDean Marx """Returns the current size of the ring on the specified queue.""" 2143*c986c339SDean Marx command = f"show {'rxq' if is_rx_queue else 'txq'} info {port_id} {queue_id}" 2144*c986c339SDean Marx queue_info = TestPmdQueueInfo.parse(self.send_command(command)) 2145*c986c339SDean Marx return queue_info.ring_size 2146*c986c339SDean Marx 2147*c986c339SDean Marx def set_queue_ring_size( 2148*c986c339SDean Marx self, 2149*c986c339SDean Marx port_id: int, 2150*c986c339SDean Marx queue_id: int, 2151*c986c339SDean Marx size: int, 2152*c986c339SDean Marx is_rx_queue: bool, 2153*c986c339SDean Marx verify: bool = True, 2154*c986c339SDean Marx ) -> None: 2155*c986c339SDean Marx """Update the ring size of an Rx/Tx queue on a given port. 2156*c986c339SDean Marx 2157*c986c339SDean Marx Queue is setup after setting the ring size so that the queue info reflects this change and 2158*c986c339SDean Marx it can be verified. 2159*c986c339SDean Marx 2160*c986c339SDean Marx Args: 2161*c986c339SDean Marx port_id: The port that the queue resides on. 2162*c986c339SDean Marx queue_id: The ID of the queue on the port. 2163*c986c339SDean Marx size: The size to update the ring size to. 2164*c986c339SDean Marx is_rx_queue: Whether to modify an RX or TX queue. If :data:`True` an RX queue will be 2165*c986c339SDean Marx updated, otherwise a TX queue will be updated. 2166*c986c339SDean Marx verify: If :data:`True` an additional command will be sent to check the ring size of 2167*c986c339SDean Marx the queue in an attempt to validate that the size was changes properly. 2168*c986c339SDean Marx 2169*c986c339SDean Marx Raises: 2170*c986c339SDean Marx InteractiveCommandExecutionError: If `verify` is :data:`True` and there is a failure 2171*c986c339SDean Marx when updating ring size. 2172*c986c339SDean Marx """ 2173*c986c339SDean Marx queue_type = "rxq" if is_rx_queue else "txq" 2174*c986c339SDean Marx self.send_command(f"port config {port_id} {queue_type} {queue_id} ring_size {size}") 2175*c986c339SDean Marx self.setup_port_queue(port_id, queue_id, is_rx_queue) 2176*c986c339SDean Marx if verify: 2177*c986c339SDean Marx curr_ring_size = self.get_queue_ring_size(port_id, queue_id, is_rx_queue) 2178*c986c339SDean Marx if curr_ring_size != size: 2179*c986c339SDean Marx self._logger.debug( 2180*c986c339SDean Marx f"Failed up update ring size of queue {queue_id} on port {port_id}. Current" 2181*c986c339SDean Marx f" ring size is {curr_ring_size}." 2182*c986c339SDean Marx ) 2183*c986c339SDean Marx raise InteractiveCommandExecutionError( 2184*c986c339SDean Marx f"Failed to update ring size of queue {queue_id} on port {port_id}" 2185*c986c339SDean Marx ) 2186*c986c339SDean Marx 2187a79884f9SJuraj Linkeš def _update_capabilities_from_flag( 2188a79884f9SJuraj Linkeš self, 2189a79884f9SJuraj Linkeš supported_capabilities: MutableSet["NicCapability"], 2190a79884f9SJuraj Linkeš unsupported_capabilities: MutableSet["NicCapability"], 2191a79884f9SJuraj Linkeš flag_class: type[Flag], 2192a79884f9SJuraj Linkeš supported_flags: Flag, 2193a79884f9SJuraj Linkeš ) -> None: 2194a79884f9SJuraj Linkeš """Divide all flags from `flag_class` into supported and unsupported.""" 2195a79884f9SJuraj Linkeš for flag in flag_class: 2196a79884f9SJuraj Linkeš if flag in supported_flags: 2197a79884f9SJuraj Linkeš supported_capabilities.add(NicCapability[str(flag.name)]) 2198a79884f9SJuraj Linkeš else: 2199a79884f9SJuraj Linkeš unsupported_capabilities.add(NicCapability[str(flag.name)]) 2200a79884f9SJuraj Linkeš 2201c0119400SJuraj Linkeš @requires_started_ports 2202c0119400SJuraj Linkeš def get_capabilities_rxq_info( 2203c0119400SJuraj Linkeš self, 2204c0119400SJuraj Linkeš supported_capabilities: MutableSet["NicCapability"], 2205c0119400SJuraj Linkeš unsupported_capabilities: MutableSet["NicCapability"], 2206c0119400SJuraj Linkeš ) -> None: 2207c0119400SJuraj Linkeš """Get all rxq capabilities and divide them into supported and unsupported. 2208c0119400SJuraj Linkeš 2209c0119400SJuraj Linkeš Args: 2210c0119400SJuraj Linkeš supported_capabilities: Supported capabilities will be added to this set. 2211c0119400SJuraj Linkeš unsupported_capabilities: Unsupported capabilities will be added to this set. 2212c0119400SJuraj Linkeš """ 2213c0119400SJuraj Linkeš self._logger.debug("Getting rxq capabilities.") 2214c0119400SJuraj Linkeš command = f"show rxq info {self.ports[0].id} 0" 2215c0119400SJuraj Linkeš rxq_info = TestPmdRxqInfo.parse(self.send_command(command)) 2216*c986c339SDean Marx if rxq_info.scattered_packets: 2217c0119400SJuraj Linkeš supported_capabilities.add(NicCapability.SCATTERED_RX_ENABLED) 2218c0119400SJuraj Linkeš else: 2219c0119400SJuraj Linkeš unsupported_capabilities.add(NicCapability.SCATTERED_RX_ENABLED) 2220c0119400SJuraj Linkeš 2221d64f6ba5SJuraj Linkeš def get_capabilities_show_port_info( 2222d64f6ba5SJuraj Linkeš self, 2223d64f6ba5SJuraj Linkeš supported_capabilities: MutableSet["NicCapability"], 2224d64f6ba5SJuraj Linkeš unsupported_capabilities: MutableSet["NicCapability"], 2225d64f6ba5SJuraj Linkeš ) -> None: 2226d64f6ba5SJuraj Linkeš """Get all capabilities from show port info and divide them into supported and unsupported. 2227d64f6ba5SJuraj Linkeš 2228d64f6ba5SJuraj Linkeš Args: 2229d64f6ba5SJuraj Linkeš supported_capabilities: Supported capabilities will be added to this set. 2230d64f6ba5SJuraj Linkeš unsupported_capabilities: Unsupported capabilities will be added to this set. 2231d64f6ba5SJuraj Linkeš """ 2232d64f6ba5SJuraj Linkeš self._update_capabilities_from_flag( 2233d64f6ba5SJuraj Linkeš supported_capabilities, 2234d64f6ba5SJuraj Linkeš unsupported_capabilities, 2235d64f6ba5SJuraj Linkeš DeviceCapabilitiesFlag, 2236d64f6ba5SJuraj Linkeš self.ports[0].device_capabilities, 2237d64f6ba5SJuraj Linkeš ) 2238d64f6ba5SJuraj Linkeš 2239474ce443SNicholas Pratte def get_capabilities_mcast_filtering( 2240474ce443SNicholas Pratte self, 2241474ce443SNicholas Pratte supported_capabilities: MutableSet["NicCapability"], 2242474ce443SNicholas Pratte unsupported_capabilities: MutableSet["NicCapability"], 2243474ce443SNicholas Pratte ) -> None: 2244474ce443SNicholas Pratte """Get multicast filtering capability from mcast_addr add and check for testpmd error code. 2245474ce443SNicholas Pratte 2246474ce443SNicholas Pratte Args: 2247474ce443SNicholas Pratte supported_capabilities: Supported capabilities will be added to this set. 2248474ce443SNicholas Pratte unsupported_capabilities: Unsupported capabilities will be added to this set. 2249474ce443SNicholas Pratte """ 2250474ce443SNicholas Pratte self._logger.debug("Getting mcast filter capabilities.") 2251474ce443SNicholas Pratte command = f"mcast_addr add {self.ports[0].id} 01:00:5E:00:00:00" 2252474ce443SNicholas Pratte output = self.send_command(command) 2253474ce443SNicholas Pratte if "diag=-95" in output: 2254474ce443SNicholas Pratte unsupported_capabilities.add(NicCapability.MCAST_FILTERING) 2255474ce443SNicholas Pratte else: 2256474ce443SNicholas Pratte supported_capabilities.add(NicCapability.MCAST_FILTERING) 2257474ce443SNicholas Pratte command = str.replace(command, "add", "remove", 1) 2258474ce443SNicholas Pratte self.send_command(command) 2259474ce443SNicholas Pratte 2260c89d0038SJuraj Linkeš 2261c89d0038SJuraj Linkešclass NicCapability(NoAliasEnum): 2262c89d0038SJuraj Linkeš """A mapping between capability names and the associated :class:`TestPmdShell` methods. 2263c89d0038SJuraj Linkeš 2264c89d0038SJuraj Linkeš The :class:`TestPmdShell` capability checking method executes the command that checks 2265c89d0038SJuraj Linkeš whether the capability is supported. 2266c89d0038SJuraj Linkeš A decorator may optionally be added to the method that will add and remove configuration 2267c89d0038SJuraj Linkeš that's necessary to retrieve the capability support status. 2268c89d0038SJuraj Linkeš The Enum members may be assigned the method itself or a tuple of 2269c89d0038SJuraj Linkeš (capability_checking_method, decorator_function). 2270c89d0038SJuraj Linkeš 2271c89d0038SJuraj Linkeš The signature of each :class:`TestPmdShell` capability checking method must be:: 2272c89d0038SJuraj Linkeš 2273c89d0038SJuraj Linkeš fn(self, supported_capabilities: MutableSet, unsupported_capabilities: MutableSet) -> None 2274c89d0038SJuraj Linkeš 2275c89d0038SJuraj Linkeš The capability checking method must get whether a capability is supported or not 2276c89d0038SJuraj Linkeš from a testpmd command. If multiple capabilities can be obtained from a testpmd command, 2277c89d0038SJuraj Linkeš each should be obtained in the method. These capabilities should then 2278c89d0038SJuraj Linkeš be added to `supported_capabilities` or `unsupported_capabilities` based on their support. 2279c89d0038SJuraj Linkeš 2280c89d0038SJuraj Linkeš The two dictionaries are shared across all capability discovery function calls in a given 2281c0119400SJuraj Linkeš test run so that we don't call the same function multiple times. For example, when we find 2282c0119400SJuraj Linkeš :attr:`SCATTERED_RX_ENABLED` in :meth:`TestPmdShell.get_capabilities_rxq_info`, 2283c0119400SJuraj Linkeš we don't go looking for it again if a different test case also needs it. 2284c89d0038SJuraj Linkeš """ 2285c89d0038SJuraj Linkeš 2286c0119400SJuraj Linkeš #: Scattered packets Rx enabled 2287c0119400SJuraj Linkeš SCATTERED_RX_ENABLED: TestPmdShellNicCapability = ( 2288c0119400SJuraj Linkeš TestPmdShell.get_capabilities_rxq_info, 2289c0119400SJuraj Linkeš add_remove_mtu(9000), 2290c0119400SJuraj Linkeš ) 2291a79884f9SJuraj Linkeš #: 2292a79884f9SJuraj Linkeš RX_OFFLOAD_VLAN_STRIP: TestPmdShellCapabilityMethod = functools.partial( 2293a79884f9SJuraj Linkeš TestPmdShell.get_capabilities_rx_offload 2294a79884f9SJuraj Linkeš ) 2295a79884f9SJuraj Linkeš #: Device supports L3 checksum offload. 2296a79884f9SJuraj Linkeš RX_OFFLOAD_IPV4_CKSUM: TestPmdShellCapabilityMethod = functools.partial( 2297a79884f9SJuraj Linkeš TestPmdShell.get_capabilities_rx_offload 2298a79884f9SJuraj Linkeš ) 2299a79884f9SJuraj Linkeš #: Device supports L4 checksum offload. 2300a79884f9SJuraj Linkeš RX_OFFLOAD_UDP_CKSUM: TestPmdShellCapabilityMethod = functools.partial( 2301a79884f9SJuraj Linkeš TestPmdShell.get_capabilities_rx_offload 2302a79884f9SJuraj Linkeš ) 2303a79884f9SJuraj Linkeš #: Device supports L4 checksum offload. 2304a79884f9SJuraj Linkeš RX_OFFLOAD_TCP_CKSUM: TestPmdShellCapabilityMethod = functools.partial( 2305a79884f9SJuraj Linkeš TestPmdShell.get_capabilities_rx_offload 2306a79884f9SJuraj Linkeš ) 2307a79884f9SJuraj Linkeš #: Device supports Large Receive Offload. 2308a79884f9SJuraj Linkeš RX_OFFLOAD_TCP_LRO: TestPmdShellCapabilityMethod = functools.partial( 2309a79884f9SJuraj Linkeš TestPmdShell.get_capabilities_rx_offload 2310a79884f9SJuraj Linkeš ) 2311a79884f9SJuraj Linkeš #: Device supports QinQ (queue in queue) offload. 2312a79884f9SJuraj Linkeš RX_OFFLOAD_QINQ_STRIP: TestPmdShellCapabilityMethod = functools.partial( 2313a79884f9SJuraj Linkeš TestPmdShell.get_capabilities_rx_offload 2314a79884f9SJuraj Linkeš ) 2315a79884f9SJuraj Linkeš #: Device supports inner packet L3 checksum. 2316a79884f9SJuraj Linkeš RX_OFFLOAD_OUTER_IPV4_CKSUM: TestPmdShellCapabilityMethod = functools.partial( 2317a79884f9SJuraj Linkeš TestPmdShell.get_capabilities_rx_offload 2318a79884f9SJuraj Linkeš ) 2319a79884f9SJuraj Linkeš #: Device supports MACsec. 2320a79884f9SJuraj Linkeš RX_OFFLOAD_MACSEC_STRIP: TestPmdShellCapabilityMethod = functools.partial( 2321a79884f9SJuraj Linkeš TestPmdShell.get_capabilities_rx_offload 2322a79884f9SJuraj Linkeš ) 2323a79884f9SJuraj Linkeš #: Device supports filtering of a VLAN Tag identifier. 2324a79884f9SJuraj Linkeš RX_OFFLOAD_VLAN_FILTER: TestPmdShellCapabilityMethod = functools.partial( 2325a79884f9SJuraj Linkeš TestPmdShell.get_capabilities_rx_offload 2326a79884f9SJuraj Linkeš ) 2327a79884f9SJuraj Linkeš #: Device supports VLAN offload. 2328a79884f9SJuraj Linkeš RX_OFFLOAD_VLAN_EXTEND: TestPmdShellCapabilityMethod = functools.partial( 2329a79884f9SJuraj Linkeš TestPmdShell.get_capabilities_rx_offload 2330a79884f9SJuraj Linkeš ) 2331a79884f9SJuraj Linkeš #: Device supports receiving segmented mbufs. 2332a79884f9SJuraj Linkeš RX_OFFLOAD_SCATTER: TestPmdShellCapabilityMethod = functools.partial( 2333a79884f9SJuraj Linkeš TestPmdShell.get_capabilities_rx_offload 2334a79884f9SJuraj Linkeš ) 2335a79884f9SJuraj Linkeš #: Device supports Timestamp. 2336a79884f9SJuraj Linkeš RX_OFFLOAD_TIMESTAMP: TestPmdShellCapabilityMethod = functools.partial( 2337a79884f9SJuraj Linkeš TestPmdShell.get_capabilities_rx_offload 2338a79884f9SJuraj Linkeš ) 2339a79884f9SJuraj Linkeš #: Device supports crypto processing while packet is received in NIC. 2340a79884f9SJuraj Linkeš RX_OFFLOAD_SECURITY: TestPmdShellCapabilityMethod = functools.partial( 2341a79884f9SJuraj Linkeš TestPmdShell.get_capabilities_rx_offload 2342a79884f9SJuraj Linkeš ) 2343a79884f9SJuraj Linkeš #: Device supports CRC stripping. 2344a79884f9SJuraj Linkeš RX_OFFLOAD_KEEP_CRC: TestPmdShellCapabilityMethod = functools.partial( 2345a79884f9SJuraj Linkeš TestPmdShell.get_capabilities_rx_offload 2346a79884f9SJuraj Linkeš ) 2347a79884f9SJuraj Linkeš #: Device supports L4 checksum offload. 2348a79884f9SJuraj Linkeš RX_OFFLOAD_SCTP_CKSUM: TestPmdShellCapabilityMethod = functools.partial( 2349a79884f9SJuraj Linkeš TestPmdShell.get_capabilities_rx_offload 2350a79884f9SJuraj Linkeš ) 2351a79884f9SJuraj Linkeš #: Device supports inner packet L4 checksum. 2352a79884f9SJuraj Linkeš RX_OFFLOAD_OUTER_UDP_CKSUM: TestPmdShellCapabilityMethod = functools.partial( 2353a79884f9SJuraj Linkeš TestPmdShell.get_capabilities_rx_offload 2354a79884f9SJuraj Linkeš ) 2355a79884f9SJuraj Linkeš #: Device supports RSS hashing. 2356a79884f9SJuraj Linkeš RX_OFFLOAD_RSS_HASH: TestPmdShellCapabilityMethod = functools.partial( 2357a79884f9SJuraj Linkeš TestPmdShell.get_capabilities_rx_offload 2358a79884f9SJuraj Linkeš ) 2359a79884f9SJuraj Linkeš #: Device supports scatter Rx packets to segmented mbufs. 2360a79884f9SJuraj Linkeš RX_OFFLOAD_BUFFER_SPLIT: TestPmdShellCapabilityMethod = functools.partial( 2361a79884f9SJuraj Linkeš TestPmdShell.get_capabilities_rx_offload 2362a79884f9SJuraj Linkeš ) 2363a79884f9SJuraj Linkeš #: Device supports all checksum capabilities. 2364a79884f9SJuraj Linkeš RX_OFFLOAD_CHECKSUM: TestPmdShellCapabilityMethod = functools.partial( 2365a79884f9SJuraj Linkeš TestPmdShell.get_capabilities_rx_offload 2366a79884f9SJuraj Linkeš ) 2367a79884f9SJuraj Linkeš #: Device supports all VLAN capabilities. 2368a79884f9SJuraj Linkeš RX_OFFLOAD_VLAN: TestPmdShellCapabilityMethod = functools.partial( 2369a79884f9SJuraj Linkeš TestPmdShell.get_capabilities_rx_offload 2370a79884f9SJuraj Linkeš ) 2371d64f6ba5SJuraj Linkeš #: Device supports Rx queue setup after device started. 2372d64f6ba5SJuraj Linkeš RUNTIME_RX_QUEUE_SETUP: TestPmdShellCapabilityMethod = functools.partial( 2373d64f6ba5SJuraj Linkeš TestPmdShell.get_capabilities_show_port_info 2374d64f6ba5SJuraj Linkeš ) 2375d64f6ba5SJuraj Linkeš #: Device supports Tx queue setup after device started. 2376d64f6ba5SJuraj Linkeš RUNTIME_TX_QUEUE_SETUP: TestPmdShellCapabilityMethod = functools.partial( 2377d64f6ba5SJuraj Linkeš TestPmdShell.get_capabilities_show_port_info 2378d64f6ba5SJuraj Linkeš ) 2379d64f6ba5SJuraj Linkeš #: Device supports shared Rx queue among ports within Rx domain and switch domain. 2380d64f6ba5SJuraj Linkeš RXQ_SHARE: TestPmdShellCapabilityMethod = functools.partial( 2381d64f6ba5SJuraj Linkeš TestPmdShell.get_capabilities_show_port_info 2382d64f6ba5SJuraj Linkeš ) 2383d64f6ba5SJuraj Linkeš #: Device supports keeping flow rules across restart. 2384d64f6ba5SJuraj Linkeš FLOW_RULE_KEEP: TestPmdShellCapabilityMethod = functools.partial( 2385d64f6ba5SJuraj Linkeš TestPmdShell.get_capabilities_show_port_info 2386d64f6ba5SJuraj Linkeš ) 2387d64f6ba5SJuraj Linkeš #: Device supports keeping shared flow objects across restart. 2388d64f6ba5SJuraj Linkeš FLOW_SHARED_OBJECT_KEEP: TestPmdShellCapabilityMethod = functools.partial( 2389d64f6ba5SJuraj Linkeš TestPmdShell.get_capabilities_show_port_info 2390d64f6ba5SJuraj Linkeš ) 2391474ce443SNicholas Pratte #: Device supports multicast address filtering. 2392474ce443SNicholas Pratte MCAST_FILTERING: TestPmdShellCapabilityMethod = functools.partial( 2393474ce443SNicholas Pratte TestPmdShell.get_capabilities_mcast_filtering 2394474ce443SNicholas Pratte ) 2395c0119400SJuraj Linkeš 2396c89d0038SJuraj Linkeš def __call__( 2397c89d0038SJuraj Linkeš self, 2398c89d0038SJuraj Linkeš testpmd_shell: TestPmdShell, 2399c89d0038SJuraj Linkeš supported_capabilities: MutableSet[Self], 2400c89d0038SJuraj Linkeš unsupported_capabilities: MutableSet[Self], 2401c89d0038SJuraj Linkeš ) -> None: 2402c89d0038SJuraj Linkeš """Execute the associated capability retrieval function. 2403c89d0038SJuraj Linkeš 2404c89d0038SJuraj Linkeš Args: 2405c89d0038SJuraj Linkeš testpmd_shell: :class:`TestPmdShell` object to which the function will be bound to. 2406c89d0038SJuraj Linkeš supported_capabilities: The dictionary storing the supported capabilities 2407c89d0038SJuraj Linkeš of a given test run. 2408c89d0038SJuraj Linkeš unsupported_capabilities: The dictionary storing the unsupported capabilities 2409c89d0038SJuraj Linkeš of a given test run. 2410c89d0038SJuraj Linkeš """ 2411c89d0038SJuraj Linkeš self.value(testpmd_shell, supported_capabilities, unsupported_capabilities) 2412