# SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2024 Arm Limited """Base interactive shell for DPDK applications. Provides a base class to create interactive shells based on DPDK. """ from abc import ABC from pathlib import PurePath from framework.params.eal import EalParams from framework.remote_session.single_active_interactive_shell import ( SingleActiveInteractiveShell, ) from framework.settings import SETTINGS from framework.testbed_model.cpu import LogicalCoreCount, LogicalCoreList from framework.testbed_model.sut_node import SutNode def compute_eal_params( sut_node: SutNode, params: EalParams | None = None, lcore_filter_specifier: LogicalCoreCount | LogicalCoreList = LogicalCoreCount(), ascending_cores: bool = True, append_prefix_timestamp: bool = True, ) -> EalParams: """Compute EAL parameters based on the node's specifications. Args: sut_node: The SUT node to compute the values for. params: If :data:`None`, a new object is created and returned. Otherwise `params.lcore_list` is modified according to `lcore_filter_specifier`. A DPDK file prefix is also added. If `params.ports` is :data:`None`, then `sut_node.ports` is assigned to it. lcore_filter_specifier: A number of lcores/cores/sockets to use or a list of lcore ids to use. The default will select one lcore for each of two cores on one socket, in ascending order of core ids. ascending_cores: Sort cores in ascending order (lowest to highest IDs). If :data:`False`, sort in descending order. append_prefix_timestamp: If :data:`True`, will append a timestamp to DPDK file prefix. """ if params is None: params = EalParams() if params.lcore_list is None: params.lcore_list = LogicalCoreList( sut_node.filter_lcores(lcore_filter_specifier, ascending_cores) ) prefix = params.prefix if append_prefix_timestamp: prefix = f"{prefix}_{sut_node.dpdk_timestamp}" prefix = sut_node.main_session.get_dpdk_file_prefix(prefix) if prefix: sut_node.dpdk_prefix_list.append(prefix) params.prefix = prefix if params.allowed_ports is None: params.allowed_ports = sut_node.ports return params class DPDKShell(SingleActiveInteractiveShell, ABC): """The base class for managing DPDK-based interactive shells. This class shouldn't be instantiated directly, but instead be extended. It automatically injects computed EAL parameters based on the node in the supplied app parameters. """ _node: SutNode _app_params: EalParams def __init__( self, node: SutNode, privileged: bool = True, timeout: float = SETTINGS.timeout, lcore_filter_specifier: LogicalCoreCount | LogicalCoreList = LogicalCoreCount(), ascending_cores: bool = True, append_prefix_timestamp: bool = True, app_params: EalParams = EalParams(), name: str | None = None, ) -> None: """Extends :meth:`~.interactive_shell.InteractiveShell.__init__`. Adds the `lcore_filter_specifier`, `ascending_cores` and `append_prefix_timestamp` arguments which are then used to compute the EAL parameters based on the node's configuration. """ app_params = compute_eal_params( node, app_params, lcore_filter_specifier, ascending_cores, append_prefix_timestamp, ) super().__init__(node, privileged, timeout, app_params, name) def _update_real_path(self, path: PurePath) -> None: """Extends :meth:`~.interactive_shell.InteractiveShell._update_real_path`. Adds the remote DPDK build directory to the path. """ super()._update_real_path(PurePath(self._node.remote_dpdk_build_dir).joinpath(path))