1# SPDX-License-Identifier: BSD-3-Clause 2# Copyright(c) 2024 University of New Hampshire 3 4"""Test the support of VLAN Offload Features by Poll Mode Drivers. 5 6This test suite verifies that VLAN filtering, stripping, and header insertion all 7function as expected. When a VLAN ID is in the filter list, all packets with that 8ID should be forwarded and all others should be dropped. While stripping is enabled, 9packets sent with a VLAN ID should have the ID removed and then be forwarded. 10Additionally, when header insertion is enabled packets without a 11VLAN ID should have a specified ID inserted and then be forwarded. 12 13""" 14 15from scapy.layers.l2 import Dot1Q, Ether # type: ignore[import-untyped] 16from scapy.packet import Raw # type: ignore[import-untyped] 17 18from framework.remote_session.testpmd_shell import SimpleForwardingModes, TestPmdShell 19from framework.test_suite import TestSuite, func_test 20from framework.testbed_model.capability import NicCapability, TopologyType, requires 21 22 23@requires(NicCapability.RX_OFFLOAD_VLAN_FILTER) 24@requires(topology_type=TopologyType.two_links) 25class TestVlan(TestSuite): 26 """DPDK VLAN test suite. 27 28 Ensures VLAN packet reception, stripping, and insertion on the Poll Mode Driver 29 when the appropriate conditions are met. The suite contains four test cases: 30 31 1. VLAN reception no stripping - verifies that a VLAN packet with a tag 32 within the filter list is received. 33 2. VLAN reception stripping - verifies that a VLAN packet with a tag 34 within the filter list is received without the VLAN tag. 35 3. VLAN no reception - verifies that a VLAN packet with a tag not within 36 the filter list is dropped. 37 4. VLAN insertion - verifies that a non VLAN packet is received with a VLAN 38 tag when insertion is enabled. 39 """ 40 41 def send_vlan_packet_and_verify(self, should_receive: bool, strip: bool, vlan_id: int) -> None: 42 """Generate a VLAN packet, send and verify packet with same payload is received on the dut. 43 44 Args: 45 should_receive: Indicate whether the packet should be successfully received. 46 strip: If :data:`False`, will verify received packets match the given VLAN ID, 47 otherwise verifies that the received packet has no VLAN ID 48 (as it has been stripped off.) 49 vlan_id: Expected VLAN ID. 50 """ 51 packet = Ether() / Dot1Q(vlan=vlan_id) / Raw(load="xxxxx") 52 received_packets = self.send_packet_and_capture(packet) 53 test_packet = None 54 for packet in received_packets: 55 if hasattr(packet, "load") and b"xxxxx" in packet.load: 56 test_packet = packet 57 break 58 if should_receive: 59 self.verify( 60 test_packet is not None, "Packet was dropped when it should have been received" 61 ) 62 if test_packet is not None: 63 if strip: 64 self.verify( 65 not test_packet.haslayer(Dot1Q), "VLAN tag was not stripped successfully" 66 ) 67 else: 68 self.verify( 69 test_packet.vlan == vlan_id, 70 "The received tag did not match the expected tag", 71 ) 72 else: 73 self.verify( 74 test_packet is None, 75 "Packet was received when it should have been dropped", 76 ) 77 78 def send_packet_and_verify_insertion(self, expected_id: int) -> None: 79 """Generate a packet with no VLAN tag, send and verify on the dut. 80 81 Args: 82 expected_id: The VLAN id that is being inserted through tx_offload configuration. 83 """ 84 packet = Ether() / Raw(load="xxxxx") 85 received_packets = self.send_packet_and_capture(packet) 86 test_packet = None 87 for packet in received_packets: 88 if hasattr(packet, "load") and b"xxxxx" in packet.load: 89 test_packet = packet 90 break 91 self.verify(test_packet is not None, "Packet was dropped when it should have been received") 92 if test_packet is not None: 93 self.verify(test_packet.haslayer(Dot1Q), "The received packet did not have a VLAN tag") 94 self.verify( 95 test_packet.vlan == expected_id, "The received tag did not match the expected tag" 96 ) 97 98 def vlan_setup(self, testpmd: TestPmdShell, port_id: int, filtered_id: int) -> None: 99 """Setup method for all test cases. 100 101 Args: 102 testpmd: Testpmd shell session to send commands to. 103 port_id: Number of port to use for setup. 104 filtered_id: ID to be added to the VLAN filter list. 105 106 Returns: 107 TestPmdShell: Testpmd session being configured. 108 """ 109 testpmd.set_forward_mode(SimpleForwardingModes.mac) 110 testpmd.set_promisc(port_id, False) 111 testpmd.set_vlan_filter(port=port_id, enable=True) 112 testpmd.rx_vlan(vlan=filtered_id, port=port_id, add=True) 113 114 @func_test 115 def test_vlan_receipt_no_stripping(self) -> None: 116 """Verify packets are received with their VLAN IDs when stripping is disabled. 117 118 Test: 119 Create an interactive testpmd shell and verify a VLAN packet. 120 """ 121 with TestPmdShell(node=self.sut_node) as testpmd: 122 self.vlan_setup(testpmd=testpmd, port_id=0, filtered_id=1) 123 testpmd.start() 124 self.send_vlan_packet_and_verify(True, strip=False, vlan_id=1) 125 126 @requires(NicCapability.RX_OFFLOAD_VLAN_STRIP) 127 @func_test 128 def test_vlan_receipt_stripping(self) -> None: 129 """Ensure VLAN packet received with no tag when receipts and header stripping are enabled. 130 131 Test: 132 Create an interactive testpmd shell and verify a VLAN packet. 133 """ 134 with TestPmdShell(node=self.sut_node) as testpmd: 135 self.vlan_setup(testpmd=testpmd, port_id=0, filtered_id=1) 136 testpmd.set_vlan_strip(port=0, enable=True) 137 testpmd.start() 138 self.send_vlan_packet_and_verify(should_receive=True, strip=True, vlan_id=1) 139 140 @func_test 141 def test_vlan_no_receipt(self) -> None: 142 """Ensure VLAN packet dropped when filter is on and sent tag not in the filter list. 143 144 Test: 145 Create an interactive testpmd shell and verify a VLAN packet. 146 """ 147 with TestPmdShell(node=self.sut_node) as testpmd: 148 self.vlan_setup(testpmd=testpmd, port_id=0, filtered_id=1) 149 testpmd.start() 150 self.send_vlan_packet_and_verify(should_receive=False, strip=False, vlan_id=2) 151 152 @func_test 153 def test_vlan_header_insertion(self) -> None: 154 """Ensure that VLAN packet is received with the correct inserted VLAN tag. 155 156 Test: 157 Create an interactive testpmd shell and verify a non-VLAN packet. 158 """ 159 with TestPmdShell(node=self.sut_node) as testpmd: 160 testpmd.set_forward_mode(SimpleForwardingModes.mac) 161 testpmd.set_promisc(port=0, enable=False) 162 testpmd.stop_all_ports() 163 testpmd.tx_vlan_set(port=1, enable=True, vlan=51) 164 testpmd.start_all_ports() 165 testpmd.start() 166 self.send_packet_and_verify_insertion(expected_id=51) 167