17e138863SJeremy Spewock# SPDX-License-Identifier: BSD-3-Clause 27e138863SJeremy Spewock# Copyright(c) 2023-2024 University of New Hampshire 37e138863SJeremy Spewock 47e138863SJeremy Spewock"""Multi-segment packet scattering testing suite. 57e138863SJeremy Spewock 67e138863SJeremy SpewockThis testing suite tests the support of transmitting and receiving scattered packets. 77e138863SJeremy SpewockThis is shown by the Poll Mode Driver being able to forward 87e138863SJeremy Spewockscattered multi-segment packets composed of multiple non-contiguous memory buffers. 97e138863SJeremy SpewockTo ensure the receipt of scattered packets, 107e138863SJeremy Spewockthe DMA rings of the port's Rx queues must be configured 117e138863SJeremy Spewockwith mbuf data buffers whose size is less than the maximum length. 127e138863SJeremy Spewock 137e138863SJeremy SpewockIf it is the case that the Poll Mode Driver can forward scattered packets which it receives, 147e138863SJeremy Spewockthen this suffices to show the Poll Mode Driver is capable of both receiving and transmitting 157e138863SJeremy Spewockscattered packets. 167e138863SJeremy Spewock""" 177e138863SJeremy Spewock 187e138863SJeremy Spewockimport struct 197e138863SJeremy Spewock 20*282688eaSLuca Vizzarrofrom scapy.layers.inet import IP # type: ignore[import-untyped] 21*282688eaSLuca Vizzarrofrom scapy.layers.l2 import Ether # type: ignore[import-untyped] 22*282688eaSLuca Vizzarrofrom scapy.packet import Raw # type: ignore[import-untyped] 23*282688eaSLuca Vizzarrofrom scapy.utils import hexstr # type: ignore[import-untyped] 247e138863SJeremy Spewock 257e138863SJeremy Spewockfrom framework.remote_session.testpmd_shell import TestPmdForwardingModes, TestPmdShell 267e138863SJeremy Spewockfrom framework.test_suite import TestSuite 277e138863SJeremy Spewock 287e138863SJeremy Spewock 297e138863SJeremy Spewockclass TestPmdBufferScatter(TestSuite): 307e138863SJeremy Spewock """DPDK PMD packet scattering test suite. 317e138863SJeremy Spewock 327e138863SJeremy Spewock Configure the Rx queues to have mbuf data buffers 337e138863SJeremy Spewock whose sizes are smaller than the maximum packet size. 347e138863SJeremy Spewock Specifically, set mbuf data buffers to have a size of 2048 357e138863SJeremy Spewock to fit a full 1512-byte (CRC included) ethernet frame in a mono-segment packet. 367e138863SJeremy Spewock The testing of scattered packets is done by sending a packet 377e138863SJeremy Spewock whose length is greater than the size of the configured size of mbuf data buffers. 387e138863SJeremy Spewock There are a total of 5 packets sent within test cases 397e138863SJeremy Spewock which have lengths less than, equal to, and greater than the mbuf size. 407e138863SJeremy Spewock There are multiple packets sent with lengths greater than the mbuf size 417e138863SJeremy Spewock in order to test cases such as: 427e138863SJeremy Spewock 437e138863SJeremy Spewock 1. A single byte of the CRC being in a second buffer 447e138863SJeremy Spewock while the remaining 3 bytes are stored in the first buffer alongside packet data. 457e138863SJeremy Spewock 2. The entire CRC being stored in a second buffer 467e138863SJeremy Spewock while all of the packet data is stored in the first. 477e138863SJeremy Spewock 3. Most of the packet data being stored in the first buffer 487e138863SJeremy Spewock and a single byte of packet data stored in a second buffer alongside the CRC. 497e138863SJeremy Spewock """ 507e138863SJeremy Spewock 517e138863SJeremy Spewock def set_up_suite(self) -> None: 527e138863SJeremy Spewock """Set up the test suite. 537e138863SJeremy Spewock 547e138863SJeremy Spewock Setup: 557e138863SJeremy Spewock Verify that we have at least 2 port links in the current execution 567e138863SJeremy Spewock and increase the MTU of both ports on the traffic generator to 9000 577e138863SJeremy Spewock to support larger packet sizes. 587e138863SJeremy Spewock """ 597e138863SJeremy Spewock self.verify( 607e138863SJeremy Spewock len(self._port_links) > 1, 617e138863SJeremy Spewock "There must be at least two port links to run the scatter test suite", 627e138863SJeremy Spewock ) 637e138863SJeremy Spewock 647e138863SJeremy Spewock self.tg_node.main_session.configure_port_mtu(9000, self._tg_port_egress) 657e138863SJeremy Spewock self.tg_node.main_session.configure_port_mtu(9000, self._tg_port_ingress) 667e138863SJeremy Spewock 677e138863SJeremy Spewock def scatter_pktgen_send_packet(self, pktsize: int) -> str: 687e138863SJeremy Spewock """Generate and send a packet to the SUT then capture what is forwarded back. 697e138863SJeremy Spewock 707e138863SJeremy Spewock Generate an IP packet of a specific length and send it to the SUT, 717e138863SJeremy Spewock then capture the resulting received packet and extract its payload. 727e138863SJeremy Spewock The desired length of the packet is met by packing its payload 737e138863SJeremy Spewock with the letter "X" in hexadecimal. 747e138863SJeremy Spewock 757e138863SJeremy Spewock Args: 767e138863SJeremy Spewock pktsize: Size of the packet to generate and send. 777e138863SJeremy Spewock 787e138863SJeremy Spewock Returns: 797e138863SJeremy Spewock The payload of the received packet as a string. 807e138863SJeremy Spewock """ 817e138863SJeremy Spewock packet = Ether() / IP() / Raw() 827e138863SJeremy Spewock packet.getlayer(2).load = "" 837e138863SJeremy Spewock payload_len = pktsize - len(packet) - 4 847e138863SJeremy Spewock payload = ["58"] * payload_len 857e138863SJeremy Spewock # pack the payload 867e138863SJeremy Spewock for X_in_hex in payload: 877e138863SJeremy Spewock packet.load += struct.pack("=B", int("%s%s" % (X_in_hex[0], X_in_hex[1]), 16)) 887e138863SJeremy Spewock received_packets = self.send_packet_and_capture(packet) 897e138863SJeremy Spewock self.verify(len(received_packets) > 0, "Did not receive any packets.") 907e138863SJeremy Spewock load = hexstr(received_packets[0].getlayer(2), onlyhex=1) 917e138863SJeremy Spewock 927e138863SJeremy Spewock return load 937e138863SJeremy Spewock 947e138863SJeremy Spewock def pmd_scatter(self, mbsize: int) -> None: 957e138863SJeremy Spewock """Testpmd support of receiving and sending scattered multi-segment packets. 967e138863SJeremy Spewock 977e138863SJeremy Spewock Support for scattered packets is shown by sending 5 packets of differing length 987e138863SJeremy Spewock where the length of the packet is calculated by taking mbuf-size + an offset. 997e138863SJeremy Spewock The offsets used in the test are -1, 0, 1, 4, 5 respectively. 1007e138863SJeremy Spewock 1017e138863SJeremy Spewock Test: 1027e138863SJeremy Spewock Start testpmd and run functional test with preset mbsize. 1037e138863SJeremy Spewock """ 1047e138863SJeremy Spewock testpmd = self.sut_node.create_interactive_shell( 1057e138863SJeremy Spewock TestPmdShell, 1067e138863SJeremy Spewock app_parameters=( 1077e138863SJeremy Spewock "--mbcache=200 " 1087e138863SJeremy Spewock f"--mbuf-size={mbsize} " 1097e138863SJeremy Spewock "--max-pkt-len=9000 " 1107e138863SJeremy Spewock "--port-topology=paired " 1117e138863SJeremy Spewock "--tx-offloads=0x00008000" 1127e138863SJeremy Spewock ), 1137e138863SJeremy Spewock privileged=True, 1147e138863SJeremy Spewock ) 1157e138863SJeremy Spewock testpmd.set_forward_mode(TestPmdForwardingModes.mac) 1167e138863SJeremy Spewock testpmd.start() 1177e138863SJeremy Spewock 1187e138863SJeremy Spewock for offset in [-1, 0, 1, 4, 5]: 1197e138863SJeremy Spewock recv_payload = self.scatter_pktgen_send_packet(mbsize + offset) 1207e138863SJeremy Spewock self._logger.debug(f"Payload of scattered packet after forwarding: \n{recv_payload}") 1217e138863SJeremy Spewock self.verify( 1227e138863SJeremy Spewock ("58 " * 8).strip() in recv_payload, 1237e138863SJeremy Spewock f"Payload of scattered packet did not match expected payload with offset {offset}.", 1247e138863SJeremy Spewock ) 1257e138863SJeremy Spewock testpmd.stop() 1267e138863SJeremy Spewock 1277e138863SJeremy Spewock def test_scatter_mbuf_2048(self) -> None: 1287e138863SJeremy Spewock """Run the :meth:`pmd_scatter` test with `mbsize` set to 2048.""" 1297e138863SJeremy Spewock self.pmd_scatter(mbsize=2048) 1307e138863SJeremy Spewock 1317e138863SJeremy Spewock def tear_down_suite(self) -> None: 1327e138863SJeremy Spewock """Tear down the test suite. 1337e138863SJeremy Spewock 1347e138863SJeremy Spewock Teardown: 1357e138863SJeremy Spewock Set the MTU of the tg_node back to a more standard size of 1500. 1367e138863SJeremy Spewock """ 1377e138863SJeremy Spewock self.tg_node.main_session.configure_port_mtu(1500, self._tg_port_egress) 1387e138863SJeremy Spewock self.tg_node.main_session.configure_port_mtu(1500, self._tg_port_ingress) 139