[v2] dts: add VLAN methods to testpmd shell
Checks
Commit Message
added the following methods to testpmd shell class:
vlan set filter on/off, rx vlan add/rm,
vlan set strip on/off, tx vlan set/reset,
set promisc/verbose
Fixes: 61d5bc9bf974 ("dts: add port info command to testpmd shell")
Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
---
dts/framework/remote_session/testpmd_shell.py | 175 +++++++++++++++++-
1 file changed, 174 insertions(+), 1 deletion(-)
Comments
On Wed, Sep 18, 2024 at 3:41 PM Dean Marx <dmarx@iol.unh.edu> wrote:
>
<snip>
> +
> + def tx_vlan_set(self, port: int, vlan: int, verify: bool = True) -> None:
One thing to note is that I think this method (unlike rx_vlan_set for
some reason) requires the ports to be stopped for it to work, so we
should probably decorate this with @requires_stopped_ports to make it
more convenient for the developer.
> + """Set hardware insertion of vlan tags in packets sent on a port.
> +
> + Args:
> + port: The port number to use, should be within 0-32.
> + vlan: The vlan tag to insert, should be within 1-4094.
> + verify: If :data:`True`, the output of the command is scanned to verify that
> + vlan insertion was enabled on the specified port. If not, it is
> + considered an error.
> +
> + Raises:
> + InteractiveCommandExecutionError: If `verify` is :data:`True` and the insertion
> + tag is not set.
> + """
> + vlan_insert_output = self.send_command(f"tx_vlan set {port} {vlan}")
> + if verify:
> + if (
> + "Please stop port" in vlan_insert_output
> + or "Invalid vlan_id" in vlan_insert_output
> + or "Invalid port" in vlan_insert_output
> + ):
> + self._logger.debug(
> + f"Failed to set vlan tag {vlan} on port {port}:\n{vlan_insert_output}"
> + )
> + raise InteractiveCommandExecutionError(
> + f"Testpmd failed to set vlan insertion tag {vlan} on port {port}."
> + )
> +
> + def tx_vlan_reset(self, port: int, verify: bool = True) -> None:
I believe this method also required ports to be stopped.
> + """Disable hardware insertion of vlan tags in packets sent on a port.
> +
> + Args:
> + port: The port number to use, should be within 0-32.
> + verify: If :data:`True`, the output of the command is scanned to verify that
> + vlan insertion was disabled on the specified port. If not, it is
> + considered an error.
> +
> + Raises:
> + InteractiveCommandExecutionError: If `verify` is :data:`True` and the insertion
> + tag is not reset.
> + """
> + vlan_insert_output = self.send_command(f"tx_vlan reset {port}")
> + if verify:
> + if "Please stop port" in vlan_insert_output or "Invalid port" in vlan_insert_output:
> + self._logger.debug(
> + f"Failed to reset vlan insertion on port {port}: \n{vlan_insert_output}"
> + )
> + raise InteractiveCommandExecutionError(
> + f"Testpmd failed to reset vlan insertion on port {port}."
> + )
> +
<snip>
> 2.44.0
>
We should bring up the exact names of method used in this patch and talk
through them in the call.
On 18. 9. 2024 21:41, Dean Marx wrote:
> added the following methods to testpmd shell class:
Capitalize please.
> vlan set filter on/off, rx vlan add/rm,
> vlan set strip on/off, tx vlan set/reset,
> set promisc/verbose
>
> Fixes: 61d5bc9bf974 ("dts: add port info command to testpmd shell")
Is the fix related to the rest of the changes? It looks like it is. The
relation to the other changes should be explained in the commit message
as well as what the fix fixes (or in which cases the original
implementation didn't work properly).
>
> Signed-off-by: Dean Marx <dmarx@iol.unh.edu>
> ---
> dts/framework/remote_session/testpmd_shell.py | 175 +++++++++++++++++-
> 1 file changed, 174 insertions(+), 1 deletion(-)
>
> diff --git a/dts/framework/remote_session/testpmd_shell.py b/dts/framework/remote_session/testpmd_shell.py
> index 8c228af39f..5c5e681841 100644
> --- a/dts/framework/remote_session/testpmd_shell.py
> +++ b/dts/framework/remote_session/testpmd_shell.py
> @@ -102,7 +102,7 @@ def make_parser(cls) -> ParserFn:
> r"strip (?P<STRIP>on|off), "
> r"filter (?P<FILTER>on|off), "
> r"extend (?P<EXTEND>on|off), "
> - r"qinq strip (?P<QINQ_STRIP>on|off)$",
> + r"qinq strip (?P<QINQ_STRIP>on|off)",
> re.MULTILINE,
> named=True,
> ),
> @@ -982,6 +982,179 @@ def set_port_mtu_all(self, mtu: int, verify: bool = True) -> None:
> for port in self.ports:
> self.set_port_mtu(port.id, mtu, verify)
>
> + def vlan_filter_set(self, port: int, on: bool, verify: bool = True) -> None:
The names should follow the same naming scheme. I think the scheme says
it doesn't necessarily have to follow testpmd commands, so I'd say let's
name it the same way as the mtu methods - set_vlan_filter.
> + """Set vlan filter on.
Out of curiosity, what is vlan filter?
> +
> + Args:
> + port: The port number to enable VLAN filter on, should be within 0-32.
Where is this 0-32 coming from? And why 32 and not 31?
> + on: Sets filter on if :data:`True`, otherwise turns off.
I'd use third person and add the port:
Enable the filter on `port` if :data:`True`, otherwise disable it.
> + verify: If :data:`True`, the output of the command and show port info
> + is scanned to verify that vlan filtering was enabled successfully.
> + If not, it is considered an error.
This is not 100% clear whether this means if False or if not enabled
successfully. Looks like this should be updated everywhere.
> +
> + Raises:
> + InteractiveCommandExecutionError: If `verify` is :data:`True` and the filter
> + fails to update.
> + """
> + filter_cmd_output = self.send_command(f"vlan set filter {'on' if on else 'off'} {port}")
> + if verify:
> + vlan_settings = self.show_port_info(port_id=port).vlan_offload
> + if on ^ (vlan_settings is not None and VLANOffloadFlag.FILTER in vlan_settings):
This is an awesome condition.
> + self._logger.debug(f"Failed to set filter on port {port}: \n{filter_cmd_output}")
> + raise InteractiveCommandExecutionError(
> + f"Testpmd failed to set VLAN filter on port {port}."
> + )
We should say whether we're enabling or disabling the filter in both the
log and error. Does filter_cmd_output contain this? What about the other
commands (every one of them except verbose_output)?
> +
> + def rx_vlan(self, vlan: int, port: int, add: bool, verify: bool = True) -> None:
We have set as the prefix for boolean configs and configs that only set
the value, here we probabaly want add_del_rx_vlan. We really should talk
about these names in the call.
> + """Add specified vlan tag to the filter list on a port.
The command doesn't mention the filter. Does this mean the filter needs
to be enabled before we can config vlans on the port?
> +
> + Args:
> + vlan: The vlan tag to add, should be within 1-1005, 1-4094 extended.
The method mentions extended vlans only in this place. It's not clear
when can we use extended vlans (where is it configured or enforced).
> + port: The port number to add the tag on, should be within 0-32.
> + add: Adds the tag if :data:`True`, otherwise removes tag.
removes the tag
> + verify: If :data:`True`, the output of the command is scanned to verify that
> + the vlan tag was added to the filter list on the specified port. If not, it is
> + considered an error.> +
> + Raises:
> + InteractiveCommandExecutionError: If `verify` is :data:`True` and the tag
> + is not added.
I guess this would also be raised if removal is unsuccessful.
> + """
> + rx_output = self.send_command(f"rx_vlan {'add' if add else 'rm'} {vlan} {port}")
As Patrick mentioned, the other method has cmd in the name of the
variable, it would be useful here as well.
> + if verify:
> + if (
> + "VLAN-filtering disabled" in rx_output
> + or "Invalid vlan_id" in rx_output
> + or "Bad arguments" in rx_output
> + ):
> + self._logger.debug(
> + f"Failed to {'add' if add else 'remove'} tag {vlan} port {port}: \n{rx_output}"
> + )
> + raise InteractiveCommandExecutionError(
> + f"Testpmd failed to {'add' if add else 'remove'} tag {vlan} on port {port}."
> + )
> +
> + def vlan_strip_set(self, port: int, on: bool, verify: bool = True) -> None:
> + """Enable vlan stripping on the specified port.
This should say enable or disable.
> +
> + Args:
> + port: The port number to use, should be within 0-32.
> + on: If :data:`True`, will turn strip on, otherwise will turn off.
Let's not be lazy: turn vlan stripping on
> + verify: If :data:`True`, the output of the command and show port info
> + is scanned to verify that vlan stripping was enabled on the specified port.
> + If not, it is considered an error.
> +
> + Raises:
> + InteractiveCommandExecutionError: If `verify` is :data:`True` and stripping
> + fails to update.
> + """
> + strip_output = self.send_command(f"vlan set strip {'on' if on else 'off'} {port}")
Also add cmd to the var name.
> + if verify:
> + vlan_settings = self.show_port_info(port_id=port).vlan_offload
> + if on ^ (vlan_settings is not None and VLANOffloadFlag.STRIP in vlan_settings):
> + self._logger.debug(
> + f"Failed to set strip {'on' if on else 'off'} port {port}: \n{strip_output}"
> + )
> + raise InteractiveCommandExecutionError(
> + f"Testpmd failed to set strip {'on' if on else 'off'} port {port}."
> + )
> +
> + def tx_vlan_set(self, port: int, vlan: int, verify: bool = True) -> None:
> + """Set hardware insertion of vlan tags in packets sent on a port.
> +
> + Args:
> + port: The port number to use, should be within 0-32.
> + vlan: The vlan tag to insert, should be within 1-4094.
This says 1-4094 right away. Both docstrings should say the same thing.
> + verify: If :data:`True`, the output of the command is scanned to verify that
> + vlan insertion was enabled on the specified port. If not, it is
> + considered an error.
> +
> + Raises:
> + InteractiveCommandExecutionError: If `verify` is :data:`True` and the insertion
> + tag is not set.
> + """
> + vlan_insert_output = self.send_command(f"tx_vlan set {port} {vlan}")
Also add cmd to the var name.
> + if verify:
> + if (
> + "Please stop port" in vlan_insert_output
> + or "Invalid vlan_id" in vlan_insert_output
> + or "Invalid port" in vlan_insert_output
> + ):
> + self._logger.debug(
> + f"Failed to set vlan tag {vlan} on port {port}:\n{vlan_insert_output}"
> + )
> + raise InteractiveCommandExecutionError(
> + f"Testpmd failed to set vlan insertion tag {vlan} on port {port}."
> + )
> +
> + def tx_vlan_reset(self, port: int, verify: bool = True) -> None:
I think this could be merged with the previous method. We only need to
add the "on" parameter. Now that I think about it, we should rename on
-> enable, as we'll have a clear, unified name regardless of what the
actual command uses (on, off, set, reset, etc.).
> + """Disable hardware insertion of vlan tags in packets sent on a port.
> +
> + Args:
> + port: The port number to use, should be within 0-32.
> + verify: If :data:`True`, the output of the command is scanned to verify that
> + vlan insertion was disabled on the specified port. If not, it is
> + considered an error.
> +
> + Raises:
> + InteractiveCommandExecutionError: If `verify` is :data:`True` and the insertion
> + tag is not reset.
> + """
> + vlan_insert_output = self.send_command(f"tx_vlan reset {port}")
> + if verify:
> + if "Please stop port" in vlan_insert_output or "Invalid port" in vlan_insert_output:
> + self._logger.debug(
> + f"Failed to reset vlan insertion on port {port}: \n{vlan_insert_output}"
> + )
> + raise InteractiveCommandExecutionError(
> + f"Testpmd failed to reset vlan insertion on port {port}."
> + )
> +
> + def set_promisc(self, port: int, on: bool, verify: bool = True) -> None:
> + """Turns promiscuous mode on/off for the specified port.
In line with previous comments, this should say Enable/disable
promiscuous mode on the specified port.
> +
> + Args:
> + port: Port number to use, should be within 0-32.
> + on: If :data:`True`, turn promisc mode on, otherwise turn off.
> + verify: If :data:`True` an additional command will be sent to verify that promisc mode
> + is properly set. Defaults to :data:`True`.
> +
> + Raises:
> + InteractiveCommandExecutionError: If `verify` is :data:`True` and promisc mode
> + is not correctly set.
> + """
promisc -> promiscuous in the whole docstring
> + promisc_output = self.send_command(f"set promisc {port} {'on' if on else 'off'}")
> + if verify:
> + stats = self.show_port_info(port_id=port)
> + if on ^ stats.is_promiscuous_mode_enabled:
> + self._logger.debug(f"Failed to set promisc mode on port {port}: \n{promisc_output}")
> + raise InteractiveCommandExecutionError(
> + f"Testpmd failed to set promisc mode on port {port}."
> + )
And in these two: promisc -> promiscuous.
> +
> + def set_verbose(self, level: int, verify: bool = True) -> None:
> + """Set debug verbosity level.
> +
> + Args:
> + level: 0 - silent except for error
> + 1 - fully verbose except for Tx packets
> + 2 - fully verbose except for Rx packets
> + >2 - fully verbose
> + verify: If :data:`True` the command output will be scanned to verify that verbose level
> + is properly set. Defaults to :data:`True`.
> +
> + Raises:
> + InteractiveCommandExecutionError: If `verify` is :data:`True` and verbose level
> + is not correctly set.
> + """
> + verbose_output = self.send_command(f"set verbose {level}")
Also add cmd to the var name.
> + if verify:
> + if "Change verbose level" not in verbose_output:
> + self._logger.debug(f"Failed to set verbose level to {level}: \n{verbose_output}")
> + raise InteractiveCommandExecutionError(
> + f"Testpmd failed to set verbose level to {level}."
> + )
> +
> def _close(self) -> None:
> """Overrides :meth:`~.interactive_shell.close`."""
> self.stop()
@@ -102,7 +102,7 @@ def make_parser(cls) -> ParserFn:
r"strip (?P<STRIP>on|off), "
r"filter (?P<FILTER>on|off), "
r"extend (?P<EXTEND>on|off), "
- r"qinq strip (?P<QINQ_STRIP>on|off)$",
+ r"qinq strip (?P<QINQ_STRIP>on|off)",
re.MULTILINE,
named=True,
),
@@ -982,6 +982,179 @@ def set_port_mtu_all(self, mtu: int, verify: bool = True) -> None:
for port in self.ports:
self.set_port_mtu(port.id, mtu, verify)
+ def vlan_filter_set(self, port: int, on: bool, verify: bool = True) -> None:
+ """Set vlan filter on.
+
+ Args:
+ port: The port number to enable VLAN filter on, should be within 0-32.
+ on: Sets filter on if :data:`True`, otherwise turns off.
+ verify: If :data:`True`, the output of the command and show port info
+ is scanned to verify that vlan filtering was enabled successfully.
+ If not, it is considered an error.
+
+ Raises:
+ InteractiveCommandExecutionError: If `verify` is :data:`True` and the filter
+ fails to update.
+ """
+ filter_cmd_output = self.send_command(f"vlan set filter {'on' if on else 'off'} {port}")
+ if verify:
+ vlan_settings = self.show_port_info(port_id=port).vlan_offload
+ if on ^ (vlan_settings is not None and VLANOffloadFlag.FILTER in vlan_settings):
+ self._logger.debug(f"Failed to set filter on port {port}: \n{filter_cmd_output}")
+ raise InteractiveCommandExecutionError(
+ f"Testpmd failed to set VLAN filter on port {port}."
+ )
+
+ def rx_vlan(self, vlan: int, port: int, add: bool, verify: bool = True) -> None:
+ """Add specified vlan tag to the filter list on a port.
+
+ Args:
+ vlan: The vlan tag to add, should be within 1-1005, 1-4094 extended.
+ port: The port number to add the tag on, should be within 0-32.
+ add: Adds the tag if :data:`True`, otherwise removes tag.
+ verify: If :data:`True`, the output of the command is scanned to verify that
+ the vlan tag was added to the filter list on the specified port. If not, it is
+ considered an error.
+
+ Raises:
+ InteractiveCommandExecutionError: If `verify` is :data:`True` and the tag
+ is not added.
+ """
+ rx_output = self.send_command(f"rx_vlan {'add' if add else 'rm'} {vlan} {port}")
+ if verify:
+ if (
+ "VLAN-filtering disabled" in rx_output
+ or "Invalid vlan_id" in rx_output
+ or "Bad arguments" in rx_output
+ ):
+ self._logger.debug(
+ f"Failed to {'add' if add else 'remove'} tag {vlan} port {port}: \n{rx_output}"
+ )
+ raise InteractiveCommandExecutionError(
+ f"Testpmd failed to {'add' if add else 'remove'} tag {vlan} on port {port}."
+ )
+
+ def vlan_strip_set(self, port: int, on: bool, verify: bool = True) -> None:
+ """Enable vlan stripping on the specified port.
+
+ Args:
+ port: The port number to use, should be within 0-32.
+ on: If :data:`True`, will turn strip on, otherwise will turn off.
+ verify: If :data:`True`, the output of the command and show port info
+ is scanned to verify that vlan stripping was enabled on the specified port.
+ If not, it is considered an error.
+
+ Raises:
+ InteractiveCommandExecutionError: If `verify` is :data:`True` and stripping
+ fails to update.
+ """
+ strip_output = self.send_command(f"vlan set strip {'on' if on else 'off'} {port}")
+ if verify:
+ vlan_settings = self.show_port_info(port_id=port).vlan_offload
+ if on ^ (vlan_settings is not None and VLANOffloadFlag.STRIP in vlan_settings):
+ self._logger.debug(
+ f"Failed to set strip {'on' if on else 'off'} port {port}: \n{strip_output}"
+ )
+ raise InteractiveCommandExecutionError(
+ f"Testpmd failed to set strip {'on' if on else 'off'} port {port}."
+ )
+
+ def tx_vlan_set(self, port: int, vlan: int, verify: bool = True) -> None:
+ """Set hardware insertion of vlan tags in packets sent on a port.
+
+ Args:
+ port: The port number to use, should be within 0-32.
+ vlan: The vlan tag to insert, should be within 1-4094.
+ verify: If :data:`True`, the output of the command is scanned to verify that
+ vlan insertion was enabled on the specified port. If not, it is
+ considered an error.
+
+ Raises:
+ InteractiveCommandExecutionError: If `verify` is :data:`True` and the insertion
+ tag is not set.
+ """
+ vlan_insert_output = self.send_command(f"tx_vlan set {port} {vlan}")
+ if verify:
+ if (
+ "Please stop port" in vlan_insert_output
+ or "Invalid vlan_id" in vlan_insert_output
+ or "Invalid port" in vlan_insert_output
+ ):
+ self._logger.debug(
+ f"Failed to set vlan tag {vlan} on port {port}:\n{vlan_insert_output}"
+ )
+ raise InteractiveCommandExecutionError(
+ f"Testpmd failed to set vlan insertion tag {vlan} on port {port}."
+ )
+
+ def tx_vlan_reset(self, port: int, verify: bool = True) -> None:
+ """Disable hardware insertion of vlan tags in packets sent on a port.
+
+ Args:
+ port: The port number to use, should be within 0-32.
+ verify: If :data:`True`, the output of the command is scanned to verify that
+ vlan insertion was disabled on the specified port. If not, it is
+ considered an error.
+
+ Raises:
+ InteractiveCommandExecutionError: If `verify` is :data:`True` and the insertion
+ tag is not reset.
+ """
+ vlan_insert_output = self.send_command(f"tx_vlan reset {port}")
+ if verify:
+ if "Please stop port" in vlan_insert_output or "Invalid port" in vlan_insert_output:
+ self._logger.debug(
+ f"Failed to reset vlan insertion on port {port}: \n{vlan_insert_output}"
+ )
+ raise InteractiveCommandExecutionError(
+ f"Testpmd failed to reset vlan insertion on port {port}."
+ )
+
+ def set_promisc(self, port: int, on: bool, verify: bool = True) -> None:
+ """Turns promiscuous mode on/off for the specified port.
+
+ Args:
+ port: Port number to use, should be within 0-32.
+ on: If :data:`True`, turn promisc mode on, otherwise turn off.
+ verify: If :data:`True` an additional command will be sent to verify that promisc mode
+ is properly set. Defaults to :data:`True`.
+
+ Raises:
+ InteractiveCommandExecutionError: If `verify` is :data:`True` and promisc mode
+ is not correctly set.
+ """
+ promisc_output = self.send_command(f"set promisc {port} {'on' if on else 'off'}")
+ if verify:
+ stats = self.show_port_info(port_id=port)
+ if on ^ stats.is_promiscuous_mode_enabled:
+ self._logger.debug(f"Failed to set promisc mode on port {port}: \n{promisc_output}")
+ raise InteractiveCommandExecutionError(
+ f"Testpmd failed to set promisc mode on port {port}."
+ )
+
+ def set_verbose(self, level: int, verify: bool = True) -> None:
+ """Set debug verbosity level.
+
+ Args:
+ level: 0 - silent except for error
+ 1 - fully verbose except for Tx packets
+ 2 - fully verbose except for Rx packets
+ >2 - fully verbose
+ verify: If :data:`True` the command output will be scanned to verify that verbose level
+ is properly set. Defaults to :data:`True`.
+
+ Raises:
+ InteractiveCommandExecutionError: If `verify` is :data:`True` and verbose level
+ is not correctly set.
+ """
+ verbose_output = self.send_command(f"set verbose {level}")
+ if verify:
+ if "Change verbose level" not in verbose_output:
+ self._logger.debug(f"Failed to set verbose level to {level}: \n{verbose_output}")
+ raise InteractiveCommandExecutionError(
+ f"Testpmd failed to set verbose level to {level}."
+ )
+
def _close(self) -> None:
"""Overrides :meth:`~.interactive_shell.close`."""
self.stop()