@@ -3,6 +3,8 @@
from pathlib import PurePath
from typing import Callable
+from framework.settings import SETTINGS
+import time
from .interactive_shell import InteractiveShell
@@ -29,7 +31,7 @@ def _start_application(
self, get_privileged_command: Callable[[str], str] | None
) -> None:
"""See "_start_application" in InteractiveShell."""
- self._app_args += " -- -i"
+ self._app_args += " -i"
super()._start_application(get_privileged_command)
def get_devices(self) -> list[TestPmdDevice]:
@@ -47,3 +49,29 @@ def get_devices(self) -> list[TestPmdDevice]:
if "device name:" in line.lower():
dev_list.append(TestPmdDevice(line))
return dev_list
+
+ def wait_link_status_up(self, port_id: int, timeout=SETTINGS.timeout) -> bool:
+ """Wait until the link status on the given port is "up".
+
+ Arguments:
+ port_id: Port to check the link status on.
+ timeout: time to wait for the link to come up.
+
+ Returns:
+ If the link came up in time or not.
+ """
+ time_to_stop = time.time() + timeout
+ while time.time() < time_to_stop:
+ port_info = self.send_command(f"show port info {port_id}")
+ if "Link status: up" in port_info:
+ break
+ time.sleep(0.5)
+ else:
+ self._logger.error(
+ f"The link for port {port_id} did not come up in the given timeout."
+ )
+ return "Link status: up" in port_info
+
+ def close(self) -> None:
+ self.send_command("exit", "")
+ return super().close()
@@ -17,6 +17,8 @@
LogicalCoreListFilter,
VirtualDevice,
lcore_filter,
+ Port,
+ PortLink
)
from .node import Node
from .sut_node import SutNode
@@ -12,6 +12,7 @@
LogicalCoreListFilter,
)
from .virtual_device import VirtualDevice
+from .port import Port, PortLink
def lcore_filter(
@@ -27,6 +27,7 @@ class Port:
Example: mlx5_core
peer: The identifier of a port this port is connected with.
+ logical_name: The logical name of the port (e.g. ens162)
"""
identifier: PortIdentifier
@@ -35,6 +36,7 @@ class Port:
peer: PortIdentifier
mac_address: str = ""
logical_name: str = ""
+ _id: int | None
def __init__(self, node_name: str, config: PortConfig):
self.identifier = PortIdentifier(
@@ -44,6 +46,7 @@ def __init__(self, node_name: str, config: PortConfig):
self.os_driver = config.os_driver
self.os_driver_for_dpdk = config.os_driver_for_dpdk
self.peer = PortIdentifier(node=config.peer_node, pci=config.peer_pci)
+ self._id = None
@property
def node(self) -> str:
@@ -53,6 +56,12 @@ def node(self) -> str:
def pci(self) -> str:
return self.identifier.pci
+ @property
+ def id(self) -> int:
+ if self._id is None:
+ self._id = self.pci.split(".")[-1]
+ return self._id
+
@dataclass(slots=True, frozen=True)
class PortLink:
@@ -360,6 +360,7 @@ def create_interactive_shell(
timeout: float = SETTINGS.timeout,
privileged: bool = False,
eal_parameters: EalParameters | str | None = None,
+ app_parameters: str | None = None
) -> InteractiveShellType:
"""Factory method for creating a handler for an interactive session.
@@ -374,6 +375,8 @@ def create_interactive_shell(
eal_parameters: List of EAL parameters to use to launch the app. If this
isn't provided or an empty string is passed, it will default to calling
create_eal_parameters().
+ app_parameters: Additional arguments to pass into the application on the
+ command-line.
Returns:
Instance of the desired interactive application.
"""
@@ -387,5 +390,5 @@ def create_interactive_shell(
)
return super().create_interactive_shell(
- shell_cls, timeout, privileged, str(eal_parameters)
+ shell_cls, timeout, privileged, f"{eal_parameters} -- {app_parameters}"
)
new file mode 100644
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2023 University of New Hampshire
+
+from framework.test_suite import TestSuite
+from framework.testbed_model import PortLink
+from framework.remote_session import TestPmdShell
+
+
+class Scatter(TestSuite):
+ port_link_for_testing: PortLink
+ mbsize: int
+
+ def set_up_suite(self) -> None:
+ self.verify(
+ len(self._port_links) > 0,
+ "Must have at least one port link to run scatter"
+ )
+ self.port_link_for_testing = self._port_links[0]
+ self.mbsize = 1024 # TODO: make this 2048 for some NICs like in old DTS
+ self.tg_node.main_session.send_command(
+ f"ifconfig {self.port_link_for_testing.tg_port.logical_name} mtu 9000"
+ )
+
+ def scatter_pktgen_send_packet(self, pktsize: int) -> None:
+ """Generate and send packet to the SUT.
+
+ Functional test for scatter packets.
+
+ Args:
+ pktsize: Size of the packet to generate and send.
+ """
+ dest_mac = self.port_link_for_testing.sut_port.mac_address
+ # TODO: Need to create the packet and then send it and receive
+
+ def test_scatter_mbuf_2048(self) -> None:
+ """
+ Test:
+ Start testpmd and run functional test with preset mbsize.
+ """
+ testpmd = self.sut_node.create_interactive_shell(
+ TestPmdShell,
+ app_parameters=f"--mbcache=200 \
+ --mbuf-size={self.mbsize} \
+ --portmask=0x1 \
+ --max-pkt-len=9000 \
+ --port-topology=loop \
+ --tx-offloads=0x00008000"
+ )
+ testpmd.send_command("set fwd mac")
+ testpmd.send_command("start")
+ link_is_up = testpmd.wait_link_status_up(self.port_link_for_testing.sut_port.id)
+ self.verify(link_is_up, "Link never came up in TestPMD.")
+
+ for offset in [-1, 0, 1, 4, 5]:
+ self.scatter_pktgen_send_packet(self.mbsize + offset)
+
+ testpmd.send_command("stop")
+
+ def tear_down_suite(self) -> None:
+ self.tg_node.main_session.send_command(
+ f"ifconfig {self.port_link_for_testing.tg_port.logical_name} mtu 1500"
+ )