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