xref: /dpdk/dts/framework/remote_session/dpdk_shell.py (revision cfa443351ef581b7189467842ca102ab710cb7d2)
1# SPDX-License-Identifier: BSD-3-Clause
2# Copyright(c) 2024 Arm Limited
3
4"""Base interactive shell for DPDK applications.
5
6Provides a base class to create interactive shells based on DPDK.
7"""
8
9
10from abc import ABC
11from pathlib import PurePath
12
13from framework.params.eal import EalParams
14from framework.remote_session.interactive_shell import InteractiveShell
15from framework.settings import SETTINGS
16from framework.testbed_model.cpu import LogicalCoreCount, LogicalCoreList
17from framework.testbed_model.sut_node import SutNode
18
19
20def compute_eal_params(
21    sut_node: SutNode,
22    params: EalParams | None = None,
23    lcore_filter_specifier: LogicalCoreCount | LogicalCoreList = LogicalCoreCount(),
24    ascending_cores: bool = True,
25    append_prefix_timestamp: bool = True,
26) -> EalParams:
27    """Compute EAL parameters based on the node's specifications.
28
29    Args:
30        sut_node: The SUT node to compute the values for.
31        params: If :data:`None`, a new object is created and returned. Otherwise `params.lcore_list`
32            is modified according to `lcore_filter_specifier`. A DPDK file prefix is also added. If
33            `params.ports` is :data:`None`, then `sut_node.ports` is assigned to it.
34        lcore_filter_specifier: A number of lcores/cores/sockets to use or a list of lcore ids to
35            use. The default will select one lcore for each of two cores on one socket, in ascending
36            order of core ids.
37        ascending_cores: Sort cores in ascending order (lowest to highest IDs). If :data:`False`,
38            sort in descending order.
39        append_prefix_timestamp: If :data:`True`, will append a timestamp to DPDK file prefix.
40    """
41    if params is None:
42        params = EalParams()
43
44    if params.lcore_list is None:
45        params.lcore_list = LogicalCoreList(
46            sut_node.filter_lcores(lcore_filter_specifier, ascending_cores)
47        )
48
49    prefix = params.prefix
50    if append_prefix_timestamp:
51        prefix = f"{prefix}_{sut_node.dpdk_timestamp}"
52    prefix = sut_node.main_session.get_dpdk_file_prefix(prefix)
53    if prefix:
54        sut_node.dpdk_prefix_list.append(prefix)
55    params.prefix = prefix
56
57    if params.ports is None:
58        params.ports = sut_node.ports
59
60    return params
61
62
63class DPDKShell(InteractiveShell, ABC):
64    """The base class for managing DPDK-based interactive shells.
65
66    This class shouldn't be instantiated directly, but instead be extended.
67    It automatically injects computed EAL parameters based on the node in the
68    supplied app parameters.
69    """
70
71    _node: SutNode
72    _app_params: EalParams
73
74    def __init__(
75        self,
76        node: SutNode,
77        privileged: bool = True,
78        timeout: float = SETTINGS.timeout,
79        lcore_filter_specifier: LogicalCoreCount | LogicalCoreList = LogicalCoreCount(),
80        ascending_cores: bool = True,
81        append_prefix_timestamp: bool = True,
82        start_on_init: bool = True,
83        app_params: EalParams = EalParams(),
84    ) -> None:
85        """Extends :meth:`~.interactive_shell.InteractiveShell.__init__`.
86
87        Adds the `lcore_filter_specifier`, `ascending_cores` and `append_prefix_timestamp` arguments
88        which are then used to compute the EAL parameters based on the node's configuration.
89        """
90        app_params = compute_eal_params(
91            node,
92            app_params,
93            lcore_filter_specifier,
94            ascending_cores,
95            append_prefix_timestamp,
96        )
97
98        super().__init__(node, privileged, timeout, start_on_init, app_params)
99
100    def _update_real_path(self, path: PurePath) -> None:
101        """Extends :meth:`~.interactive_shell.InteractiveShell._update_real_path`.
102
103        Adds the remote DPDK build directory to the path.
104        """
105        super()._update_real_path(self._node.remote_dpdk_build_dir.joinpath(path))
106