The scatter Rx offload capability is needed for the pmd_buffer_scatter test suite. The command that retrieves the capability is: show port <port_id> rx_offload capabilities
The command also retrieves a lot of other capabilities (RX_OFFLOAD_*) which are all added into a Flag. The Flag members correspond to NIC capability names so a convenience function that looks for the supported Flags in a testpmd output is also added. The NIC capability names (mentioned above) are copy-pasted from the Flag. Dynamic addition of Enum members runs into problems with typing (mypy doesn't know about the members) and documentation generation (Sphinx doesn't know about the members). Signed-off-by: Juraj Linkeš <juraj.lin...@pantheon.tech> --- dts/framework/remote_session/testpmd_shell.py | 213 ++++++++++++++++++ dts/tests/TestSuite_pmd_buffer_scatter.py | 1 + 2 files changed, 214 insertions(+) diff --git a/dts/framework/remote_session/testpmd_shell.py b/dts/framework/remote_session/testpmd_shell.py index 48c31124d1..f83569669e 100644 --- a/dts/framework/remote_session/testpmd_shell.py +++ b/dts/framework/remote_session/testpmd_shell.py @@ -659,6 +659,103 @@ class TestPmdPortStats(TextParser): tx_bps: int = field(metadata=TextParser.find_int(r"Tx-bps:\s+(\d+)")) +class RxOffloadCapability(Flag): + """Rx offload capabilities of a device.""" + + #: + RX_OFFLOAD_VLAN_STRIP = auto() + #: Device supports L3 checksum offload. + RX_OFFLOAD_IPV4_CKSUM = auto() + #: Device supports L4 checksum offload. + RX_OFFLOAD_UDP_CKSUM = auto() + #: Device supports L4 checksum offload. + RX_OFFLOAD_TCP_CKSUM = auto() + #: Device supports Large Receive Offload. + RX_OFFLOAD_TCP_LRO = auto() + #: Device supports QinQ (queue in queue) offload. + RX_OFFLOAD_QINQ_STRIP = auto() + #: Device supports inner packet L3 checksum. + RX_OFFLOAD_OUTER_IPV4_CKSUM = auto() + #: Device supports MACsec. + RX_OFFLOAD_MACSEC_STRIP = auto() + #: Device supports filtering of a VLAN Tag identifier. + RX_OFFLOAD_VLAN_FILTER = 1 << 9 + #: Device supports VLAN offload. + RX_OFFLOAD_VLAN_EXTEND = auto() + #: Device supports receiving segmented mbufs. + RX_OFFLOAD_SCATTER = 1 << 13 + #: Device supports Timestamp. + RX_OFFLOAD_TIMESTAMP = auto() + #: Device supports crypto processing while packet is received in NIC. + RX_OFFLOAD_SECURITY = auto() + #: Device supports CRC stripping. + RX_OFFLOAD_KEEP_CRC = auto() + #: Device supports L4 checksum offload. + RX_OFFLOAD_SCTP_CKSUM = auto() + #: Device supports inner packet L4 checksum. + RX_OFFLOAD_OUTER_UDP_CKSUM = auto() + #: Device supports RSS hashing. + RX_OFFLOAD_RSS_HASH = auto() + #: Device supports + RX_OFFLOAD_BUFFER_SPLIT = auto() + #: Device supports all checksum capabilities. + RX_OFFLOAD_CHECKSUM = RX_OFFLOAD_IPV4_CKSUM | RX_OFFLOAD_UDP_CKSUM | RX_OFFLOAD_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 + ) + + @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[f"RX_OFFLOAD_{flag_name}"] + return flag + + @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. + + 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, + ) + + +@dataclass +class RxOffloadCapabilities(TextParser): + """The result of testpmd's ``show port <port_id> rx_offload capabilities`` command.""" + + #: + port_id: int = field( + metadata=TextParser.find_int(r"Rx Offloading Capabilities of port (\d+) :") + ) + #: Per-queue Rx offload capabilities. + per_queue: RxOffloadCapability = field(metadata=RxOffloadCapability.make_parser(False)) + #: Capabilities other than per-queue Rx offload capabilities. + per_port: RxOffloadCapability = field(metadata=RxOffloadCapability.make_parser(True)) + + T = TypeVarTuple("T") # type: ignore[misc] @@ -1048,6 +1145,42 @@ def _close(self) -> None: ====== Capability retrieval methods ====== """ + def get_capabilities_rx_offload( + self, + supported_capabilities: MutableSet["NicCapability"], + unsupported_capabilities: MutableSet["NicCapability"], + ) -> None: + """Get all rx offload capabilities and divide them into supported and unsupported. + + Args: + supported_capabilities: Supported capabilities will be added to this set. + unsupported_capabilities: Unsupported capabilities will be added to this set. + """ + self._logger.debug("Getting rx offload capabilities.") + command = f"show port {self.ports[0].id} rx_offload capabilities" + rx_offload_capabilities_out = self.send_command(command) + rx_offload_capabilities = RxOffloadCapabilities.parse(rx_offload_capabilities_out) + self._update_capabilities_from_flag( + supported_capabilities, + unsupported_capabilities, + RxOffloadCapability, + rx_offload_capabilities.per_port | rx_offload_capabilities.per_queue, + ) + + def _update_capabilities_from_flag( + self, + supported_capabilities: MutableSet["NicCapability"], + unsupported_capabilities: MutableSet["NicCapability"], + flag_class: type[Flag], + supported_flags: Flag, + ) -> 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)]) + else: + unsupported_capabilities.add(NicCapability[str(flag.name)]) + def get_capabilities_rxq_info( self, supported_capabilities: MutableSet["NicCapability"], @@ -1119,6 +1252,86 @@ class NicCapability(NoAliasEnum): SCATTERED_RX_ENABLED: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_capabilities_rxq_info ) + #: + RX_OFFLOAD_VLAN_STRIP: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_capabilities_rx_offload + ) + #: Device supports L3 checksum offload. + RX_OFFLOAD_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_capabilities_rx_offload + ) + #: Device supports L4 checksum offload. + RX_OFFLOAD_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_capabilities_rx_offload + ) + #: Device supports L4 checksum offload. + RX_OFFLOAD_TCP_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_capabilities_rx_offload + ) + #: Device supports Large Receive Offload. + RX_OFFLOAD_TCP_LRO: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_capabilities_rx_offload + ) + #: Device supports QinQ (queue in queue) offload. + RX_OFFLOAD_QINQ_STRIP: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_capabilities_rx_offload + ) + #: Device supports inner packet L3 checksum. + RX_OFFLOAD_OUTER_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_capabilities_rx_offload + ) + #: Device supports MACsec. + RX_OFFLOAD_MACSEC_STRIP: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_capabilities_rx_offload + ) + #: Device supports filtering of a VLAN Tag identifier. + RX_OFFLOAD_VLAN_FILTER: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_capabilities_rx_offload + ) + #: Device supports VLAN offload. + RX_OFFLOAD_VLAN_EXTEND: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_capabilities_rx_offload + ) + #: Device supports receiving segmented mbufs. + RX_OFFLOAD_SCATTER: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_capabilities_rx_offload + ) + #: Device supports Timestamp. + RX_OFFLOAD_TIMESTAMP: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_capabilities_rx_offload + ) + #: Device supports crypto processing while packet is received in NIC. + RX_OFFLOAD_SECURITY: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_capabilities_rx_offload + ) + #: Device supports CRC stripping. + RX_OFFLOAD_KEEP_CRC: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_capabilities_rx_offload + ) + #: Device supports L4 checksum offload. + RX_OFFLOAD_SCTP_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_capabilities_rx_offload + ) + #: Device supports inner packet L4 checksum. + RX_OFFLOAD_OUTER_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_capabilities_rx_offload + ) + #: Device supports RSS hashing. + RX_OFFLOAD_RSS_HASH: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_capabilities_rx_offload + ) + #: Device supports scatter Rx packets to segmented mbufs. + RX_OFFLOAD_BUFFER_SPLIT: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_capabilities_rx_offload + ) + #: Device supports all checksum capabilities. + RX_OFFLOAD_CHECKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_capabilities_rx_offload + ) + #: Device supports all VLAN capabilities. + RX_OFFLOAD_VLAN: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_capabilities_rx_offload + ) def __call__( self, diff --git a/dts/tests/TestSuite_pmd_buffer_scatter.py b/dts/tests/TestSuite_pmd_buffer_scatter.py index 89ece2ef56..64c48b0793 100644 --- a/dts/tests/TestSuite_pmd_buffer_scatter.py +++ b/dts/tests/TestSuite_pmd_buffer_scatter.py @@ -28,6 +28,7 @@ from framework.testbed_model.capability import NicCapability, requires +@requires(NicCapability.RX_OFFLOAD_SCATTER) class TestPmdBufferScatter(TestSuite): """DPDK PMD packet scattering test suite. -- 2.34.1