<div dir="ltr"><div>I think this patch looks good. Thanks Thomas and thanks Ivan for your insights.</div><div><br></div>Reviewed-by: Patrick Robb <<a href="mailto:probb@iol.unh.edu" target="_blank">probb@iol.unh.edu</a>></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Jul 30, 2025 at 8:59 AM Thomas Wilks <<a href="mailto:thomas.wilks@arm.com" target="_blank">thomas.wilks@arm.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">From: Alex Chapman <<a href="mailto:alex.chapman@arm.com" target="_blank">alex.chapman@arm.com</a>><br>
<br>
This patch adds the required functionality for the RSS key_update,<br>
RETA, and hash test suites. This includes:<br>
The setting of custom RETA values for routing packets to specific<br>
queues.<br>
The setting of the RSS mode on all ports, to specify how to hash<br>
the packets.<br>
The updating of the RSS hash key used during the hashing process.<br>
<br>
Alongside this, there is the addition of a __str__ method to the<br>
RSSOffloadTypesFlags class, so that when flag names are cast to<br>
a string they will use '-' as separators, instead of '_'.<br>
This allows them to be directly used within testpmd RSS commands<br>
without any further changes.<br>
<br>
Signed-off-by: Alex Chapman <<a href="mailto:alex.chapman@arm.com" target="_blank">alex.chapman@arm.com</a>><br>
Signed-off-by: Thomas Wilks <<a href="mailto:thomas.wilks@arm.com" target="_blank">thomas.wilks@arm.com</a>><br>
<br>
Reviewed-by: Paul Szczepanek <<a href="mailto:paul.szczepanek@arm.com" target="_blank">paul.szczepanek@arm.com</a>><br>
Reviewed-by: Patrick Robb <<a href="mailto:probb@iol.unh.edu" target="_blank">probb@iol.unh.edu</a>><br>
Tested-by: Patrick Robb <<a href="mailto:probb@iol.unh.edu" target="_blank">probb@iol.unh.edu</a>><br>
---<br>
dts/framework/remote_session/testpmd_shell.py | 104 ++++++++++++++++--<br>
1 file changed, 97 insertions(+), 7 deletions(-)<br>
<br>
diff --git a/dts/framework/remote_session/testpmd_shell.py b/dts/framework/remote_session/testpmd_shell.py<br>
index ad8cb273dc..473333f8fb 100644<br>
--- a/dts/framework/remote_session/testpmd_shell.py<br>
+++ b/dts/framework/remote_session/testpmd_shell.py<br>
@@ -343,6 +343,12 @@ def make_parser(cls) -> ParserFn:<br>
RSSOffloadTypesFlag.from_list_string,<br>
)<br>
<br>
+ def __str__(self):<br>
+ """Replaces underscores with hyphens to produce valid testpmd value."""<br>
+ if <a href="http://self.name" rel="noreferrer" target="_blank">self.name</a> is None:<br>
+ return ""<br>
+ return self.name.replace("_", "-")<br>
+<br>
<br>
class DeviceCapabilitiesFlag(Flag):<br>
"""Flag representing the device capabilities."""<br>
@@ -644,11 +650,13 @@ class TestPmdPort(TextParser):<br>
)<br>
#: Maximum number of VFs<br>
max_vfs_num: int | None = field(<br>
- default=None, metadata=TextParser.find_int(r"Maximum number of VFs: (\d+)")<br>
+ default=None,<br>
+ metadata=TextParser.find_int(r"Maximum number of VFs: (\d+)"),<br>
)<br>
#: Maximum number of VMDq pools<br>
max_vmdq_pools_num: int | None = field(<br>
- default=None, metadata=TextParser.find_int(r"Maximum number of VMDq pools: (\d+)")<br>
+ default=None,<br>
+ metadata=TextParser.find_int(r"Maximum number of VMDq pools: (\d+)"),<br>
)<br>
<br>
#:<br>
@@ -1734,6 +1742,82 @@ def close_all_ports(self, verify: bool = True) -> None:<br>
if not all(f"Port {p_id} is closed" in port_close_output for p_id in range(num_ports)):<br>
raise InteractiveCommandExecutionError("Ports were not closed successfully.")<br>
<br>
+ def port_config_rss_reta(<br>
+ self, port_id: int, hash_index: int, queue_id: int, verify: bool = True<br>
+ ) -> None:<br>
+ """Configure a port's RSS redirection table.<br>
+<br>
+ Args:<br>
+ port_id: The port where the redirection table will be configured.<br>
+ hash_index: The index into the redirection table associated with the destination queue.<br>
+ queue_id: The destination queue of the packet.<br>
+ verify: If :data:`True`, verifies if a port's redirection table<br>
+ was correctly configured.<br>
+<br>
+ Raises:<br>
+ InteractiveCommandExecutionError: If `verify` is :data:`True`<br>
+ Testpmd failed to config RSS reta.<br>
+ """<br>
+ out = self.send_command(f"port config {port_id} rss reta ({hash_index},{queue_id})")<br>
+ if verify:<br>
+ if f"The reta size of port {port_id} is" not in out:<br>
+ self._logger.debug(f"Failed to config RSS reta: \n{out}")<br>
+ raise InteractiveCommandExecutionError("Testpmd failed to config RSS reta.")<br>
+<br>
+ def port_config_all_rss_offload_type(<br>
+ self, flag: RSSOffloadTypesFlag, verify: bool = True<br>
+ ) -> None:<br>
+ """Set the RSS mode on all ports.<br>
+<br>
+ Args:<br>
+ flag: The RSS iptype all ports will be configured to.<br>
+ verify: If :data:`True`, it verifies if all ports RSS offload type<br>
+ was correctly configured.<br>
+<br>
+ Raises:<br>
+ InteractiveCommandExecutionError: If `verify` is :data:`True`<br>
+ Testpmd failed to config the RSS mode on all ports.<br>
+ """<br>
+ out = self.send_command(f"port config all rss {<a href="http://flag.name" rel="noreferrer" target="_blank">flag.name</a>}")<br>
+ if verify:<br>
+ if "error" in out:<br>
+ self._logger.debug(f"Failed to config the RSS mode on all ports: \n{out}")<br>
+ raise InteractiveCommandExecutionError(<br>
+ f"Testpmd failed to change RSS mode to {<a href="http://flag.name" rel="noreferrer" target="_blank">flag.name</a>}"<br>
+ )<br>
+<br>
+ def port_config_rss_hash_key(<br>
+ self,<br>
+ port_id: int,<br>
+ offload_type: RSSOffloadTypesFlag,<br>
+ hex_str: str,<br>
+ verify: bool = True,<br>
+ ) -> str:<br>
+ """Sets the RSS hash key for the specified port.<br>
+<br>
+ Args:<br>
+ port_id: The port that will have the hash key applied to.<br>
+ offload_type: The offload type the hash key will be applied to.<br>
+ hex_str: The hash key to set.<br>
+ verify: If :data:`True`, verify that RSS has the key.<br>
+<br>
+ Raises:<br>
+ InteractiveCommandExecutionError: If `verify` is :data:`True`<br>
+ Testpmd failed to set the RSS hash key.<br>
+ """<br>
+ output = self.send_command(<br>
+ f"port config {port_id} rss-hash-key {offload_type} {hex_str}",<br>
+ skip_first_line=True,<br>
+ )<br>
+<br>
+ if verify:<br>
+ if output.strip():<br>
+ self._logger.debug(f"Failed to set rss hash key: \n{output}")<br>
+ raise InteractiveCommandExecutionError(<br>
+ f"Testpmd failed to set {hex_str} on {port_id} with a flag of {offload_type}."<br>
+ )<br>
+ return output<br>
+<br>
def show_port_info_all(self) -> list[TestPmdPort]:<br>
"""Returns the information of all the ports.<br>
<br>
@@ -1952,22 +2036,28 @@ def csum_set_hw(<br>
{port_id}:\n{csum_output}"""<br>
)<br>
<br>
- def flow_create(self, flow_rule: FlowRule, port_id: int) -> int:<br>
+ def flow_create(self, flow_rule: FlowRule, port_id: int, verify: bool = True) -> int:<br>
"""Creates a flow rule in the testpmd session.<br>
<br>
- This command is implicitly verified as needed to return the created flow rule id.<br>
-<br>
Args:<br>
flow_rule: :class:`FlowRule` object used for creating testpmd flow rule.<br>
port_id: Integer representing the port to use.<br>
+ verify: If :data:`True`, the output of the command is scanned<br>
+ to ensure the flow rule was created successfully.<br>
<br>
Raises:<br>
InteractiveCommandExecutionError: If flow rule is invalid.<br>
<br>
Returns:<br>
- Id of created flow rule.<br>
+ Id of created flow rule as an integer.<br>
"""<br>
flow_output = self.send_command(f"flow create {port_id} {flow_rule}")<br>
+ if verify:<br>
+ if "created" not in flow_output:<br>
+ self._logger.debug(f"Failed to create flow rule:\n{flow_output}")<br>
+ raise InteractiveCommandExecutionError(<br>
+ f"Failed to create flow rule:\n{flow_output}"<br>
+ )<br>
match = re.search(r"#(\d+)", flow_output)<br>
if match is not None:<br>
match_str = match.group(1)<br>
@@ -1996,7 +2086,7 @@ def flow_delete(self, flow_id: int, port_id: int, verify: bool = True) -> None:<br>
"""Deletes the specified flow rule from the testpmd session.<br>
<br>
Args:<br>
- flow_id: ID of the flow to remove.<br>
+ flow_id: :class:`FlowRule` id used for deleting testpmd flow rule.<br>
port_id: Integer representing the port to use.<br>
verify: If :data:`True`, the output of the command is scanned<br>
to ensure the flow rule was deleted successfully.<br>
-- <br>
2.43.0<br>
<br>
</blockquote></div>