@@ -246,7 +246,9 @@ def get_supported_capabilities(
for capability in capabilities:
if capability not in supported_capas or capability not in unsupported_capas:
capability.value(testpmd_shell, supported_capas, unsupported_capas)
- del testpmd_shell
+ testpmd_shell.close()
+ # it can take up to 3 seconds for a host to cleanup EAL before testpmd can be used again.
+ time.sleep(3)
return supported_capas
def _set_up_build_target(self, build_target_config: BuildTargetConfiguration) -> None:
@@ -16,14 +16,20 @@
"""
import struct
+import time
+from typing import ClassVar
from scapy.layers.inet import IP # type: ignore[import]
from scapy.layers.l2 import Ether # type: ignore[import]
-from scapy.packet import Raw # type: ignore[import]
+from scapy.packet import Packet, Raw # type: ignore[import]
from scapy.utils import hexstr # type: ignore[import]
-from framework.remote_session.testpmd_shell import TestPmdForwardingModes, TestPmdShell
-from framework.test_suite import TestSuite
+from framework.remote_session.testpmd_shell import (
+ NicCapability,
+ TestPmdForwardingModes,
+ TestPmdShell,
+)
+from framework.test_suite import TestSuite, requires
class TestPmdBufferScatter(TestSuite):
@@ -48,13 +54,22 @@ class TestPmdBufferScatter(TestSuite):
and a single byte of packet data stored in a second buffer alongside the CRC.
"""
+ #: Parameters for testing scatter using testpmd which are universal across all test cases.
+ base_testpmd_parameters: ClassVar[list[str]] = [
+ "--mbcache=200",
+ "--max-pkt-len=9000",
+ "--port-topology=paired",
+ "--tx-offloads=0x00008000",
+ ]
+
def set_up_suite(self) -> None:
"""Set up the test suite.
Setup:
- Verify that we have at least 2 port links in the current execution
- and increase the MTU of both ports on the traffic generator to 9000
- to support larger packet sizes.
+ Verify that we have at least 2 port links in the current execution and increase the MTU
+ of both ports on the traffic generator to 9000 to support larger packet sizes. The
+ traffic generator needs to send and receive packets that are, at most, as large as the
+ mbuf size of the ports + 5 in each test case, so 9000 should more than suffice.
"""
self.verify(
len(self._port_links) > 1,
@@ -64,19 +79,19 @@ def set_up_suite(self) -> None:
self.tg_node.main_session.configure_port_mtu(9000, self._tg_port_egress)
self.tg_node.main_session.configure_port_mtu(9000, self._tg_port_ingress)
- def scatter_pktgen_send_packet(self, pktsize: int) -> str:
+ def scatter_pktgen_send_packet(self, pktsize: int) -> list[Packet]:
"""Generate and send a packet to the SUT then capture what is forwarded back.
Generate an IP packet of a specific length and send it to the SUT,
- then capture the resulting received packet and extract its payload.
- The desired length of the packet is met by packing its payload
+ then capture the resulting received packets and filter them down to the ones that have the
+ correct layers. The desired length of the packet is met by packing its payload
with the letter "X" in hexadecimal.
Args:
pktsize: Size of the packet to generate and send.
Returns:
- The payload of the received packet as a string.
+ The filtered down list of received packets.
"""
packet = Ether() / IP() / Raw()
packet.getlayer(2).load = ""
@@ -86,48 +101,71 @@ def scatter_pktgen_send_packet(self, pktsize: int) -> str:
for X_in_hex in payload:
packet.load += struct.pack("=B", int("%s%s" % (X_in_hex[0], X_in_hex[1]), 16))
received_packets = self.send_packet_and_capture(packet)
+ # filter down the list to packets that have the appropriate structure
+ received_packets = list(
+ filter(lambda p: Ether in p and IP in p and Raw in p, received_packets)
+ )
self.verify(len(received_packets) > 0, "Did not receive any packets.")
- load = hexstr(received_packets[0].getlayer(2), onlyhex=1)
- return load
+ return received_packets
- def pmd_scatter(self, mbsize: int) -> None:
+ def pmd_scatter(self, mbsize: int, extra_testpmd_params: list[str] = []) -> None:
"""Testpmd support of receiving and sending scattered multi-segment packets.
Support for scattered packets is shown by sending 5 packets of differing length
where the length of the packet is calculated by taking mbuf-size + an offset.
The offsets used in the test are -1, 0, 1, 4, 5 respectively.
+ Args:
+ mbsize: Size to set memory buffers to when starting testpmd.
+ extra_testpmd_params: Additional parameters to add to the base list when starting
+ testpmd.
+
Test:
- Start testpmd and run functional test with preset mbsize.
+ Start testpmd and run functional test with preset `mbsize`.
"""
testpmd = self.sut_node.create_interactive_shell(
TestPmdShell,
- app_parameters=(
- "--mbcache=200 "
- f"--mbuf-size={mbsize} "
- "--max-pkt-len=9000 "
- "--port-topology=paired "
- "--tx-offloads=0x00008000"
+ app_parameters=" ".join(
+ [*self.base_testpmd_parameters, f"--mbuf-size={mbsize}", *extra_testpmd_params]
),
privileged=True,
)
testpmd.set_forward_mode(TestPmdForwardingModes.mac)
+ # adjust the MTU of the SUT ports to handle packets at least as large as `mbsize` + 5
+ for port_id in range(testpmd.number_of_ports):
+ testpmd.set_port_mtu(port_id, 9000)
testpmd.start()
for offset in [-1, 0, 1, 4, 5]:
- recv_payload = self.scatter_pktgen_send_packet(mbsize + offset)
- self._logger.debug(f"Payload of scattered packet after forwarding: \n{recv_payload}")
+ recv_packets = self.scatter_pktgen_send_packet(mbsize + offset)
+ self._logger.debug(f"Relevant captured packets: \n{recv_packets}")
+
self.verify(
- ("58 " * 8).strip() in recv_payload,
- f"Payload of scattered packet did not match expected payload with offset {offset}.",
+ any(
+ " ".join(["58"] * 8) in hexstr(pakt.getlayer(2), onlyhex=1)
+ for pakt in recv_packets
+ ),
+ "Payload of scattered packet did not match expected payload with offset "
+ f"{offset}.",
)
testpmd.stop()
-
+ # reset the MTU of the SUT ports
+ for port_id in range(testpmd.number_of_ports):
+ testpmd.set_port_mtu(port_id, 1500)
+ testpmd.close()
+ # it can take up to 3 seconds for a host to cleanup EAL before testpmd can be used again.
+ time.sleep(3)
+
+ @requires(NicCapability.scattered_rx)
def test_scatter_mbuf_2048(self) -> None:
"""Run the :meth:`pmd_scatter` test with `mbsize` set to 2048."""
self.pmd_scatter(mbsize=2048)
+ def test_scatter_mbuf_2048_with_offload(self) -> None:
+ """Run the :meth:`pmd_scatter` test with `mbsize` set to 2048 and rx_scatter offload."""
+ self.pmd_scatter(mbsize=2048, extra_testpmd_params=["--enable-scatter"])
+
def tear_down_suite(self) -> None:
"""Tear down the test suite.