DPDK patches and discussions
 help / color / mirror / Atom feed
From: Patrick Robb <probb@iol.unh.edu>
To: Thomas Wilks <thomas.wilks@arm.com>
Cc: dev@dpdk.org, Paul Szczepanek <paul.szczepanek@arm.com>,
	 Luca Vizzarro <luca.vizzarro@arm.com>
Subject: Re: [PATCH v2 2/6] dts: add utils for PMD RSS testsuites
Date: Sun, 13 Apr 2025 23:11:34 -0400	[thread overview]
Message-ID: <CAJvnSUBC1=Nv8oNkkyjjqYYCoEiy7akUAwyWbj=1rEyV6tjhdA@mail.gmail.com> (raw)
In-Reply-To: <20250225153345.331216-3-thomas.wilks@arm.com>

[-- Attachment #1: Type: text/plain, Size: 9466 bytes --]

Thanks Thomas and Alex.

On Tue, Feb 25, 2025 at 10:34 AM Thomas Wilks <thomas.wilks@arm.com> wrote:

> From: Alex Chapman <alex.chapman@arm.com>
>
> To reduce the amount of maintenance and code duplication,
> common functionality between the rss_key_update, pmd_rss_reta
> and pmd_rss_hash test suites has been collated into a single
> file called rss_utils.
>
> It contains 3 main functions:
> 1. verify that a packets RSS hash correctly associates with
>     the packets RSS queue.
> 2. Send test packets specific to RSS, such as symmetric
>     packets that have the L4 port src and dst swapped.
> 3. The setting up of the RSS environment which is common
>     between all 3 tets suites.
>

tets -> test.


> Signed-off-by: Alex Chapman <alex.chapman@arm.com>
> Signed-off-by: Thomas Wilks <thomas.wilks@arm.com>
>
> Reviewed-by: Paul Szczepanek <paul.szczepanek@arm.com>
> ---
>  dts/tests/pmd_rss_utils.py | 195 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 195 insertions(+)
>  create mode 100644 dts/tests/pmd_rss_utils.py
>
> diff --git a/dts/tests/pmd_rss_utils.py b/dts/tests/pmd_rss_utils.py
> new file mode 100644
> index 0000000000..2d9b333859
> --- /dev/null
> +++ b/dts/tests/pmd_rss_utils.py
> @@ -0,0 +1,195 @@
> +# SPDX-License-Identifier: BSD-3-Clause
> +# Copyright(c) 2025 Arm Limited
> +
> +"""PMD RSS Test Suite Utils.
> +
> +Utility functions for the pmd_rss_... test suite series
> +"""
> +
> +import random
> +
> +from scapy.layers.inet import IP, UDP
> +from scapy.layers.l2 import Ether
> +
> +from framework.exception import InteractiveCommandExecutionError
> +from framework.params.testpmd import SimpleForwardingModes
> +from framework.remote_session.testpmd_shell import (
> +    FlowRule,
> +    RSSOffloadTypesFlag,
> +    TestPmdShell,
> +    TestPmdVerbosePacket,
> +)
> +from framework.test_suite import TestSuite
> +
> +
> +def VerifyHashQueue(
>

Should be snake case - VerifyHashQueue -> verify_hash_queue.

And that applies to the later functions in this patch also.


> +    test_suite: TestSuite,
> +    reta: list[int],
> +    received_packets: list[TestPmdVerbosePacket],
> +    verify_packet_pairs: bool,
> +) -> None:
> +    """Verifies the packet hash corresponds to the packet queue.
> +
> +    Given the received packets in the verbose output, iterate through
> each packet.
> +    Lookup the packet hash in the RETA and get its intended queue.
> +    Verify the intended queue is the same as the actual queue the packet
> was received in.
> +    If the hash algorithm is symmetric, verify that pairs of packets have
> the same hash,
> +    as the pairs of packets sent have "mirrored" L4 ports.
> +    e.g. received_packets[0, 1, 2, 3, ...] hash(0) = hash(1), hash(2) =
> hash(3), ...
> +
> +    Args:
> +        test_suite: The reference to the currently running test suite.
> +        reta: Used to get predicted queue based on hash.
> +        received_packets: Packets received in the verbose output of
> testpmd.
> +        verify_packet_pairs: Verify pairs of packets have the same hash.
> +
> +    Raises:
> +        InteractiveCommandExecutionError: If packet_hash is None.
> +    """
> +    # List of packet hashes, used for symmetric algorithms
> +    hash_list = []
> +    for packet in received_packets:
> +        if packet.port_id != 0 or packet.src_mac != "02:00:00:00:00:00":
> +            continue
> +
> +        # Get packet hash
> +        packet_hash = packet.rss_hash
> +        if packet_hash is None:
> +            raise InteractiveCommandExecutionError(
> +                "Packet sent by the Traffic Generator has no RSS hash
> attribute."
> +            )
> +
> +        packet_queue = packet.rss_queue
> +
> +        # Calculate the predicted packet queue
> +        predicted_reta_index = packet_hash % len(reta)
> +        predicted_queue = reta[predicted_reta_index]
> +
> +        # Verify packets are in the correct queue
> +        test_suite.verify(
> +            predicted_queue == packet_queue,
> +            "Packet sent by the Traffic Generator has no RSS queue
> attribute.",
> +        )
> +
> +        if verify_packet_pairs:
> +            hash_list.append(packet_hash)
> +
> +    if verify_packet_pairs:
> +        # Go through pairs of hashes in list and verify they are the same
> +        for odd_hash, even_hash in zip(hash_list[0::2], hash_list[1::2]):
> +            test_suite.verify(
> +                odd_hash == even_hash,
> +                "Packet pair do not have same hash. Hash algorithm is not
> symmetric.",
> +            )
> +
> +
> +def SendTestPackets(
>

Aside from the snake case, I think this function name could more clearly
indicate its purpose as it relates to RSS functions.


> +    TestSuite: TestSuite,
> +    testpmd: TestPmdShell,
> +    send_additional_mirrored_packet: bool,
> +) -> list[TestPmdVerbosePacket]:
> +    """Sends test packets.
> +
> +    Send 10 packets from the TG to SUT, parsing the verbose output and
> returning it.
> +    If the algorithm chosen is symmetric, send an additional packet for
> each initial
> +    packet sent, which has the L4 src and dst swapped.
> +
> +    Args:
> +        TestSuite: The reference to the currently running test suite.
> +        testpmd: Used to send packets and send commands to testpmd.
> +        send_additional_mirrored_packet: Send an additional mirrored
> packet for each packet sent.
> +
> +    Returns:
> +        TestPmdVerbosePacket: List of packets.
> +    """
> +    # Create test packets
> +    packets = []
> +    for i in range(10):
> +        packets.append(
> +            Ether(src="02:00:00:00:00:00", dst="11:00:00:00:00:00")
> +            / IP()
> +            / UDP(sport=i, dport=i + 1),
> +        )
> +        if send_additional_mirrored_packet:  # If symmetric, send the
> inverse packets
> +            packets.append(
> +                Ether(src="02:00:00:00:00:00", dst="11:00:00:00:00:00")
> +                / IP()
> +                / UDP(sport=i + 1, dport=i),
> +            )
> +
> +    # Set verbose packet information and start packet capture
> +    testpmd.set_verbose(3)
> +    testpmd.start()
> +    testpmd.start_all_ports()
> +    TestSuite.send_packets_and_capture(packets)
> +
> +    # Stop packet capture and revert verbose packet information
> +    testpmd_shell_out = testpmd.stop()
> +    testpmd.set_verbose(0)
> +    # Parse the packets and return them
> +    return testpmd.extract_verbose_output(testpmd_shell_out)
> +
> +
> +def SetupRssEnvironment(
> +    TestSuite: TestSuite,
> +    testpmd: TestPmdShell,
> +    num_queues: int,
> +    flow_rule: FlowRule | None,
> +) -> tuple[list[int], int]:
> +    """Sets up the testpmd environment for RSS test suites.
> +
> +    This involves:
> +    1. Setting the testpmd forward mode to rx_only.
> +    2. Setting RSS on the NIC to UDP.
> +    3. Creating a flow if provided.
> +    4. Configuring RETA.
> +
> +    The reta and key_size of the NIC are then returned
> +
> +    Args:
> +        TestSuite: TestSuite environment.
> +        testpmd: Where the environment will be set.
> +        num_queues: Number of queues in the RETA table.
> +        flow_rule: The flow rule for altering packet fate.
> +
> +    Raises:
> +        InteractiveCommandExecutionError: If size of hash key for driver
> is None.
> +        InteractiveCommandExecutionError: If size of RETA table for
> driver is None.
> +
> +    Returns:
> +        reta: Configured Redirection Table.
> +        key_size: key size supported by NIC.
> +    """
> +    ports = []
> +    for port_id, _ in enumerate(TestSuite.topology.sut_ports):
> +        ports.append(port_id)
> +
> +    port_info = testpmd.show_port_info(ports[0])
> +
> +    # Get hash key size
> +    key_size = port_info.hash_key_size
> +    if key_size is None:
> +        raise InteractiveCommandExecutionError("Size of hash key for
> driver is None.")
> +
> +    # Get RETA table size
> +    reta_size = port_info.redirection_table_size
> +    if reta_size is None:
> +        raise InteractiveCommandExecutionError("Size of RETA table for
> driver is None.")
> +
> +    # Set forward mode to receive only, to remove forwarded packets from
> verbose output
> +    testpmd.set_forward_mode(SimpleForwardingModes.rxonly)
> +
> +    # Reset RSS settings and only RSS udp packets
> +    testpmd.port_config_all_rss_offload_type(RSSOffloadTypesFlag.udp)
> +
> +    # Create flow rule
> +    if flow_rule is not None:
> +        testpmd.flow_create(flow_rule, ports[0])
> +
> +    # Configure the RETA with random queues
> +    reta: list[int] = []
> +    for i in range(reta_size):
> +        reta.insert(i, random.randint(0, num_queues - 1))
> +        testpmd.port_config_rss_reta(ports[0], i, reta[i])
> +
> +    return reta, key_size
> --
> 2.43.0
>
>
Thanks, the function logic seems good.

I do want to reduce code duplication where possible, so having these
functions makes sense in principle. But, we have tried to maintain such
functions as a part of the testsuite class. So, I think that it would be
fine to move these functions to the testsuite class - but let me know what
you think.

Happy to discuss on Thursday at the DPDK CI meeting.

[-- Attachment #2: Type: text/html, Size: 11729 bytes --]

  reply	other threads:[~2025-04-14  3:15 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-29 12:50 [PATCH] dts: add RSS functions to testpmd Alex Chapman
2024-09-06 14:29 ` Juraj Linkeš
2025-02-25 15:33 ` [PATCH v2 0/6] Added RSS functions and tests Thomas Wilks
2025-02-25 15:33   ` [PATCH v2 1/6] dts: add RSS functions to testpmd Thomas Wilks
2025-04-14  3:11     ` Patrick Robb
2025-02-25 15:33   ` [PATCH v2 2/6] dts: add utils for PMD RSS testsuites Thomas Wilks
2025-04-14  3:11     ` Patrick Robb [this message]
2025-02-25 15:33   ` [PATCH v2 3/6] dts: add PMD RSS hash testsuite Thomas Wilks
2025-04-14  3:30     ` Patrick Robb
2025-02-25 15:33   ` [PATCH v2 4/6] dts: add PMD RSS RETA testsuite Thomas Wilks
2025-02-25 15:33   ` [PATCH v2 5/6] dts: add PMD RSS key update testsuite Thomas Wilks
2025-02-25 15:33   ` [PATCH v2 6/6] dts: add NIC capabilities for hash algorithms Thomas Wilks

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='CAJvnSUBC1=Nv8oNkkyjjqYYCoEiy7akUAwyWbj=1rEyV6tjhdA@mail.gmail.com' \
    --to=probb@iol.unh.edu \
    --cc=dev@dpdk.org \
    --cc=luca.vizzarro@arm.com \
    --cc=paul.szczepanek@arm.com \
    --cc=thomas.wilks@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).