[v2,5/5] dts: add `show port stats` command to TestPmdShell
Checks
Commit Message
Add a new TestPmdPortStats data structure to represent the output
returned by `show port stats`, which is implemented as part of
TestPmdShell.
Bugzilla ID: 1407
Signed-off-by: Luca Vizzarro <luca.vizzarro@arm.com>
Reviewed-by: Paul Szczepanek <paul.szczepanek@arm.com>
---
dts/framework/remote_session/testpmd_shell.py | 68 +++++++++++++++++++
1 file changed, 68 insertions(+)
Comments
I've been running some local tests using a mock test suite. Each
method you created generates output as expected, but
show_port_stats_all() is printing out an empty list; I'm not sure this
is intentional or not. I don't have much experience with regular
expressions to be able to discern what is going on in the code within
a reasonable amount of time, so I wanted to bring this to your
attention.
On Thu, May 9, 2024 at 7:27 AM Luca Vizzarro <luca.vizzarro@arm.com> wrote:
>
> Add a new TestPmdPortStats data structure to represent the output
> returned by `show port stats`, which is implemented as part of
> TestPmdShell.
>
> Bugzilla ID: 1407
>
> Signed-off-by: Luca Vizzarro <luca.vizzarro@arm.com>
> Reviewed-by: Paul Szczepanek <paul.szczepanek@arm.com>
> ---
> dts/framework/remote_session/testpmd_shell.py | 68 +++++++++++++++++++
> 1 file changed, 68 insertions(+)
>
> diff --git a/dts/framework/remote_session/testpmd_shell.py b/dts/framework/remote_session/testpmd_shell.py
> index 7910e17fed..d0b6da50f0 100644
> --- a/dts/framework/remote_session/testpmd_shell.py
> +++ b/dts/framework/remote_session/testpmd_shell.py
> @@ -531,6 +531,42 @@ class TestPmdPort(TextParser):
> )
>
>
> +@dataclass
> +class TestPmdPortStats(TextParser):
> + """Port statistics."""
> +
> + #:
> + port_id: int = field(metadata=TextParser.find_int(r"NIC statistics for port (\d+)"))
> +
> + #:
> + rx_packets: int = field(metadata=TextParser.find_int(r"RX-packets:\s+(\d+)"))
> + #:
> + rx_missed: int = field(metadata=TextParser.find_int(r"RX-missed:\s+(\d+)"))
> + #:
> + rx_bytes: int = field(metadata=TextParser.find_int(r"RX-bytes:\s+(\d+)"))
> + #:
> + rx_errors: int = field(metadata=TextParser.find_int(r"RX-errors:\s+(\d+)"))
> + #:
> + rx_nombuf: int = field(metadata=TextParser.find_int(r"RX-nombuf:\s+(\d+)"))
> +
> + #:
> + tx_packets: int = field(metadata=TextParser.find_int(r"TX-packets:\s+(\d+)"))
> + #:
> + tx_errors: int = field(metadata=TextParser.find_int(r"TX-errors:\s+(\d+)"))
> + #:
> + tx_bytes: int = field(metadata=TextParser.find_int(r"TX-bytes:\s+(\d+)"))
> +
> + #:
> + rx_pps: int = field(metadata=TextParser.find_int(r"Rx-pps:\s+(\d+)"))
> + #:
> + rx_bps: int = field(metadata=TextParser.find_int(r"Rx-bps:\s+(\d+)"))
> +
> + #:
> + tx_pps: int = field(metadata=TextParser.find_int(r"Tx-pps:\s+(\d+)"))
> + #:
> + tx_bps: int = field(metadata=TextParser.find_int(r"Tx-bps:\s+(\d+)"))
> +
> +
> class TestPmdShell(InteractiveShell):
> """Testpmd interactive shell.
>
> @@ -713,6 +749,38 @@ def show_port_info(self, port_id: int) -> TestPmdPort:
>
> return TestPmdPort.parse(output)
>
> + def show_port_stats_all(self) -> list[TestPmdPortStats]:
> + """Returns the statistics of all the ports."""
> + output = self.send_command("show port stats all")
> +
> + # Sample output of the "all" command looks like:
> + #
> + # ########### NIC statistics for port 0 ###########
> + # values...
> + # #################################################
> + #
> + # ########### NIC statistics for port 1 ###########
> + # values...
> + # #################################################
> + #
> + iter = re.finditer(r"(^ #*.+#*$[^#]+)^ #*$", output, re.MULTILINE)
> + return [TestPmdPortStats.parse(block.group(1)) for block in iter]
> +
> + def show_port_stats(self, port_id: int) -> TestPmdPortStats:
> + """Returns the given port statistics.
> +
> + Args:
> + port_id: The port ID to gather information for.
> +
> + Raises:
> + InteractiveCommandExecutionError: If `port_id` is invalid.
> + """
> + output = self.send_command(f"show port stats {port_id}", skip_first_line=True)
> + if output.startswith("Invalid port"):
> + raise InteractiveCommandExecutionError("invalid port given")
> +
> + return TestPmdPortStats.parse(output)
> +
> def close(self) -> None:
> """Overrides :meth:`~.interactive_shell.close`."""
> self.send_command("quit", "")
> --
> 2.34.1
>
On 20/05/2024 15:26, Nicholas Pratte wrote:
> I've been running some local tests using a mock test suite. Each
> method you created generates output as expected, but
> show_port_stats_all() is printing out an empty list; I'm not sure this
> is intentional or not. I don't have much experience with regular
> expressions to be able to discern what is going on in the code within
> a reasonable amount of time, so I wanted to bring this to your
> attention.
Yeah, well spotted! I must have missed it in my testing... it looks like
it's the fault of the sneaky \r being added at the end of the lines by
the paramiko shell.
Other than Nick's comment:
Reviewed-by: Jeremy Spewock <jspewock@iol.unh.edu>
@@ -531,6 +531,42 @@ class TestPmdPort(TextParser):
)
+@dataclass
+class TestPmdPortStats(TextParser):
+ """Port statistics."""
+
+ #:
+ port_id: int = field(metadata=TextParser.find_int(r"NIC statistics for port (\d+)"))
+
+ #:
+ rx_packets: int = field(metadata=TextParser.find_int(r"RX-packets:\s+(\d+)"))
+ #:
+ rx_missed: int = field(metadata=TextParser.find_int(r"RX-missed:\s+(\d+)"))
+ #:
+ rx_bytes: int = field(metadata=TextParser.find_int(r"RX-bytes:\s+(\d+)"))
+ #:
+ rx_errors: int = field(metadata=TextParser.find_int(r"RX-errors:\s+(\d+)"))
+ #:
+ rx_nombuf: int = field(metadata=TextParser.find_int(r"RX-nombuf:\s+(\d+)"))
+
+ #:
+ tx_packets: int = field(metadata=TextParser.find_int(r"TX-packets:\s+(\d+)"))
+ #:
+ tx_errors: int = field(metadata=TextParser.find_int(r"TX-errors:\s+(\d+)"))
+ #:
+ tx_bytes: int = field(metadata=TextParser.find_int(r"TX-bytes:\s+(\d+)"))
+
+ #:
+ rx_pps: int = field(metadata=TextParser.find_int(r"Rx-pps:\s+(\d+)"))
+ #:
+ rx_bps: int = field(metadata=TextParser.find_int(r"Rx-bps:\s+(\d+)"))
+
+ #:
+ tx_pps: int = field(metadata=TextParser.find_int(r"Tx-pps:\s+(\d+)"))
+ #:
+ tx_bps: int = field(metadata=TextParser.find_int(r"Tx-bps:\s+(\d+)"))
+
+
class TestPmdShell(InteractiveShell):
"""Testpmd interactive shell.
@@ -713,6 +749,38 @@ def show_port_info(self, port_id: int) -> TestPmdPort:
return TestPmdPort.parse(output)
+ def show_port_stats_all(self) -> list[TestPmdPortStats]:
+ """Returns the statistics of all the ports."""
+ output = self.send_command("show port stats all")
+
+ # Sample output of the "all" command looks like:
+ #
+ # ########### NIC statistics for port 0 ###########
+ # values...
+ # #################################################
+ #
+ # ########### NIC statistics for port 1 ###########
+ # values...
+ # #################################################
+ #
+ iter = re.finditer(r"(^ #*.+#*$[^#]+)^ #*$", output, re.MULTILINE)
+ return [TestPmdPortStats.parse(block.group(1)) for block in iter]
+
+ def show_port_stats(self, port_id: int) -> TestPmdPortStats:
+ """Returns the given port statistics.
+
+ Args:
+ port_id: The port ID to gather information for.
+
+ Raises:
+ InteractiveCommandExecutionError: If `port_id` is invalid.
+ """
+ output = self.send_command(f"show port stats {port_id}", skip_first_line=True)
+ if output.startswith("Invalid port"):
+ raise InteractiveCommandExecutionError("invalid port given")
+
+ return TestPmdPortStats.parse(output)
+
def close(self) -> None:
"""Overrides :meth:`~.interactive_shell.close`."""
self.send_command("quit", "")