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