DPDK patches and discussions
 help / color / mirror / Atom feed
From: Patrick Robb <probb@iol.unh.edu>
To: jspewock@iol.unh.edu
Cc: yoan.picchi@foss.arm.com, paul.szczepanek@arm.com,
	 juraj.linkes@pantheon.tech, Luca.Vizzarro@arm.com,
	 Honnappa.Nagarahalli@arm.com, thomas@monjalon.net,
	npratte@iol.unh.edu,  wathsala.vithanage@arm.com, dev@dpdk.org
Subject: Re: [PATCH v3 1/2] dts: add dual_vlan testing suite
Date: Wed, 11 Sep 2024 23:46:02 -0400	[thread overview]
Message-ID: <CAJvnSUCOQJccPc1-ZJ48=dod6gS1mYL5iQDccz2Au3W01FKdNQ@mail.gmail.com> (raw)
In-Reply-To: <20240724171345.341495-2-jspewock@iol.unh.edu>

Looks good other than updating the testpmd_shell method names

Reviewed-by: Patrick Robb <probb@iol.unh.edu>

On Wed, Jul 24, 2024 at 1:13 PM <jspewock@iol.unh.edu> wrote:
> +class TestDualVlan(TestSuite):
> +    """DPDK Dual VLAN test suite.
> +
> +    This suite tests the behavior of VLAN functions and properties in the presence of two VLAN
> +    headers. All VLAN functions which are tested in this suite are specified using the inner class
> +    :class:`TestCaseOptions` and should have cases for configuring them in
> +    :meth:`configure_testpmd` as well as cases for testing their behavior in
> +    :meth:`verify_vlan_functions`. Every combination of VLAN functions being enabled should be
> +    tested. Additionally, attributes of VLAN headers, such as priority, are tested to ensure they
> +    are not modified in the case of two VLAN headers.
> +    """
> +
> +    class TestCaseOptions(Flag):
> +        """Flag for specifying which VLAN functions to configure."""
> +
> +        #:
> +        VLAN_STRIP = auto()
> +        #:
> +        VLAN_FILTER_INNER = auto()
> +        #:
> +        VLAN_FILTER_OUTER = auto()

I think this can now be dropped and we can import VLANOffloadFlag from
testpmd_shell in its place.

> +
> +    #: ID to set on inner VLAN tags.
> +    inner_vlan_tag: ClassVar[int] = 2
> +    #: ID to set on outer VLAN tags.
> +    outer_vlan_tag: ClassVar[int] = 1
> +    #: ID to use when inserting VLAN tags.
> +    vlan_insert_tag: ClassVar[int] = 3
> +    #:
> +    rx_port: ClassVar[int] = 0
> +    #:
> +    tx_port: ClassVar[int] = 1
> +
> +    def is_relevant_packet(self, pkt: Packet) -> bool:
> +        """Check if a packet was sent by functions in this suite.
> +
> +        All functions in this test suite send packets with a payload that is packed with 20 "X"
> +        characters. This method, therefore, can determine if the packet was sent by this test suite
> +        by just checking to see if this payload exists on the received packet.
> +
> +        Args:
> +            pkt: Packet to check for relevancy.
> +
> +        Returns:
> +            :data:`True` if the packet contains the expected payload, :data:`False` otherwise.
> +        """
> +        return hasattr(pkt, "load") and "X" * 20 in str(pkt.load)
> +
> +    def pkt_payload_contains_layers(self, pkt: Packet, *expected_layers: Dot1Q) -> bool:
> +        """Verify that the payload of the packet matches `expected_layers`.
> +
> +        The layers in the payload of `pkt` must match the type and the user-defined fields of the
> +        layers in `expected_layers` in order.
> +
> +        Args:
> +            pkt: Packet to check the payload of.
> +            *expected_layers: Layers expected to be in the payload of `pkt`.
> +
> +        Returns:
> +            :data:`True` if the payload of `pkt` matches the layers in `expected_layers` in order,
> +            :data:`False` otherwise.
> +        """
> +        current_pkt_layer = pkt.payload
> +        ret = True
> +        for layer in expected_layers:
> +            ret &= isinstance(current_pkt_layer, type(layer))
> +            if not ret:
> +                break
> +            for field, val in layer.fields.items():
> +                ret &= (
> +                    hasattr(current_pkt_layer, field) and getattr(current_pkt_layer, field) == val
> +                )
> +            current_pkt_layer = current_pkt_layer.payload
> +        return ret
> +
> +    def verify_vlan_functions(self, send_packet: Packet, options: TestCaseOptions) -> None:
> +        """Send packet and verify the received packet has the expected structure.
> +
> +        Expected structure is defined by `options` according to the following table:
> +        +----------------------------------------------+-----------------------+
> +        |                  Configure setting           |       Result          |
> +        +=======+=======+========+============+========+=======+=======+=======+
> +        | Outer | Inner |  Vlan  |   Vlan     | Vlan   | Pass/ | Outer | Inner |
> +        | vlan  | vlan  |  strip |   filter   | insert | Drop  | vlan  | vlan  |
> +        +-------+-------+--------+------------+--------+-------+-------+-------+
> +        |  0x1  |  0x2  |   no   |     no     |   no   | pass  |  0x1  |  0x2  |
> +        +-------+-------+--------+------------+--------+-------+-------+-------+
> +        |  0x1  |  0x2  |  yes   |     no     |   no   | pass  |  no   |  0x2  |
> +        +-------+-------+--------+------------+--------+-------+-------+-------+
> +        |  0x1  |  0x2  |   no   |  yes,0x1   |   no   | pass  |  0x1  |  0x2  |
> +        +-------+-------+--------+------------+--------+-------+-------+-------+
> +        |  0x1  |  0x2  |   no   |  yes,0x2   |   no   | pass  |  0x1  |  0x2  |
> +        +-------+-------+--------+------------+--------+-------+-------+-------+
> +        |  0x1  |  0x2  |   no   | yes,0x1,0x2|   no   | pass  |  0x1  |  0x2  |
> +        +-------+-------+--------+------------+--------+-------+-------+-------+
> +        |  0x1  |  0x2  |  yes   |  yes,0x1   |   no   | pass  |  no   |  0x2  |
> +        +-------+-------+--------+------------+--------+-------+-------+-------+
> +        |  0x1  |  0x2  |  yes   |  yes,0x2   |   no   | pass  |  no   |  0x2  |
> +        +-------+-------+--------+------------+--------+-------+-------+-------+
> +        |  0x1  |  0x2  |  yes   | yes,0x1,0x2|   no   | pass  |  no   |  0x2  |
> +        +-------+-------+--------+------------+--------+-------+-------+-------+
> +
> +        Args:
> +            send_packet: Packet to send for testing.
> +            options: Flag which defines the currents configured settings in testpmd.
> +        """
> +        recv = self.send_packet_and_capture(send_packet)
> +        recv = list(filter(self.is_relevant_packet, recv))
> +        expected_layers: list[Packet] = []
> +
> +        if self.TestCaseOptions.VLAN_STRIP not in options:
> +            expected_layers.append(Dot1Q(vlan=self.outer_vlan_tag))
> +        expected_layers.append(Dot1Q(vlan=self.inner_vlan_tag))
> +
> +        self.verify(
> +            len(recv) > 0,
> +            f"Expected to receive packet with the payload {expected_layers} but got nothing.",
> +        )
> +
> +        for pkt in recv:
> +            self.verify(
> +                self.pkt_payload_contains_layers(pkt, *expected_layers),
> +                f"Received packet ({pkt.summary()}) did not match the expected sequence of layers "
> +                f"{expected_layers} with options {options}.",
> +            )
> +
> +    def configure_testpmd(self, shell: TestPmdShell, options: TestCaseOptions, add: bool) -> None:
> +        """Configure VLAN functions in testpmd based on `options`.
> +
> +        Args:
> +            shell: Testpmd session to configure the settings on. Expected to already be running
> +                with all ports stopped before being passed into this function.

Instead of having this requirement that all ports be stopped for the
testpmd session, we can just use testpmd_shell.requires_stopped_ports
decorator now.

> +            options: Settings to modify in `shell`.
> +            add: If :data:`True`, turn the settings in `options` on, otherwise turn them off.
> +        """
> +        if (
> +            self.TestCaseOptions.VLAN_FILTER_INNER in options
> +            or self.TestCaseOptions.VLAN_FILTER_OUTER in options
> +        ):
> +            if add:
> +                # If we are adding a filter, filtering has to be enabled first
> +                shell.vlan_filter_set(self.rx_port, True)
> +
> +            if self.TestCaseOptions.VLAN_FILTER_INNER in options:
> +                shell.rx_vlan(self.inner_vlan_tag, self.rx_port, add)
> +            if self.TestCaseOptions.VLAN_FILTER_OUTER in options:
> +                shell.rx_vlan(self.outer_vlan_tag, self.rx_port, add)
> +
> +            if not add:
> +                # If we are removing filters then we need to remove the filters before we can
> +                # disable filtering.
> +                shell.vlan_filter_set(self.rx_port, False)
> +        if self.TestCaseOptions.VLAN_STRIP in options:
> +            shell.vlan_strip_set(self.rx_port, add)
> +
> +    def test_insert_second_vlan(self) -> None:
> +        """Test that a packet with a single VLAN can have an additional one inserted into it."""
> +        with TestPmdShell(self.sut_node, forward_mode=SimpleForwardingModes.mac) as testpmd:
> +            testpmd.port_stop_all()

Should be testpmd.stop_all_ports() now per luca's pktegen/testpmd patch.

> +            testpmd.tx_vlan_set(self.tx_port, self.vlan_insert_tag)
> +            testpmd.port_start_all()

start_all_ports()

> +            testpmd.start()
> +            recv = self.send_packet_and_capture(
> +                Ether() / Dot1Q(vlan=self.outer_vlan_tag) / Raw("X" * 20)
> +            )
> +            self.verify(len(recv) > 0, "Did not receive any packets when testing VLAN insertion.")
> +            self.verify(
> +                any(
> +                    self.is_relevant_packet(p)
> +                    and self.pkt_payload_contains_layers(
> +                        p, *[Dot1Q(vlan=self.vlan_insert_tag), Dot1Q(vlan=self.outer_vlan_tag)]
> +                    )
> +                    for p in recv
> +                ),
> +                "Packet was unable to insert a second VLAN tag.",
> +            )
> +
> +    def test_all_vlan_functions(self) -> None:
> +        """Test that all combinations of :class:`TestCaseOptions` behave as expected.
> +
> +        To test this, the base case is tested first, ensuring that a packet with two VLANs is
> +        unchanged without the VLAN modification functions enabled. Then the same Testpmd shell is
> +        modified to enable all necessary VLAN functions, followed by verification that the
> +        functions work as expected, and finally the functions are disabled to allow for a clean
> +        environment for the next test.
> +        """
> +        send_pakt = (
> +            Ether()
> +            / Dot1Q(vlan=self.outer_vlan_tag)
> +            / Dot1Q(vlan=self.inner_vlan_tag)
> +            / Raw("X" * 20)
> +        )
> +        with TestPmdShell(self.sut_node, forward_mode=SimpleForwardingModes.mac) as testpmd:
> +            testpmd.start()
> +            recv = self.send_packet_and_capture(send_pakt)
> +            self.verify(len(recv) > 0, "Unmodified packet was not received.")
> +            self.verify(
> +                any(
> +                    self.is_relevant_packet(p)
> +                    and self.pkt_payload_contains_layers(
> +                        p, *[Dot1Q(vlan=self.outer_vlan_tag), Dot1Q(vlan=self.inner_vlan_tag)]
> +                    )
> +                    for p in recv
> +                ),
> +                "Packet was modified without any VLAN functions applied.",
> +            )
> +            testpmd.stop()
> +            testpmd.port_stop_all()

stop_all_ports(). I'll stop mentioning this below. :)

  parent reply	other threads:[~2024-09-12  3:46 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-07-15 19:58 [PATCH v1 0/3] dts: add test suite for dual VLANs jspewock
2024-07-15 19:58 ` [PATCH v1 1/3] dts: fix Testpmd function for resetting VLAN insertion jspewock
2024-07-15 19:58 ` [PATCH v1 2/3] dts: add dual_vlan testing suite jspewock
2024-07-22 17:38   ` Dean Marx
2024-07-25 13:56     ` Jeremy Spewock
2024-07-31 13:54       ` Jeremy Spewock
2024-07-15 19:58 ` [PATCH v1 3/3] dts: add dual_vlan test suite to the yaml schema jspewock
2024-07-16 21:24 ` [PATCH v2 0/2] dts: add test suite for dual VLANs jspewock
2024-07-16 21:24   ` [PATCH v2 1/2] dts: add dual_vlan testing suite jspewock
2024-08-07 19:07     ` Dean Marx
2024-07-16 21:24   ` [PATCH v2 2/2] dts: add dual_vlan test suite to the yaml schema jspewock
2024-07-24 17:13 ` [PATCH v3 0/2] dts: add test suite for dual VLANs jspewock
2024-07-24 17:13   ` [PATCH v3 1/2] dts: add dual_vlan testing suite jspewock
2024-08-13 19:47     ` Dean Marx
2024-09-12  3:46     ` Patrick Robb [this message]
2024-07-24 17:13   ` [PATCH v3 2/2] dts: add dual_vlan test suite to the yaml schema jspewock
2024-08-13 19:48     ` Dean Marx

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAJvnSUCOQJccPc1-ZJ48=dod6gS1mYL5iQDccz2Au3W01FKdNQ@mail.gmail.com' \
    --to=probb@iol.unh.edu \
    --cc=Honnappa.Nagarahalli@arm.com \
    --cc=Luca.Vizzarro@arm.com \
    --cc=dev@dpdk.org \
    --cc=jspewock@iol.unh.edu \
    --cc=juraj.linkes@pantheon.tech \
    --cc=npratte@iol.unh.edu \
    --cc=paul.szczepanek@arm.com \
    --cc=thomas@monjalon.net \
    --cc=wathsala.vithanage@arm.com \
    --cc=yoan.picchi@foss.arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).