* [PATCH 0/2] dts: add generic blocking app class
@ 2025-07-02 16:42 Luca Vizzarro
2025-07-02 16:42 ` [PATCH 1/2] dts: add DPDK build app helper function Luca Vizzarro
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Luca Vizzarro @ 2025-07-02 16:42 UTC (permalink / raw)
To: dev; +Cc: Luca Vizzarro, Patrick Robb, Paul Szczepanek
Hello,
sending in some minor improvements that unlocks the possibility of
running any app in the background.
Best,
Luca
Luca Vizzarro (2):
dts: add DPDK build app helper function
dts: add generic blocking app class
dts/framework/remote_session/blocking_app.py | 135 +++++++++++++++++++
dts/framework/remote_session/dpdk.py | 8 +-
dts/framework/remote_session/dpdk_app.py | 80 -----------
dts/tests/TestSuite_packet_capture.py | 66 +++------
4 files changed, 160 insertions(+), 129 deletions(-)
create mode 100644 dts/framework/remote_session/blocking_app.py
delete mode 100644 dts/framework/remote_session/dpdk_app.py
--
2.43.0
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/2] dts: add DPDK build app helper function
2025-07-02 16:42 [PATCH 0/2] dts: add generic blocking app class Luca Vizzarro
@ 2025-07-02 16:42 ` Luca Vizzarro
2025-07-03 15:35 ` Dean Marx
2025-07-04 3:04 ` Patrick Robb
2025-07-02 16:42 ` [PATCH 2/2] dts: add generic blocking app class Luca Vizzarro
2025-07-04 15:29 ` [PATCH v2 0/2] " Luca Vizzarro
2 siblings, 2 replies; 12+ messages in thread
From: Luca Vizzarro @ 2025-07-02 16:42 UTC (permalink / raw)
To: dev; +Cc: Luca Vizzarro, Paul Szczepanek, Patrick Robb
Make a distinction between example apps and app/ apps by renaming the
build app function. Moreover, provide a dedicated helper function to
retrieve the path to a DPDK app.
Signed-off-by: Luca Vizzarro <luca.vizzarro@arm.com>
Reviewed-by: Paul Szczepanek <paul.szczepanek@arm.com>
---
dts/framework/remote_session/dpdk.py | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index e00c4a9bf9..ed1f808bdd 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -267,8 +267,8 @@ def _build_dpdk(self) -> None:
self.remote_dpdk_build_dir,
)
- def build_dpdk_app(self, app_name: str, **meson_dpdk_args: str | bool) -> PurePath:
- """Build one or all DPDK apps.
+ def build_dpdk_example_app(self, app_name: str, **meson_dpdk_args: str | bool) -> PurePath:
+ """Build one or all DPDK example apps.
Requires DPDK to be already built on the SUT node.
@@ -298,6 +298,10 @@ def build_dpdk_app(self, app_name: str, **meson_dpdk_args: str | bool) -> PurePa
self.remote_dpdk_build_dir, "examples", f"dpdk-{app_name}"
)
+ def get_app(self, app_name: str) -> PurePath:
+ """Retrieve path for a DPDK app."""
+ return self._session.join_remote_path(self.remote_dpdk_build_dir, "app", f"dpdk-{app_name}")
+
@cached_property
def remote_dpdk_tree_path(self) -> PurePath:
"""The remote DPDK tree path."""
--
2.43.0
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 2/2] dts: add generic blocking app class
2025-07-02 16:42 [PATCH 0/2] dts: add generic blocking app class Luca Vizzarro
2025-07-02 16:42 ` [PATCH 1/2] dts: add DPDK build app helper function Luca Vizzarro
@ 2025-07-02 16:42 ` Luca Vizzarro
2025-07-03 15:35 ` Dean Marx
2025-07-04 3:23 ` Patrick Robb
2025-07-04 15:29 ` [PATCH v2 0/2] " Luca Vizzarro
2 siblings, 2 replies; 12+ messages in thread
From: Luca Vizzarro @ 2025-07-02 16:42 UTC (permalink / raw)
To: dev; +Cc: Luca Vizzarro, Paul Szczepanek, Patrick Robb
Add a generic blocking app class to allow a test writer to run any app
in the background. Make the original BlockingDPDKApp class inherit from
this one. Implement the new BlockingApp class in the packet_capture test
suite.
Signed-off-by: Luca Vizzarro <luca.vizzarro@arm.com>
Reviewed-by: Paul Szczepanek <paul.szczepanek@arm.com>
---
dts/framework/remote_session/blocking_app.py | 135 +++++++++++++++++++
dts/framework/remote_session/dpdk_app.py | 80 -----------
dts/tests/TestSuite_packet_capture.py | 66 +++------
3 files changed, 154 insertions(+), 127 deletions(-)
create mode 100644 dts/framework/remote_session/blocking_app.py
delete mode 100644 dts/framework/remote_session/dpdk_app.py
diff --git a/dts/framework/remote_session/blocking_app.py b/dts/framework/remote_session/blocking_app.py
new file mode 100644
index 0000000000..8de536c259
--- /dev/null
+++ b/dts/framework/remote_session/blocking_app.py
@@ -0,0 +1,135 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2025 Arm Limited
+
+"""Class to run blocking apps in the background.
+
+The class won't automatically start the app. The start-up is done as part of the
+:meth:`BlockingApp.wait_until_ready` method, which will return execution to the caller only
+when the desired stdout has been returned by the app. Usually this is used to detect when the app
+has been loaded and ready to be used.
+
+This module also provides the class :class:`BlockingDPDKApp` useful to run any DPDK app from the
+DPDK build dir.
+
+Example:
+ ..code:: python
+
+ pdump = BlockingDPDKApp(
+ PurePath("app/dpdk-pdump"),
+ app_params="--pdump 'port=0,queue=*,rx-dev=/tmp/rx-dev.pcap'"
+ )
+ pdump.wait_until_ready("65535") # start app
+
+ # pdump is now ready to capture
+
+ pdump.close() # stop/close app
+"""
+
+from pathlib import PurePath
+from typing import Generic, TypeVar, cast
+
+from typing_extensions import Self
+
+from framework.context import get_ctx
+from framework.params import Params
+from framework.params.eal import EalParams
+from framework.remote_session.dpdk_shell import compute_eal_params
+from framework.remote_session.interactive_shell import InteractiveShell
+from framework.testbed_model.node import Node
+
+P = TypeVar("P", bound=Params)
+
+
+class BlockingApp(InteractiveShell, Generic[P]):
+ """Class to manage generic blocking apps."""
+
+ _app_params: P
+
+ def __init__(
+ self,
+ node: Node,
+ path: PurePath,
+ name: str | None = None,
+ privileged: bool = False,
+ app_params: P | str = "",
+ ) -> None:
+ """Constructor.
+
+ Args:
+ node: The node to run the app on.
+ path: Path to the application on the node.
+ name: Name to identify this application.
+ privileged: Run as privileged user.
+ app_params: The application parameters. Can be of any type inheriting :class:`Params` or
+ a plain string.
+ """
+ if isinstance(app_params, str):
+ params = Params()
+ params.append_str(app_params)
+ app_params = cast(P, params)
+
+ self._path = path
+
+ super().__init__(node, name, privileged, app_params)
+
+ @property
+ def path(self) -> PurePath:
+ """The path of the DPDK app relative to the DPDK build folder."""
+ return self._path
+
+ def wait_until_ready(self, end_token: str) -> Self:
+ """Start app and wait until ready.
+
+ Args:
+ end_token: The string at the end of a line that indicates the app is ready.
+
+ Returns:
+ Itself.
+ """
+ self.start_application(end_token)
+ return self
+
+ def close(self) -> None:
+ """Close the application.
+
+ Sends a SIGINT to close the application.
+ """
+ self.send_command("\x03")
+ super().close()
+
+
+PE = TypeVar("PE", bound=EalParams)
+
+
+class BlockingDPDKApp(BlockingApp, Generic[PE]):
+ """Class to manage blocking DPDK apps on the SUT."""
+
+ _app_params: PE
+
+ def __init__(
+ self,
+ path: PurePath,
+ name: str | None = None,
+ privileged: bool = True,
+ app_params: PE | str = "",
+ ) -> None:
+ """Constructor.
+
+ Args:
+ path: Path relative to the DPDK build to the executable.
+ name: Name to identify this application.
+ privileged: Run as privileged user.
+ app_params: The application parameters. If a string or an incomplete :class:`EalParams`
+ object are passed, the EAL params are computed based on the current context.
+ """
+ if isinstance(app_params, str):
+ eal_params = compute_eal_params()
+ eal_params.append_str(app_params)
+ app_params = cast(PE, eal_params)
+ else:
+ app_params = cast(PE, compute_eal_params(app_params))
+
+ node = get_ctx().sut_node
+ path = PurePath(get_ctx().dpdk_build.remote_dpdk_build_dir).joinpath(self.path)
+
+ super().__init__(node, path, name, privileged, app_params)
diff --git a/dts/framework/remote_session/dpdk_app.py b/dts/framework/remote_session/dpdk_app.py
deleted file mode 100644
index dc4b817bdd..0000000000
--- a/dts/framework/remote_session/dpdk_app.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# SPDX-License-Identifier: BSD-3-Clause
-# Copyright(c) 2025 Arm Limited
-
-"""Class to run blocking DPDK apps in the background.
-
-The class won't automatically start the app. The start-up is done as part of the
-:meth:`BlockingDPDKApp.wait_until_ready` method, which will return execution to the caller only
-when the desired stdout has been returned by the app. Usually this is used to detect when the app
-has been loaded and ready to be used.
-
-Example:
- ..code:: python
-
- pdump = BlockingDPDKApp(
- PurePath("app/dpdk-pdump"),
- app_params="--pdump 'port=0,queue=*,rx-dev=/tmp/rx-dev.pcap'"
- )
- pdump.wait_until_ready("65535") # start app
-
- # pdump is now ready to capture
-
- pdump.close() # stop/close app
-"""
-
-from pathlib import PurePath
-
-from framework.params.eal import EalParams
-from framework.remote_session.dpdk_shell import DPDKShell
-
-
-class BlockingDPDKApp(DPDKShell):
- """Class to manage blocking DPDK apps."""
-
- def __init__(
- self,
- path: PurePath,
- name: str | None = None,
- privileged: bool = True,
- app_params: EalParams | str = "",
- ) -> None:
- """Constructor.
-
- Overrides :meth:`~.dpdk_shell.DPDKShell.__init__`.
-
- Args:
- path: Path relative to the DPDK build to the executable.
- name: Name to identify this application.
- privileged: Run as privileged user.
- app_params: The application parameters. If a string or an incomplete :class:`EalParams`
- object are passed, the EAL params are computed based on the current context.
- """
- if isinstance(app_params, str):
- eal_params = EalParams()
- eal_params.append_str(app_params)
- app_params = eal_params
-
- self._path = path
-
- super().__init__(name, privileged, app_params)
-
- @property
- def path(self) -> PurePath:
- """The path of the DPDK app relative to the DPDK build folder."""
- return self._path
-
- def wait_until_ready(self, end_token: str) -> None:
- """Start app and wait until ready.
-
- Args:
- end_token: The string at the end of a line that indicates the app is ready.
- """
- self.start_application(end_token)
-
- def close(self) -> None:
- """Close the application.
-
- Sends a SIGINT to close the application.
- """
- self.send_command("\x03")
- super().close()
diff --git a/dts/tests/TestSuite_packet_capture.py b/dts/tests/TestSuite_packet_capture.py
index e162bded87..bad243a571 100644
--- a/dts/tests/TestSuite_packet_capture.py
+++ b/dts/tests/TestSuite_packet_capture.py
@@ -24,12 +24,10 @@
from scapy.layers.sctp import SCTP
from scapy.packet import Packet, Raw, raw
from scapy.utils import rdpcap
-from typing_extensions import Self
-from framework.context import get_ctx
from framework.params import Params
+from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.dpdk_shell import compute_eal_params
-from framework.remote_session.interactive_shell import InteractiveShell
from framework.remote_session.testpmd_shell import TestPmdShell
from framework.settings import SETTINGS
from framework.test_suite import TestSuite, func_test
@@ -61,57 +59,31 @@ class DumpcapParams(Params):
packet_filter: str | None = field(default=None, metadata=Params.short("f"))
-class Dumpcap(InteractiveShell):
- """Class to spawn and manage a dpdk-dumpcap process.
-
- The dpdk-dumpcap is a DPDK app but instead of providing a regular DPDK EAL interface to the
- user, it replicates the Wireshark dumpcap app.
- """
-
- _app_params: DumpcapParams
-
- def __init__(self, params: DumpcapParams) -> None:
- """Extends :meth:`~.interactive_shell.InteractiveShell.__init__`."""
- self.ctx = get_ctx()
- eal_params = compute_eal_params()
- params.lcore_list = eal_params.lcore_list
- params.file_prefix = eal_params.prefix
-
- super().__init__(self.ctx.sut_node, name=None, privileged=True, app_params=params)
-
- @property
- def path(self) -> PurePath:
- """Path to the shell executable."""
- return PurePath(self.ctx.dpdk_build.remote_dpdk_build_dir).joinpath("app/dpdk-dumpcap")
-
- def wait_until_ready(self) -> Self:
- """Start app and wait until ready."""
- self.start_application(f"Capturing on '{self._app_params.interface}'")
- return self
-
- def close(self) -> None:
- """Close the application.
-
- Sends a SIGINT to close the application.
- """
- self.send_command("\x03")
- super().close()
-
-
@requires(topology_type=TopologyType.two_links)
class TestPacketCapture(TestSuite):
"""Packet Capture TestSuite.
Attributes:
- packets: List of packets to send for testing pdump.
- rx_pcap_path: The remote path where to create the Rx packets pcap with pdump.
- tx_pcap_path: The remote path where to create the Tx packets pcap with pdump.
+ packets: List of packets to send for testing dumpcap.
+ rx_pcap_path: The remote path where to create the Rx packets pcap with dumpcap.
+ tx_pcap_path: The remote path where to create the Tx packets pcap with dumpcap.
"""
packets: list[Packet]
rx_pcap_path: PurePath
tx_pcap_path: PurePath
+ def _run_dumpcap(self, params: DumpcapParams) -> BlockingApp:
+ eal_params = compute_eal_params()
+ params.lcore_list = eal_params.lcore_list
+ params.file_prefix = eal_params.prefix
+ return BlockingApp(
+ self._ctx.sut_node,
+ self._ctx.dpdk_build.get_app("dumpcap"),
+ app_params=params,
+ privileged=True,
+ ).wait_until_ready(f"Capturing on '{params.interface}'")
+
def set_up_suite(self) -> None:
"""Test suite setup.
@@ -147,21 +119,21 @@ def _load_pcap_packets(self, remote_pcap_path: PurePath) -> list[Packet]:
def _send_and_dump(
self, packet_filter: str | None = None, rx_only: bool = False
) -> list[Packet]:
- dumpcap_rx = Dumpcap(
+ dumpcap_rx = self._run_dumpcap(
DumpcapParams(
interface=self.topology.sut_port_ingress.pci,
output_pcap_path=self.rx_pcap_path,
packet_filter=packet_filter,
)
- ).wait_until_ready()
+ )
if not rx_only:
- dumpcap_tx = Dumpcap(
+ dumpcap_tx = self._run_dumpcap(
DumpcapParams(
interface=self.topology.sut_port_egress.pci,
output_pcap_path=self.tx_pcap_path,
packet_filter=packet_filter,
)
- ).wait_until_ready()
+ )
received_packets = self.send_packets_and_capture(
self.packets, PacketFilteringConfig(no_lldp=False)
--
2.43.0
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] dts: add DPDK build app helper function
2025-07-02 16:42 ` [PATCH 1/2] dts: add DPDK build app helper function Luca Vizzarro
@ 2025-07-03 15:35 ` Dean Marx
2025-07-04 3:04 ` Patrick Robb
1 sibling, 0 replies; 12+ messages in thread
From: Dean Marx @ 2025-07-03 15:35 UTC (permalink / raw)
To: Luca Vizzarro; +Cc: dev, Paul Szczepanek, Patrick Robb
Reviewed-by: Dean Marx <dmarx@iol.unh.edu>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] dts: add generic blocking app class
2025-07-02 16:42 ` [PATCH 2/2] dts: add generic blocking app class Luca Vizzarro
@ 2025-07-03 15:35 ` Dean Marx
2025-07-04 3:23 ` Patrick Robb
1 sibling, 0 replies; 12+ messages in thread
From: Dean Marx @ 2025-07-03 15:35 UTC (permalink / raw)
To: Luca Vizzarro; +Cc: dev, Paul Szczepanek, Patrick Robb
Reviewed-by: Dean Marx <dmarx@iol.unh.edu>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/2] dts: add DPDK build app helper function
2025-07-02 16:42 ` [PATCH 1/2] dts: add DPDK build app helper function Luca Vizzarro
2025-07-03 15:35 ` Dean Marx
@ 2025-07-04 3:04 ` Patrick Robb
1 sibling, 0 replies; 12+ messages in thread
From: Patrick Robb @ 2025-07-04 3:04 UTC (permalink / raw)
To: Luca Vizzarro; +Cc: dev, Paul Szczepanek
[-- Attachment #1: Type: text/plain, Size: 2146 bytes --]
On Wed, Jul 2, 2025 at 12:43 PM Luca Vizzarro <luca.vizzarro@arm.com> wrote:
> Make a distinction between example apps and app/ apps by renaming the
> build app function. Moreover, provide a dedicated helper function to
> retrieve the path to a DPDK app.
>
> Signed-off-by: Luca Vizzarro <luca.vizzarro@arm.com>
> Reviewed-by: Paul Szczepanek <paul.szczepanek@arm.com>
> ---
> dts/framework/remote_session/dpdk.py | 8 ++++++--
> 1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/dts/framework/remote_session/dpdk.py
> b/dts/framework/remote_session/dpdk.py
> index e00c4a9bf9..ed1f808bdd 100644
> --- a/dts/framework/remote_session/dpdk.py
> +++ b/dts/framework/remote_session/dpdk.py
> @@ -267,8 +267,8 @@ def _build_dpdk(self) -> None:
> self.remote_dpdk_build_dir,
> )
>
> - def build_dpdk_app(self, app_name: str, **meson_dpdk_args: str |
> bool) -> PurePath:
> - """Build one or all DPDK apps.
> + def build_dpdk_example_app(self, app_name: str, **meson_dpdk_args:
> str | bool) -> PurePath:
> + """Build one or all DPDK example apps.
>
>
We have previously been encouraged to avoid using sample apps unless
absolutely necessary, so it probably doesn't make sense for us to add this
in until we have a specific reason and justification for supporting example
apps (and this may never happen).
> Requires DPDK to be already built on the SUT node.
>
> @@ -298,6 +298,10 @@ def build_dpdk_app(self, app_name: str,
> **meson_dpdk_args: str | bool) -> PurePa
> self.remote_dpdk_build_dir, "examples", f"dpdk-{app_name}"
> )
>
> + def get_app(self, app_name: str) -> PurePath:
> + """Retrieve path for a DPDK app."""
> + return self._session.join_remote_path(self.remote_dpdk_build_dir,
> "app", f"dpdk-{app_name}")
> +
> @cached_property
> def remote_dpdk_tree_path(self) -> PurePath:
> """The remote DPDK tree path."""
> --
> 2.43.0
>
>
Otherwise this looks fine for dumpcap and the others /app apps - thanks.
Reviewed-by: Patrick Robb <probb@iol.unh.edu>
[-- Attachment #2: Type: text/html, Size: 3155 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/2] dts: add generic blocking app class
2025-07-02 16:42 ` [PATCH 2/2] dts: add generic blocking app class Luca Vizzarro
2025-07-03 15:35 ` Dean Marx
@ 2025-07-04 3:23 ` Patrick Robb
1 sibling, 0 replies; 12+ messages in thread
From: Patrick Robb @ 2025-07-04 3:23 UTC (permalink / raw)
To: Luca Vizzarro; +Cc: dev, Paul Szczepanek
[-- Attachment #1: Type: text/plain, Size: 416 bytes --]
LGTM, thanks.
As it relates to the TREX patch, yes I will try to refactor towards using
this to handle the TREX foreground server process. I guess the one change I
would need to make is changing the default InteractiveShell timeout from 5
seconds to a larger number (like 20) since TREX can take a long time to
start up and produce the "end_token." That could be a part of my patch
though, not this patch.
Thanks.
[-- Attachment #2: Type: text/html, Size: 498 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 0/2] dts: add generic blocking app class
2025-07-02 16:42 [PATCH 0/2] dts: add generic blocking app class Luca Vizzarro
2025-07-02 16:42 ` [PATCH 1/2] dts: add DPDK build app helper function Luca Vizzarro
2025-07-02 16:42 ` [PATCH 2/2] dts: add generic blocking app class Luca Vizzarro
@ 2025-07-04 15:29 ` Luca Vizzarro
2025-07-04 15:29 ` [PATCH v2 1/2] dts: remove dpdk example build function Luca Vizzarro
2025-07-04 15:29 ` [PATCH v2 2/2] dts: add generic blocking app class Luca Vizzarro
2 siblings, 2 replies; 12+ messages in thread
From: Luca Vizzarro @ 2025-07-04 15:29 UTC (permalink / raw)
To: dev; +Cc: Luca Vizzarro, Patrick Robb, Paul Szczepanek
Hi again,
sending v2.
v2:
- removing the build dpdk example app as not needed.
Luca Vizzarro (2):
dts: remove dpdk example build function
dts: add generic blocking app class
dts/framework/remote_session/blocking_app.py | 135 +++++++++++++++++++
dts/framework/remote_session/dpdk.py | 33 +----
dts/framework/remote_session/dpdk_app.py | 80 -----------
dts/tests/TestSuite_packet_capture.py | 66 +++------
4 files changed, 157 insertions(+), 157 deletions(-)
create mode 100644 dts/framework/remote_session/blocking_app.py
delete mode 100644 dts/framework/remote_session/dpdk_app.py
--
2.43.0
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 1/2] dts: remove dpdk example build function
2025-07-04 15:29 ` [PATCH v2 0/2] " Luca Vizzarro
@ 2025-07-04 15:29 ` Luca Vizzarro
2025-07-04 16:36 ` Patrick Robb
2025-07-04 15:29 ` [PATCH v2 2/2] dts: add generic blocking app class Luca Vizzarro
1 sibling, 1 reply; 12+ messages in thread
From: Luca Vizzarro @ 2025-07-04 15:29 UTC (permalink / raw)
To: dev; +Cc: Luca Vizzarro, Patrick Robb, Paul Szczepanek
Usage of example DPDK apps should be avoided. Therefore, remove
the function that allows to build example apps. Moreover,
provide a dedicated helper function to retrieve the path to a
DPDK app.
Signed-off-by: Luca Vizzarro <luca.vizzarro@arm.com>
---
dts/framework/remote_session/dpdk.py | 33 +++-------------------------
1 file changed, 3 insertions(+), 30 deletions(-)
diff --git a/dts/framework/remote_session/dpdk.py b/dts/framework/remote_session/dpdk.py
index e00c4a9bf9..606d6e22fe 100644
--- a/dts/framework/remote_session/dpdk.py
+++ b/dts/framework/remote_session/dpdk.py
@@ -267,36 +267,9 @@ def _build_dpdk(self) -> None:
self.remote_dpdk_build_dir,
)
- def build_dpdk_app(self, app_name: str, **meson_dpdk_args: str | bool) -> PurePath:
- """Build one or all DPDK apps.
-
- Requires DPDK to be already built on the SUT node.
-
- Args:
- app_name: The name of the DPDK app to build.
- When `app_name` is ``all``, build all example apps.
- meson_dpdk_args: The arguments found in ``meson_options.txt`` in root DPDK directory.
- Do not use ``-D`` with them.
-
- Returns:
- The directory path of the built app. If building all apps, return
- the path to the examples directory (where all apps reside).
- """
- self._session.build_dpdk(
- self._env_vars,
- MesonArgs(examples=app_name, **meson_dpdk_args), # type: ignore [arg-type]
- # ^^ https://github.com/python/mypy/issues/11583
- self.remote_dpdk_tree_path,
- self.remote_dpdk_build_dir,
- rebuild=True,
- timeout=self._app_compile_timeout,
- )
-
- if app_name == "all":
- return self._session.join_remote_path(self.remote_dpdk_build_dir, "examples")
- return self._session.join_remote_path(
- self.remote_dpdk_build_dir, "examples", f"dpdk-{app_name}"
- )
+ def get_app(self, app_name: str) -> PurePath:
+ """Retrieve path for a DPDK app."""
+ return self._session.join_remote_path(self.remote_dpdk_build_dir, "app", f"dpdk-{app_name}")
@cached_property
def remote_dpdk_tree_path(self) -> PurePath:
--
2.43.0
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v2 2/2] dts: add generic blocking app class
2025-07-04 15:29 ` [PATCH v2 0/2] " Luca Vizzarro
2025-07-04 15:29 ` [PATCH v2 1/2] dts: remove dpdk example build function Luca Vizzarro
@ 2025-07-04 15:29 ` Luca Vizzarro
2025-07-04 16:36 ` Patrick Robb
1 sibling, 1 reply; 12+ messages in thread
From: Luca Vizzarro @ 2025-07-04 15:29 UTC (permalink / raw)
To: dev; +Cc: Luca Vizzarro, Paul Szczepanek, Patrick Robb
Add a generic blocking app class to allow a test writer to run any app
in the background. Make the original BlockingDPDKApp class inherit from
this one. Implement the new BlockingApp class in the packet_capture test
suite.
Signed-off-by: Luca Vizzarro <luca.vizzarro@arm.com>
Reviewed-by: Paul Szczepanek <paul.szczepanek@arm.com>
---
dts/framework/remote_session/blocking_app.py | 135 +++++++++++++++++++
dts/framework/remote_session/dpdk_app.py | 80 -----------
dts/tests/TestSuite_packet_capture.py | 66 +++------
3 files changed, 154 insertions(+), 127 deletions(-)
create mode 100644 dts/framework/remote_session/blocking_app.py
delete mode 100644 dts/framework/remote_session/dpdk_app.py
diff --git a/dts/framework/remote_session/blocking_app.py b/dts/framework/remote_session/blocking_app.py
new file mode 100644
index 0000000000..8de536c259
--- /dev/null
+++ b/dts/framework/remote_session/blocking_app.py
@@ -0,0 +1,135 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2025 Arm Limited
+
+"""Class to run blocking apps in the background.
+
+The class won't automatically start the app. The start-up is done as part of the
+:meth:`BlockingApp.wait_until_ready` method, which will return execution to the caller only
+when the desired stdout has been returned by the app. Usually this is used to detect when the app
+has been loaded and ready to be used.
+
+This module also provides the class :class:`BlockingDPDKApp` useful to run any DPDK app from the
+DPDK build dir.
+
+Example:
+ ..code:: python
+
+ pdump = BlockingDPDKApp(
+ PurePath("app/dpdk-pdump"),
+ app_params="--pdump 'port=0,queue=*,rx-dev=/tmp/rx-dev.pcap'"
+ )
+ pdump.wait_until_ready("65535") # start app
+
+ # pdump is now ready to capture
+
+ pdump.close() # stop/close app
+"""
+
+from pathlib import PurePath
+from typing import Generic, TypeVar, cast
+
+from typing_extensions import Self
+
+from framework.context import get_ctx
+from framework.params import Params
+from framework.params.eal import EalParams
+from framework.remote_session.dpdk_shell import compute_eal_params
+from framework.remote_session.interactive_shell import InteractiveShell
+from framework.testbed_model.node import Node
+
+P = TypeVar("P", bound=Params)
+
+
+class BlockingApp(InteractiveShell, Generic[P]):
+ """Class to manage generic blocking apps."""
+
+ _app_params: P
+
+ def __init__(
+ self,
+ node: Node,
+ path: PurePath,
+ name: str | None = None,
+ privileged: bool = False,
+ app_params: P | str = "",
+ ) -> None:
+ """Constructor.
+
+ Args:
+ node: The node to run the app on.
+ path: Path to the application on the node.
+ name: Name to identify this application.
+ privileged: Run as privileged user.
+ app_params: The application parameters. Can be of any type inheriting :class:`Params` or
+ a plain string.
+ """
+ if isinstance(app_params, str):
+ params = Params()
+ params.append_str(app_params)
+ app_params = cast(P, params)
+
+ self._path = path
+
+ super().__init__(node, name, privileged, app_params)
+
+ @property
+ def path(self) -> PurePath:
+ """The path of the DPDK app relative to the DPDK build folder."""
+ return self._path
+
+ def wait_until_ready(self, end_token: str) -> Self:
+ """Start app and wait until ready.
+
+ Args:
+ end_token: The string at the end of a line that indicates the app is ready.
+
+ Returns:
+ Itself.
+ """
+ self.start_application(end_token)
+ return self
+
+ def close(self) -> None:
+ """Close the application.
+
+ Sends a SIGINT to close the application.
+ """
+ self.send_command("\x03")
+ super().close()
+
+
+PE = TypeVar("PE", bound=EalParams)
+
+
+class BlockingDPDKApp(BlockingApp, Generic[PE]):
+ """Class to manage blocking DPDK apps on the SUT."""
+
+ _app_params: PE
+
+ def __init__(
+ self,
+ path: PurePath,
+ name: str | None = None,
+ privileged: bool = True,
+ app_params: PE | str = "",
+ ) -> None:
+ """Constructor.
+
+ Args:
+ path: Path relative to the DPDK build to the executable.
+ name: Name to identify this application.
+ privileged: Run as privileged user.
+ app_params: The application parameters. If a string or an incomplete :class:`EalParams`
+ object are passed, the EAL params are computed based on the current context.
+ """
+ if isinstance(app_params, str):
+ eal_params = compute_eal_params()
+ eal_params.append_str(app_params)
+ app_params = cast(PE, eal_params)
+ else:
+ app_params = cast(PE, compute_eal_params(app_params))
+
+ node = get_ctx().sut_node
+ path = PurePath(get_ctx().dpdk_build.remote_dpdk_build_dir).joinpath(self.path)
+
+ super().__init__(node, path, name, privileged, app_params)
diff --git a/dts/framework/remote_session/dpdk_app.py b/dts/framework/remote_session/dpdk_app.py
deleted file mode 100644
index dc4b817bdd..0000000000
--- a/dts/framework/remote_session/dpdk_app.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# SPDX-License-Identifier: BSD-3-Clause
-# Copyright(c) 2025 Arm Limited
-
-"""Class to run blocking DPDK apps in the background.
-
-The class won't automatically start the app. The start-up is done as part of the
-:meth:`BlockingDPDKApp.wait_until_ready` method, which will return execution to the caller only
-when the desired stdout has been returned by the app. Usually this is used to detect when the app
-has been loaded and ready to be used.
-
-Example:
- ..code:: python
-
- pdump = BlockingDPDKApp(
- PurePath("app/dpdk-pdump"),
- app_params="--pdump 'port=0,queue=*,rx-dev=/tmp/rx-dev.pcap'"
- )
- pdump.wait_until_ready("65535") # start app
-
- # pdump is now ready to capture
-
- pdump.close() # stop/close app
-"""
-
-from pathlib import PurePath
-
-from framework.params.eal import EalParams
-from framework.remote_session.dpdk_shell import DPDKShell
-
-
-class BlockingDPDKApp(DPDKShell):
- """Class to manage blocking DPDK apps."""
-
- def __init__(
- self,
- path: PurePath,
- name: str | None = None,
- privileged: bool = True,
- app_params: EalParams | str = "",
- ) -> None:
- """Constructor.
-
- Overrides :meth:`~.dpdk_shell.DPDKShell.__init__`.
-
- Args:
- path: Path relative to the DPDK build to the executable.
- name: Name to identify this application.
- privileged: Run as privileged user.
- app_params: The application parameters. If a string or an incomplete :class:`EalParams`
- object are passed, the EAL params are computed based on the current context.
- """
- if isinstance(app_params, str):
- eal_params = EalParams()
- eal_params.append_str(app_params)
- app_params = eal_params
-
- self._path = path
-
- super().__init__(name, privileged, app_params)
-
- @property
- def path(self) -> PurePath:
- """The path of the DPDK app relative to the DPDK build folder."""
- return self._path
-
- def wait_until_ready(self, end_token: str) -> None:
- """Start app and wait until ready.
-
- Args:
- end_token: The string at the end of a line that indicates the app is ready.
- """
- self.start_application(end_token)
-
- def close(self) -> None:
- """Close the application.
-
- Sends a SIGINT to close the application.
- """
- self.send_command("\x03")
- super().close()
diff --git a/dts/tests/TestSuite_packet_capture.py b/dts/tests/TestSuite_packet_capture.py
index e162bded87..bad243a571 100644
--- a/dts/tests/TestSuite_packet_capture.py
+++ b/dts/tests/TestSuite_packet_capture.py
@@ -24,12 +24,10 @@
from scapy.layers.sctp import SCTP
from scapy.packet import Packet, Raw, raw
from scapy.utils import rdpcap
-from typing_extensions import Self
-from framework.context import get_ctx
from framework.params import Params
+from framework.remote_session.blocking_app import BlockingApp
from framework.remote_session.dpdk_shell import compute_eal_params
-from framework.remote_session.interactive_shell import InteractiveShell
from framework.remote_session.testpmd_shell import TestPmdShell
from framework.settings import SETTINGS
from framework.test_suite import TestSuite, func_test
@@ -61,57 +59,31 @@ class DumpcapParams(Params):
packet_filter: str | None = field(default=None, metadata=Params.short("f"))
-class Dumpcap(InteractiveShell):
- """Class to spawn and manage a dpdk-dumpcap process.
-
- The dpdk-dumpcap is a DPDK app but instead of providing a regular DPDK EAL interface to the
- user, it replicates the Wireshark dumpcap app.
- """
-
- _app_params: DumpcapParams
-
- def __init__(self, params: DumpcapParams) -> None:
- """Extends :meth:`~.interactive_shell.InteractiveShell.__init__`."""
- self.ctx = get_ctx()
- eal_params = compute_eal_params()
- params.lcore_list = eal_params.lcore_list
- params.file_prefix = eal_params.prefix
-
- super().__init__(self.ctx.sut_node, name=None, privileged=True, app_params=params)
-
- @property
- def path(self) -> PurePath:
- """Path to the shell executable."""
- return PurePath(self.ctx.dpdk_build.remote_dpdk_build_dir).joinpath("app/dpdk-dumpcap")
-
- def wait_until_ready(self) -> Self:
- """Start app and wait until ready."""
- self.start_application(f"Capturing on '{self._app_params.interface}'")
- return self
-
- def close(self) -> None:
- """Close the application.
-
- Sends a SIGINT to close the application.
- """
- self.send_command("\x03")
- super().close()
-
-
@requires(topology_type=TopologyType.two_links)
class TestPacketCapture(TestSuite):
"""Packet Capture TestSuite.
Attributes:
- packets: List of packets to send for testing pdump.
- rx_pcap_path: The remote path where to create the Rx packets pcap with pdump.
- tx_pcap_path: The remote path where to create the Tx packets pcap with pdump.
+ packets: List of packets to send for testing dumpcap.
+ rx_pcap_path: The remote path where to create the Rx packets pcap with dumpcap.
+ tx_pcap_path: The remote path where to create the Tx packets pcap with dumpcap.
"""
packets: list[Packet]
rx_pcap_path: PurePath
tx_pcap_path: PurePath
+ def _run_dumpcap(self, params: DumpcapParams) -> BlockingApp:
+ eal_params = compute_eal_params()
+ params.lcore_list = eal_params.lcore_list
+ params.file_prefix = eal_params.prefix
+ return BlockingApp(
+ self._ctx.sut_node,
+ self._ctx.dpdk_build.get_app("dumpcap"),
+ app_params=params,
+ privileged=True,
+ ).wait_until_ready(f"Capturing on '{params.interface}'")
+
def set_up_suite(self) -> None:
"""Test suite setup.
@@ -147,21 +119,21 @@ def _load_pcap_packets(self, remote_pcap_path: PurePath) -> list[Packet]:
def _send_and_dump(
self, packet_filter: str | None = None, rx_only: bool = False
) -> list[Packet]:
- dumpcap_rx = Dumpcap(
+ dumpcap_rx = self._run_dumpcap(
DumpcapParams(
interface=self.topology.sut_port_ingress.pci,
output_pcap_path=self.rx_pcap_path,
packet_filter=packet_filter,
)
- ).wait_until_ready()
+ )
if not rx_only:
- dumpcap_tx = Dumpcap(
+ dumpcap_tx = self._run_dumpcap(
DumpcapParams(
interface=self.topology.sut_port_egress.pci,
output_pcap_path=self.tx_pcap_path,
packet_filter=packet_filter,
)
- ).wait_until_ready()
+ )
received_packets = self.send_packets_and_capture(
self.packets, PacketFilteringConfig(no_lldp=False)
--
2.43.0
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 1/2] dts: remove dpdk example build function
2025-07-04 15:29 ` [PATCH v2 1/2] dts: remove dpdk example build function Luca Vizzarro
@ 2025-07-04 16:36 ` Patrick Robb
0 siblings, 0 replies; 12+ messages in thread
From: Patrick Robb @ 2025-07-04 16:36 UTC (permalink / raw)
To: Luca Vizzarro; +Cc: dev, Paul Szczepanek
[-- Attachment #1: Type: text/plain, Size: 2580 bytes --]
Applied to next-dts, thanks.
On Fri, Jul 4, 2025 at 11:30 AM Luca Vizzarro <luca.vizzarro@arm.com> wrote:
> Usage of example DPDK apps should be avoided. Therefore, remove
> the function that allows to build example apps. Moreover,
> provide a dedicated helper function to retrieve the path to a
> DPDK app.
>
> Signed-off-by: Luca Vizzarro <luca.vizzarro@arm.com>
> ---
> dts/framework/remote_session/dpdk.py | 33 +++-------------------------
> 1 file changed, 3 insertions(+), 30 deletions(-)
>
> diff --git a/dts/framework/remote_session/dpdk.py
> b/dts/framework/remote_session/dpdk.py
> index e00c4a9bf9..606d6e22fe 100644
> --- a/dts/framework/remote_session/dpdk.py
> +++ b/dts/framework/remote_session/dpdk.py
> @@ -267,36 +267,9 @@ def _build_dpdk(self) -> None:
> self.remote_dpdk_build_dir,
> )
>
> - def build_dpdk_app(self, app_name: str, **meson_dpdk_args: str |
> bool) -> PurePath:
> - """Build one or all DPDK apps.
> -
> - Requires DPDK to be already built on the SUT node.
> -
> - Args:
> - app_name: The name of the DPDK app to build.
> - When `app_name` is ``all``, build all example apps.
> - meson_dpdk_args: The arguments found in ``meson_options.txt``
> in root DPDK directory.
> - Do not use ``-D`` with them.
> -
> - Returns:
> - The directory path of the built app. If building all apps,
> return
> - the path to the examples directory (where all apps reside).
> - """
> - self._session.build_dpdk(
> - self._env_vars,
> - MesonArgs(examples=app_name, **meson_dpdk_args), # type:
> ignore [arg-type]
> - # ^^ https://github.com/python/mypy/issues/11583
> - self.remote_dpdk_tree_path,
> - self.remote_dpdk_build_dir,
> - rebuild=True,
> - timeout=self._app_compile_timeout,
> - )
> -
> - if app_name == "all":
> - return
> self._session.join_remote_path(self.remote_dpdk_build_dir, "examples")
> - return self._session.join_remote_path(
> - self.remote_dpdk_build_dir, "examples", f"dpdk-{app_name}"
> - )
> + def get_app(self, app_name: str) -> PurePath:
> + """Retrieve path for a DPDK app."""
> + return self._session.join_remote_path(self.remote_dpdk_build_dir,
> "app", f"dpdk-{app_name}")
>
> @cached_property
> def remote_dpdk_tree_path(self) -> PurePath:
> --
> 2.43.0
>
>
[-- Attachment #2: Type: text/html, Size: 3430 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2 2/2] dts: add generic blocking app class
2025-07-04 15:29 ` [PATCH v2 2/2] dts: add generic blocking app class Luca Vizzarro
@ 2025-07-04 16:36 ` Patrick Robb
0 siblings, 0 replies; 12+ messages in thread
From: Patrick Robb @ 2025-07-04 16:36 UTC (permalink / raw)
To: Luca Vizzarro; +Cc: dev, Paul Szczepanek
[-- Attachment #1: Type: text/plain, Size: 13742 bytes --]
Applied to next-dts, thanks.
On Fri, Jul 4, 2025 at 11:30 AM Luca Vizzarro <luca.vizzarro@arm.com> wrote:
> Add a generic blocking app class to allow a test writer to run any app
> in the background. Make the original BlockingDPDKApp class inherit from
> this one. Implement the new BlockingApp class in the packet_capture test
> suite.
>
> Signed-off-by: Luca Vizzarro <luca.vizzarro@arm.com>
> Reviewed-by: Paul Szczepanek <paul.szczepanek@arm.com>
> ---
> dts/framework/remote_session/blocking_app.py | 135 +++++++++++++++++++
> dts/framework/remote_session/dpdk_app.py | 80 -----------
> dts/tests/TestSuite_packet_capture.py | 66 +++------
> 3 files changed, 154 insertions(+), 127 deletions(-)
> create mode 100644 dts/framework/remote_session/blocking_app.py
> delete mode 100644 dts/framework/remote_session/dpdk_app.py
>
> diff --git a/dts/framework/remote_session/blocking_app.py
> b/dts/framework/remote_session/blocking_app.py
> new file mode 100644
> index 0000000000..8de536c259
> --- /dev/null
> +++ b/dts/framework/remote_session/blocking_app.py
> @@ -0,0 +1,135 @@
> +# SPDX-License-Identifier: BSD-3-Clause
> +# Copyright(c) 2025 Arm Limited
> +
> +"""Class to run blocking apps in the background.
> +
> +The class won't automatically start the app. The start-up is done as part
> of the
> +:meth:`BlockingApp.wait_until_ready` method, which will return execution
> to the caller only
> +when the desired stdout has been returned by the app. Usually this is
> used to detect when the app
> +has been loaded and ready to be used.
> +
> +This module also provides the class :class:`BlockingDPDKApp` useful to
> run any DPDK app from the
> +DPDK build dir.
> +
> +Example:
> + ..code:: python
> +
> + pdump = BlockingDPDKApp(
> + PurePath("app/dpdk-pdump"),
> + app_params="--pdump 'port=0,queue=*,rx-dev=/tmp/rx-dev.pcap'"
> + )
> + pdump.wait_until_ready("65535") # start app
> +
> + # pdump is now ready to capture
> +
> + pdump.close() # stop/close app
> +"""
> +
> +from pathlib import PurePath
> +from typing import Generic, TypeVar, cast
> +
> +from typing_extensions import Self
> +
> +from framework.context import get_ctx
> +from framework.params import Params
> +from framework.params.eal import EalParams
> +from framework.remote_session.dpdk_shell import compute_eal_params
> +from framework.remote_session.interactive_shell import InteractiveShell
> +from framework.testbed_model.node import Node
> +
> +P = TypeVar("P", bound=Params)
> +
> +
> +class BlockingApp(InteractiveShell, Generic[P]):
> + """Class to manage generic blocking apps."""
> +
> + _app_params: P
> +
> + def __init__(
> + self,
> + node: Node,
> + path: PurePath,
> + name: str | None = None,
> + privileged: bool = False,
> + app_params: P | str = "",
> + ) -> None:
> + """Constructor.
> +
> + Args:
> + node: The node to run the app on.
> + path: Path to the application on the node.
> + name: Name to identify this application.
> + privileged: Run as privileged user.
> + app_params: The application parameters. Can be of any type
> inheriting :class:`Params` or
> + a plain string.
> + """
> + if isinstance(app_params, str):
> + params = Params()
> + params.append_str(app_params)
> + app_params = cast(P, params)
> +
> + self._path = path
> +
> + super().__init__(node, name, privileged, app_params)
> +
> + @property
> + def path(self) -> PurePath:
> + """The path of the DPDK app relative to the DPDK build folder."""
> + return self._path
> +
> + def wait_until_ready(self, end_token: str) -> Self:
> + """Start app and wait until ready.
> +
> + Args:
> + end_token: The string at the end of a line that indicates the
> app is ready.
> +
> + Returns:
> + Itself.
> + """
> + self.start_application(end_token)
> + return self
> +
> + def close(self) -> None:
> + """Close the application.
> +
> + Sends a SIGINT to close the application.
> + """
> + self.send_command("\x03")
> + super().close()
> +
> +
> +PE = TypeVar("PE", bound=EalParams)
> +
> +
> +class BlockingDPDKApp(BlockingApp, Generic[PE]):
> + """Class to manage blocking DPDK apps on the SUT."""
> +
> + _app_params: PE
> +
> + def __init__(
> + self,
> + path: PurePath,
> + name: str | None = None,
> + privileged: bool = True,
> + app_params: PE | str = "",
> + ) -> None:
> + """Constructor.
> +
> + Args:
> + path: Path relative to the DPDK build to the executable.
> + name: Name to identify this application.
> + privileged: Run as privileged user.
> + app_params: The application parameters. If a string or an
> incomplete :class:`EalParams`
> + object are passed, the EAL params are computed based on
> the current context.
> + """
> + if isinstance(app_params, str):
> + eal_params = compute_eal_params()
> + eal_params.append_str(app_params)
> + app_params = cast(PE, eal_params)
> + else:
> + app_params = cast(PE, compute_eal_params(app_params))
> +
> + node = get_ctx().sut_node
> + path =
> PurePath(get_ctx().dpdk_build.remote_dpdk_build_dir).joinpath(self.path)
> +
> + super().__init__(node, path, name, privileged, app_params)
> diff --git a/dts/framework/remote_session/dpdk_app.py
> b/dts/framework/remote_session/dpdk_app.py
> deleted file mode 100644
> index dc4b817bdd..0000000000
> --- a/dts/framework/remote_session/dpdk_app.py
> +++ /dev/null
> @@ -1,80 +0,0 @@
> -# SPDX-License-Identifier: BSD-3-Clause
> -# Copyright(c) 2025 Arm Limited
> -
> -"""Class to run blocking DPDK apps in the background.
> -
> -The class won't automatically start the app. The start-up is done as part
> of the
> -:meth:`BlockingDPDKApp.wait_until_ready` method, which will return
> execution to the caller only
> -when the desired stdout has been returned by the app. Usually this is
> used to detect when the app
> -has been loaded and ready to be used.
> -
> -Example:
> - ..code:: python
> -
> - pdump = BlockingDPDKApp(
> - PurePath("app/dpdk-pdump"),
> - app_params="--pdump 'port=0,queue=*,rx-dev=/tmp/rx-dev.pcap'"
> - )
> - pdump.wait_until_ready("65535") # start app
> -
> - # pdump is now ready to capture
> -
> - pdump.close() # stop/close app
> -"""
> -
> -from pathlib import PurePath
> -
> -from framework.params.eal import EalParams
> -from framework.remote_session.dpdk_shell import DPDKShell
> -
> -
> -class BlockingDPDKApp(DPDKShell):
> - """Class to manage blocking DPDK apps."""
> -
> - def __init__(
> - self,
> - path: PurePath,
> - name: str | None = None,
> - privileged: bool = True,
> - app_params: EalParams | str = "",
> - ) -> None:
> - """Constructor.
> -
> - Overrides :meth:`~.dpdk_shell.DPDKShell.__init__`.
> -
> - Args:
> - path: Path relative to the DPDK build to the executable.
> - name: Name to identify this application.
> - privileged: Run as privileged user.
> - app_params: The application parameters. If a string or an
> incomplete :class:`EalParams`
> - object are passed, the EAL params are computed based on
> the current context.
> - """
> - if isinstance(app_params, str):
> - eal_params = EalParams()
> - eal_params.append_str(app_params)
> - app_params = eal_params
> -
> - self._path = path
> -
> - super().__init__(name, privileged, app_params)
> -
> - @property
> - def path(self) -> PurePath:
> - """The path of the DPDK app relative to the DPDK build folder."""
> - return self._path
> -
> - def wait_until_ready(self, end_token: str) -> None:
> - """Start app and wait until ready.
> -
> - Args:
> - end_token: The string at the end of a line that indicates the
> app is ready.
> - """
> - self.start_application(end_token)
> -
> - def close(self) -> None:
> - """Close the application.
> -
> - Sends a SIGINT to close the application.
> - """
> - self.send_command("\x03")
> - super().close()
> diff --git a/dts/tests/TestSuite_packet_capture.py
> b/dts/tests/TestSuite_packet_capture.py
> index e162bded87..bad243a571 100644
> --- a/dts/tests/TestSuite_packet_capture.py
> +++ b/dts/tests/TestSuite_packet_capture.py
> @@ -24,12 +24,10 @@
> from scapy.layers.sctp import SCTP
> from scapy.packet import Packet, Raw, raw
> from scapy.utils import rdpcap
> -from typing_extensions import Self
>
> -from framework.context import get_ctx
> from framework.params import Params
> +from framework.remote_session.blocking_app import BlockingApp
> from framework.remote_session.dpdk_shell import compute_eal_params
> -from framework.remote_session.interactive_shell import InteractiveShell
> from framework.remote_session.testpmd_shell import TestPmdShell
> from framework.settings import SETTINGS
> from framework.test_suite import TestSuite, func_test
> @@ -61,57 +59,31 @@ class DumpcapParams(Params):
> packet_filter: str | None = field(default=None,
> metadata=Params.short("f"))
>
>
> -class Dumpcap(InteractiveShell):
> - """Class to spawn and manage a dpdk-dumpcap process.
> -
> - The dpdk-dumpcap is a DPDK app but instead of providing a regular
> DPDK EAL interface to the
> - user, it replicates the Wireshark dumpcap app.
> - """
> -
> - _app_params: DumpcapParams
> -
> - def __init__(self, params: DumpcapParams) -> None:
> - """Extends
> :meth:`~.interactive_shell.InteractiveShell.__init__`."""
> - self.ctx = get_ctx()
> - eal_params = compute_eal_params()
> - params.lcore_list = eal_params.lcore_list
> - params.file_prefix = eal_params.prefix
> -
> - super().__init__(self.ctx.sut_node, name=None, privileged=True,
> app_params=params)
> -
> - @property
> - def path(self) -> PurePath:
> - """Path to the shell executable."""
> - return
> PurePath(self.ctx.dpdk_build.remote_dpdk_build_dir).joinpath("app/dpdk-dumpcap")
> -
> - def wait_until_ready(self) -> Self:
> - """Start app and wait until ready."""
> - self.start_application(f"Capturing on
> '{self._app_params.interface}'")
> - return self
> -
> - def close(self) -> None:
> - """Close the application.
> -
> - Sends a SIGINT to close the application.
> - """
> - self.send_command("\x03")
> - super().close()
> -
> -
> @requires(topology_type=TopologyType.two_links)
> class TestPacketCapture(TestSuite):
> """Packet Capture TestSuite.
>
> Attributes:
> - packets: List of packets to send for testing pdump.
> - rx_pcap_path: The remote path where to create the Rx packets pcap
> with pdump.
> - tx_pcap_path: The remote path where to create the Tx packets pcap
> with pdump.
> + packets: List of packets to send for testing dumpcap.
> + rx_pcap_path: The remote path where to create the Rx packets pcap
> with dumpcap.
> + tx_pcap_path: The remote path where to create the Tx packets pcap
> with dumpcap.
> """
>
> packets: list[Packet]
> rx_pcap_path: PurePath
> tx_pcap_path: PurePath
>
> + def _run_dumpcap(self, params: DumpcapParams) -> BlockingApp:
> + eal_params = compute_eal_params()
> + params.lcore_list = eal_params.lcore_list
> + params.file_prefix = eal_params.prefix
> + return BlockingApp(
> + self._ctx.sut_node,
> + self._ctx.dpdk_build.get_app("dumpcap"),
> + app_params=params,
> + privileged=True,
> + ).wait_until_ready(f"Capturing on '{params.interface}'")
> +
> def set_up_suite(self) -> None:
> """Test suite setup.
>
> @@ -147,21 +119,21 @@ def _load_pcap_packets(self, remote_pcap_path:
> PurePath) -> list[Packet]:
> def _send_and_dump(
> self, packet_filter: str | None = None, rx_only: bool = False
> ) -> list[Packet]:
> - dumpcap_rx = Dumpcap(
> + dumpcap_rx = self._run_dumpcap(
> DumpcapParams(
> interface=self.topology.sut_port_ingress.pci,
> output_pcap_path=self.rx_pcap_path,
> packet_filter=packet_filter,
> )
> - ).wait_until_ready()
> + )
> if not rx_only:
> - dumpcap_tx = Dumpcap(
> + dumpcap_tx = self._run_dumpcap(
> DumpcapParams(
> interface=self.topology.sut_port_egress.pci,
> output_pcap_path=self.tx_pcap_path,
> packet_filter=packet_filter,
> )
> - ).wait_until_ready()
> + )
>
> received_packets = self.send_packets_and_capture(
> self.packets, PacketFilteringConfig(no_lldp=False)
> --
> 2.43.0
>
>
[-- Attachment #2: Type: text/html, Size: 16611 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2025-07-04 16:42 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-07-02 16:42 [PATCH 0/2] dts: add generic blocking app class Luca Vizzarro
2025-07-02 16:42 ` [PATCH 1/2] dts: add DPDK build app helper function Luca Vizzarro
2025-07-03 15:35 ` Dean Marx
2025-07-04 3:04 ` Patrick Robb
2025-07-02 16:42 ` [PATCH 2/2] dts: add generic blocking app class Luca Vizzarro
2025-07-03 15:35 ` Dean Marx
2025-07-04 3:23 ` Patrick Robb
2025-07-04 15:29 ` [PATCH v2 0/2] " Luca Vizzarro
2025-07-04 15:29 ` [PATCH v2 1/2] dts: remove dpdk example build function Luca Vizzarro
2025-07-04 16:36 ` Patrick Robb
2025-07-04 15:29 ` [PATCH v2 2/2] dts: add generic blocking app class Luca Vizzarro
2025-07-04 16:36 ` Patrick Robb
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).