Skip to content

ndr: add performance test scenarios - #755

Merged
christophefontaine merged 5 commits into
DPDK:mainfrom
rjarry:ndr
Sep 24, 2026
Merged

christophefontaine merged 5 commits into
DPDK:mainfrom
rjarry:ndr

Conversation

@rjarry

@rjarry rjarry commented Sep 23, 2026

Copy link
Copy Markdown
Collaborator

Add an ndr/ directory holding self-contained performance test scenarios for grout. Each scenario is a pair of files sharing a base name: a grcli configuration applied on top of a partially configured grout (CPU affinity and the two physical ports p0/p1 already created), and a matching TRex stateless traffic profile. Together they fully describe what grout and a back-to-back TRex must do, so an external harness can discover them, configure grout, load the profile and run a bidirectional RFC 2544 throughput search.

Keep everything static with hardcoded MAC addresses, so the scenarios run without FRR and without ARP or NDP. This keeps them independent of the physical NIC addresses and prevents a top-of-rack switch from getting confused.

Cover plain IPv4 and IPv6 forwarding, a dual-stack mix, 802.1Q VLAN, an IMIX distribution, the SRv6 datapath (transit End, L3VPN with H.Encaps and End.DT4, reduced H.Encaps.Red, and uSID uDT4) and VXLAN in bridged and routed modes over both IPv4 and IPv6 underlays.

Since the traffic generation harness lives elsewhere, also ship a small dummy harness under ndr/harness/ that starts grout in test mode, creates the two ports as taps and replays a profile with scapy through a mock of the TRex API. It only checks that traffic is forwarded, but it lets a scenario be smoke-tested locally without TRex (make ndr-validate).

Include one small CLI change as an enabler: fdb add gains an optional vtep address, so static VXLAN L2VPN forwarding entries can be created without relying on learning.

The FDB API can already bind a static entry to a remote VXLAN VTEP, but
the "fdb add" command could not set it. Expose the vtep address as an
optional argument so static tunnel entries can be created from the CLI.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
Reviewed-by: Anthony Harivel <aharivel@redhat.com>
Add a home for self-contained non-drop-rate performance scenarios. Each
scenario is a pair of files sharing a base name: a grcli configuration
applied on top of a partially configured grout, and a TRex stateless
traffic profile. Together they describe what grout and a back-to-back
TRex must do, so an external harness can discover and run them as RFC
2544 Non-Drop Rate tests.

Also ship a small dummy harness that starts grout in test mode, creates
the two ports as taps and replays the profile with scapy through a mock
of the TRex API. It only checks that traffic is forwarded, but lets
a scenario be smoke-tested without any TRex.

Run the validation as part of the automated CI.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
Reviewed-by: Anthony Harivel <aharivel@redhat.com>
Cover the common forwarding paths with plain IPv4, plain IPv6,
a dual-stack mix, 802.1Q VLAN and an IMIX packet-size distribution.
These are the baseline throughput references the tunnel scenarios build
on.

All next hops are static with hardcoded MAC addresses so the tests run
without FRR, ARP or NDP and stay independent of the physical NIC
addresses.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
Reviewed-by: Anthony Harivel <aharivel@redhat.com>
Exercise the SRv6 datapath: a transit node doing plain End (rewrite the
destination and forward), and an L3VPN endpoint that encapsulates IPv4
into SRv6 one way and decapsulates with End.DT4 the other. Two variants
add the reduced encapsulation (H.Encaps.Red) and compressed SIDs (a uSID
uN transit followed by an End.DT4 endpoint).

Signed-off-by: Robin Jarry <rjarry@redhat.com>
Reviewed-by: Anthony Harivel <aharivel@redhat.com>
Exercise the VXLAN datapath in both bridged (L2VPN) and routed (L3VPN)
modes, each over an IPv4 and an IPv6 underlay. One side encapsulates and
the other decapsulates, so a single run covers both nodes.

The L3VPN scenarios follow the symmetric IRB model: the underlay stays
in the main VRF while the overlay lives in a separate tenant VRF, and
the VXLAN interface encapsulates through the main VRF. Keeping the two
apart stops the encapsulated outer packet from being routed back into
the tunnel. The overlay prefix is reached through an EVPN-style remote
next hop carrying the remote RMAC, and the VXLAN interface uses a fixed
local RMAC so decapsulated inner frames addressed to it are accepted and
routed.

The decap direction sweeps the outer UDP source port to spread the load
over the receive queues. Over an IPv6 underlay grout validates the outer
UDP checksum, so the field engine recomputes it in lockstep with the
swept port instead of relying on hardware offload, which corrupts the
inner IPv4 checksum on real NICs.

Signed-off-by: Robin Jarry <rjarry@redhat.com>
Comment thread ndr/ipv6.py
eth = Ether(src=TREX_P1_MAC, dst=GROUT_P1_MAC)
ip = IPv6(src=HOST_P1, dst=HOST_P0)

pkt = eth / ip / UDP(sport=1024, dport=1024, chksum=0)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Ipv6 scenarios send malformed traffic 🐞 Bug ≡ Correctness

ipv6.py, dualstack.py, and srv6_transit.py explicitly set IPv6 UDP checksums to zero while
sport_vm() rewrites only UDP.sport without repairing the checksum. Once TRex sweeps the source
port, packets can be discarded before the forwarding path is measured, affecting the standalone IPv6
stream, half of each equal-rate dual-stack run, and both segment-routing transit directions, while
the IPv4 stream may retain its legal zero checksum.
Agent Prompt
## Issue description
The standalone IPv6, dual-stack IPv6, and segment-routing profiles generate IPv6 UDP packets with a zero checksum, then sweep the UDP source port without updating the checksum. The IPv4 dual-stack stream may retain its existing zero-checksum behavior.

## Fix Focus Areas
- ndr/ipv6.py[23-27]
- ndr/ipv6.py[39-43]
- ndr/dualstack.py[24-28]
- ndr/dualstack.py[43-51]
- ndr/srv6_transit.py[34-38]

## Recommended Fix
Build each IPv6 UDP packet with a valid computed checksum and update that checksum whenever the VM changes `UDP:0.sport`. Add the appropriate TRex VM checksum-recalculation instruction after each source-port write, or use the same bounded lockstep checksum-variable technique as the IPv6 VXLAN profiles. In `dualstack.py`, use a distinct valid-checksum packet builder and VM for the IPv6 stream while retaining the existing zero-checksum behavior only for IPv4.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@christophefontaine
christophefontaine merged commit 839089b into DPDK:main Sep 24, 2026
17 checks passed
@rjarry
rjarry deleted the ndr branch September 24, 2026 08:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants