1# SPDX-License-Identifier: BSD-3-Clause 2# Copyright(c) 2023 University of New Hampshire 3# Copyright(c) 2023 PANTHEON.tech s.r.o. 4 5"""Testpmd interactive shell. 6 7Typical usage example in a TestSuite:: 8 9 testpmd_shell = self.sut_node.create_interactive_shell( 10 TestPmdShell, privileged=True 11 ) 12 devices = testpmd_shell.get_devices() 13 for device in devices: 14 print(device) 15 testpmd_shell.close() 16""" 17 18from pathlib import PurePath 19from typing import Callable, ClassVar 20 21from .interactive_shell import InteractiveShell 22 23 24class TestPmdDevice(object): 25 """The data of a device that testpmd can recognize. 26 27 Attributes: 28 pci_address: The PCI address of the device. 29 """ 30 31 pci_address: str 32 33 def __init__(self, pci_address_line: str): 34 """Initialize the device from the testpmd output line string. 35 36 Args: 37 pci_address_line: A line of testpmd output that contains a device. 38 """ 39 self.pci_address = pci_address_line.strip().split(": ")[1].strip() 40 41 def __str__(self) -> str: 42 """The PCI address captures what the device is.""" 43 return self.pci_address 44 45 46class TestPmdShell(InteractiveShell): 47 """Testpmd interactive shell. 48 49 The testpmd shell users should never use 50 the :meth:`~.interactive_shell.InteractiveShell.send_command` method directly, but rather 51 call specialized methods. If there isn't one that satisfies a need, it should be added. 52 """ 53 54 #: The path to the testpmd executable. 55 path: ClassVar[PurePath] = PurePath("app", "dpdk-testpmd") 56 57 #: Flag this as a DPDK app so that it's clear this is not a system app and 58 #: needs to be looked in a specific path. 59 dpdk_app: ClassVar[bool] = True 60 61 #: The testpmd's prompt. 62 _default_prompt: ClassVar[str] = "testpmd>" 63 64 #: This forces the prompt to appear after sending a command. 65 _command_extra_chars: ClassVar[str] = "\n" 66 67 def _start_application(self, get_privileged_command: Callable[[str], str] | None) -> None: 68 self._app_args += " -- -i" 69 super()._start_application(get_privileged_command) 70 71 def get_devices(self) -> list[TestPmdDevice]: 72 """Get a list of device names that are known to testpmd. 73 74 Uses the device info listed in testpmd and then parses the output. 75 76 Returns: 77 A list of devices. 78 """ 79 dev_info: str = self.send_command("show device info all") 80 dev_list: list[TestPmdDevice] = [] 81 for line in dev_info.split("\n"): 82 if "device name:" in line.lower(): 83 dev_list.append(TestPmdDevice(line)) 84 return dev_list 85