1*7e138863SJeremy Spewock# SPDX-License-Identifier: BSD-3-Clause 2*7e138863SJeremy Spewock# Copyright(c) 2023-2024 University of New Hampshire 3*7e138863SJeremy Spewock 4*7e138863SJeremy Spewock"""Multi-segment packet scattering testing suite. 5*7e138863SJeremy Spewock 6*7e138863SJeremy SpewockThis testing suite tests the support of transmitting and receiving scattered packets. 7*7e138863SJeremy SpewockThis is shown by the Poll Mode Driver being able to forward 8*7e138863SJeremy Spewockscattered multi-segment packets composed of multiple non-contiguous memory buffers. 9*7e138863SJeremy SpewockTo ensure the receipt of scattered packets, 10*7e138863SJeremy Spewockthe DMA rings of the port's Rx queues must be configured 11*7e138863SJeremy Spewockwith mbuf data buffers whose size is less than the maximum length. 12*7e138863SJeremy Spewock 13*7e138863SJeremy SpewockIf it is the case that the Poll Mode Driver can forward scattered packets which it receives, 14*7e138863SJeremy Spewockthen this suffices to show the Poll Mode Driver is capable of both receiving and transmitting 15*7e138863SJeremy Spewockscattered packets. 16*7e138863SJeremy Spewock""" 17*7e138863SJeremy Spewock 18*7e138863SJeremy Spewockimport struct 19*7e138863SJeremy Spewock 20*7e138863SJeremy Spewockfrom scapy.layers.inet import IP # type: ignore[import] 21*7e138863SJeremy Spewockfrom scapy.layers.l2 import Ether # type: ignore[import] 22*7e138863SJeremy Spewockfrom scapy.packet import Raw # type: ignore[import] 23*7e138863SJeremy Spewockfrom scapy.utils import hexstr # type: ignore[import] 24*7e138863SJeremy Spewock 25*7e138863SJeremy Spewockfrom framework.remote_session.testpmd_shell import TestPmdForwardingModes, TestPmdShell 26*7e138863SJeremy Spewockfrom framework.test_suite import TestSuite 27*7e138863SJeremy Spewock 28*7e138863SJeremy Spewock 29*7e138863SJeremy Spewockclass TestPmdBufferScatter(TestSuite): 30*7e138863SJeremy Spewock """DPDK PMD packet scattering test suite. 31*7e138863SJeremy Spewock 32*7e138863SJeremy Spewock Configure the Rx queues to have mbuf data buffers 33*7e138863SJeremy Spewock whose sizes are smaller than the maximum packet size. 34*7e138863SJeremy Spewock Specifically, set mbuf data buffers to have a size of 2048 35*7e138863SJeremy Spewock to fit a full 1512-byte (CRC included) ethernet frame in a mono-segment packet. 36*7e138863SJeremy Spewock The testing of scattered packets is done by sending a packet 37*7e138863SJeremy Spewock whose length is greater than the size of the configured size of mbuf data buffers. 38*7e138863SJeremy Spewock There are a total of 5 packets sent within test cases 39*7e138863SJeremy Spewock which have lengths less than, equal to, and greater than the mbuf size. 40*7e138863SJeremy Spewock There are multiple packets sent with lengths greater than the mbuf size 41*7e138863SJeremy Spewock in order to test cases such as: 42*7e138863SJeremy Spewock 43*7e138863SJeremy Spewock 1. A single byte of the CRC being in a second buffer 44*7e138863SJeremy Spewock while the remaining 3 bytes are stored in the first buffer alongside packet data. 45*7e138863SJeremy Spewock 2. The entire CRC being stored in a second buffer 46*7e138863SJeremy Spewock while all of the packet data is stored in the first. 47*7e138863SJeremy Spewock 3. Most of the packet data being stored in the first buffer 48*7e138863SJeremy Spewock and a single byte of packet data stored in a second buffer alongside the CRC. 49*7e138863SJeremy Spewock """ 50*7e138863SJeremy Spewock 51*7e138863SJeremy Spewock def set_up_suite(self) -> None: 52*7e138863SJeremy Spewock """Set up the test suite. 53*7e138863SJeremy Spewock 54*7e138863SJeremy Spewock Setup: 55*7e138863SJeremy Spewock Verify that we have at least 2 port links in the current execution 56*7e138863SJeremy Spewock and increase the MTU of both ports on the traffic generator to 9000 57*7e138863SJeremy Spewock to support larger packet sizes. 58*7e138863SJeremy Spewock """ 59*7e138863SJeremy Spewock self.verify( 60*7e138863SJeremy Spewock len(self._port_links) > 1, 61*7e138863SJeremy Spewock "There must be at least two port links to run the scatter test suite", 62*7e138863SJeremy Spewock ) 63*7e138863SJeremy Spewock 64*7e138863SJeremy Spewock self.tg_node.main_session.configure_port_mtu(9000, self._tg_port_egress) 65*7e138863SJeremy Spewock self.tg_node.main_session.configure_port_mtu(9000, self._tg_port_ingress) 66*7e138863SJeremy Spewock 67*7e138863SJeremy Spewock def scatter_pktgen_send_packet(self, pktsize: int) -> str: 68*7e138863SJeremy Spewock """Generate and send a packet to the SUT then capture what is forwarded back. 69*7e138863SJeremy Spewock 70*7e138863SJeremy Spewock Generate an IP packet of a specific length and send it to the SUT, 71*7e138863SJeremy Spewock then capture the resulting received packet and extract its payload. 72*7e138863SJeremy Spewock The desired length of the packet is met by packing its payload 73*7e138863SJeremy Spewock with the letter "X" in hexadecimal. 74*7e138863SJeremy Spewock 75*7e138863SJeremy Spewock Args: 76*7e138863SJeremy Spewock pktsize: Size of the packet to generate and send. 77*7e138863SJeremy Spewock 78*7e138863SJeremy Spewock Returns: 79*7e138863SJeremy Spewock The payload of the received packet as a string. 80*7e138863SJeremy Spewock """ 81*7e138863SJeremy Spewock packet = Ether() / IP() / Raw() 82*7e138863SJeremy Spewock packet.getlayer(2).load = "" 83*7e138863SJeremy Spewock payload_len = pktsize - len(packet) - 4 84*7e138863SJeremy Spewock payload = ["58"] * payload_len 85*7e138863SJeremy Spewock # pack the payload 86*7e138863SJeremy Spewock for X_in_hex in payload: 87*7e138863SJeremy Spewock packet.load += struct.pack("=B", int("%s%s" % (X_in_hex[0], X_in_hex[1]), 16)) 88*7e138863SJeremy Spewock received_packets = self.send_packet_and_capture(packet) 89*7e138863SJeremy Spewock self.verify(len(received_packets) > 0, "Did not receive any packets.") 90*7e138863SJeremy Spewock load = hexstr(received_packets[0].getlayer(2), onlyhex=1) 91*7e138863SJeremy Spewock 92*7e138863SJeremy Spewock return load 93*7e138863SJeremy Spewock 94*7e138863SJeremy Spewock def pmd_scatter(self, mbsize: int) -> None: 95*7e138863SJeremy Spewock """Testpmd support of receiving and sending scattered multi-segment packets. 96*7e138863SJeremy Spewock 97*7e138863SJeremy Spewock Support for scattered packets is shown by sending 5 packets of differing length 98*7e138863SJeremy Spewock where the length of the packet is calculated by taking mbuf-size + an offset. 99*7e138863SJeremy Spewock The offsets used in the test are -1, 0, 1, 4, 5 respectively. 100*7e138863SJeremy Spewock 101*7e138863SJeremy Spewock Test: 102*7e138863SJeremy Spewock Start testpmd and run functional test with preset mbsize. 103*7e138863SJeremy Spewock """ 104*7e138863SJeremy Spewock testpmd = self.sut_node.create_interactive_shell( 105*7e138863SJeremy Spewock TestPmdShell, 106*7e138863SJeremy Spewock app_parameters=( 107*7e138863SJeremy Spewock "--mbcache=200 " 108*7e138863SJeremy Spewock f"--mbuf-size={mbsize} " 109*7e138863SJeremy Spewock "--max-pkt-len=9000 " 110*7e138863SJeremy Spewock "--port-topology=paired " 111*7e138863SJeremy Spewock "--tx-offloads=0x00008000" 112*7e138863SJeremy Spewock ), 113*7e138863SJeremy Spewock privileged=True, 114*7e138863SJeremy Spewock ) 115*7e138863SJeremy Spewock testpmd.set_forward_mode(TestPmdForwardingModes.mac) 116*7e138863SJeremy Spewock testpmd.start() 117*7e138863SJeremy Spewock 118*7e138863SJeremy Spewock for offset in [-1, 0, 1, 4, 5]: 119*7e138863SJeremy Spewock recv_payload = self.scatter_pktgen_send_packet(mbsize + offset) 120*7e138863SJeremy Spewock self._logger.debug(f"Payload of scattered packet after forwarding: \n{recv_payload}") 121*7e138863SJeremy Spewock self.verify( 122*7e138863SJeremy Spewock ("58 " * 8).strip() in recv_payload, 123*7e138863SJeremy Spewock f"Payload of scattered packet did not match expected payload with offset {offset}.", 124*7e138863SJeremy Spewock ) 125*7e138863SJeremy Spewock testpmd.stop() 126*7e138863SJeremy Spewock 127*7e138863SJeremy Spewock def test_scatter_mbuf_2048(self) -> None: 128*7e138863SJeremy Spewock """Run the :meth:`pmd_scatter` test with `mbsize` set to 2048.""" 129*7e138863SJeremy Spewock self.pmd_scatter(mbsize=2048) 130*7e138863SJeremy Spewock 131*7e138863SJeremy Spewock def tear_down_suite(self) -> None: 132*7e138863SJeremy Spewock """Tear down the test suite. 133*7e138863SJeremy Spewock 134*7e138863SJeremy Spewock Teardown: 135*7e138863SJeremy Spewock Set the MTU of the tg_node back to a more standard size of 1500. 136*7e138863SJeremy Spewock """ 137*7e138863SJeremy Spewock self.tg_node.main_session.configure_port_mtu(1500, self._tg_port_egress) 138*7e138863SJeremy Spewock self.tg_node.main_session.configure_port_mtu(1500, self._tg_port_ingress) 139