On Mon, Oct 27, 2025 at 9:02 AM Andrew Bailey wrote: > Currently, there is no support for tracking tx_offload capabilities and > there is no separation between port capabilities and queue > capabilities. This is an issue if a test case requires a tx_offload > capability or if a test case requires that a card supports a capability > on a queue. This causes test cases with said requirements to not be > skipped when appropriate. Add tx_offload capabilities and distinguish > capabilities between ports and queues. > > Signed-off-by: Andrew Bailey > Signed-off-by: Jeremy Spewock > --- > dts/api/capabilities.py | 126 ++++++++++-- > dts/api/testpmd/__init__.py | 97 ++++++++- > dts/api/testpmd/types.py | 227 +++++++++++++++------- > dts/framework/parser.py | 30 +++ > dts/framework/testbed_model/capability.py | 109 +++++++++-- > dts/tests/TestSuite_checksum_offload.py | 10 +- > dts/tests/TestSuite_pmd_buffer_scatter.py | 4 +- > dts/tests/TestSuite_vlan.py | 4 +- > 8 files changed, 489 insertions(+), 118 deletions(-) > > diff --git a/dts/api/capabilities.py b/dts/api/capabilities.py > index 1a79413f6f..243759668f 100644 > --- a/dts/api/capabilities.py > +++ b/dts/api/capabilities.py > @@ -77,45 +77,65 @@ class NicCapability(IntEnum): > #: Scattered packets Rx enabled. > SCATTERED_RX_ENABLED = 0 > #: Device supports VLAN stripping. > - RX_OFFLOAD_VLAN_STRIP = auto() > + PORT_RX_OFFLOAD_VLAN_STRIP = auto() > + QUEUE_RX_OFFLOAD_VLAN_STRIP = auto() > #: Device supports L3 checksum offload. > - RX_OFFLOAD_IPV4_CKSUM = auto() > + PORT_RX_OFFLOAD_IPV4_CKSUM = auto() > + QUEUE_RX_OFFLOAD_IPV4_CKSUM = auto() > #: Device supports L4 checksum offload. > - RX_OFFLOAD_UDP_CKSUM = auto() > + PORT_RX_OFFLOAD_UDP_CKSUM = auto() > + QUEUE_RX_OFFLOAD_UDP_CKSUM = auto() > #: Device supports L4 checksum offload. > - RX_OFFLOAD_TCP_CKSUM = auto() > + PORT_RX_OFFLOAD_TCP_CKSUM = auto() > + QUEUE_RX_OFFLOAD_TCP_CKSUM = auto() > #: Device supports Large Receive Offload. > - RX_OFFLOAD_TCP_LRO = auto() > + PORT_RX_OFFLOAD_TCP_LRO = auto() > + QUEUE_RX_OFFLOAD_TCP_LRO = auto() > #: Device supports QinQ (queue in queue) offload. > - RX_OFFLOAD_QINQ_STRIP = auto() > + PORT_RX_OFFLOAD_QINQ_STRIP = auto() > + QUEUE_RX_OFFLOAD_QINQ_STRIP = auto() > #: Device supports inner packet L3 checksum. > - RX_OFFLOAD_OUTER_IPV4_CKSUM = auto() > + PORT_RX_OFFLOAD_OUTER_IPV4_CKSUM = auto() > + QUEUE_RX_OFFLOAD_OUTER_IPV4_CKSUM = auto() > #: Device supports MACsec. > - RX_OFFLOAD_MACSEC_STRIP = auto() > + PORT_RX_OFFLOAD_MACSEC_STRIP = auto() > + QUEUE_RX_OFFLOAD_MACSEC_STRIP = auto() > #: Device supports filtering of a VLAN Tag identifier. > - RX_OFFLOAD_VLAN_FILTER = auto() > + PORT_RX_OFFLOAD_VLAN_FILTER = auto() > + QUEUE_RX_OFFLOAD_VLAN_FILTER = auto() > #: Device supports VLAN offload. > - RX_OFFLOAD_VLAN_EXTEND = auto() > + PORT_RX_OFFLOAD_VLAN_EXTEND = auto() > + QUEUE_RX_OFFLOAD_VLAN_EXTEND = auto() > #: Device supports receiving segmented mbufs. > - RX_OFFLOAD_SCATTER = auto() > + PORT_RX_OFFLOAD_SCATTER = auto() > + QUEUE_RX_OFFLOAD_SCATTER = auto() > #: Device supports Timestamp. > - RX_OFFLOAD_TIMESTAMP = auto() > + PORT_RX_OFFLOAD_TIMESTAMP = auto() > + QUEUE_RX_OFFLOAD_TIMESTAMP = auto() > #: Device supports crypto processing while packet is received in NIC. > - RX_OFFLOAD_SECURITY = auto() > + PORT_RX_OFFLOAD_SECURITY = auto() > + QUEUE_RX_OFFLOAD_SECURITY = auto() > #: Device supports CRC stripping. > - RX_OFFLOAD_KEEP_CRC = auto() > + PORT_RX_OFFLOAD_KEEP_CRC = auto() > + QUEUE_RX_OFFLOAD_KEEP_CRC = auto() > #: Device supports L4 checksum offload. > - RX_OFFLOAD_SCTP_CKSUM = auto() > + PORT_RX_OFFLOAD_SCTP_CKSUM = auto() > + QUEUE_RX_OFFLOAD_SCTP_CKSUM = auto() > #: Device supports inner packet L4 checksum. > - RX_OFFLOAD_OUTER_UDP_CKSUM = auto() > + PORT_RX_OFFLOAD_OUTER_UDP_CKSUM = auto() > + QUEUE_RX_OFFLOAD_OUTER_UDP_CKSUM = auto() > #: Device supports RSS hashing. > - RX_OFFLOAD_RSS_HASH = auto() > + PORT_RX_OFFLOAD_RSS_HASH = auto() > + QUEUE_RX_OFFLOAD_RSS_HASH = auto() > #: Device supports scatter Rx packets to segmented mbufs. > - RX_OFFLOAD_BUFFER_SPLIT = auto() > + PORT_RX_OFFLOAD_BUFFER_SPLIT = auto() > + QUEUE_RX_OFFLOAD_BUFFER_SPLIT = auto() > #: Device supports all checksum capabilities. > - RX_OFFLOAD_CHECKSUM = auto() > + PORT_RX_OFFLOAD_CHECKSUM = auto() > + QUEUE_RX_OFFLOAD_CHECKSUM = auto() > #: Device supports all VLAN capabilities. > - RX_OFFLOAD_VLAN = auto() > + PORT_RX_OFFLOAD_VLAN = auto() > + QUEUE_RX_OFFLOAD_VLAN = auto() > #: Device supports Rx queue setup after device started. > RUNTIME_RX_QUEUE_SETUP = auto() > #: Device supports Tx queue setup after device started. > @@ -132,6 +152,72 @@ class NicCapability(IntEnum): > FLOW_CTRL = auto() > #: Device is running on a physical function. > PHYSICAL_FUNCTION = auto() > + #: > + PORT_TX_OFFLOAD_VLAN_INSERT = auto() > + QUEUE_TX_OFFLOAD_VLAN_INSERT = auto() > + #: > + PORT_TX_OFFLOAD_IPV4_CKSUM = auto() > + QUEUE_TX_OFFLOAD_IPV4_CKSUM = auto() > + #: > + PORT_TX_OFFLOAD_UDP_CKSUM = auto() > + QUEUE_TX_OFFLOAD_UDP_CKSUM = auto() > + #: > + PORT_TX_OFFLOAD_TCP_CKSUM = auto() > + QUEUE_TX_OFFLOAD_TCP_CKSUM = auto() > + #: > + PORT_TX_OFFLOAD_SCTP_CKSUM = auto() > + QUEUE_TX_OFFLOAD_SCTP_CKSUM = auto() > + #: > + PORT_TX_OFFLOAD_TCP_TSO = auto() > + QUEUE_TX_OFFLOAD_TCP_TSO = auto() > + #: > + PORT_TX_OFFLOAD_UDP_TSO = auto() > + QUEUE_TX_OFFLOAD_UDP_TSO = auto() > + #: > + PORT_TX_OFFLOAD_OUTER_IPV4_CKSUM = auto() > + QUEUE_TX_OFFLOAD_OUTER_IPV4_CKSUM = auto() > + #: > + PORT_TX_OFFLOAD_QINQ_INSERT = auto() > + QUEUE_TX_OFFLOAD_QINQ_INSERT = auto() > + #: > + PORT_TX_OFFLOAD_VXLAN_TNL_TSO = auto() > + QUEUE_TX_OFFLOAD_VXLAN_TNL_TSO = auto() > + #: > + PORT_TX_OFFLOAD_GRE_TNL_TSO = auto() > + QUEUE_TX_OFFLOAD_GRE_TNL_TSO = auto() > + #: > + PORT_TX_OFFLOAD_IPIP_TNL_TSO = auto() > + QUEUE_TX_OFFLOAD_IPIP_TNL_TSO = auto() > + #: > + PORT_TX_OFFLOAD_GENEVE_TNL_TSO = auto() > + QUEUE_TX_OFFLOAD_GENEVE_TNL_TSO = auto() > + #: > + PORT_TX_OFFLOAD_MACSEC_INSERT = auto() > + QUEUE_TX_OFFLOAD_MACSEC_INSERT = auto() > + #: > + PORT_TX_OFFLOAD_MT_LOCKFREE = auto() > + QUEUE_TX_OFFLOAD_MT_LOCKFREE = auto() > + #: > + PORT_TX_OFFLOAD_MULTI_SEGS = auto() > + QUEUE_TX_OFFLOAD_MULTI_SEGS = auto() > + #: > + PORT_TX_OFFLOAD_MBUF_FAST_FREE = auto() > + QUEUE_TX_OFFLOAD_MBUF_FAST_FREE = auto() > + #: > + PORT_TX_OFFLOAD_SECURITY = auto() > + QUEUE_TX_OFFLOAD_SECURITY = auto() > + #: > + PORT_TX_OFFLOAD_UDP_TNL_TSO = auto() > + QUEUE_TX_OFFLOAD_UDP_TNL_TSO = auto() > + #: > + PORT_TX_OFFLOAD_IP_TNL_TSO = auto() > + QUEUE_TX_OFFLOAD_IP_TNL_TSO = auto() > + #: > + PORT_TX_OFFLOAD_OUTER_UDP_CKSUM = auto() > + QUEUE_TX_OFFLOAD_OUTER_UDP_CKSUM = auto() > + #: > + PORT_TX_OFFLOAD_SEND_ON_TIMESTAMP = auto() > + QUEUE_TX_OFFLOAD_SEND_ON_TIMESTAMP = auto() > > > def requires_link_topology( > diff --git a/dts/api/testpmd/__init__.py b/dts/api/testpmd/__init__.py > index 9e9cbaf495..aadb7f4e70 100644 > --- a/dts/api/testpmd/__init__.py > +++ b/dts/api/testpmd/__init__.py > @@ -39,6 +39,8 @@ > FlowRule, > RxOffloadCapabilities, > RxOffloadCapability, > + RxOffloadConfiguration, > + RxTxLiteralSwitch, > TestPmdDevice, > TestPmdPort, > TestPmdPortFlowCtrl, > @@ -46,6 +48,9 @@ > TestPmdQueueInfo, > TestPmdRxqInfo, > TestPmdVerbosePacket, > + TxOffloadCapabilities, > + TxOffloadCapability, > + TxOffloadConfiguration, > VLANOffloadFlag, > ) > from framework.context import get_ctx > @@ -1190,13 +1195,14 @@ def _update_capabilities_from_flag( > unsupported_capabilities: MutableSet["NicCapability"], > flag_class: type[Flag], > supported_flags: Flag, > + prefix: str = "", > ) -> None: > """Divide all flags from `flag_class` into supported and > unsupported.""" > for flag in flag_class: > if flag in supported_flags: > - supported_capabilities.add(NicCapability[str(flag.name)]) > + supported_capabilities.add(NicCapability[f"{prefix}{ > flag.name}"]) > else: > - unsupported_capabilities.add(NicCapability[str(flag.name > )]) > + unsupported_capabilities.add(NicCapability[f"{prefix}{ > flag.name}"]) > > @_requires_started_ports > def get_capabilities_rxq_info( > @@ -1293,6 +1299,55 @@ def get_capabilities_physical_function( > else: > unsupported_capabilities.add(NicCapability.PHYSICAL_FUNCTION) > > + @staticmethod > + def get_offload_capabilities_func( > + rxtx: RxTxLiteralSwitch, > + ) -> Callable[["TestPmd", MutableSet["NicCapability"], > MutableSet["NicCapability"]], None]: > + """High-order function that returns a method for gathering Rx/Tx > offload capabilities. > + > + Args: > + rxtx: whether to gather the rx or tx capabilities in the > returned method. > + > + Returns: > + A method for gathering Rx/Tx offload capabilities that meets > the required structure. > + """ > + > + def get_capabilities( > + self: "TestPmd", > + supported_capabilities: MutableSet["NicCapability"], > + unsupported_capabilities: MutableSet["NicCapability"], > + ) -> None: > + """Get all rx/tx offload capabilities and divide them into > supported and unsupported. > + > + Args: > + self: The shell instance to get the capabilities from. > + supported_capabilities: Supported capabilities will be > added to this set. > + unsupported_capabilities: Unsupported capabilities will > be added to this set. > + """ > + self._logger.info(f"Getting {rxtx} offload capabilities.") > + command = f"show port {self.ports[0].id} {rxtx}_offload > capabilities" > + offload_capabilities_out = self.send_command(command) > + > + capabilities = TxOffloadCapabilities if rxtx == "tx" else > RxOffloadCapabilities > + offload_capabilities = > capabilities.parse(offload_capabilities_out) > + > + self._update_capabilities_from_flag( > + supported_capabilities, > + unsupported_capabilities, > + TxOffloadCapability if rxtx == "tx" else > RxOffloadCapability, > + offload_capabilities.per_port | > offload_capabilities.per_queue, > + prefix=f"PORT_{rxtx.upper()}_OFFLOAD_", > + ) > + self._update_capabilities_from_flag( > + supported_capabilities, > + unsupported_capabilities, > + TxOffloadCapability if rxtx == "tx" else > RxOffloadCapability, > + offload_capabilities.per_queue, > + prefix=f"QUEUE_{rxtx.upper()}_OFFLOAD_", > + ) > + > + return get_capabilities > + > @_requires_stopped_ports > def set_port_mbuf_fast_free( > self, > @@ -1352,3 +1407,41 @@ def set_queue_mbuf_fast_free( > raise InteractiveCommandExecutionError( > f"Failed to get offload config on port {port_id}, queue > {queue_id}:\n{output}" > ) > + > + @_requires_started_ports > + def get_offload_config( > + self, > + port_id: int, > + rxtx: RxTxLiteralSwitch, > + /, > + verify: bool = True, > + ) -> RxOffloadConfiguration | TxOffloadConfiguration: > + """Get the Rx or Tx offload configuration of the queues from the > given port. > + > + Args: > + port_id: The port ID that contains the desired queues. > + rxtx: Whether to get the Rx or Tx configuration of the given > queues. > + verify: If :data:`True` the output of the command will be > scanned in an attempt to > + verify that the offload configuration was retrieved > successfully on all queues. > + > + Returns: > + An offload configuration containing the capabilities of the > port and queues. > + > + Raises: > + InteractiveCommandExecutionError: If all queue offload > configurations could not be > + retrieved. > + """ > + config_output = self.send_command(f"show port {port_id} > {rxtx}_offload configuration") > + if verify: > + if ( > + f"Rx Offloading Configuration of port {port_id}" not in > config_output > + and f"Tx Offloading Configuration of port {port_id}" not > in config_output > + ): > + self._logger.debug(f"Get port offload config > error\n{config_output}") > + raise InteractiveCommandExecutionError( > + f"Failed to get offload config on port > {port_id}:\n{config_output}" > + ) > + if rxtx == "rx": > + return RxOffloadConfiguration.parse(config_output) > + else: > + return TxOffloadConfiguration.parse(config_output) > diff --git a/dts/api/testpmd/types.py b/dts/api/testpmd/types.py > index d1ebf6f2d1..7e28235b18 100644 > --- a/dts/api/testpmd/types.py > +++ b/dts/api/testpmd/types.py > @@ -18,6 +18,8 @@ > from framework.parser import ParserFn, TextParser > from framework.utils import REGEX_FOR_MAC_ADDRESS, StrEnum > > +RxTxLiteralSwitch = Literal["rx", "tx"] > + > > class TestPmdDevice: > """The data of a device that testpmd can recognize. > @@ -1246,7 +1248,99 @@ class TestPmdVerbosePacket(TextParser): > ) > > > -class RxOffloadCapability(Flag): > +class OffloadCapability(Flag): > + """Flags generated from RxOffloadCapabilites and > TxOffloadCapabilities classes.""" > + > + @classmethod > + def from_string(cls, line: str) -> Self: > + """Make an instance from a string containing the flag names > separated with a space. > + > + Args: > + line: The line to parse. > + > + Returns: > + A new instance containing all found flags. > + """ > + flag = cls(0) > + for flag_name in line.split(): > + flag |= cls[flag_name] > + return flag > + > + @classmethod > + def from_list(cls, lines: list[str]) -> list[Self]: > + """Gather capabilities from a list of strings. > + > + Args: > + lines: The list of capabilities to make flags from. > + """ > + return [cls.from_string(line) for line in lines] > + > + @classmethod > + def make_parser( > + cls, port_or_queue: Literal["port", "queue"], /, find_multiple: > bool = False > + ) -> ParserFn: > + """Make a parser function. > + > + Args: > + port_or_queue: If :data:`True`, will return capabilities per > port. If :data:`False`, > + will return capabilities per queue. > + find_multiple: If :data:`True`, will use > :func:`TextParser.find_all` to find all > + matches for the regex query and return a list of > instances based on those matches. > + If :data:`False`, will return a single instance of the > flag based off a single > + match. > + > + Returns: > + ParserFn: A dictionary for the `dataclasses.field` metadata > argument containing a > + parser function that makes an instance of this flag from > text. > + """ > + granularity = port_or_queue.capitalize() > + regex = rf"{granularity}[\s\[\]\d]+:(.*)$" > + if find_multiple: > + return TextParser.wrap(TextParser.find_all(regex, > re.MULTILINE), cls.from_list) > + return TextParser.wrap(TextParser.find(regex, re.MULTILINE), > cls.from_string) > + > + > +class TxOffloadCapability(OffloadCapability): > + """Tx offload capabilities of a device. > + > + The flags are taken from ``lib/ethdev/rte_ethdev.h``. > + They're prefixed with ``RTE_ETH_TX_OFFLOAD`` in > ``lib/ethdev/rte_ethdev.h`` > + instead of ``TX_OFFLOAD``, which is what testpmd changes the prefix > to. > + > + The ``TX_OFFLOAD`` prefix has been preserved so that the same flag > names can be used > + in :class:`NicCapability`. The prefix is needed in > :class:`NicCapability` since there's > + no other qualifier which would sufficiently distinguish it from other > capabilities. > + > + References: > + DPDK lib: ``lib/ethdev/rte_ethdev.h`` > + testpmd display function: > ``app/test-pmd/cmdline.c:print_rx_offloads()`` > + """ > + > + VLAN_INSERT = auto() > + IPV4_CKSUM = auto() > + UDP_CKSUM = auto() > + TCP_CKSUM = auto() > + SCTP_CKSUM = auto() > + TCP_TSO = auto() > + UDP_TSO = auto() > + OUTER_IPV4_CKSUM = auto() > + QINQ_INSERT = auto() > + VXLAN_TNL_TSO = auto() > + GRE_TNL_TSO = auto() > + IPIP_TNL_TSO = auto() > + GENEVE_TNL_TSO = auto() > + MACSEC_INSERT = auto() > + MT_LOCKFREE = auto() > + MULTI_SEGS = auto() > + MBUF_FAST_FREE = auto() > + SECURITY = auto() > + UDP_TNL_TSO = auto() > + IP_TNL_TSO = auto() > + OUTER_UDP_CKSUM = auto() > + SEND_ON_TIMESTAMP = auto() > + > + > +class RxOffloadCapability(OffloadCapability): > """Rx offload capabilities of a device. > > The flags are taken from ``lib/ethdev/rte_ethdev.h``. > @@ -1265,102 +1359,103 @@ class RxOffloadCapability(Flag): > """ > > #: > - RX_OFFLOAD_VLAN_STRIP = auto() > + VLAN_STRIP = auto() > #: Device supports L3 checksum offload. > - RX_OFFLOAD_IPV4_CKSUM = auto() > + IPV4_CKSUM = auto() > #: Device supports L4 checksum offload. > - RX_OFFLOAD_UDP_CKSUM = auto() > + UDP_CKSUM = auto() > #: Device supports L4 checksum offload. > - RX_OFFLOAD_TCP_CKSUM = auto() > + TCP_CKSUM = auto() > #: Device supports Large Receive Offload. > - RX_OFFLOAD_TCP_LRO = auto() > + TCP_LRO = auto() > #: Device supports QinQ (queue in queue) offload. > - RX_OFFLOAD_QINQ_STRIP = auto() > + QINQ_STRIP = auto() > #: Device supports inner packet L3 checksum. > - RX_OFFLOAD_OUTER_IPV4_CKSUM = auto() > + OUTER_IPV4_CKSUM = auto() > #: Device supports MACsec. > - RX_OFFLOAD_MACSEC_STRIP = auto() > + MACSEC_STRIP = auto() > #: Device supports filtering of a VLAN Tag identifier. > - RX_OFFLOAD_VLAN_FILTER = 1 << 9 > + VLAN_FILTER = 1 << 9 > #: Device supports VLAN offload. > - RX_OFFLOAD_VLAN_EXTEND = auto() > + VLAN_EXTEND = auto() > #: Device supports receiving segmented mbufs. > - RX_OFFLOAD_SCATTER = 1 << 13 > + SCATTER = 1 << 13 > #: Device supports Timestamp. > - RX_OFFLOAD_TIMESTAMP = auto() > + TIMESTAMP = auto() > #: Device supports crypto processing while packet is received in NIC. > - RX_OFFLOAD_SECURITY = auto() > + SECURITY = auto() > #: Device supports CRC stripping. > - RX_OFFLOAD_KEEP_CRC = auto() > + KEEP_CRC = auto() > #: Device supports L4 checksum offload. > - RX_OFFLOAD_SCTP_CKSUM = auto() > + SCTP_CKSUM = auto() > #: Device supports inner packet L4 checksum. > - RX_OFFLOAD_OUTER_UDP_CKSUM = auto() > + OUTER_UDP_CKSUM = auto() > #: Device supports RSS hashing. > - RX_OFFLOAD_RSS_HASH = auto() > + RSS_HASH = auto() > #: Device supports > - RX_OFFLOAD_BUFFER_SPLIT = auto() > + BUFFER_SPLIT = auto() > #: Device supports all checksum capabilities. > - RX_OFFLOAD_CHECKSUM = RX_OFFLOAD_IPV4_CKSUM | RX_OFFLOAD_UDP_CKSUM | > RX_OFFLOAD_TCP_CKSUM > + CHECKSUM = IPV4_CKSUM | UDP_CKSUM | TCP_CKSUM > #: Device supports all VLAN capabilities. > - RX_OFFLOAD_VLAN = ( > - RX_OFFLOAD_VLAN_STRIP > - | RX_OFFLOAD_VLAN_FILTER > - | RX_OFFLOAD_VLAN_EXTEND > - | RX_OFFLOAD_QINQ_STRIP > - ) > + VLAN = VLAN_STRIP | VLAN_FILTER | VLAN_EXTEND | QINQ_STRIP > > - @classmethod > - def from_string(cls, line: str) -> Self: > - """Make an instance from a string containing the flag names > separated with a space. > > - Args: > - line: The line to parse. > +@dataclass > +class OffloadCapabilities(TextParser): > + """The result of testpmd's ``show port rx/tx_offload > capabilities`` command.""" > > - Returns: > - A new instance containing all found flags. > - """ > - flag = cls(0) > - for flag_name in line.split(): > - flag |= cls[f"RX_OFFLOAD_{flag_name}"] > - return flag > + port_id: int = field(metadata=TextParser.find_int(r"Offloading > Capabilities of port (\d+) :")) > + #: Per-queue offload capabilities. > + per_queue: OffloadCapability > + #: Capabilities other than per-queue offload capabilities. > + per_port: OffloadCapability > > - @classmethod > - def make_parser(cls, per_port: bool) -> ParserFn: > - """Make a parser function. > > - Args: > - per_port: If :data:`True`, will return capabilities per port. > If :data:`False`, > - will return capabilities per queue. > +@dataclass > +class RxOffloadCapabilities(OffloadCapabilities): > + """Extends :class:`OffloadCapabilities` with Rx specific > functionality.""" > > - Returns: > - ParserFn: A dictionary for the `dataclasses.field` metadata > argument containing a > - parser function that makes an instance of this flag from > text. > - """ > - granularity = "Port" if per_port else "Queue" > - return TextParser.wrap( > - TextParser.find(rf"Per {granularity}\s+:(.*)$", re.MULTILINE), > - cls.from_string, > - ) > + per_queue: OffloadCapability = > field(metadata=RxOffloadCapability.make_parser("queue")) > + per_port: OffloadCapability = > field(metadata=RxOffloadCapability.make_parser("port")) > > > @dataclass > -class RxOffloadCapabilities(TextParser): > - """The result of testpmd's ``show port rx_offload > capabilities`` command. > +class TxOffloadCapabilities(OffloadCapabilities): > + """Extends :class:`OffloadCapabilities` with Tx specific > functionality.""" > > - References: > - testpmd command function: > ``app/test-pmd/cmdline.c:cmd_rx_offload_get_capa()`` > - testpmd display function: > ``app/test-pmd/cmdline.c:cmd_rx_offload_get_capa_parsed()`` > - """ > + per_queue: OffloadCapability = > field(metadata=TxOffloadCapability.make_parser("queue")) > + per_port: OffloadCapability = > field(metadata=TxOffloadCapability.make_parser("port")) > > - #: > - port_id: int = field( > - metadata=TextParser.find_int(r"Rx Offloading Capabilities of port > (\d+) :") > + > +@dataclass > +class OffloadConfiguration(TextParser): > + """The result of testpmd's ``show port rx/tx_offload > configuration`` command.""" > + > + port_id: int = field(metadata=TextParser.find_int(r"Offloading > Configuration of port (\d+) :")) > + #: Queue offload configurations. > + queues: list[OffloadCapability] > + #: Port offload configuration. > + port: OffloadCapability > One final nit - I think attribute names queue_configs and port_config would read more clearly. What do you think? Reviewed-by: Patrick Robb