* [RFC PATCH v1 0/5] dts: port over Rx/Tx offload suite @ 2024-08-31 0:00 jspewock 2024-08-31 0:00 ` [RFC PATCH v1 1/5] dts: add TX offload capabilities jspewock ` (5 more replies) 0 siblings, 6 replies; 12+ messages in thread From: jspewock @ 2024-08-31 0:00 UTC (permalink / raw) To: Honnappa.Nagarahalli, probb, paul.szczepanek, juraj.linkes, yoan.picchi, npratte, wathsala.vithanage, Luca.Vizzarro, alex.chapman, thomas Cc: dev, Jeremy Spewock From: Jeremy Spewock <jspewock@iol.unh.edu> This series ports over the functionality of the Rx/Tx offloading test suite from Old DTS. I marked this suite as an RFC since there are still some errors that I need to fix from the formatting script, but I felt that the commits were in a place where they could be viewed to understand the idea of what I was working on. There are a lot of dependencies for this series, I listed them below in the order that I applied them. depends-on: patch-142691 (“dts:add send_packets to test suites and rework packet addressing”) depends-on: series-32799 (“dts: add test skipping based on capabilities”) depends-on: patch-143033 (“dts: add text parser for testpmd verbose output”) depends-on: patch-143385 (“dts: add VLAN methods to testpmd shell”) depends-on: patch-143113 ("dts: add flow rule dataclass to testpmd shell") Jeremy Spewock (5): dts: add TX offload capabilities dts: add a distinction between port and queue offload capabilities dts: add offload configuration querying to testpmd dts: add methods for configuring offloads on a device in testpmd dts: add test suite for RX and TX offloads dts/framework/config/conf_yaml_schema.json | 3 +- dts/framework/remote_session/testpmd_shell.py | 908 +++++++++++++++--- dts/tests/TestSuite_pmd_buffer_scatter.py | 2 +- dts/tests/TestSuite_rxtx_offload.py | 622 ++++++++++++ 4 files changed, 1414 insertions(+), 121 deletions(-) create mode 100644 dts/tests/TestSuite_rxtx_offload.py -- 2.46.0 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC PATCH v1 1/5] dts: add TX offload capabilities 2024-08-31 0:00 [RFC PATCH v1 0/5] dts: port over Rx/Tx offload suite jspewock @ 2024-08-31 0:00 ` jspewock 2024-08-31 0:00 ` [RFC PATCH v1 2/5] dts: add a distinction between port and queue " jspewock ` (4 subsequent siblings) 5 siblings, 0 replies; 12+ messages in thread From: jspewock @ 2024-08-31 0:00 UTC (permalink / raw) To: Honnappa.Nagarahalli, probb, paul.szczepanek, juraj.linkes, yoan.picchi, npratte, wathsala.vithanage, Luca.Vizzarro, alex.chapman, thomas Cc: dev, Jeremy Spewock From: Jeremy Spewock <jspewock@iol.unh.edu> The ability to query RX offloading capabilities of a device already exist, but there are situations in other test suites where skipping a test case/suite based on if a TX capability is missing is also desirable. This patch expands the RX offloading capabilities class to also allow for collecting TX offloading capabilities by creating a common parent class with parsing utility that is generalized to both. Signed-off-by: Jeremy Spewock <jspewock@iol.unh.edu> --- dts/framework/remote_session/testpmd_shell.py | 382 +++++++++++++----- 1 file changed, 287 insertions(+), 95 deletions(-) diff --git a/dts/framework/remote_session/testpmd_shell.py b/dts/framework/remote_session/testpmd_shell.py index e097a10751..cccc49ce9c 100644 --- a/dts/framework/remote_session/testpmd_shell.py +++ b/dts/framework/remote_session/testpmd_shell.py @@ -661,55 +661,8 @@ 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 - ) +class OffloadCapability(Flag): + """Offload capabilities of a device.""" @classmethod def from_string(cls, line: str) -> Self: @@ -723,7 +676,7 @@ def from_string(cls, line: str) -> Self: """ flag = cls(0) for flag_name in line.split(): - flag |= cls[f"RX_OFFLOAD_{flag_name}"] + flag |= cls[flag_name] return flag @classmethod @@ -745,20 +698,132 @@ def make_parser(cls, per_port: bool) -> ParserFn: ) +class RxOffloadCapability(OffloadCapability): + """Rx offload capabilities of a device.""" + + #: Device supports L3 checksum offload. + IPV4_CKSUM = auto() + #: Device supports L4 checksum offload. + UDP_CKSUM = auto() + #: Device supports L4 checksum offload. + TCP_CKSUM = auto() + #: Device supports inner packet L3 checksum. + OUTER_IPV4_CKSUM = auto() + #: Device supports crypto processing while packet is received in NIC. + SECURITY = auto() + #: + VLAN_STRIP = auto() + #: Device supports Large Receive Offload. + TCP_LRO = auto() + #: Device supports QinQ (queue in queue) offload. + QINQ_STRIP = auto() + #: Device supports MACsec. + MACSEC_STRIP = auto() + #: Device supports filtering of a VLAN Tag identifier. + VLAN_FILTER = 1 << 9 + #: Device supports VLAN offload. + VLAN_EXTEND = auto() + #: Device supports receiving segmented mbufs. + SCATTER = 1 << 13 + #: Device supports Timestamp. + TIMESTAMP = auto() + #: Device supports CRC stripping. + KEEP_CRC = auto() + #: Device supports L4 checksum offload. + SCTP_CKSUM = auto() + #: Device supports inner packet L4 checksum. + OUTER_UDP_CKSUM = auto() + #: Device supports RSS hashing. + RSS_HASH = auto() + #: Device supports + BUFFER_SPLIT = auto() + #: Device supports all checksum capabilities. + CHECKSUM = IPV4_CKSUM | UDP_CKSUM | TCP_CKSUM + #: Device supports all VLAN capabilities. + VLAN = VLAN_STRIP | VLAN_FILTER | VLAN_EXTEND | QINQ_STRIP + + +class TxOffloadCapability(OffloadCapability): + """Tx offload capabilities of a device.""" + + #: Device supports L3 checksum offload. + IPV4_CKSUM = auto() + #: Device supports L4 checksum offload. + UDP_CKSUM = auto() + #: Device supports L4 checksum offload. + TCP_CKSUM = auto() + #: Device supports inner packet L3 checksum. + OUTER_IPV4_CKSUM = auto() + #: Device supports crypto processing while packet is received in NIC. + SECURITY = auto() + #: + VLAN_INSERT = auto() + #: + QINQ_INSERT = auto() + #: + SCTP_CKSUM = auto() + #: Device supports QinQ (queue in queue) stripping offload. + QINQ_STRIP = auto() + #: Device supports TCP Segmentation Offload. + TCP_TSO = auto() + #: Device supports TCP Segmentation Offload with UDP. + UDP_TSO = auto() + #: Device supports TCP Segmentation Offload with VXLAN tunnels. + VXLAN_TNL_TSO = auto() + #: Device supports TCP Segmentation Offload with GRE tunnels. + GRE_TNL_TSO = auto() + #: Device supports TCP Segmentation Offload with IPIP tunnels. + IPIP_TNL_TSO = auto() + #: Device supports TCP Segmentation Offload with IP tunnels. + IP_TNL_TSO = auto() + #: Device supports TCP Segmentation Offload with GENEVE tunnels. + GENEVE_TNL_TSO = auto() + #: Device supports TCP Segmentation Offload with UDP tunnels. + UDP_TNL_TSO = auto() + #: + MACSEC_INSERT = auto() + #: + MT_LOCKFREE = auto() + #: + MULTI_SEGS = auto() + #: + MBUF_FAST_FREE = auto() + + @dataclass -class RxOffloadCapabilities(TextParser): - """The result of testpmd's ``show port <port_id> rx_offload capabilities`` command.""" +class OffloadCapabilities(TextParser): + """The result of testpmd's ``show port <port_id> rx/tx_offload capabilities`` command.""" #: port_id: int = field( - metadata=TextParser.find_int(r"Rx Offloading Capabilities of port (\d+) :") + metadata=TextParser.find_int(r"Offloading Capabilities of port (\d+) :") ) - #: Per-queue Rx offload capabilities. + #: Per-queue offload capabilities. + per_queue: RxOffloadCapability | TxOffloadCapability + #: Capabilities other than per-queue offload capabilities. + per_port: RxOffloadCapability | TxOffloadCapability + + +@dataclass +class RxOffloadCapabilities(OffloadCapabilities): + """Extends :class:`OffloadCapabilities` with Rx specific functionality.""" + + #: 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)) +@dataclass +class TxOffloadCapabilities(OffloadCapabilities): + """Extends :class:`OffloadCapabilities` with Tx specific functionality.""" + + #: + per_queue: TxOffloadCapability = field(metadata=TxOffloadCapability.make_parser(False)) + #: + per_port: TxOffloadCapability = field(metadata=TxOffloadCapability.make_parser(True)) + + T = TypeVarTuple("T") # type: ignore[misc] @@ -1501,6 +1566,32 @@ def show_port_stats(self, port_id: int) -> TestPmdPortStats: return TestPmdPortStats.parse(output) + def show_port_rx_offload_capabilities(self, port_id: int) -> RxOffloadCapabilities: + """Query the offloading capabilities of a given Rx port. + + Args: + port_id: The ID of the port to query. + + Returns: + Offloading capabilities of the port whose ID matches `port_id`. + """ + command = f"show port {port_id} rx_offload capabilities" + offload_capabilities_out = self.send_command(command) + return RxOffloadCapabilities.parse(offload_capabilities_out) + + def show_port_tx_offload_capabilities(self, port_id: int) -> TxOffloadCapabilities: + """Query the offloading capabilities of a given Tx port. + + Args: + port_id: The ID of the port to query. + + Returns: + Offloading capabilities of the port whose ID matches `port_id`. + """ + command = f"show port {port_id} tx_offload capabilities" + offload_capabilities_out = self.send_command(command) + return TxOffloadCapabilities.parse(offload_capabilities_out) + def _stop_port(self, port_id: int, verify: bool = True) -> None: """Stop port with `port_id` in testpmd. @@ -1855,27 +1946,43 @@ 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. + @staticmethod + def get_offload_capabilities_func(is_rx: bool) -> Callable[["TestPmdShell", MutableSet["NicCapability"], MutableSet["NicCapability"]], None]: + """High-order function that returns a method for gathering Rx/Tx offload capabilities. Args: - supported_capabilities: Supported capabilities will be added to this set. - unsupported_capabilities: Unsupported capabilities will be added to this set. + is_rx: If :data:`True` the method that is returned will gather Rx capabilities. If + :data:`False` the returned method will return Tx capabilities. + + Returns: + A method for gathering Rx/Tx offload capabilities that meets the required structure. """ - 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 get_capabilities( + self: "TestPmdShell", + supported_capabilities: MutableSet["NicCapability"], + unsupported_capabilities: MutableSet["NicCapability"], + ) -> None: + """Get all rx/tx 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. + """ + capabilities_class = RxOffloadCapability if is_rx else TxOffloadCapability + offload_type = "RX" if is_rx else 'TX' + offload_capabilities_func = ( + self.show_port_rx_offload_capabilities if is_rx else + self.show_port_tx_offload_capabilities + ) + offload_capabilities = offload_capabilities_func(self.ports[0].id) + self._update_capabilities_from_flag( + supported_capabilities, + unsupported_capabilities, + capabilities_class, + offload_capabilities.per_port, + prefix=f"{offload_type}_OFFLOAD_" + ) + return get_capabilities def _update_capabilities_from_flag( self, @@ -1883,13 +1990,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}"]) def get_capabilities_rxq_info( self, @@ -1982,83 +2090,167 @@ class NicCapability(NoAliasEnum): ) #: RX_OFFLOAD_VLAN_STRIP: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports L3 checksum offload. RX_OFFLOAD_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports L4 checksum offload. RX_OFFLOAD_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports L4 checksum offload. RX_OFFLOAD_TCP_CKSUM: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports Large Receive Offload. RX_OFFLOAD_TCP_LRO: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports QinQ (queue in queue) offload. RX_OFFLOAD_QINQ_STRIP: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports inner packet L3 checksum. RX_OFFLOAD_OUTER_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports MACsec. RX_OFFLOAD_MACSEC_STRIP: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports filtering of a VLAN Tag identifier. RX_OFFLOAD_VLAN_FILTER: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports VLAN offload. RX_OFFLOAD_VLAN_EXTEND: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports receiving segmented mbufs. RX_OFFLOAD_SCATTER: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports Timestamp. RX_OFFLOAD_TIMESTAMP: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports crypto processing while packet is received in NIC. RX_OFFLOAD_SECURITY: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports CRC stripping. RX_OFFLOAD_KEEP_CRC: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports L4 checksum offload. RX_OFFLOAD_SCTP_CKSUM: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports inner packet L4 checksum. RX_OFFLOAD_OUTER_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports RSS hashing. RX_OFFLOAD_RSS_HASH: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports scatter Rx packets to segmented mbufs. RX_OFFLOAD_BUFFER_SPLIT: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports all checksum capabilities. RX_OFFLOAD_CHECKSUM: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports all VLAN capabilities. RX_OFFLOAD_VLAN: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports L3 checksum offload. + TX_OFFLOAD_IPV4_CKSUM = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports L4 checksum offload. + TX_OFFLOAD_UDP_CKSUM = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports L4 checksum offload. + TX_OFFLOAD_TCP_CKSUM = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports inner packet L3 checksum. + TX_OFFLOAD_OUTER_IPV4_CKSUM = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports crypto processing while packet is received in NIC. + TX_OFFLOAD_SECURITY = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + TX_OFFLOAD_VLAN_INSERT = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + TX_OFFLOAD_QINQ_INSERT = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + TX_OFFLOAD_SCTP_CKSUM = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports QinQ (queue in queue) stripping offload. + TX_OFFLOAD_QINQ_STRIP = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload. + TX_OFFLOAD_TCP_TSO = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload with UDP. + TX_OFFLOAD_UDP_TSO = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload with VXLAN tunnels. + TX_OFFLOAD_VXLAN_TNL_TSO = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload with GRE tunnels. + TX_OFFLOAD_GRE_TNL_TSO = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload with IPIP tunnels. + TX_OFFLOAD_IPIP_TNL_TSO = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload with IP tunnels. + TX_OFFLOAD_IP_TNL_TSO = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload with GENEVE tunnels. + TX_OFFLOAD_GENEVE_TNL_TSO = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload with UDP tunnels. + TX_OFFLOAD_UDP_TNL_TSO = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + TX_OFFLOAD_MACSEC_INSERT = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + TX_OFFLOAD_MT_LOCKFREE = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + TX_OFFLOAD_MULTI_SEGS = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + TX_OFFLOAD_MBUF_FAST_FREE = partial( + TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports Rx queue setup after device started. RUNTIME_RX_QUEUE_SETUP: TestPmdShellCapabilityMethod = partial( -- 2.46.0 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC PATCH v1 2/5] dts: add a distinction between port and queue offload capabilities 2024-08-31 0:00 [RFC PATCH v1 0/5] dts: port over Rx/Tx offload suite jspewock 2024-08-31 0:00 ` [RFC PATCH v1 1/5] dts: add TX offload capabilities jspewock @ 2024-08-31 0:00 ` jspewock 2024-08-31 0:00 ` [RFC PATCH v1 3/5] dts: add offload configuration querying to testpmd jspewock ` (3 subsequent siblings) 5 siblings, 0 replies; 12+ messages in thread From: jspewock @ 2024-08-31 0:00 UTC (permalink / raw) To: Honnappa.Nagarahalli, probb, paul.szczepanek, juraj.linkes, yoan.picchi, npratte, wathsala.vithanage, Luca.Vizzarro, alex.chapman, thomas Cc: dev, Jeremy Spewock From: Jeremy Spewock <jspewock@iol.unh.edu> Currently in the framework offloading capabilities are collected at a device-level meaning that, if a capability is supported on either an entire port or individual queues on that port, it is marked as supported for the device. In some cases there is a want for being able to get the granularity of if an offload can be applied on queues rather than just on the device in general since all capabilities that are supported on queues are supported on ports, but not all capabilities that are supported on ports are supported on queues. This means that the less granular option of a combination of the two is still achievable by simply specifying that you require a port to be capable of an offload. This allows for granularity where needed, but generalization elsewhere. Signed-off-by: Jeremy Spewock <jspewock@iol.unh.edu> --- dts/framework/remote_session/testpmd_shell.py | 259 +++++++++++++++--- dts/tests/TestSuite_pmd_buffer_scatter.py | 2 +- 2 files changed, 217 insertions(+), 44 deletions(-) diff --git a/dts/framework/remote_session/testpmd_shell.py b/dts/framework/remote_session/testpmd_shell.py index cccc49ce9c..cfb51e3acb 100644 --- a/dts/framework/remote_session/testpmd_shell.py +++ b/dts/framework/remote_session/testpmd_shell.py @@ -1975,12 +1975,21 @@ def get_capabilities( self.show_port_tx_offload_capabilities ) offload_capabilities = offload_capabilities_func(self.ports[0].id) + # Any offload that can be set on an individual queue can also be set on the whole port, + # but not every capability that can be set on the port can be set on each queue. self._update_capabilities_from_flag( supported_capabilities, unsupported_capabilities, capabilities_class, - offload_capabilities.per_port, - prefix=f"{offload_type}_OFFLOAD_" + offload_capabilities.per_port | offload_capabilities.per_queue, + prefix=f"PORT_{offload_type}_OFFLOAD_" + ) + self._update_capabilities_from_flag( + supported_capabilities, + unsupported_capabilities, + capabilities_class, + offload_capabilities.per_queue, + prefix=f"QUEUE_{offload_type}_OFFLOAD_" ) return get_capabilities @@ -2089,167 +2098,331 @@ class NicCapability(NoAliasEnum): TestPmdShell.get_capabilities_rxq_info ) #: - RX_OFFLOAD_VLAN_STRIP: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_VLAN_STRIP: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports L3 checksum offload. - RX_OFFLOAD_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports L4 checksum offload. - RX_OFFLOAD_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports L4 checksum offload. - RX_OFFLOAD_TCP_CKSUM: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_TCP_CKSUM: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports Large Receive Offload. - RX_OFFLOAD_TCP_LRO: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_TCP_LRO: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports QinQ (queue in queue) offload. - RX_OFFLOAD_QINQ_STRIP: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_QINQ_STRIP: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports inner packet L3 checksum. - RX_OFFLOAD_OUTER_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_OUTER_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports MACsec. - RX_OFFLOAD_MACSEC_STRIP: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_MACSEC_STRIP: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports filtering of a VLAN Tag identifier. - RX_OFFLOAD_VLAN_FILTER: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_VLAN_FILTER: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports VLAN offload. - RX_OFFLOAD_VLAN_EXTEND: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_VLAN_EXTEND: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports receiving segmented mbufs. - RX_OFFLOAD_SCATTER: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_SCATTER: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports Timestamp. - RX_OFFLOAD_TIMESTAMP: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_TIMESTAMP: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports crypto processing while packet is received in NIC. - RX_OFFLOAD_SECURITY: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_SECURITY: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports CRC stripping. - RX_OFFLOAD_KEEP_CRC: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_KEEP_CRC: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports L4 checksum offload. - RX_OFFLOAD_SCTP_CKSUM: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_SCTP_CKSUM: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports inner packet L4 checksum. - RX_OFFLOAD_OUTER_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_OUTER_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports RSS hashing. - RX_OFFLOAD_RSS_HASH: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_RSS_HASH: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports scatter Rx packets to segmented mbufs. - RX_OFFLOAD_BUFFER_SPLIT: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_BUFFER_SPLIT: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports all checksum capabilities. - RX_OFFLOAD_CHECKSUM: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_CHECKSUM: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports all VLAN capabilities. - RX_OFFLOAD_VLAN: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_VLAN: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports L3 checksum offload. - TX_OFFLOAD_IPV4_CKSUM = partial( + PORT_TX_OFFLOAD_IPV4_CKSUM = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports L4 checksum offload. - TX_OFFLOAD_UDP_CKSUM = partial( + PORT_TX_OFFLOAD_UDP_CKSUM = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports L4 checksum offload. - TX_OFFLOAD_TCP_CKSUM = partial( + PORT_TX_OFFLOAD_TCP_CKSUM = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports inner packet L3 checksum. - TX_OFFLOAD_OUTER_IPV4_CKSUM = partial( + PORT_TX_OFFLOAD_OUTER_IPV4_CKSUM = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports crypto processing while packet is received in NIC. - TX_OFFLOAD_SECURITY = partial( + PORT_TX_OFFLOAD_SECURITY = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: - TX_OFFLOAD_VLAN_INSERT = partial( + PORT_TX_OFFLOAD_VLAN_INSERT = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: - TX_OFFLOAD_QINQ_INSERT = partial( + PORT_TX_OFFLOAD_QINQ_INSERT = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: - TX_OFFLOAD_SCTP_CKSUM = partial( + PORT_TX_OFFLOAD_SCTP_CKSUM = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports QinQ (queue in queue) stripping offload. - TX_OFFLOAD_QINQ_STRIP = partial( + PORT_TX_OFFLOAD_QINQ_STRIP = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports TCP Segmentation Offload. - TX_OFFLOAD_TCP_TSO = partial( + PORT_TX_OFFLOAD_TCP_TSO = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports TCP Segmentation Offload with UDP. - TX_OFFLOAD_UDP_TSO = partial( + PORT_TX_OFFLOAD_UDP_TSO = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports TCP Segmentation Offload with VXLAN tunnels. - TX_OFFLOAD_VXLAN_TNL_TSO = partial( + PORT_TX_OFFLOAD_VXLAN_TNL_TSO = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports TCP Segmentation Offload with GRE tunnels. - TX_OFFLOAD_GRE_TNL_TSO = partial( + PORT_TX_OFFLOAD_GRE_TNL_TSO = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports TCP Segmentation Offload with IPIP tunnels. - TX_OFFLOAD_IPIP_TNL_TSO = partial( + PORT_TX_OFFLOAD_IPIP_TNL_TSO = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports TCP Segmentation Offload with IP tunnels. - TX_OFFLOAD_IP_TNL_TSO = partial( + PORT_TX_OFFLOAD_IP_TNL_TSO = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports TCP Segmentation Offload with GENEVE tunnels. - TX_OFFLOAD_GENEVE_TNL_TSO = partial( + PORT_TX_OFFLOAD_GENEVE_TNL_TSO = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports TCP Segmentation Offload with UDP tunnels. - TX_OFFLOAD_UDP_TNL_TSO = partial( + PORT_TX_OFFLOAD_UDP_TNL_TSO = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + PORT_TX_OFFLOAD_MACSEC_INSERT = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + PORT_TX_OFFLOAD_MT_LOCKFREE = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + PORT_TX_OFFLOAD_MULTI_SEGS = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + PORT_TX_OFFLOAD_MBUF_FAST_FREE = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + QUEUE_RX_OFFLOAD_VLAN_STRIP: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports L3 checksum offload on queues. + QUEUE_RX_OFFLOAD_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports L4 checksum offload on queues. + QUEUE_RX_OFFLOAD_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports L4 checksum offload on queues. + QUEUE_RX_OFFLOAD_TCP_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports Large Receive Offload on queues. + QUEUE_RX_OFFLOAD_TCP_LRO: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports QinQ (queue in queue) offload on queues. + QUEUE_RX_OFFLOAD_QINQ_STRIP: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports inner packet L3 checksum on queues. + QUEUE_RX_OFFLOAD_OUTER_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports MACsec on queues. + QUEUE_RX_OFFLOAD_MACSEC_STRIP: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports filtering of a VLAN Tag identifier on queues. + QUEUE_RX_OFFLOAD_VLAN_FILTER: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports VLAN offload on queues. + QUEUE_RX_OFFLOAD_VLAN_EXTEND: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports receiving segmented mbufs on queues. + QUEUE_RX_OFFLOAD_SCATTER: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports Timestamp on queues. + QUEUE_RX_OFFLOAD_TIMESTAMP: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports crypto processing on queues while packet is received in NIC. + QUEUE_RX_OFFLOAD_SECURITY: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports CRC stripping on queues. + QUEUE_RX_OFFLOAD_KEEP_CRC: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports L4 checksum offload on queues. + QUEUE_RX_OFFLOAD_SCTP_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports inner packet L4 checksum o nqueues. + QUEUE_RX_OFFLOAD_OUTER_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports RSS hashing on queues. + QUEUE_RX_OFFLOAD_RSS_HASH: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports scatter Rx packets to segmented mbufs on queues. + QUEUE_RX_OFFLOAD_BUFFER_SPLIT: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports all checksum capabilities on queues. + QUEUE_RX_OFFLOAD_CHECKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports all VLAN capabilities on queues. + QUEUE_RX_OFFLOAD_VLAN: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports L3 checksum offload on queues. + QUEUE_TX_OFFLOAD_IPV4_CKSUM = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports L4 checksum offload on queues. + QUEUE_TX_OFFLOAD_UDP_CKSUM = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports L4 checksum offload on queues. + QUEUE_TX_OFFLOAD_TCP_CKSUM = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports inner packet L3 checksum on queues. + QUEUE_TX_OFFLOAD_OUTER_IPV4_CKSUM = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports crypto processing on queues while packet is received in NIC. + QUEUE_TX_OFFLOAD_SECURITY = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + QUEUE_TX_OFFLOAD_VLAN_INSERT = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + QUEUE_TX_OFFLOAD_QINQ_INSERT = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + QUEUE_TX_OFFLOAD_SCTP_CKSUM = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports QinQ (queue in queue) stripping offload on queues. + QUEUE_TX_OFFLOAD_QINQ_STRIP = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload on queues. + QUEUE_TX_OFFLOAD_TCP_TSO = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload on queues with UDP. + QUEUE_TX_OFFLOAD_UDP_TSO = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload on queues with VXLAN tunnels. + QUEUE_TX_OFFLOAD_VXLAN_TNL_TSO = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload on queues with GRE tunnels. + QUEUE_TX_OFFLOAD_GRE_TNL_TSO = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload on queues with IPIP tunnels. + QUEUE_TX_OFFLOAD_IPIP_TNL_TSO = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload on queues with IP tunnels. + QUEUE_TX_OFFLOAD_IP_TNL_TSO = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload on queues with GENEVE tunnels. + QUEUE_TX_OFFLOAD_GENEVE_TNL_TSO = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: #: Device supports TCP Segmentation Offload on queues with UDP tunnels. + QUEUE_TX_OFFLOAD_UDP_TNL_TSO = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: - TX_OFFLOAD_MACSEC_INSERT = partial( + QUEUE_TX_OFFLOAD_MACSEC_INSERT = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: - TX_OFFLOAD_MT_LOCKFREE = partial( + QUEUE_TX_OFFLOAD_MT_LOCKFREE = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: - TX_OFFLOAD_MULTI_SEGS = partial( + QUEUE_TX_OFFLOAD_MULTI_SEGS = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: - TX_OFFLOAD_MBUF_FAST_FREE = partial( + QUEUE_TX_OFFLOAD_MBUF_FAST_FREE = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports Rx queue setup after device started. diff --git a/dts/tests/TestSuite_pmd_buffer_scatter.py b/dts/tests/TestSuite_pmd_buffer_scatter.py index 64c48b0793..a1803588da 100644 --- a/dts/tests/TestSuite_pmd_buffer_scatter.py +++ b/dts/tests/TestSuite_pmd_buffer_scatter.py @@ -28,7 +28,7 @@ from framework.testbed_model.capability import NicCapability, requires -@requires(NicCapability.RX_OFFLOAD_SCATTER) +@requires(NicCapability.PORT_RX_OFFLOAD_SCATTER) class TestPmdBufferScatter(TestSuite): """DPDK PMD packet scattering test suite. -- 2.46.0 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC PATCH v1 3/5] dts: add offload configuration querying to testpmd 2024-08-31 0:00 [RFC PATCH v1 0/5] dts: port over Rx/Tx offload suite jspewock 2024-08-31 0:00 ` [RFC PATCH v1 1/5] dts: add TX offload capabilities jspewock 2024-08-31 0:00 ` [RFC PATCH v1 2/5] dts: add a distinction between port and queue " jspewock @ 2024-08-31 0:00 ` jspewock 2024-08-31 0:00 ` [RFC PATCH v1 4/5] dts: add methods for configuring offloads on a device in testpmd jspewock ` (2 subsequent siblings) 5 siblings, 0 replies; 12+ messages in thread From: jspewock @ 2024-08-31 0:00 UTC (permalink / raw) To: Honnappa.Nagarahalli, probb, paul.szczepanek, juraj.linkes, yoan.picchi, npratte, wathsala.vithanage, Luca.Vizzarro, alex.chapman, thomas Cc: dev, Jeremy Spewock From: Jeremy Spewock <jspewock@iol.unh.edu> Testpmd offers methods for querying the runtime configuration of offloads on a device that are useful for verification, but bindings to reach these methods do not exist in the Testpmd API offered in the framework. This patch creates methods that can query this configuration and also generalizes the OffloadCapability class to allow it to account for parsing the configuration output as well since the flag values will be the same. Signed-off-by: Jeremy Spewock <jspewock@iol.unh.edu> --- dts/framework/remote_session/testpmd_shell.py | 84 ++++++++++++++++++- 1 file changed, 81 insertions(+), 3 deletions(-) diff --git a/dts/framework/remote_session/testpmd_shell.py b/dts/framework/remote_session/testpmd_shell.py index cfb51e3acb..58b8995d21 100644 --- a/dts/framework/remote_session/testpmd_shell.py +++ b/dts/framework/remote_session/testpmd_shell.py @@ -680,21 +680,41 @@ def from_string(cls, line: str) -> Self: return flag @classmethod - def make_parser(cls, per_port: bool) -> ParserFn: + def from_list(cls, lines: list[str]) -> list[Self]: + """Make a list of instances from a list of strings that contain flag names. + + The strings are expected to separate the flag names by whitespace. + + Args: + lines: The list of strings to parse. + + Returns: + A list of instances parsed from each string in `lines`. + """ + return [cls.from_string(line) for line in lines] + + @classmethod + def make_parser(cls, per_port: bool, find_multiple: bool = False) -> ParserFn: """Make a parser function. Args: per_port: 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" if per_port else "Queue" + parser_func = TextParser.find_all if find_multiple else TextParser.find + instance_func = cls.from_list if find_multiple else cls.from_string return TextParser.wrap( - TextParser.find(rf"Per {granularity}\s+:(.*)$", re.MULTILINE), - cls.from_string, + parser_func(rf"{granularity}[\s\[\]\d]+:(.*)$", re.MULTILINE), + instance_func, ) @@ -824,6 +844,38 @@ class TxOffloadCapabilities(OffloadCapabilities): per_port: TxOffloadCapability = field(metadata=TxOffloadCapability.make_parser(True)) +@dataclass +class OffloadConfiguration(TextParser): + """The result of testpmd's ``show port <port_id> rx/tx_offload configuration`` command.""" + + #: + port_id: int = field( + metadata=TextParser.find_int(r"Offloading Configuration of port (\d+) :") + ) + #: Queue offload configurations. + queues: list[RxOffloadCapability] | list[TxOffloadCapability] + #: Port offload configuration. + port: RxOffloadCapability | TxOffloadCapability + + +@dataclass +class RxOffloadConfiguration(OffloadConfiguration): + """Extends :class:`OffloadingConfiguration` with Rx specific functionality.""" + #: + queues: list[RxOffloadCapability] = field(metadata=RxOffloadCapability.make_parser(False, find_multiple=True)) + #: + port: RxOffloadCapability = field(metadata=RxOffloadCapability.make_parser(True)) + + +@dataclass +class TxOffloadConfiguration(OffloadConfiguration): + """Extends :class:`OffloadingConfiguration` with Tx specific functionality.""" + #: + queues: list[TxOffloadCapability] = field(metadata=TxOffloadCapability.make_parser(False, find_multiple=True)) + #: + port: TxOffloadCapability = field(metadata=TxOffloadCapability.make_parser(True)) + + T = TypeVarTuple("T") # type: ignore[misc] @@ -1592,6 +1644,32 @@ def show_port_tx_offload_capabilities(self, port_id: int) -> TxOffloadCapabiliti offload_capabilities_out = self.send_command(command) return TxOffloadCapabilities.parse(offload_capabilities_out) + def show_port_rx_offload_configuration(self, port_id: int) -> RxOffloadConfiguration: + """Get the Rx offload configuration on a given port. + + Args: + port_id: The ID of the port to query the configuration of. + + Returns: + An instance of :class:`RxOffloadConfiguration` containing the offload configuration of + the port. + """ + output = self.send_command(f"show port {port_id} rx_offload configuration") + return RxOffloadConfiguration.parse(output) + + def show_port_tx_offload_configuration(self, port_id: int) -> TxOffloadConfiguration: + """Get the Tx offload configuration on a given port. + + Args: + port_id: The ID of the port to query the configuration of. + + Returns: + An instance of :class:`TxOffloadConfiguration` containing the offload configuration of + the port. + """ + output = self.send_command(f"show port {port_id} tx_offload configuration") + return TxOffloadConfiguration.parse(output) + def _stop_port(self, port_id: int, verify: bool = True) -> None: """Stop port with `port_id` in testpmd. -- 2.46.0 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC PATCH v1 4/5] dts: add methods for configuring offloads on a device in testpmd 2024-08-31 0:00 [RFC PATCH v1 0/5] dts: port over Rx/Tx offload suite jspewock ` (2 preceding siblings ...) 2024-08-31 0:00 ` [RFC PATCH v1 3/5] dts: add offload configuration querying to testpmd jspewock @ 2024-08-31 0:00 ` jspewock 2024-08-31 0:00 ` [RFC PATCH v1 5/5] dts: add test suite for RX and TX offloads jspewock 2024-09-03 19:46 ` [PATCH v2 0/5] dts: port over Rx/Tx offload suite jspewock 5 siblings, 0 replies; 12+ messages in thread From: jspewock @ 2024-08-31 0:00 UTC (permalink / raw) To: Honnappa.Nagarahalli, probb, paul.szczepanek, juraj.linkes, yoan.picchi, npratte, wathsala.vithanage, Luca.Vizzarro, alex.chapman, thomas Cc: dev, Jeremy Spewock From: Jeremy Spewock <jspewock@iol.unh.edu> Testpmd offers methods to add and remove offloads from both ports and queues on ports, but there are not yet method bindings in the Testpmd API that the framework provides to reach them. This patch adds these bindings for future test cases/suites that require certain functionalities to be offloaded on the device. Signed-off-by: Jeremy Spewock <jspewock@iol.unh.edu> --- dts/framework/remote_session/testpmd_shell.py | 229 +++++++++++++++++- 1 file changed, 228 insertions(+), 1 deletion(-) diff --git a/dts/framework/remote_session/testpmd_shell.py b/dts/framework/remote_session/testpmd_shell.py index 58b8995d21..383a3c48b8 100644 --- a/dts/framework/remote_session/testpmd_shell.py +++ b/dts/framework/remote_session/testpmd_shell.py @@ -32,7 +32,7 @@ from typing_extensions import TypeVarTuple -from framework.exception import InteractiveCommandExecutionError +from framework.exception import InteractiveCommandExecutionError, InternalError from framework.params.testpmd import SimpleForwardingModes, TestPmdParams from framework.params.types import TestPmdParamsDict from framework.parser import ParserFn, TextParser @@ -1314,6 +1314,54 @@ class TestPmdVerbosePacket(TextParser): l4_len: int | None = field(default=None, metadata=TextParser.find_int(r"l4_len=(\d+)")) +class TestPmdOffloadCapabilities(StrEnum): + """Base class for offload capabilities of ports/queues in testpmd. + + This base class is primarily used to give the Rx and Tx variants a common parent type. + """ + + pass + + +class TestPmdRxOffloadCapabilities(TestPmdOffloadCapabilities): + """Rx offload capabilities of ports/queues in testpmd.""" + + # *** Common attributes *** # + #: + all = auto() + #: + ipv4_cksum = auto() + #: + udp_cksum = auto() + #: + tcp_cksum = auto() + #: + outer_ipv4_cksum = auto() + #: + security = auto() + # *** End ***# + #: + vlan_strip = auto() + #: + tcp_lro = auto() + #: + qinq_strip = auto() + #: + macsec_strip = auto() + #: + vlan_filter = auto() + #: + vlan_extend = auto() + #: + scatter = auto() + #: + timestamp = auto() + #: + keep_crc = auto() + #: + rss_hash = auto() + + @dataclass class FlowRule: """Dataclass for setting flow rule parameters.""" @@ -1352,6 +1400,51 @@ def __str__(self) -> str: return ret +class TestPmdTxOffloadCapabilities(TestPmdOffloadCapabilities): + """Tx offload capabilities of ports/queues in testpmd.""" + + # *** Common attributes *** # + #: + all = auto() + #: + ipv4_cksum = auto() + #: + udp_cksum = auto() + #: + tcp_cksum = auto() + #: + outer_ipv4_cksum = auto() + #: + security = auto() + # *** End *** # + #: + vlan_insert = auto() + #: + sctp_cksum = auto() + #: + tcp_tso = auto() + #: + udp_tso = 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() + + class TestPmdShell(DPDKShell): """Testpmd interactive shell. @@ -1995,6 +2088,140 @@ def set_verbose(self, level: int, verify: bool = True) -> None: f"Testpmd failed to set verbose level to {level}." ) + @stop_then_start_port() + def _set_offload( + self, + port_id: int, + is_rx: bool, + offloads: OffloadCapability, + on: bool, + queue_id: int | None = None, + verify: bool = True, + ) -> None: + """Base method for configuring offloads on ports and queues. + + If `queue_id` is not specified then it is assumed that you want to set the offloads on the + port rather than a queue. + """ + for offload in type(offloads): + if offload not in offloads: + continue + port_type = "rx" if is_rx else "tx" + command = [ + "port", + f"{port_id}", + f"{port_type}_offload", + f"{offload.name}", + f"{'on' if on else 'off'}", + ] + if queue_id is not None: + # If modifying queues the command is "port <id> rxq <q_id> ..." + command.insert(2, f"{port_type}q {queue_id}") + else: + # If modifying a port the command is "port config <id> ..." + command.insert(1, "config") + + self.send_command(" ".join(command)) + if verify: + # verification of ports has to be done based on if it was applied to all queues or + # not because the "Per Port" line doesn't get modified until the port is started. + current_offload_conf: OffloadConfiguration = ( + self.show_port_rx_offload_configuration(port_id) if is_rx else + self.show_port_tx_offload_configuration(port_id) + ) + if queue_id is not None and len(current_offload_conf.queues) < queue_id + 1: + raise InternalError(f"Queue {queue_id} does not exist in testpmd") + capability_is_set = ( + len(current_offload_conf.queues) > 0 and + (queue_id is not None and offload in current_offload_conf.queues[queue_id]) or + all(offload in conf for conf in current_offload_conf.queues) + ) + if capability_is_set != on: + self._logger.debug( + f"Test pmd failed to modify capabilities on port {port_id}:\n" + f"{current_offload_conf.queues}" + ) + raise InteractiveCommandExecutionError( + f"Test pmd failed to {'add' if on else 'remove'} capability {offload.name} " + f"{'to' if on else 'from'} port {port_id}." + ) + + def set_port_offload( + self, + port_id: int, + is_rx: bool, + offload: OffloadCapability, + on: bool, + verify: bool = True, + ) -> None: + """Configure Rx/Tx offload on a port. + + Args: + port_id: The ID of the port to set configure the offload on. + is_rx: A flag that signifies which type of offload to set. If :data:`True` an Rx + offload will be set, otherwise a Tx offload will be set. + offload: The offload to set on the port. + on: If :data:`True` the specified offload will be set turned on, otherwise the offload + will be turned off. + verify: If :data:`True` an additional command will be sent to check the configuration + of offloads on the port to verify `offload` was set properly. Defaults to + :data:`True`. + + Raises: + InteractiveCommandExecutionError: If `verify` is :data:`True` and testpmd failed to + set the offload on the port. + """ + self._set_offload(port_id, is_rx, offload, on, None, verify) + + def set_queue_offload( + self, + port_id: int, + queue_id: int, + is_rx: bool, + offload: OffloadCapability, + on: bool, + verify: bool = True, + ) -> None: + """Configure Rx/Tx offload on a queue that resides on a specified port. + + Args: + port_id: The ID of the port where the queue resides. + queue_id: The ID of the queue on the port. + is_rx: A flag that signifies which type of offload to set. If :data:`True` an Rx + offload will be set, otherwise a Tx offload will be set. + offload: The offload to set on a port. + on: If :data:`True` the offload will be turned on, otherwise the offload will be turned + off. + verify: If :data:`True` an additional command will be sent to check the configuration + of the queue to validate that the offload was configured properly. Defaults to + :data:`True`. + + Raises: + InteractiveCommandExecutionError: If `verify` is :data:`True` and testpmd failed to + set the offload on the queue. + """ + self._set_offload(port_id, is_rx, offload, on, queue_id, verify) + + def is_port_offload_configured( + self, port_id: int, is_rx: bool, offload: OffloadCapability + ) -> bool: + """Verify whether or not an Rx/Tx offload is currently configured on a port. + + Args: + port_id: The ID of the port to check the configuration of. + is_rx: If :data:`True` the Rx offloads of the port will be checked, otherwise the Tx + offloads will be checked. + offload: The offload to search for on the port. + + Returns: + :data:`True` if the offload is configured on the port, :data:`False` otherwise. + """ + offload_config: OffloadConfiguration = ( + self.show_port_rx_offload_configuration(port_id) if is_rx else + self.show_port_tx_offload_configuration(port_id) + ) + return offload in offload_config.port + def flow_create(self, cmd: FlowRule, verify: bool = True) -> None: """Creates a flow rule in the testpmd session. -- 2.46.0 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC PATCH v1 5/5] dts: add test suite for RX and TX offloads 2024-08-31 0:00 [RFC PATCH v1 0/5] dts: port over Rx/Tx offload suite jspewock ` (3 preceding siblings ...) 2024-08-31 0:00 ` [RFC PATCH v1 4/5] dts: add methods for configuring offloads on a device in testpmd jspewock @ 2024-08-31 0:00 ` jspewock 2024-09-03 19:46 ` [PATCH v2 0/5] dts: port over Rx/Tx offload suite jspewock 5 siblings, 0 replies; 12+ messages in thread From: jspewock @ 2024-08-31 0:00 UTC (permalink / raw) To: Honnappa.Nagarahalli, probb, paul.szczepanek, juraj.linkes, yoan.picchi, npratte, wathsala.vithanage, Luca.Vizzarro, alex.chapman, thomas Cc: dev, Jeremy Spewock From: Jeremy Spewock <jspewock@iol.unh.edu> This patch adds a test sutie that ports over and expands upon functionality provided in the RxTx test sutie in Old DTS. This test suite provides convenience methods and decorators in an attempt to reduce code duplication when developers are tasked with testing the same offloaded functionality through 3 different mediums (passed on the command-line, configured on a port at runtime, and configured on queues at runtime). Signed-off-by: Jeremy Spewock <jspewock@iol.unh.edu> --- dts/framework/config/conf_yaml_schema.json | 3 +- dts/tests/TestSuite_rxtx_offload.py | 622 +++++++++++++++++++++ 2 files changed, 624 insertions(+), 1 deletion(-) create mode 100644 dts/tests/TestSuite_rxtx_offload.py diff --git a/dts/framework/config/conf_yaml_schema.json b/dts/framework/config/conf_yaml_schema.json index f02a310bb5..c1243ea5d8 100644 --- a/dts/framework/config/conf_yaml_schema.json +++ b/dts/framework/config/conf_yaml_schema.json @@ -187,7 +187,8 @@ "enum": [ "hello_world", "os_udp", - "pmd_buffer_scatter" + "pmd_buffer_scatter", + "rxtx_offload" ] }, "test_target": { diff --git a/dts/tests/TestSuite_rxtx_offload.py b/dts/tests/TestSuite_rxtx_offload.py new file mode 100644 index 0000000000..c9ed04f29d --- /dev/null +++ b/dts/tests/TestSuite_rxtx_offload.py @@ -0,0 +1,622 @@ +"""Rx/Tx offload configuration suite. + +The goal of this suite is to test the support for three different methods of offloading different +capabilities using testpmd: On a queue, on a port, and on the command-line. Support for configuring +the capability through different means is testing alongside verifying the functionality of the +capability when offloaded. Each of the three methods of setting the capability should be tested +using the same criteria to monitor for differences between the methods. + +Testing consists of enabling the capability if it wasn't passed in through the command-line, +verifying that the capability performs it's expected task, then, in the general case, disabling the +capability and verifying that the same result is not achieved in a default state. Some cases do not +check the base-case since their functionality is enabled by default without offloading the +capability (like invalid checksum verification, for example). + +There should be test cases for each of the 3 configuration strategies for every offload that is +tested. Additionally, there are two additional test cases that validates the ability to enable +every offload that a device supports on its port without actually testing the functionality of the +offload for both Rx and Tx. +""" + +import random +from typing import Callable, ClassVar, Protocol + +from scapy.layers.inet import IP, TCP, UDP +from scapy.layers.l2 import Dot1Q, Ether +from scapy.packet import Packet, Raw +from typing_extensions import Unpack + +from framework.exception import InteractiveCommandExecutionError, TestCaseVerifyError +from framework.params.types import TestPmdParamsDict +from framework.remote_session.testpmd_shell import ( + SimpleForwardingModes, + OffloadCapability, + RxOffloadCapability, + TxOffloadCapability, + TestPmdShell, + OLFlag, + TestPmdVerbosePacket, + NicCapability, + FlowRule +) +from framework.testbed_model.capability import requires +from framework.test_suite import TestSuite, func_test + + +class DecoratedFuncType(Protocol): + """Protocol used to provide a useful typehint for methods that are decorated. + + Methods decorated by :meth:`TestRxtxOffload.setup_testpmd` are able to pass kwargs into the + a :class:`TestPmdShell` upon creation and therefore have many non-obvious arguments. This type + allows static type checkers the ability to unpack and expose all of those non-obvious + arguments. + """ + + def __call__( + self, + test: "TestRxtxOffload", + port_id: int, + no_set: bool = False, + modify_queues: bool = False, + no_invert: bool = False, + **kwargs: Unpack[TestPmdParamsDict], + ) -> None: + """Function stub to create callable type. + + Args: + test: Instance of the test suite class that the methods belong to. + port_id: ID of the port to set the offloads on. + no_set: Whether to enable the offload before testing or not. When :data:`True`, + the method will validate that the offload is already configured rather than + enabling it. This is used in test cases that enable the offload using the + command-line. Defaults to :data:`False`. + modify_queues: Whether to add offloads to individual queues or the entire port. + If :data:`True`, individual queues will be modified, otherwise the whole + port will. Defaults to :data:`False`. + no_invert: If :data:`True` skip testing behavior of testpmd without the offload + enabled. Defaults to :data:`False`. + """ + ... + + +def set_offload( + offload: OffloadCapability, + testpmd: TestPmdShell, + is_rx: bool, + port_id: int, + queues_to_modify: set[int], + on: bool, +) -> None: + """Set offload on a port/queue using testpmd. + + This helper method allows you to reach both the :meth:`TestPmdShell.set_queue_offload` and + :meth:`TestPmdShell.set_port_offload` through a single method, and update the offloads on + multiple queues at once. + + Args: + offload: Offload to configure. + testpmd: Testpmd shell to use for modifying the offload configuration. This shell is + expected to be running before being passed into this method. + is_rx: If :data:`True` the offload will be configured on an Rx port/queue, otherwise it + will be configured on a Tx port/queue. + port_id: ID of the port to make configuration changes on. + queues_to_modify: IDs of queues to make configuration changes on. If this set is empty then + changes will only be made to the port configuration. + on: If :data:`True`, then enable the offload, otherwise disable it. + """ + if len(queues_to_modify) > 0: + for queue_id in queues_to_modify: + testpmd.set_queue_offload(port_id, queue_id, is_rx, offload, on, verify=True) + else: + testpmd.set_port_offload(port_id, is_rx, offload, on, verify=True) + + +class TestRxtxOffload(TestSuite): + """Rx/Tx offload testing suite. + + There are three ways to configure offloads in testpmd: Through the command line, at runtime on + a port, or at runtime on individual queues. Each of these configuration methods should be + tested for each of the offloads that are tested in this suite. Methods for testing each of the + offloads functionalities should be designed to be decorated by :func:`setup_testpmd`, meaning + their first parameter must be a :class:`TestPmdShell` (which will be running once the method + receives it) and the second parameter must be a bool signifying whether testing is to be done + on an entire port, or individual queues (:data:`True` for testing on a port, otherwise testing + on a queue). This decorator allows for testpmd to be configured with the proper offloads before + being passed to the method for testing. + """ + + #: + rx_port_for_testing: ClassVar[int] = 0 + #: + tx_port_for_testing: ClassVar[int] = 1 + #: Specify the number of queues to use for test cases the set offloads on queues. This should + #: generally be an odd integer since the test cases will apply offloads to the majority of + #: queues. + number_of_queues: ClassVar[int] = 5 + #: Common testpmd parameters for all tests to use. + common_testpmd_params: ClassVar[dict] = { + "forward_mode": SimpleForwardingModes.mac, + "rx_queues": number_of_queues, + "tx_queues": number_of_queues, + } + #: + relevant_checksum_errors: ClassVar[OLFlag] = ( + OLFlag.RTE_MBUF_F_RX_IP_CKSUM_BAD | + OLFlag.RTE_MBUF_F_RX_L4_CKSUM_BAD | + OLFlag.RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD + ) + + @staticmethod + def setup_testpmd( + offloads: OffloadCapability, is_rx: bool + ) -> Callable[[Callable[["TestRxtxOffload", TestPmdShell, bool], bool]], DecoratedFuncType]: + """Decorator function that initializes testpmd before running a test. + + All offloads in `offloads` are either enabled if they weren't passed in on the + command-line, or verified to be enabled on the port before running the decorated method. + The decorated method must return a boolean that represents whether or not the expected + behavior took place while the offload was enabled which will be used for verification that + the test functioned as expected. By default, this decorator will also disable all of the + offloads in `offloads` and verify that the decorated method instead returns :data:`False` + where it was expected to return :data:`True` with them enabled. This functionality can be + overridden, however, for cases where the opposite functionality cannot be easily tested + (like invalid checksums, for example). + + The decorated method additionally can be used for both setting offloads across the entire + port or on individual queues using the `modify_queues` parameter. If individual queues are + being modified then the majority of queues ((x / 2) + 1 where x is the number of queues) + will have the offload enabled rather than all of them. All decorated functions must be a + method of :class:`TestRxtxOffload` and take a testpmd shell for testing along with a + boolean that signifies whether it is a port being tested or individual queues. + + Args: + offloads: Offloads to set in testpmd prior to running decorated function. + is_rx: Whether to set Rx or Tx offloads when testing. + + Returns: + Decorator function that enables all offloads, runs the decorated method, then optionally + disables offloads and runs the test method again. + """ + + def wrap( + func: Callable[["TestRxtxOffload", TestPmdShell, bool], bool] + ) -> DecoratedFuncType: + def wrapper( + test: "TestRxtxOffload", + port_id: int, + no_set: bool = False, + modify_queues: bool = False, + no_invert: bool = False, + **kwargs: Unpack[TestPmdParamsDict], + ) -> None: + """Function that wraps the decorated method. + + Refer to :class:`DecoratedFuncType` for information about parameters of this + method. + """ + queues_to_modify: set[int] = set() + if modify_queues: + while len(queues_to_modify) < int(test.number_of_queues / 2 + 1): + queues_to_modify.add(random.randint(0, test.number_of_queues - 1)) + with TestPmdShell(test.sut_node, **test.common_testpmd_params, **kwargs) as testpmd: + # If no_set then it should have been passed on the command-line and already + # be configured, else we need to set them ourselves. + if no_set: + testpmd.is_port_offload_configured(port_id, is_rx, offloads) + else: + set_offload(offloads, testpmd, is_rx, port_id, queues_to_modify, on=True) + + test.verify( + func(test, testpmd, not modify_queues), + f"Offloaded capabilities ({offloads}) failed.", + ) + + set_offload(offloads, testpmd, is_rx, port_id, queues_to_modify, on=False) + if not no_invert: + test.verify( + not func(test, testpmd, not modify_queues), + f"After disabling capabilities ({offloads}) the " + "result was the same.", + ) + + return wrapper + + return wrap + + """ ========== Verify methods ========== + All verify methods must match the type + Callable[[list[Packet], list[TestPmdVerbosePacket]], bool] where their + first parameter is a list of packets that were forwarded back to the TG in the test and the + second parameter is the verbose information gathered by testpmd while packets were being + forwarded. These methods are meant to return a boolean that represents whether or not a + packet that matches their expected behavior can be found among any of their parameters in + order to be used by :meth:`send_packets_and_verify` for testing functionality. + """ + + @staticmethod + def _packet_is_relevant(pakt: Packet) -> bool: + """Helper method to test whether or not a packet was sent by a method in this test suite. + + All packets in this test suite are sent with a payload of 20 "X" characters, so this method + checks to see if `pakt` has a matching payload. + + Args: + pakt: The packet to validate. + + Returns: + :data:`True` if the packet has a valid payload, :data:`False` otherwise. + """ + return hasattr(pakt, "load") and pakt.load == bytes("X" * 20, "utf-8") + + @staticmethod + def verify_insertion(packets: list[Packet], *_) -> bool: + """Method to verify VLAN headers were inserted into sent packets. + + Checks to make sure that there is at least one packet in `packets` that is relevant to the + test suite with a VLAN header in it. This method consumes all arguments after `packets` to + conform to the type + Callable[[list[Packet], list[TestPmdVerbosePacket]], bool] even though + it does not need the verbose packet information. + + Args: + packets: Packets to scan for a valid result. + + Returns: + :data:`True` if there is at least one packet in `packets` that is relevant to the test + suite with a VLAN header in it, :data:`False` otherwise. + """ + return any(TestRxtxOffload._packet_is_relevant(pakt) and Dot1Q in pakt for pakt in packets) + + @staticmethod + def verify_stripping(packets: list[Packet], *_) -> bool: + """Method to verify VLAN headers were stripped from sent packets. + + Checks to make sure there is at least one packet in `packets` that is relevant to the suite + which does not contain a VLAN header. This method consumes all arguments after `packets` to + conform to the type + Callable[[list[Packet], list[TestPmdVerbosePacket]], bool] even though + it does not need the verbose packets. + + Args: + packets: The list of packets to scan for a valid result. + + Returns: + :data:`True` if there is at least one packet that is relevant to the suite in `packets` + without a VLAN header, :data:`False` otherwise. + """ + return any(TestRxtxOffload._packet_is_relevant(pakt) and Dot1Q not in pakt for pakt in packets) + + @classmethod + def verify_chksum( + cls, expected_errors: OLFlag | None = None + ) -> Callable[[list[Packet], list[TestPmdVerbosePacket]], bool]: + """Verify that the expected checksum errors appear in the forwarding statistics. + + Provides a closure for the wrapped function that stores the errors to expect in the + output. The wrapped function then accepts a list of packets received from forwarding as + well as forwarding statistics to validate with. The list of received packets are unused. + + Args: + expected_error: Errors to search for in the forwarding statistics. If flag is + :data:`None`, verify that none of the :attr:`relevant_checksum_errors` appear in + the forwarding status. Defaults to :data:`None`. + + Returns: + A function that searches for the expected errors in the forwarding statistics and + returns :data:`True` if they are all present or if `expected_errors` is :data:`None` + and there are no errors present. The function will return :data:`False` otherwise. + """ + + def wrap(_, fwd_stats: list[TestPmdVerbosePacket]) -> bool: + """Method that fits the expected type of verify methods.""" + if expected_errors is None: + return all( + cls.relevant_checksum_errors & pakt.ol_flags == OLFlag(0) for pakt in fwd_stats + ) + else: + return any( + expected_errors in pakt.ol_flags for pakt in fwd_stats + ) + + return wrap + + """ ========== End verify methods ========= """ + + def send_packets_and_verify( + self, + testpmd: TestPmdShell, + packets: list[Packet], + verify_meth: Callable[[list[Packet], list[TestPmdVerbosePacket]], bool], + is_port: bool, + ) -> bool: + """Send packets and verify the result using `verify_meth`. + + If testing is being done on queues, this method makes flow rules that make it so that + anything that has the source address 192.168.1.X will be handled by queue X in testpmd. + Then, before sending packets in all cases, this method will adjust the source IP addresses + of the packets in `packets` to ensure they are all different and processed by different, + start testpmd, send all of the packets in `packets`, and captures the resulting received + traffic and forwarding stats. The received traffic and forwarding stats are then passed + into `verify_meth` to test if the expected result took place. + + In the case of testing the results of queues, it is expected that the majority of queues + (but not all) have the offload enabled and, therefore, only the majority of packets in + `packets` need to return :data:`True` from `verify_meth` to get a positive + result. + + Args: + testpmd: Testpmd shell that is handling the packet forwarding. This shell is expected + to already be started before being passed into this method. + packets: List of packets to send to the SUT during testing. + verify_meth: Method used to verify that the packet matches the expected results. + is_port: Flag to differentiate testing results from an offload set on a port from an + offload set on a queue. + + Returns: + :data:`True` if `verify_meth` returned :data:`True` for every packet in `packets` if + testing offloads on a port, or the majority of packets if testing offloads on queues. + :data:`False` otherwise. + """ + majority = int(self.number_of_queues / 2 + 1) + dst_ip_addr = "192.168.1.{}" + verify_results: list[bool] = [] + base_pattern = f"eth / {'vlan /' if packets[0].haslayer(Dot1Q) else ''} " "ipv4 dst is {}" + base_action = "queue index {}" + if not is_port: + rule = FlowRule(self.rx_port_for_testing, True, "", "") + for queue_id in range(self.number_of_queues): + rule.pattern = base_pattern.format(dst_ip_addr.format(queue_id)) + rule.actions = base_action.format(queue_id) + testpmd.flow_create(rule) + + for ind, pakt in enumerate(packets): + testpmd.start() + pakt.getlayer(IP).dst = dst_ip_addr.format(ind % self.number_of_queues) + recv = self.send_packet_and_capture(pakt) + stats = TestPmdShell.extract_verbose_output(testpmd.stop()) + verify_results.append(verify_meth(recv, stats)) + return all(verify_results) if is_port else verify_results.count(True) == majority + + """ ========== Functionality testing methods ========== + Functionality testing methods are the methods that test, assuming the offloads are already + configured in the environment, Rx/Tx offloads perform their expected behavior. These + methods must conform to the type Callable[["TestRxtxOffload", TestPmdShell, bool], bool] + so that they can be decorated by :func:`setup_testpmd`. + """ + + @setup_testpmd(TxOffloadCapability.VLAN_INSERT, False) + def tx_vlan_insertion_test(self, testpmd: TestPmdShell, is_port: bool) -> bool: + """Testing method for VLAN insertion on a Tx port/queue. + + Testing is done by sending one packet without a VLAN header for as many queues as there are + configured and verifying with :meth:`verify_insertion`. + + Args: + testpmd: Testpmd shell to use for testing. It is expected that this shell is already + running. + is_port: If :data:`True`, do testing on a port, otherwise do testing on individual + queues. + + Returns: + :data:`True` if the received traffic contained a VLAN header when expected with the + offload enabled. + """ + return self.send_packets_and_verify( + testpmd, + [Ether() / IP() / Raw("X" * 20)] * self.number_of_queues, + TestRxtxOffload.verify_insertion, + is_port, + ) + + @setup_testpmd(RxOffloadCapability.VLAN_STRIP, True) + def rx_vlan_stripping(self, testpmd: TestPmdShell, is_port: bool) -> bool: + """Testing method for VLAN stripping on an Rx port/queue. + + Testing is done by sending one packet with a VLAN header for every configured queue and + verifying using :func:`verify_stripping` that the received packets had their VLAN header + stripped. + + Args: + testpmd: Testpmd shell to use for testing. This shell is expected to already be + running when passed into this method. + is_port: If :data:`True`, do testing on a port, otherwise do testing on individual + queues. + + Returns: + :data:`True` if the expected amount of received packets had their VLAN headers stripped + when the offload is enabled, :data:`False` otherwise. + """ + return self.send_packets_and_verify( + testpmd, + [Ether() / Dot1Q() / IP() / Raw("X" * 20)] * self.number_of_queues, + TestRxtxOffload.verify_stripping, + is_port, + ) + + @setup_testpmd( + RxOffloadCapability.UDP_CKSUM | + RxOffloadCapability.TCP_CKSUM | + RxOffloadCapability.IPV4_CKSUM, + True, + ) + def rx_cksum_test(self, testpmd: TestPmdShell, is_port: bool) -> bool: + """Test for verifying invalid checksum reporting. + + Testing is done in multiple stages for checksum test cases. Testpmd must first be set to + Rx-only verbose mode to capture the checksum errors reported by testpmd when receiving + packets with a bad checksum. There are then 4 main cases to test: + + * Valid packets do not display any checksum errors. + * Packets with a bad IP checksum and a bad layer 4 checksum report both errors properly. + * Packets with only a bad layer 4 checksum report only that error properly. + * Packets with only a bad IP checksum report only that error properly. + + All of these cases must pass for this method to return :data:`True`. + + Args: + testpmd: Testpmd shell to use for testing. It is expected that this shell is already + running when it is passed into this method. + is_port: If :data:`True`, do testing on a port, otherwise do testing on individual + queues. + + Returns: + :data:`True` if all 4 cases pass, :data:`False` otherwise. + """ + testpmd.set_verbose(1) + results = [ + self.send_packets_and_verify( + testpmd, [Ether() / IP() / TCP() / ("X" * 20)], self.verify_chksum(), is_port + ), + self.send_packets_and_verify( + testpmd, + [Ether() / IP(chksum=0x0) / TCP(chksum=0xF) / ("X" * 20)], + TestRxtxOffload.verify_chksum( + OLFlag.RTE_MBUF_F_RX_IP_CKSUM_BAD | OLFlag.RTE_MBUF_F_RX_L4_CKSUM_BAD + ), + is_port, + ), + self.send_packets_and_verify( + testpmd, + [Ether() / IP() / UDP(chksum=0xF) / ("X" * 20)], + TestRxtxOffload.verify_chksum(OLFlag.RTE_MBUF_F_RX_L4_CKSUM_BAD), + is_port, + ), + self.send_packets_and_verify( + testpmd, + [Ether() / IP(chksum=0x0) / UDP() / ("X" * 20)], + TestRxtxOffload.verify_chksum(OLFlag.RTE_MBUF_F_RX_IP_CKSUM_BAD), + is_port, + ), + ] + return all(results) + + """ ========== End functionality testing methods ========== """ + + @requires(NicCapability.PORT_TX_OFFLOAD_VLAN_INSERT) + @func_test + def test_tx_port_vlan_insertion(self) -> None: + """Run :meth:`tx_vlan_insertion_test` with common testpmd parameters.""" + self.tx_vlan_insertion_test(self.tx_port_for_testing) + + @requires(NicCapability.PORT_TX_OFFLOAD_VLAN_INSERT) + @func_test + def test_tx_cmdline_vlan_insertion(self) -> None: + """Run :meth:`tx_vlan_insertion_test` with insertion offload passed on the command-line. + + This requires specifying that the offload should not be set at runtime when calling the + method. + """ + self.tx_vlan_insertion_test( + self.tx_port_for_testing, no_set=True, tx_offloads=0x0001 + ) + + @requires(NicCapability.QUEUE_TX_OFFLOAD_VLAN_INSERT) + @func_test + def test_tx_queue_vlan_insertion(self) -> None: + """Run :meth:`tx_vlan_insertion_test` specifying queues should be modified.""" + self.tx_vlan_insertion_test(self.tx_port_for_testing, modify_queues=True) + + @requires(NicCapability.PORT_RX_OFFLOAD_VLAN_STRIP) + @func_test + def test_rx_port_vlan_strip(self) -> None: + """Run :meth:`rx_vlan_stripping` with common testpmd parameters.""" + self.rx_vlan_stripping(self.rx_port_for_testing) + + @requires(NicCapability.PORT_RX_OFFLOAD_VLAN_STRIP) + @func_test + def test_rx_cmdline_vlan_strip(self) -> None: + """Run :meth:`rx_vlan_stripping` with stripping offload passed on the command-line. + + This requires specifying that the offload should not be set at runtime when calling the + method. + """ + self.rx_vlan_stripping(self.rx_port_for_testing, no_set=True, enable_hw_vlan_strip=True) + + @requires(NicCapability.QUEUE_RX_OFFLOAD_VLAN_STRIP) + @func_test + def test_rx_queue_vlan_strip(self) -> None: + """Run :meth:`rx_vlan_stripping` specifying queues should be modified.""" + self.rx_vlan_stripping(self.rx_port_for_testing, modify_queues=True) + + @requires( + NicCapability.PORT_RX_OFFLOAD_UDP_CKSUM, + NicCapability.PORT_RX_OFFLOAD_TCP_CKSUM, + NicCapability.PORT_RX_OFFLOAD_IPV4_CKSUM + ) + @func_test + def test_rx_port_chksum(self) -> None: + """Run :meth:`rx_cksum_test` with common testpmd parameters. + + Since checksum errors will be thrown even when the offload is disabled, specify not to + invert testing. + """ + self.rx_cksum_test(self.rx_port_for_testing, no_invert=True) + + @requires( + NicCapability.PORT_RX_OFFLOAD_UDP_CKSUM, + NicCapability.PORT_RX_OFFLOAD_TCP_CKSUM, + NicCapability.PORT_RX_OFFLOAD_IPV4_CKSUM + ) + @func_test + def test_rx_cmdline_chksum(self) -> None: + """Run :meth:`rx_cksum_test` with checksum offloads enabled through the command-line. + + Since checksum errors will be thrown even when the offload is disabled, specify not to + invert testing. Additionally, specify that the offload should not be set at runtime. + """ + self.rx_cksum_test( + self.rx_port_for_testing, + no_set=True, + no_invert=True, + enable_rx_cksum=True, + ) + + @requires( + NicCapability.QUEUE_RX_OFFLOAD_UDP_CKSUM, + NicCapability.QUEUE_RX_OFFLOAD_TCP_CKSUM, + NicCapability.QUEUE_RX_OFFLOAD_IPV4_CKSUM + ) + @func_test + def test_rx_queue_chksum(self) -> None: + """Run :meth:`rx_cksum_test` specifying testing should be run on queues. + + Since checksum errors will be thrown even when the offload is disabled, specify not to + invert testing. + """ + self.rx_cksum_test( + self.rx_port_for_testing, + modify_queues=True, + no_invert=True, + ) + + @func_test + def test_rx_all_port_offloads(self) -> None: + """Verify that testpmd is able to set all Rx offloads the port is capable of at runtime.""" + with TestPmdShell(self.sut_node) as testpmd: + supported_capabilities = testpmd.show_port_rx_offload_capabilities( + self.rx_port_for_testing + ).per_port + try: + testpmd.set_port_offload( + self.rx_port_for_testing, True, supported_capabilities, True, verify=True + ) + except InteractiveCommandExecutionError as e: + raise TestCaseVerifyError( + f"Failed to set all Rx offloads on port {self.rx_port_for_testing}" + ) from e + + @func_test + def test_tx_all_port_offloads(self) -> None: + """Verify that testpmd is able to set all Tx offloads the port is capable of at runtime.""" + with TestPmdShell(self.sut_node) as testpmd: + supported_capabilities = testpmd.show_port_tx_offload_capabilities( + self.tx_port_for_testing + ).per_port + try: + testpmd.set_port_offload( + self.tx_port_for_testing, False, supported_capabilities, True, verify=True + ) + except InteractiveCommandExecutionError as e: + raise TestCaseVerifyError( + f"Failed to set all Tx offloads on port {self.tx_port_for_testing}" + ) from e -- 2.46.0 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 0/5] dts: port over Rx/Tx offload suite 2024-08-31 0:00 [RFC PATCH v1 0/5] dts: port over Rx/Tx offload suite jspewock ` (4 preceding siblings ...) 2024-08-31 0:00 ` [RFC PATCH v1 5/5] dts: add test suite for RX and TX offloads jspewock @ 2024-09-03 19:46 ` jspewock 2024-09-03 19:46 ` [PATCH v2 1/5] dts: add TX offload capabilities jspewock ` (4 more replies) 5 siblings, 5 replies; 12+ messages in thread From: jspewock @ 2024-09-03 19:46 UTC (permalink / raw) To: yoan.picchi, npratte, juraj.linkes, probb, thomas, paul.szczepanek, wathsala.vithanage, alex.chapman, Luca.Vizzarro, Honnappa.Nagarahalli Cc: dev, Jeremy Spewock From: Jeremy Spewock <jspewock@iol.unh.edu> v2: * added fixes to allow for passing the formatting script * removed some unused classes in TestPmdShell There are a lot of dependencies for this series, I listed them below in the order that I applied them. depends-on: patch-142691 (“dts:add send_packets to test suites and rework packet addressing”) depends-on: series-32799 (“dts: add test skipping based on capabilities”) depends-on: patch-143033 (“dts: add text parser for testpmd verbose output”) depends-on: patch-143385 (“dts: add VLAN methods to testpmd shell”) depends-on: patch-143113 ("dts: add flow rule dataclass to testpmd shell") Jeremy Spewock (5): dts: add TX offload capabilities dts: add a distinction between port and queue offload capabilities dts: add offload configuration querying to testpmd dts: add methods for configuring offloads on a device in testpmd dts: add test suite for RX and TX offloads dts/framework/config/conf_yaml_schema.json | 3 +- dts/framework/remote_session/testpmd_shell.py | 842 +++++++++++++++--- dts/tests/TestSuite_pmd_buffer_scatter.py | 2 +- dts/tests/TestSuite_rxtx_offload.py | 627 +++++++++++++ 4 files changed, 1350 insertions(+), 124 deletions(-) create mode 100644 dts/tests/TestSuite_rxtx_offload.py -- 2.46.0 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 1/5] dts: add TX offload capabilities 2024-09-03 19:46 ` [PATCH v2 0/5] dts: port over Rx/Tx offload suite jspewock @ 2024-09-03 19:46 ` jspewock 2024-09-03 19:46 ` [PATCH v2 2/5] dts: add a distinction between port and queue " jspewock ` (3 subsequent siblings) 4 siblings, 0 replies; 12+ messages in thread From: jspewock @ 2024-09-03 19:46 UTC (permalink / raw) To: yoan.picchi, npratte, juraj.linkes, probb, thomas, paul.szczepanek, wathsala.vithanage, alex.chapman, Luca.Vizzarro, Honnappa.Nagarahalli Cc: dev, Jeremy Spewock From: Jeremy Spewock <jspewock@iol.unh.edu> The ability to query RX offloading capabilities of a device already exist, but there are situations in other test suites where skipping a test case/suite based on if a TX capability is missing is also desirable. This patch expands the RX offloading capabilities class to also allow for collecting TX offloading capabilities by creating a common parent class with parsing utility that is generalized to both. Signed-off-by: Jeremy Spewock <jspewock@iol.unh.edu> --- dts/framework/remote_session/testpmd_shell.py | 395 +++++++++++++----- 1 file changed, 297 insertions(+), 98 deletions(-) diff --git a/dts/framework/remote_session/testpmd_shell.py b/dts/framework/remote_session/testpmd_shell.py index 99f327a91b..13001d6666 100644 --- a/dts/framework/remote_session/testpmd_shell.py +++ b/dts/framework/remote_session/testpmd_shell.py @@ -21,7 +21,7 @@ from enum import Flag, auto from functools import partial from pathlib import PurePath -from typing import TYPE_CHECKING, Any, ClassVar, TypeAlias +from typing import TYPE_CHECKING, Any, ClassVar, TypeAlias, cast if TYPE_CHECKING: from enum import Enum as NoAliasEnum @@ -661,55 +661,8 @@ 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 - ) +class OffloadCapability(Flag): + """Offload capabilities of a device.""" @classmethod def from_string(cls, line: str) -> Self: @@ -723,7 +676,7 @@ def from_string(cls, line: str) -> Self: """ flag = cls(0) for flag_name in line.split(): - flag |= cls[f"RX_OFFLOAD_{flag_name}"] + flag |= cls[flag_name] return flag @classmethod @@ -745,20 +698,130 @@ def make_parser(cls, per_port: bool) -> ParserFn: ) +class RxOffloadCapability(OffloadCapability): + """Rx offload capabilities of a device.""" + + #: Device supports L3 checksum offload. + IPV4_CKSUM = auto() + #: Device supports L4 checksum offload. + UDP_CKSUM = auto() + #: Device supports L4 checksum offload. + TCP_CKSUM = auto() + #: Device supports inner packet L3 checksum. + OUTER_IPV4_CKSUM = auto() + #: Device supports crypto processing while packet is received in NIC. + SECURITY = auto() + #: + VLAN_STRIP = auto() + #: Device supports Large Receive Offload. + TCP_LRO = auto() + #: Device supports QinQ (queue in queue) offload. + QINQ_STRIP = auto() + #: Device supports MACsec. + MACSEC_STRIP = auto() + #: Device supports filtering of a VLAN Tag identifier. + VLAN_FILTER = 1 << 9 + #: Device supports VLAN offload. + VLAN_EXTEND = auto() + #: Device supports receiving segmented mbufs. + SCATTER = 1 << 13 + #: Device supports Timestamp. + TIMESTAMP = auto() + #: Device supports CRC stripping. + KEEP_CRC = auto() + #: Device supports L4 checksum offload. + SCTP_CKSUM = auto() + #: Device supports inner packet L4 checksum. + OUTER_UDP_CKSUM = auto() + #: Device supports RSS hashing. + RSS_HASH = auto() + #: Device supports + BUFFER_SPLIT = auto() + #: Device supports all checksum capabilities. + CHECKSUM = IPV4_CKSUM | UDP_CKSUM | TCP_CKSUM + #: Device supports all VLAN capabilities. + VLAN = VLAN_STRIP | VLAN_FILTER | VLAN_EXTEND | QINQ_STRIP + + +class TxOffloadCapability(OffloadCapability): + """Tx offload capabilities of a device.""" + + #: Device supports L3 checksum offload. + IPV4_CKSUM = auto() + #: Device supports L4 checksum offload. + UDP_CKSUM = auto() + #: Device supports L4 checksum offload. + TCP_CKSUM = auto() + #: Device supports inner packet L3 checksum. + OUTER_IPV4_CKSUM = auto() + #: Device supports crypto processing while packet is received in NIC. + SECURITY = auto() + #: + VLAN_INSERT = auto() + #: + QINQ_INSERT = auto() + #: + SCTP_CKSUM = auto() + #: Device supports QinQ (queue in queue) stripping offload. + QINQ_STRIP = auto() + #: Device supports TCP Segmentation Offload. + TCP_TSO = auto() + #: Device supports TCP Segmentation Offload with UDP. + UDP_TSO = auto() + #: Device supports TCP Segmentation Offload with VXLAN tunnels. + VXLAN_TNL_TSO = auto() + #: Device supports TCP Segmentation Offload with GRE tunnels. + GRE_TNL_TSO = auto() + #: Device supports TCP Segmentation Offload with IPIP tunnels. + IPIP_TNL_TSO = auto() + #: Device supports TCP Segmentation Offload with IP tunnels. + IP_TNL_TSO = auto() + #: Device supports TCP Segmentation Offload with GENEVE tunnels. + GENEVE_TNL_TSO = auto() + #: Device supports TCP Segmentation Offload with UDP tunnels. + UDP_TNL_TSO = auto() + #: + MACSEC_INSERT = auto() + #: + MT_LOCKFREE = auto() + #: + MULTI_SEGS = auto() + #: + MBUF_FAST_FREE = auto() + + @dataclass -class RxOffloadCapabilities(TextParser): - """The result of testpmd's ``show port <port_id> rx_offload capabilities`` command.""" +class OffloadCapabilities(TextParser): + """The result of testpmd's ``show port <port_id> rx/tx_offload capabilities`` command.""" + + #: + port_id: int = field(metadata=TextParser.find_int(r"Offloading Capabilities of port (\d+) :")) + #: Per-queue offload capabilities. + per_queue: RxOffloadCapability | TxOffloadCapability + #: Capabilities other than per-queue offload capabilities. + per_port: RxOffloadCapability | TxOffloadCapability + + +@dataclass +class RxOffloadCapabilities(OffloadCapabilities): + """Extends :class:`OffloadCapabilities` with Rx specific functionality.""" #: - 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)) +@dataclass +class TxOffloadCapabilities(OffloadCapabilities): + """Extends :class:`OffloadCapabilities` with Tx specific functionality.""" + + #: + per_queue: TxOffloadCapability = field(metadata=TxOffloadCapability.make_parser(False)) + #: + per_port: TxOffloadCapability = field(metadata=TxOffloadCapability.make_parser(True)) + + T = TypeVarTuple("T") # type: ignore[misc] @@ -1501,6 +1564,32 @@ def show_port_stats(self, port_id: int) -> TestPmdPortStats: return TestPmdPortStats.parse(output) + def show_port_rx_offload_capabilities(self, port_id: int) -> RxOffloadCapabilities: + """Query the offloading capabilities of a given Rx port. + + Args: + port_id: The ID of the port to query. + + Returns: + Offloading capabilities of the port whose ID matches `port_id`. + """ + command = f"show port {port_id} rx_offload capabilities" + offload_capabilities_out = self.send_command(command) + return RxOffloadCapabilities.parse(offload_capabilities_out) + + def show_port_tx_offload_capabilities(self, port_id: int) -> TxOffloadCapabilities: + """Query the offloading capabilities of a given Tx port. + + Args: + port_id: The ID of the port to query. + + Returns: + Offloading capabilities of the port whose ID matches `port_id`. + """ + command = f"show port {port_id} tx_offload capabilities" + offload_capabilities_out = self.send_command(command) + return TxOffloadCapabilities.parse(offload_capabilities_out) + def _stop_port(self, port_id: int, verify: bool = True) -> None: """Stop port with `port_id` in testpmd. @@ -1856,27 +1945,52 @@ 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. + @staticmethod + def get_offload_capabilities_func( + is_rx: bool, + ) -> Callable[["TestPmdShell", MutableSet["NicCapability"], MutableSet["NicCapability"]], None]: + """High-order function that returns a method for gathering Rx/Tx offload capabilities. Args: - supported_capabilities: Supported capabilities will be added to this set. - unsupported_capabilities: Unsupported capabilities will be added to this set. + is_rx: If :data:`True` the method that is returned will gather Rx capabilities. If + :data:`False` the returned method will return Tx capabilities. + + Returns: + A method for gathering Rx/Tx offload capabilities that meets the required structure. """ - 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 get_capabilities( + self: "TestPmdShell", + 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 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. + """ + capabilities_class = RxOffloadCapability if is_rx else TxOffloadCapability + offload_type = "RX" if is_rx else "TX" + offload_capabilities_func = ( + self.show_port_rx_offload_capabilities + if is_rx + else self.show_port_tx_offload_capabilities + ) + offload_capabilities = offload_capabilities_func(self.ports[0].id) + # Cast to the generic type for mypy + per_port = cast(OffloadCapability, offload_capabilities.per_port) + per_queue = cast(OffloadCapability, offload_capabilities.per_queue) + self._update_capabilities_from_flag( + supported_capabilities, + unsupported_capabilities, + capabilities_class, + per_port | per_queue, + prefix=f"{offload_type}_OFFLOAD_", + ) + + return get_capabilities def _update_capabilities_from_flag( self, @@ -1884,13 +1998,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}"]) def get_capabilities_rxq_info( self, @@ -1983,83 +2098,167 @@ class NicCapability(NoAliasEnum): ) #: RX_OFFLOAD_VLAN_STRIP: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports L3 checksum offload. RX_OFFLOAD_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports L4 checksum offload. RX_OFFLOAD_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports L4 checksum offload. RX_OFFLOAD_TCP_CKSUM: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports Large Receive Offload. RX_OFFLOAD_TCP_LRO: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports QinQ (queue in queue) offload. RX_OFFLOAD_QINQ_STRIP: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports inner packet L3 checksum. RX_OFFLOAD_OUTER_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports MACsec. RX_OFFLOAD_MACSEC_STRIP: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports filtering of a VLAN Tag identifier. RX_OFFLOAD_VLAN_FILTER: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports VLAN offload. RX_OFFLOAD_VLAN_EXTEND: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports receiving segmented mbufs. RX_OFFLOAD_SCATTER: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports Timestamp. RX_OFFLOAD_TIMESTAMP: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports crypto processing while packet is received in NIC. RX_OFFLOAD_SECURITY: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports CRC stripping. RX_OFFLOAD_KEEP_CRC: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports L4 checksum offload. RX_OFFLOAD_SCTP_CKSUM: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports inner packet L4 checksum. RX_OFFLOAD_OUTER_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports RSS hashing. RX_OFFLOAD_RSS_HASH: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports scatter Rx packets to segmented mbufs. RX_OFFLOAD_BUFFER_SPLIT: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports all checksum capabilities. RX_OFFLOAD_CHECKSUM: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports all VLAN capabilities. RX_OFFLOAD_VLAN: TestPmdShellCapabilityMethod = partial( - TestPmdShell.get_capabilities_rx_offload + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports L3 checksum offload. + TX_OFFLOAD_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports L4 checksum offload. + TX_OFFLOAD_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports L4 checksum offload. + TX_OFFLOAD_TCP_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports inner packet L3 checksum. + TX_OFFLOAD_OUTER_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports crypto processing while packet is received in NIC. + TX_OFFLOAD_SECURITY: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + TX_OFFLOAD_VLAN_INSERT: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + TX_OFFLOAD_QINQ_INSERT: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + TX_OFFLOAD_SCTP_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports QinQ (queue in queue) stripping offload. + TX_OFFLOAD_QINQ_STRIP: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload. + TX_OFFLOAD_TCP_TSO: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload with UDP. + TX_OFFLOAD_UDP_TSO: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload with VXLAN tunnels. + TX_OFFLOAD_VXLAN_TNL_TSO: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload with GRE tunnels. + TX_OFFLOAD_GRE_TNL_TSO: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload with IPIP tunnels. + TX_OFFLOAD_IPIP_TNL_TSO: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload with IP tunnels. + TX_OFFLOAD_IP_TNL_TSO: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload with GENEVE tunnels. + TX_OFFLOAD_GENEVE_TNL_TSO: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload with UDP tunnels. + TX_OFFLOAD_UDP_TNL_TSO: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + TX_OFFLOAD_MACSEC_INSERT: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + TX_OFFLOAD_MT_LOCKFREE: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + TX_OFFLOAD_MULTI_SEGS: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + TX_OFFLOAD_MBUF_FAST_FREE: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports Rx queue setup after device started. RUNTIME_RX_QUEUE_SETUP: TestPmdShellCapabilityMethod = partial( -- 2.46.0 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 2/5] dts: add a distinction between port and queue offload capabilities 2024-09-03 19:46 ` [PATCH v2 0/5] dts: port over Rx/Tx offload suite jspewock 2024-09-03 19:46 ` [PATCH v2 1/5] dts: add TX offload capabilities jspewock @ 2024-09-03 19:46 ` jspewock 2024-09-03 19:46 ` [PATCH v2 3/5] dts: add offload configuration querying to testpmd jspewock ` (2 subsequent siblings) 4 siblings, 0 replies; 12+ messages in thread From: jspewock @ 2024-09-03 19:46 UTC (permalink / raw) To: yoan.picchi, npratte, juraj.linkes, probb, thomas, paul.szczepanek, wathsala.vithanage, alex.chapman, Luca.Vizzarro, Honnappa.Nagarahalli Cc: dev, Jeremy Spewock From: Jeremy Spewock <jspewock@iol.unh.edu> Currently in the framework offloading capabilities are collected at a device-level meaning that, if a capability is supported on either an entire port or individual queues on that port, it is marked as supported for the device. In some cases there is a want for being able to get the granularity of if an offload can be applied on queues rather than just on the device in general since all capabilities that are supported on queues are supported on ports, but not all capabilities that are supported on ports are supported on queues. This means that the less granular option of a combination of the two is still achievable by simply specifying that you require a port to be capable of an offload. This allows for granularity where needed, but generalization elsewhere. Signed-off-by: Jeremy Spewock <jspewock@iol.unh.edu> --- dts/framework/remote_session/testpmd_shell.py | 257 +++++++++++++++--- dts/tests/TestSuite_pmd_buffer_scatter.py | 2 +- 2 files changed, 216 insertions(+), 43 deletions(-) diff --git a/dts/framework/remote_session/testpmd_shell.py b/dts/framework/remote_session/testpmd_shell.py index 13001d6666..df4ed7ce5c 100644 --- a/dts/framework/remote_session/testpmd_shell.py +++ b/dts/framework/remote_session/testpmd_shell.py @@ -1982,12 +1982,21 @@ def get_capabilities( # Cast to the generic type for mypy per_port = cast(OffloadCapability, offload_capabilities.per_port) per_queue = cast(OffloadCapability, offload_capabilities.per_queue) + # Any offload that can be set on an individual queue can also be set on the whole port, + # but not every capability that can be set on the port can be set on each queue. self._update_capabilities_from_flag( supported_capabilities, unsupported_capabilities, capabilities_class, per_port | per_queue, - prefix=f"{offload_type}_OFFLOAD_", + prefix=f"PORT_{offload_type}_OFFLOAD_", + ) + self._update_capabilities_from_flag( + supported_capabilities, + unsupported_capabilities, + capabilities_class, + per_queue, + prefix=f"QUEUE_{offload_type}_OFFLOAD_", ) return get_capabilities @@ -2097,167 +2106,331 @@ class NicCapability(NoAliasEnum): TestPmdShell.get_capabilities_rxq_info ) #: - RX_OFFLOAD_VLAN_STRIP: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_VLAN_STRIP: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports L3 checksum offload. - RX_OFFLOAD_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports L4 checksum offload. - RX_OFFLOAD_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports L4 checksum offload. - RX_OFFLOAD_TCP_CKSUM: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_TCP_CKSUM: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports Large Receive Offload. - RX_OFFLOAD_TCP_LRO: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_TCP_LRO: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports QinQ (queue in queue) offload. - RX_OFFLOAD_QINQ_STRIP: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_QINQ_STRIP: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports inner packet L3 checksum. - RX_OFFLOAD_OUTER_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_OUTER_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports MACsec. - RX_OFFLOAD_MACSEC_STRIP: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_MACSEC_STRIP: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports filtering of a VLAN Tag identifier. - RX_OFFLOAD_VLAN_FILTER: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_VLAN_FILTER: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports VLAN offload. - RX_OFFLOAD_VLAN_EXTEND: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_VLAN_EXTEND: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports receiving segmented mbufs. - RX_OFFLOAD_SCATTER: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_SCATTER: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports Timestamp. - RX_OFFLOAD_TIMESTAMP: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_TIMESTAMP: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports crypto processing while packet is received in NIC. - RX_OFFLOAD_SECURITY: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_SECURITY: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports CRC stripping. - RX_OFFLOAD_KEEP_CRC: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_KEEP_CRC: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports L4 checksum offload. - RX_OFFLOAD_SCTP_CKSUM: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_SCTP_CKSUM: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports inner packet L4 checksum. - RX_OFFLOAD_OUTER_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_OUTER_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports RSS hashing. - RX_OFFLOAD_RSS_HASH: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_RSS_HASH: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports scatter Rx packets to segmented mbufs. - RX_OFFLOAD_BUFFER_SPLIT: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_BUFFER_SPLIT: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports all checksum capabilities. - RX_OFFLOAD_CHECKSUM: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_CHECKSUM: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports all VLAN capabilities. - RX_OFFLOAD_VLAN: TestPmdShellCapabilityMethod = partial( + PORT_RX_OFFLOAD_VLAN: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(True) ) #: Device supports L3 checksum offload. - TX_OFFLOAD_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( + PORT_TX_OFFLOAD_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports L4 checksum offload. - TX_OFFLOAD_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( + PORT_TX_OFFLOAD_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports L4 checksum offload. - TX_OFFLOAD_TCP_CKSUM: TestPmdShellCapabilityMethod = partial( + PORT_TX_OFFLOAD_TCP_CKSUM: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports inner packet L3 checksum. - TX_OFFLOAD_OUTER_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( + PORT_TX_OFFLOAD_OUTER_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports crypto processing while packet is received in NIC. - TX_OFFLOAD_SECURITY: TestPmdShellCapabilityMethod = partial( + PORT_TX_OFFLOAD_SECURITY: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: - TX_OFFLOAD_VLAN_INSERT: TestPmdShellCapabilityMethod = partial( + PORT_TX_OFFLOAD_VLAN_INSERT: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: - TX_OFFLOAD_QINQ_INSERT: TestPmdShellCapabilityMethod = partial( + PORT_TX_OFFLOAD_QINQ_INSERT: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: - TX_OFFLOAD_SCTP_CKSUM: TestPmdShellCapabilityMethod = partial( + PORT_TX_OFFLOAD_SCTP_CKSUM: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports QinQ (queue in queue) stripping offload. - TX_OFFLOAD_QINQ_STRIP: TestPmdShellCapabilityMethod = partial( + PORT_TX_OFFLOAD_QINQ_STRIP: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports TCP Segmentation Offload. - TX_OFFLOAD_TCP_TSO: TestPmdShellCapabilityMethod = partial( + PORT_TX_OFFLOAD_TCP_TSO: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports TCP Segmentation Offload with UDP. - TX_OFFLOAD_UDP_TSO: TestPmdShellCapabilityMethod = partial( + PORT_TX_OFFLOAD_UDP_TSO: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports TCP Segmentation Offload with VXLAN tunnels. - TX_OFFLOAD_VXLAN_TNL_TSO: TestPmdShellCapabilityMethod = partial( + PORT_TX_OFFLOAD_VXLAN_TNL_TSO: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports TCP Segmentation Offload with GRE tunnels. - TX_OFFLOAD_GRE_TNL_TSO: TestPmdShellCapabilityMethod = partial( + PORT_TX_OFFLOAD_GRE_TNL_TSO: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports TCP Segmentation Offload with IPIP tunnels. - TX_OFFLOAD_IPIP_TNL_TSO: TestPmdShellCapabilityMethod = partial( + PORT_TX_OFFLOAD_IPIP_TNL_TSO: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports TCP Segmentation Offload with IP tunnels. - TX_OFFLOAD_IP_TNL_TSO: TestPmdShellCapabilityMethod = partial( + PORT_TX_OFFLOAD_IP_TNL_TSO: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports TCP Segmentation Offload with GENEVE tunnels. - TX_OFFLOAD_GENEVE_TNL_TSO: TestPmdShellCapabilityMethod = partial( + PORT_TX_OFFLOAD_GENEVE_TNL_TSO: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports TCP Segmentation Offload with UDP tunnels. - TX_OFFLOAD_UDP_TNL_TSO: TestPmdShellCapabilityMethod = partial( + PORT_TX_OFFLOAD_UDP_TNL_TSO: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + PORT_TX_OFFLOAD_MACSEC_INSERT: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + PORT_TX_OFFLOAD_MT_LOCKFREE: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + PORT_TX_OFFLOAD_MULTI_SEGS: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + PORT_TX_OFFLOAD_MBUF_FAST_FREE: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + QUEUE_RX_OFFLOAD_VLAN_STRIP: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports L3 checksum offload on queues. + QUEUE_RX_OFFLOAD_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports L4 checksum offload on queues. + QUEUE_RX_OFFLOAD_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports L4 checksum offload on queues. + QUEUE_RX_OFFLOAD_TCP_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports Large Receive Offload on queues. + QUEUE_RX_OFFLOAD_TCP_LRO: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports QinQ (queue in queue) offload on queues. + QUEUE_RX_OFFLOAD_QINQ_STRIP: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports inner packet L3 checksum on queues. + QUEUE_RX_OFFLOAD_OUTER_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports MACsec on queues. + QUEUE_RX_OFFLOAD_MACSEC_STRIP: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports filtering of a VLAN Tag identifier on queues. + QUEUE_RX_OFFLOAD_VLAN_FILTER: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports VLAN offload on queues. + QUEUE_RX_OFFLOAD_VLAN_EXTEND: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports receiving segmented mbufs on queues. + QUEUE_RX_OFFLOAD_SCATTER: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports Timestamp on queues. + QUEUE_RX_OFFLOAD_TIMESTAMP: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports crypto processing on queues while packet is received in NIC. + QUEUE_RX_OFFLOAD_SECURITY: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports CRC stripping on queues. + QUEUE_RX_OFFLOAD_KEEP_CRC: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports L4 checksum offload on queues. + QUEUE_RX_OFFLOAD_SCTP_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports inner packet L4 checksum o nqueues. + QUEUE_RX_OFFLOAD_OUTER_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports RSS hashing on queues. + QUEUE_RX_OFFLOAD_RSS_HASH: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports scatter Rx packets to segmented mbufs on queues. + QUEUE_RX_OFFLOAD_BUFFER_SPLIT: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports all checksum capabilities on queues. + QUEUE_RX_OFFLOAD_CHECKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports all VLAN capabilities on queues. + QUEUE_RX_OFFLOAD_VLAN: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(True) + ) + #: Device supports L3 checksum offload on queues. + QUEUE_TX_OFFLOAD_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports L4 checksum offload on queues. + QUEUE_TX_OFFLOAD_UDP_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports L4 checksum offload on queues. + QUEUE_TX_OFFLOAD_TCP_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports inner packet L3 checksum on queues. + QUEUE_TX_OFFLOAD_OUTER_IPV4_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports crypto processing on queues while packet is received in NIC. + QUEUE_TX_OFFLOAD_SECURITY: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + QUEUE_TX_OFFLOAD_VLAN_INSERT: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + QUEUE_TX_OFFLOAD_QINQ_INSERT: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: + QUEUE_TX_OFFLOAD_SCTP_CKSUM: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports QinQ (queue in queue) stripping offload on queues. + QUEUE_TX_OFFLOAD_QINQ_STRIP: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload on queues. + QUEUE_TX_OFFLOAD_TCP_TSO: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload on queues with UDP. + QUEUE_TX_OFFLOAD_UDP_TSO: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload on queues with VXLAN tunnels. + QUEUE_TX_OFFLOAD_VXLAN_TNL_TSO: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload on queues with GRE tunnels. + QUEUE_TX_OFFLOAD_GRE_TNL_TSO: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload on queues with IPIP tunnels. + QUEUE_TX_OFFLOAD_IPIP_TNL_TSO: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload on queues with IP tunnels. + QUEUE_TX_OFFLOAD_IP_TNL_TSO: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: Device supports TCP Segmentation Offload on queues with GENEVE tunnels. + QUEUE_TX_OFFLOAD_GENEVE_TNL_TSO: TestPmdShellCapabilityMethod = partial( + TestPmdShell.get_offload_capabilities_func(False) + ) + #: #: Device supports TCP Segmentation Offload on queues with UDP tunnels. + QUEUE_TX_OFFLOAD_UDP_TNL_TSO: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: - TX_OFFLOAD_MACSEC_INSERT: TestPmdShellCapabilityMethod = partial( + QUEUE_TX_OFFLOAD_MACSEC_INSERT: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: - TX_OFFLOAD_MT_LOCKFREE: TestPmdShellCapabilityMethod = partial( + QUEUE_TX_OFFLOAD_MT_LOCKFREE: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: - TX_OFFLOAD_MULTI_SEGS: TestPmdShellCapabilityMethod = partial( + QUEUE_TX_OFFLOAD_MULTI_SEGS: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: - TX_OFFLOAD_MBUF_FAST_FREE: TestPmdShellCapabilityMethod = partial( + QUEUE_TX_OFFLOAD_MBUF_FAST_FREE: TestPmdShellCapabilityMethod = partial( TestPmdShell.get_offload_capabilities_func(False) ) #: Device supports Rx queue setup after device started. diff --git a/dts/tests/TestSuite_pmd_buffer_scatter.py b/dts/tests/TestSuite_pmd_buffer_scatter.py index 64c48b0793..a1803588da 100644 --- a/dts/tests/TestSuite_pmd_buffer_scatter.py +++ b/dts/tests/TestSuite_pmd_buffer_scatter.py @@ -28,7 +28,7 @@ from framework.testbed_model.capability import NicCapability, requires -@requires(NicCapability.RX_OFFLOAD_SCATTER) +@requires(NicCapability.PORT_RX_OFFLOAD_SCATTER) class TestPmdBufferScatter(TestSuite): """DPDK PMD packet scattering test suite. -- 2.46.0 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 3/5] dts: add offload configuration querying to testpmd 2024-09-03 19:46 ` [PATCH v2 0/5] dts: port over Rx/Tx offload suite jspewock 2024-09-03 19:46 ` [PATCH v2 1/5] dts: add TX offload capabilities jspewock 2024-09-03 19:46 ` [PATCH v2 2/5] dts: add a distinction between port and queue " jspewock @ 2024-09-03 19:46 ` jspewock 2024-09-03 19:46 ` [PATCH v2 4/5] dts: add methods for configuring offloads on a device in testpmd jspewock 2024-09-03 19:46 ` [PATCH v2 5/5] dts: add test suite for RX and TX offloads jspewock 4 siblings, 0 replies; 12+ messages in thread From: jspewock @ 2024-09-03 19:46 UTC (permalink / raw) To: yoan.picchi, npratte, juraj.linkes, probb, thomas, paul.szczepanek, wathsala.vithanage, alex.chapman, Luca.Vizzarro, Honnappa.Nagarahalli Cc: dev, Jeremy Spewock From: Jeremy Spewock <jspewock@iol.unh.edu> Testpmd offers methods for querying the runtime configuration of offloads on a device that are useful for verification, but bindings to reach these methods do not exist in the Testpmd API offered in the framework. This patch creates methods that can query this configuration and also generalizes the OffloadCapability class to allow it to account for parsing the configuration output as well since the flag values will be the same. Signed-off-by: Jeremy Spewock <jspewock@iol.unh.edu> --- dts/framework/remote_session/testpmd_shell.py | 92 ++++++++++++++++++- 1 file changed, 89 insertions(+), 3 deletions(-) diff --git a/dts/framework/remote_session/testpmd_shell.py b/dts/framework/remote_session/testpmd_shell.py index df4ed7ce5c..71859c63da 100644 --- a/dts/framework/remote_session/testpmd_shell.py +++ b/dts/framework/remote_session/testpmd_shell.py @@ -680,21 +680,45 @@ def from_string(cls, line: str) -> Self: return flag @classmethod - def make_parser(cls, per_port: bool) -> ParserFn: + def from_list(cls, lines: list[str]) -> list[Self]: + """Make a list of instances from a list of strings that contain flag names. + + The strings are expected to separate the flag names by whitespace. + + Args: + lines: The list of strings to parse. + + Returns: + A list of instances parsed from each string in `lines`. + """ + return [cls.from_string(line) for line in lines] + + @classmethod + def make_parser(cls, per_port: bool, find_multiple: bool = False) -> ParserFn: """Make a parser function. Args: per_port: 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" if per_port else "Queue" + parser_func: Callable[..., ParserFn] | Callable[..., ParserFn] = ( + TextParser.find_all if find_multiple else TextParser.find + ) + instance_func: Callable[..., list[OffloadCapability]] | Callable[..., OffloadCapability] = ( + cls.from_list if find_multiple else cls.from_string + ) return TextParser.wrap( - TextParser.find(rf"Per {granularity}\s+:(.*)$", re.MULTILINE), - cls.from_string, + parser_func(rf"{granularity}[\s\[\]\d]+:(.*)$", re.MULTILINE), + instance_func, ) @@ -822,6 +846,42 @@ class TxOffloadCapabilities(OffloadCapabilities): per_port: TxOffloadCapability = field(metadata=TxOffloadCapability.make_parser(True)) +@dataclass +class OffloadConfiguration(TextParser): + """The result of testpmd's ``show port <port_id> rx/tx_offload configuration`` command.""" + + #: + port_id: int = field(metadata=TextParser.find_int(r"Offloading Configuration of port (\d+) :")) + #: Queue offload configurations. + queues: list[RxOffloadCapability] | list[TxOffloadCapability] + #: Port offload configuration. + port: RxOffloadCapability | TxOffloadCapability + + +@dataclass +class RxOffloadConfiguration(OffloadConfiguration): + """Extends :class:`OffloadingConfiguration` with Rx specific functionality.""" + + #: + queues: list[RxOffloadCapability] = field( + metadata=RxOffloadCapability.make_parser(False, find_multiple=True) + ) + #: + port: RxOffloadCapability = field(metadata=RxOffloadCapability.make_parser(True)) + + +@dataclass +class TxOffloadConfiguration(OffloadConfiguration): + """Extends :class:`OffloadingConfiguration` with Tx specific functionality.""" + + #: + queues: list[TxOffloadCapability] = field( + metadata=TxOffloadCapability.make_parser(False, find_multiple=True) + ) + #: + port: TxOffloadCapability = field(metadata=TxOffloadCapability.make_parser(True)) + + T = TypeVarTuple("T") # type: ignore[misc] @@ -1590,6 +1650,32 @@ def show_port_tx_offload_capabilities(self, port_id: int) -> TxOffloadCapabiliti offload_capabilities_out = self.send_command(command) return TxOffloadCapabilities.parse(offload_capabilities_out) + def show_port_rx_offload_configuration(self, port_id: int) -> RxOffloadConfiguration: + """Get the Rx offload configuration on a given port. + + Args: + port_id: The ID of the port to query the configuration of. + + Returns: + An instance of :class:`RxOffloadConfiguration` containing the offload configuration of + the port. + """ + output = self.send_command(f"show port {port_id} rx_offload configuration") + return RxOffloadConfiguration.parse(output) + + def show_port_tx_offload_configuration(self, port_id: int) -> TxOffloadConfiguration: + """Get the Tx offload configuration on a given port. + + Args: + port_id: The ID of the port to query the configuration of. + + Returns: + An instance of :class:`TxOffloadConfiguration` containing the offload configuration of + the port. + """ + output = self.send_command(f"show port {port_id} tx_offload configuration") + return TxOffloadConfiguration.parse(output) + def _stop_port(self, port_id: int, verify: bool = True) -> None: """Stop port with `port_id` in testpmd. -- 2.46.0 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 4/5] dts: add methods for configuring offloads on a device in testpmd 2024-09-03 19:46 ` [PATCH v2 0/5] dts: port over Rx/Tx offload suite jspewock ` (2 preceding siblings ...) 2024-09-03 19:46 ` [PATCH v2 3/5] dts: add offload configuration querying to testpmd jspewock @ 2024-09-03 19:46 ` jspewock 2024-09-03 19:46 ` [PATCH v2 5/5] dts: add test suite for RX and TX offloads jspewock 4 siblings, 0 replies; 12+ messages in thread From: jspewock @ 2024-09-03 19:46 UTC (permalink / raw) To: yoan.picchi, npratte, juraj.linkes, probb, thomas, paul.szczepanek, wathsala.vithanage, alex.chapman, Luca.Vizzarro, Honnappa.Nagarahalli Cc: dev, Jeremy Spewock From: Jeremy Spewock <jspewock@iol.unh.edu> Testpmd offers methods to add and remove offloads from both ports and queues on ports, but there are not yet method bindings in the Testpmd API that the framework provides to reach them. This patch adds these bindings for future test cases/suites that require certain functionalities to be offloaded on the device. Signed-off-by: Jeremy Spewock <jspewock@iol.unh.edu> --- dts/framework/remote_session/testpmd_shell.py | 142 +++++++++++++++++- 1 file changed, 141 insertions(+), 1 deletion(-) diff --git a/dts/framework/remote_session/testpmd_shell.py b/dts/framework/remote_session/testpmd_shell.py index 71859c63da..447d6a617d 100644 --- a/dts/framework/remote_session/testpmd_shell.py +++ b/dts/framework/remote_session/testpmd_shell.py @@ -32,7 +32,7 @@ from typing_extensions import TypeVarTuple -from framework.exception import InteractiveCommandExecutionError +from framework.exception import InteractiveCommandExecutionError, InternalError from framework.params.testpmd import SimpleForwardingModes, TestPmdParams from framework.params.types import TestPmdParamsDict from framework.parser import ParserFn, TextParser @@ -2002,6 +2002,146 @@ def set_verbose(self, level: int, verify: bool = True) -> None: f"Testpmd failed to set verbose level to {level}." ) + @stop_then_start_port() + def _set_offload( + self, + port_id: int, + is_rx: bool, + offloads: OffloadCapability, + on: bool, + queue_id: int | None = None, + verify: bool = True, + ) -> None: + """Base method for configuring offloads on ports and queues. + + If `queue_id` is not specified then it is assumed that you want to set the offloads on the + port rather than a queue. + """ + for offload in type(offloads): + if offload not in offloads or offload.name is None: + continue + port_type = "rx" if is_rx else "tx" + command = [ + "port", + f"{port_id}", + f"{port_type}_offload", + f"{offload.name.lower()}", + f"{'on' if on else 'off'}", + ] + if queue_id is not None: + # If modifying queues the command is "port <id> rxq <q_id> ..." + command.insert(2, f"{port_type}q {queue_id}") + else: + # If modifying a port the command is "port config <id> ..." + command.insert(1, "config") + + self.send_command(" ".join(command)) + if verify: + # verification of ports has to be done based on if it was applied to all queues or + # not because the "Per Port" line doesn't get modified until the port is started. + current_offload_conf: OffloadConfiguration = ( + self.show_port_rx_offload_configuration(port_id) + if is_rx + else self.show_port_tx_offload_configuration(port_id) + ) + # Casting to the generic type is required for mypy + queues_capabilities = cast(list[OffloadCapability], current_offload_conf.queues) + if queue_id is not None and len(current_offload_conf.queues) < queue_id + 1: + raise InternalError(f"Queue {queue_id} does not exist in testpmd") + capability_is_set = ( + len(current_offload_conf.queues) > 0 + and (queue_id is not None and offload in queues_capabilities[queue_id]) + or all(offload in conf for conf in queues_capabilities) + ) + if capability_is_set != on: + self._logger.debug( + f"Test pmd failed to modify capabilities on port {port_id}:\n" + f"{current_offload_conf.queues}" + ) + raise InteractiveCommandExecutionError( + f"Test pmd failed to {'add' if on else 'remove'} capability {offload.name} " + f"{'to' if on else 'from'} port {port_id}." + ) + + def set_port_offload( + self, + port_id: int, + is_rx: bool, + offload: OffloadCapability, + on: bool, + verify: bool = True, + ) -> None: + """Configure Rx/Tx offload on a port. + + Args: + port_id: The ID of the port to set configure the offload on. + is_rx: A flag that signifies which type of offload to set. If :data:`True` an Rx + offload will be set, otherwise a Tx offload will be set. + offload: The offload to set on the port. + on: If :data:`True` the specified offload will be set turned on, otherwise the offload + will be turned off. + verify: If :data:`True` an additional command will be sent to check the configuration + of offloads on the port to verify `offload` was set properly. Defaults to + :data:`True`. + + Raises: + InteractiveCommandExecutionError: If `verify` is :data:`True` and testpmd failed to + set the offload on the port. + """ + self._set_offload(port_id, is_rx, offload, on, None, verify) + + def set_queue_offload( + self, + port_id: int, + queue_id: int, + is_rx: bool, + offload: OffloadCapability, + on: bool, + verify: bool = True, + ) -> None: + """Configure Rx/Tx offload on a queue that resides on a specified port. + + Args: + port_id: The ID of the port where the queue resides. + queue_id: The ID of the queue on the port. + is_rx: A flag that signifies which type of offload to set. If :data:`True` an Rx + offload will be set, otherwise a Tx offload will be set. + offload: The offload to set on a port. + on: If :data:`True` the offload will be turned on, otherwise the offload will be turned + off. + verify: If :data:`True` an additional command will be sent to check the configuration + of the queue to validate that the offload was configured properly. Defaults to + :data:`True`. + + Raises: + InteractiveCommandExecutionError: If `verify` is :data:`True` and testpmd failed to + set the offload on the queue. + """ + self._set_offload(port_id, is_rx, offload, on, queue_id, verify) + + def is_port_offload_configured( + self, port_id: int, is_rx: bool, offload: OffloadCapability + ) -> bool: + """Verify whether or not an Rx/Tx offload is currently configured on a port. + + Args: + port_id: The ID of the port to check the configuration of. + is_rx: If :data:`True` the Rx offloads of the port will be checked, otherwise the Tx + offloads will be checked. + offload: The offload to search for on the port. + + Returns: + :data:`True` if the offload is configured on the port, :data:`False` otherwise. + """ + offload_config: OffloadConfiguration = ( + self.show_port_rx_offload_configuration(port_id) + if is_rx + else self.show_port_tx_offload_configuration(port_id) + ) + # Cast to the generic type for mypy + port_capabilities = cast(OffloadCapability, offload_config.port) + return offload in port_capabilities + def flow_create(self, cmd: FlowRule, verify: bool = True) -> None: """Creates a flow rule in the testpmd session. -- 2.46.0 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 5/5] dts: add test suite for RX and TX offloads 2024-09-03 19:46 ` [PATCH v2 0/5] dts: port over Rx/Tx offload suite jspewock ` (3 preceding siblings ...) 2024-09-03 19:46 ` [PATCH v2 4/5] dts: add methods for configuring offloads on a device in testpmd jspewock @ 2024-09-03 19:46 ` jspewock 4 siblings, 0 replies; 12+ messages in thread From: jspewock @ 2024-09-03 19:46 UTC (permalink / raw) To: yoan.picchi, npratte, juraj.linkes, probb, thomas, paul.szczepanek, wathsala.vithanage, alex.chapman, Luca.Vizzarro, Honnappa.Nagarahalli Cc: dev, Jeremy Spewock From: Jeremy Spewock <jspewock@iol.unh.edu> This patch adds a test sutie that ports over and expands upon functionality provided in the RxTx test sutie in Old DTS. This test suite provides convenience methods and decorators in an attempt to reduce code duplication when developers are tasked with testing the same offloaded functionality through 3 different mediums (passed on the command-line, configured on a port at runtime, and configured on queues at runtime). Signed-off-by: Jeremy Spewock <jspewock@iol.unh.edu> --- dts/framework/config/conf_yaml_schema.json | 3 +- dts/tests/TestSuite_rxtx_offload.py | 627 +++++++++++++++++++++ 2 files changed, 629 insertions(+), 1 deletion(-) create mode 100644 dts/tests/TestSuite_rxtx_offload.py diff --git a/dts/framework/config/conf_yaml_schema.json b/dts/framework/config/conf_yaml_schema.json index f02a310bb5..c1243ea5d8 100644 --- a/dts/framework/config/conf_yaml_schema.json +++ b/dts/framework/config/conf_yaml_schema.json @@ -187,7 +187,8 @@ "enum": [ "hello_world", "os_udp", - "pmd_buffer_scatter" + "pmd_buffer_scatter", + "rxtx_offload" ] }, "test_target": { diff --git a/dts/tests/TestSuite_rxtx_offload.py b/dts/tests/TestSuite_rxtx_offload.py new file mode 100644 index 0000000000..d994b44fc1 --- /dev/null +++ b/dts/tests/TestSuite_rxtx_offload.py @@ -0,0 +1,627 @@ +"""Rx/Tx offload configuration suite. + +The goal of this suite is to test the support for three different methods of offloading different +capabilities using testpmd: On a queue, on a port, and on the command-line. Support for configuring +the capability through different means is testing alongside verifying the functionality of the +capability when offloaded. Each of the three methods of setting the capability should be tested +using the same criteria to monitor for differences between the methods. + +Testing consists of enabling the capability if it wasn't passed in through the command-line, +verifying that the capability performs it's expected task, then, in the general case, disabling the +capability and verifying that the same result is not achieved in a default state. Some cases do not +check the base-case since their functionality is enabled by default without offloading the +capability (like invalid checksum verification, for example). + +There should be test cases for each of the 3 configuration strategies for every offload that is +tested. Additionally, there are two additional test cases that validates the ability to enable +every offload that a device supports on its port without actually testing the functionality of the +offload for both Rx and Tx. +""" + +import random +from typing import Callable, ClassVar, Protocol, TypeVar + +from scapy.layers.inet import IP, TCP, UDP # type: ignore[import-untyped] +from scapy.layers.l2 import Dot1Q, Ether # type: ignore[import-untyped] +from scapy.packet import Packet, Raw # type: ignore[import-untyped] +from typing_extensions import Unpack + +from framework.exception import InteractiveCommandExecutionError, TestCaseVerifyError +from framework.params.types import TestPmdParamsDict +from framework.remote_session.testpmd_shell import ( + FlowRule, + NicCapability, + OffloadCapability, + OLFlag, + RxOffloadCapability, + SimpleForwardingModes, + TestPmdShell, + TestPmdVerbosePacket, + TxOffloadCapability, +) +from framework.test_suite import TestSuite, func_test +from framework.testbed_model.capability import requires + +T = TypeVar("T") + + +class DecoratedFuncType(Protocol): + """Protocol used to provide a useful typehint for methods that are decorated. + + Methods decorated by :meth:`TestRxtxOffload.setup_testpmd` are able to pass kwargs into the + a :class:`TestPmdShell` upon creation and therefore have many non-obvious arguments. This type + allows static type checkers the ability to unpack and expose all of those non-obvious + arguments. + """ + + def __call__( + self: T, + port_id: int, + no_set: bool = False, + modify_queues: bool = False, + no_invert: bool = False, + **kwargs: Unpack[TestPmdParamsDict], + ) -> None: + """Function stub to create callable type. + + Args: + test: Instance of the test suite class that the methods belong to. + port_id: ID of the port to set the offloads on. + no_set: Whether to enable the offload before testing or not. When :data:`True`, + the method will validate that the offload is already configured rather than + enabling it. This is used in test cases that enable the offload using the + command-line. Defaults to :data:`False`. + modify_queues: Whether to add offloads to individual queues or the entire port. + If :data:`True`, individual queues will be modified, otherwise the whole + port will. Defaults to :data:`False`. + no_invert: If :data:`True` skip testing behavior of testpmd without the offload + enabled. Defaults to :data:`False`. + """ + ... + + +def set_offload( + offload: OffloadCapability, + testpmd: TestPmdShell, + is_rx: bool, + port_id: int, + queues_to_modify: set[int], + on: bool, +) -> None: + """Set offload on a port/queue using testpmd. + + This helper method allows you to reach both the :meth:`TestPmdShell.set_queue_offload` and + :meth:`TestPmdShell.set_port_offload` through a single method, and update the offloads on + multiple queues at once. + + Args: + offload: Offload to configure. + testpmd: Testpmd shell to use for modifying the offload configuration. This shell is + expected to be running before being passed into this method. + is_rx: If :data:`True` the offload will be configured on an Rx port/queue, otherwise it + will be configured on a Tx port/queue. + port_id: ID of the port to make configuration changes on. + queues_to_modify: IDs of queues to make configuration changes on. If this set is empty then + changes will only be made to the port configuration. + on: If :data:`True`, then enable the offload, otherwise disable it. + """ + if len(queues_to_modify) > 0: + for queue_id in queues_to_modify: + testpmd.set_queue_offload(port_id, queue_id, is_rx, offload, on, verify=True) + else: + testpmd.set_port_offload(port_id, is_rx, offload, on, verify=True) + + +class TestRxtxOffload(TestSuite): + """Rx/Tx offload testing suite. + + There are three ways to configure offloads in testpmd: Through the command line, at runtime on + a port, or at runtime on individual queues. Each of these configuration methods should be + tested for each of the offloads that are tested in this suite. Methods for testing each of the + offloads functionalities should be designed to be decorated by :func:`setup_testpmd`, meaning + their first parameter must be a :class:`TestPmdShell` (which will be running once the method + receives it) and the second parameter must be a bool signifying whether testing is to be done + on an entire port, or individual queues (:data:`True` for testing on a port, otherwise testing + on a queue). This decorator allows for testpmd to be configured with the proper offloads before + being passed to the method for testing. + """ + + #: + rx_port_for_testing: ClassVar[int] = 0 + #: + tx_port_for_testing: ClassVar[int] = 1 + #: Specify the number of queues to use for test cases the set offloads on queues. This should + #: generally be an odd integer since the test cases will apply offloads to the majority of + #: queues. + number_of_queues: ClassVar[int] = 5 + #: Common testpmd parameters for all tests to use. + common_testpmd_params: ClassVar[dict] = { + "forward_mode": SimpleForwardingModes.mac, + "rx_queues": number_of_queues, + "tx_queues": number_of_queues, + } + #: + relevant_checksum_errors: ClassVar[OLFlag] = ( + OLFlag.RTE_MBUF_F_RX_IP_CKSUM_BAD + | OLFlag.RTE_MBUF_F_RX_L4_CKSUM_BAD + | OLFlag.RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD + ) + + @staticmethod + def setup_testpmd( + offloads: OffloadCapability, is_rx: bool + ) -> Callable[[Callable[["TestRxtxOffload", TestPmdShell, bool], bool]], DecoratedFuncType]: + """Decorator function that initializes testpmd before running a test. + + All offloads in `offloads` are either enabled if they weren't passed in on the + command-line, or verified to be enabled on the port before running the decorated method. + The decorated method must return a boolean that represents whether or not the expected + behavior took place while the offload was enabled which will be used for verification that + the test functioned as expected. By default, this decorator will also disable all of the + offloads in `offloads` and verify that the decorated method instead returns :data:`False` + where it was expected to return :data:`True` with them enabled. This functionality can be + overridden, however, for cases where the opposite functionality cannot be easily tested + (like invalid checksums, for example). + + The decorated method additionally can be used for both setting offloads across the entire + port or on individual queues using the `modify_queues` parameter. If individual queues are + being modified then the majority of queues ((x / 2) + 1 where x is the number of queues) + will have the offload enabled rather than all of them. All decorated functions must be a + method of :class:`TestRxtxOffload` and take a testpmd shell for testing along with a + boolean that signifies whether it is a port being tested or individual queues. + + Args: + offloads: Offloads to set in testpmd prior to running decorated function. + is_rx: Whether to set Rx or Tx offloads when testing. + + Returns: + Decorator function that enables all offloads, runs the decorated method, then optionally + disables offloads and runs the test method again. + """ + + def wrap( + func: Callable[["TestRxtxOffload", TestPmdShell, bool], bool] + ) -> DecoratedFuncType: + def wrapper( + test: "TestRxtxOffload", + port_id: int, + no_set: bool = False, + modify_queues: bool = False, + no_invert: bool = False, + **kwargs: Unpack[TestPmdParamsDict], + ) -> None: + """Function that wraps the decorated method. + + Refer to :class:`DecoratedFuncType` for information about parameters of this + method. + """ + queues_to_modify: set[int] = set() + if modify_queues: + while len(queues_to_modify) < int(test.number_of_queues / 2 + 1): + queues_to_modify.add(random.randint(0, test.number_of_queues - 1)) + with TestPmdShell(test.sut_node, **test.common_testpmd_params, **kwargs) as testpmd: + # If no_set then it should have been passed on the command-line and already + # be configured, else we need to set them ourselves. + if no_set: + testpmd.is_port_offload_configured(port_id, is_rx, offloads) + else: + set_offload(offloads, testpmd, is_rx, port_id, queues_to_modify, on=True) + + test.verify( + func(test, testpmd, not modify_queues), + f"Offloaded capabilities ({offloads}) failed.", + ) + + set_offload(offloads, testpmd, is_rx, port_id, queues_to_modify, on=False) + if not no_invert: + test.verify( + not func(test, testpmd, not modify_queues), + f"After disabling capabilities ({offloads}) the " + "result was the same.", + ) + + # This type ignore is required to ignore the mismatch in types between the protocol + # and the wrapper function. Mypy complains that these two are not the same type since + # the type produced by the protocol does not include a parameter for "TestRxtxOffload". + # However, if you add this parameter, it makes it so that you have to explicitly pass + # the value of `self` into the method when you call it, so you cannot simply call + # methods with the standard syntax of "self.<meth_name>" without mypy complaining. + return wrapper # type: ignore[return-value] + + return wrap + + """ ========== Verify methods ========== + All verify methods must match the type + Callable[[list[Packet], list[TestPmdVerbosePacket]], bool] where their + first parameter is a list of packets that were forwarded back to the TG in the test and the + second parameter is the verbose information gathered by testpmd while packets were being + forwarded. These methods are meant to return a boolean that represents whether or not a + packet that matches their expected behavior can be found among any of their parameters in + order to be used by :meth:`send_packets_and_verify` for testing functionality. + """ + + @staticmethod + def _packet_is_relevant(pakt: Packet) -> bool: + """Helper method to test whether or not a packet was sent by a method in this test suite. + + All packets in this test suite are sent with a payload of 20 "X" characters, so this method + checks to see if `pakt` has a matching payload. + + Args: + pakt: The packet to validate. + + Returns: + :data:`True` if the packet has a valid payload, :data:`False` otherwise. + """ + return hasattr(pakt, "load") and pakt.load == bytes("X" * 20, "utf-8") + + @staticmethod + def verify_insertion(packets: list[Packet], *_) -> bool: + """Method to verify VLAN headers were inserted into sent packets. + + Checks to make sure that there is at least one packet in `packets` that is relevant to the + test suite with a VLAN header in it. This method consumes all arguments after `packets` to + conform to the type + Callable[[list[Packet], list[TestPmdVerbosePacket]], bool] even though + it does not need the verbose packet information. + + Args: + packets: Packets to scan for a valid result. + + Returns: + :data:`True` if there is at least one packet in `packets` that is relevant to the test + suite with a VLAN header in it, :data:`False` otherwise. + """ + return any(TestRxtxOffload._packet_is_relevant(pakt) and Dot1Q in pakt for pakt in packets) + + @staticmethod + def verify_stripping(packets: list[Packet], *_) -> bool: + """Method to verify VLAN headers were stripped from sent packets. + + Checks to make sure there is at least one packet in `packets` that is relevant to the suite + which does not contain a VLAN header. This method consumes all arguments after `packets` to + conform to the type + Callable[[list[Packet], list[TestPmdVerbosePacket]], bool] even though + it does not need the verbose packets. + + Args: + packets: The list of packets to scan for a valid result. + + Returns: + :data:`True` if there is at least one packet that is relevant to the suite in `packets` + without a VLAN header, :data:`False` otherwise. + """ + return any( + TestRxtxOffload._packet_is_relevant(pakt) and Dot1Q not in pakt for pakt in packets + ) + + @classmethod + def verify_chksum( + cls, expected_errors: OLFlag | None = None + ) -> Callable[[list[Packet], list[TestPmdVerbosePacket]], bool]: + """Verify that the expected checksum errors appear in the forwarding statistics. + + Provides a closure for the wrapped function that stores the errors to expect in the + output. The wrapped function then accepts a list of packets received from forwarding as + well as forwarding statistics to validate with. The list of received packets are unused. + + Args: + expected_error: Errors to search for in the forwarding statistics. If flag is + :data:`None`, verify that none of the :attr:`relevant_checksum_errors` appear in + the forwarding status. Defaults to :data:`None`. + + Returns: + A function that searches for the expected errors in the forwarding statistics and + returns :data:`True` if they are all present or if `expected_errors` is :data:`None` + and there are no errors present. The function will return :data:`False` otherwise. + """ + + def wrap(_, fwd_stats: list[TestPmdVerbosePacket]) -> bool: + """Method that fits the expected type of verify methods.""" + if expected_errors is None: + return all( + cls.relevant_checksum_errors & pakt.ol_flags == OLFlag(0) for pakt in fwd_stats + ) + else: + return any(expected_errors in pakt.ol_flags for pakt in fwd_stats) + + return wrap + + """ ========== End verify methods ========= """ + + def send_packets_and_verify( + self, + testpmd: TestPmdShell, + packets: list[Packet], + verify_meth: Callable[[list[Packet], list[TestPmdVerbosePacket]], bool], + is_port: bool, + ) -> bool: + """Send packets and verify the result using `verify_meth`. + + If testing is being done on queues, this method makes flow rules that make it so that + anything that has the source address 192.168.1.X will be handled by queue X in testpmd. + Then, before sending packets in all cases, this method will adjust the source IP addresses + of the packets in `packets` to ensure they are all different and processed by different, + start testpmd, send all of the packets in `packets`, and captures the resulting received + traffic and forwarding stats. The received traffic and forwarding stats are then passed + into `verify_meth` to test if the expected result took place. + + In the case of testing the results of queues, it is expected that the majority of queues + (but not all) have the offload enabled and, therefore, only the majority of packets in + `packets` need to return :data:`True` from `verify_meth` to get a positive + result. + + Args: + testpmd: Testpmd shell that is handling the packet forwarding. This shell is expected + to already be started before being passed into this method. + packets: List of packets to send to the SUT during testing. + verify_meth: Method used to verify that the packet matches the expected results. + is_port: Flag to differentiate testing results from an offload set on a port from an + offload set on a queue. + + Returns: + :data:`True` if `verify_meth` returned :data:`True` for every packet in `packets` if + testing offloads on a port, or the majority of packets if testing offloads on queues. + :data:`False` otherwise. + """ + majority = int(self.number_of_queues / 2 + 1) + dst_ip_addr = "192.168.1.{}" + verify_results: list[bool] = [] + base_pattern = f"eth / {'vlan /' if packets[0].haslayer(Dot1Q) else ''} " "ipv4 dst is {}" + base_action = "queue index {}" + if not is_port: + rule = FlowRule(self.rx_port_for_testing, True, "", "") + for queue_id in range(self.number_of_queues): + rule.pattern = base_pattern.format(dst_ip_addr.format(queue_id)) + rule.actions = base_action.format(queue_id) + testpmd.flow_create(rule) + + for ind, pakt in enumerate(packets): + testpmd.start() + pakt.getlayer(IP).dst = dst_ip_addr.format(ind % self.number_of_queues) + recv = self.send_packet_and_capture(pakt) + stats = TestPmdShell.extract_verbose_output(testpmd.stop()) + verify_results.append(verify_meth(recv, stats)) + return all(verify_results) if is_port else verify_results.count(True) == majority + + """ ========== Functionality testing methods ========== + Functionality testing methods are the methods that test, assuming the offloads are already + configured in the environment, Rx/Tx offloads perform their expected behavior. These + methods must conform to the type Callable[["TestRxtxOffload", TestPmdShell, bool], bool] + so that they can be decorated by :func:`setup_testpmd`. + """ + + @setup_testpmd(TxOffloadCapability.VLAN_INSERT, False) + def tx_vlan_insertion_test(self, testpmd: TestPmdShell, is_port: bool) -> bool: + """Testing method for VLAN insertion on a Tx port/queue. + + Testing is done by sending one packet without a VLAN header for as many queues as there are + configured and verifying with :meth:`verify_insertion`. + + Args: + testpmd: Testpmd shell to use for testing. It is expected that this shell is already + running. + is_port: If :data:`True`, do testing on a port, otherwise do testing on individual + queues. + + Returns: + :data:`True` if the received traffic contained a VLAN header when expected with the + offload enabled. + """ + return self.send_packets_and_verify( + testpmd, + [Ether() / IP() / Raw("X" * 20)] * self.number_of_queues, + TestRxtxOffload.verify_insertion, + is_port, + ) + + @setup_testpmd(RxOffloadCapability.VLAN_STRIP, True) + def rx_vlan_stripping(self, testpmd: TestPmdShell, is_port: bool) -> bool: + """Testing method for VLAN stripping on an Rx port/queue. + + Testing is done by sending one packet with a VLAN header for every configured queue and + verifying using :func:`verify_stripping` that the received packets had their VLAN header + stripped. + + Args: + testpmd: Testpmd shell to use for testing. This shell is expected to already be + running when passed into this method. + is_port: If :data:`True`, do testing on a port, otherwise do testing on individual + queues. + + Returns: + :data:`True` if the expected amount of received packets had their VLAN headers stripped + when the offload is enabled, :data:`False` otherwise. + """ + return self.send_packets_and_verify( + testpmd, + [Ether() / Dot1Q() / IP() / Raw("X" * 20)] * self.number_of_queues, + TestRxtxOffload.verify_stripping, + is_port, + ) + + @setup_testpmd( + RxOffloadCapability.UDP_CKSUM + | RxOffloadCapability.TCP_CKSUM + | RxOffloadCapability.IPV4_CKSUM, + True, + ) + def rx_cksum_test(self, testpmd: TestPmdShell, is_port: bool) -> bool: + """Test for verifying invalid checksum reporting. + + Testing is done in multiple stages for checksum test cases. Testpmd must first be set to + Rx-only verbose mode to capture the checksum errors reported by testpmd when receiving + packets with a bad checksum. There are then 4 main cases to test: + + * Valid packets do not display any checksum errors. + * Packets with a bad IP checksum and a bad layer 4 checksum report both errors properly. + * Packets with only a bad layer 4 checksum report only that error properly. + * Packets with only a bad IP checksum report only that error properly. + + All of these cases must pass for this method to return :data:`True`. + + Args: + testpmd: Testpmd shell to use for testing. It is expected that this shell is already + running when it is passed into this method. + is_port: If :data:`True`, do testing on a port, otherwise do testing on individual + queues. + + Returns: + :data:`True` if all 4 cases pass, :data:`False` otherwise. + """ + testpmd.set_verbose(1) + results = [ + self.send_packets_and_verify( + testpmd, [Ether() / IP() / TCP() / ("X" * 20)], self.verify_chksum(), is_port + ), + self.send_packets_and_verify( + testpmd, + [Ether() / IP(chksum=0x0) / TCP(chksum=0xF) / ("X" * 20)], + TestRxtxOffload.verify_chksum( + OLFlag.RTE_MBUF_F_RX_IP_CKSUM_BAD | OLFlag.RTE_MBUF_F_RX_L4_CKSUM_BAD + ), + is_port, + ), + self.send_packets_and_verify( + testpmd, + [Ether() / IP() / UDP(chksum=0xF) / ("X" * 20)], + TestRxtxOffload.verify_chksum(OLFlag.RTE_MBUF_F_RX_L4_CKSUM_BAD), + is_port, + ), + self.send_packets_and_verify( + testpmd, + [Ether() / IP(chksum=0x0) / UDP() / ("X" * 20)], + TestRxtxOffload.verify_chksum(OLFlag.RTE_MBUF_F_RX_IP_CKSUM_BAD), + is_port, + ), + ] + return all(results) + + """ ========== End functionality testing methods ========== """ + + @requires(NicCapability.PORT_TX_OFFLOAD_VLAN_INSERT) + @func_test + def test_tx_port_vlan_insertion(self) -> None: + """Run :meth:`tx_vlan_insertion_test` with common testpmd parameters.""" + self.tx_vlan_insertion_test(self.tx_port_for_testing) + + @requires(NicCapability.PORT_TX_OFFLOAD_VLAN_INSERT) + @func_test + def test_tx_cmdline_vlan_insertion(self) -> None: + """Run :meth:`tx_vlan_insertion_test` with insertion offload passed on the command-line. + + This requires specifying that the offload should not be set at runtime when calling the + method. + """ + self.tx_vlan_insertion_test(self.tx_port_for_testing, no_set=True, tx_offloads=0x0001) + + @requires(NicCapability.QUEUE_TX_OFFLOAD_VLAN_INSERT) + @func_test + def test_tx_queue_vlan_insertion(self) -> None: + """Run :meth:`tx_vlan_insertion_test` specifying queues should be modified.""" + self.tx_vlan_insertion_test(self.tx_port_for_testing, modify_queues=True) + + @requires(NicCapability.PORT_RX_OFFLOAD_VLAN_STRIP) + @func_test + def test_rx_port_vlan_strip(self) -> None: + """Run :meth:`rx_vlan_stripping` with common testpmd parameters.""" + self.rx_vlan_stripping(self.rx_port_for_testing) + + @requires(NicCapability.PORT_RX_OFFLOAD_VLAN_STRIP) + @func_test + def test_rx_cmdline_vlan_strip(self) -> None: + """Run :meth:`rx_vlan_stripping` with stripping offload passed on the command-line. + + This requires specifying that the offload should not be set at runtime when calling the + method. + """ + self.rx_vlan_stripping(self.rx_port_for_testing, no_set=True, enable_hw_vlan_strip=True) + + @requires(NicCapability.QUEUE_RX_OFFLOAD_VLAN_STRIP) + @func_test + def test_rx_queue_vlan_strip(self) -> None: + """Run :meth:`rx_vlan_stripping` specifying queues should be modified.""" + self.rx_vlan_stripping(self.rx_port_for_testing, modify_queues=True) + + @requires( + NicCapability.PORT_RX_OFFLOAD_UDP_CKSUM, + NicCapability.PORT_RX_OFFLOAD_TCP_CKSUM, + NicCapability.PORT_RX_OFFLOAD_IPV4_CKSUM, + ) + @func_test + def test_rx_port_chksum(self) -> None: + """Run :meth:`rx_cksum_test` with common testpmd parameters. + + Since checksum errors will be thrown even when the offload is disabled, specify not to + invert testing. + """ + self.rx_cksum_test(self.rx_port_for_testing, no_invert=True) + + @requires( + NicCapability.PORT_RX_OFFLOAD_UDP_CKSUM, + NicCapability.PORT_RX_OFFLOAD_TCP_CKSUM, + NicCapability.PORT_RX_OFFLOAD_IPV4_CKSUM, + ) + @func_test + def test_rx_cmdline_chksum(self) -> None: + """Run :meth:`rx_cksum_test` with checksum offloads enabled through the command-line. + + Since checksum errors will be thrown even when the offload is disabled, specify not to + invert testing. Additionally, specify that the offload should not be set at runtime. + """ + self.rx_cksum_test( + self.rx_port_for_testing, + no_set=True, + no_invert=True, + enable_rx_cksum=True, + ) + + @requires( + NicCapability.QUEUE_RX_OFFLOAD_UDP_CKSUM, + NicCapability.QUEUE_RX_OFFLOAD_TCP_CKSUM, + NicCapability.QUEUE_RX_OFFLOAD_IPV4_CKSUM, + ) + @func_test + def test_rx_queue_chksum(self) -> None: + """Run :meth:`rx_cksum_test` specifying testing should be run on queues. + + Since checksum errors will be thrown even when the offload is disabled, specify not to + invert testing. + """ + self.rx_cksum_test( + self.rx_port_for_testing, + modify_queues=True, + no_invert=True, + ) + + @func_test + def test_rx_all_port_offloads(self) -> None: + """Verify that testpmd is able to set all Rx offloads the port is capable of at runtime.""" + with TestPmdShell(self.sut_node) as testpmd: + supported_capabilities = testpmd.show_port_rx_offload_capabilities( + self.rx_port_for_testing + ).per_port + try: + testpmd.set_port_offload( + self.rx_port_for_testing, True, supported_capabilities, True, verify=True + ) + except InteractiveCommandExecutionError as e: + raise TestCaseVerifyError( + f"Failed to set all Rx offloads on port {self.rx_port_for_testing}" + ) from e + + @func_test + def test_tx_all_port_offloads(self) -> None: + """Verify that testpmd is able to set all Tx offloads the port is capable of at runtime.""" + with TestPmdShell(self.sut_node) as testpmd: + supported_capabilities = testpmd.show_port_tx_offload_capabilities( + self.tx_port_for_testing + ).per_port + try: + testpmd.set_port_offload( + self.tx_port_for_testing, False, supported_capabilities, True, verify=True + ) + except InteractiveCommandExecutionError as e: + raise TestCaseVerifyError( + f"Failed to set all Tx offloads on port {self.tx_port_for_testing}" + ) from e -- 2.46.0 ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2024-09-03 19:47 UTC | newest] Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2024-08-31 0:00 [RFC PATCH v1 0/5] dts: port over Rx/Tx offload suite jspewock 2024-08-31 0:00 ` [RFC PATCH v1 1/5] dts: add TX offload capabilities jspewock 2024-08-31 0:00 ` [RFC PATCH v1 2/5] dts: add a distinction between port and queue " jspewock 2024-08-31 0:00 ` [RFC PATCH v1 3/5] dts: add offload configuration querying to testpmd jspewock 2024-08-31 0:00 ` [RFC PATCH v1 4/5] dts: add methods for configuring offloads on a device in testpmd jspewock 2024-08-31 0:00 ` [RFC PATCH v1 5/5] dts: add test suite for RX and TX offloads jspewock 2024-09-03 19:46 ` [PATCH v2 0/5] dts: port over Rx/Tx offload suite jspewock 2024-09-03 19:46 ` [PATCH v2 1/5] dts: add TX offload capabilities jspewock 2024-09-03 19:46 ` [PATCH v2 2/5] dts: add a distinction between port and queue " jspewock 2024-09-03 19:46 ` [PATCH v2 3/5] dts: add offload configuration querying to testpmd jspewock 2024-09-03 19:46 ` [PATCH v2 4/5] dts: add methods for configuring offloads on a device in testpmd jspewock 2024-09-03 19:46 ` [PATCH v2 5/5] dts: add test suite for RX and TX offloads jspewock
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).