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