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