Skip to content

bench: add performance test scenarios - #748

Draft
rjarry wants to merge 5 commits into
DPDK:mainfrom
rjarry:bench
Draft

rjarry wants to merge 5 commits into
DPDK:mainfrom
rjarry:bench

Conversation

@rjarry

@rjarry rjarry commented Sep 14, 2026

Copy link
Copy Markdown
Collaborator

Add a bench/ 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 bench/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 bench-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.

@rjarry
rjarry requested a review from aharivel September 14, 2026 21:42
Comment on lines +43 to +45
echo bench-validate
echo -------------------------------------------------------------------
time make bench-validate

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. Ci fails before benchmark validation 🐞 Bug ☼ Reliability

.github/workflows/check.sh invokes bench-validate, whose injector imports Scapy, but the
workflow dependency installation does not install it. Every normal matrix job reaches this command
on a clean runner, where the first scenario terminates with an import error.
Agent Prompt
## Issue description
Benchmark validation imports Scapy, but CI does not install the package, so clean CI jobs fail before testing any scenario.

## Fix Focus Areas
- .github/workflows/check.yml[83-94]
- .github/workflows/check.sh[43-45]

## Recommended Fix
Add the distribution's Python 3 Scapy package to the system dependencies installed by the normal check job before `bench-validate` runs.

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

Comment thread bench/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

2. Ipv6 benchmarks emit malformed packets 🐞 Bug ≡ Correctness

bench/ipv6.py, the IPv6 stream in bench/dualstack.py, and the segment-routing transit profile
explicitly construct packets with UDP(chksum=0), while sport_vm() rewrites UDP:0.sport without
a checksum-fix instruction. Every generated IPv6 flow therefore carries a malformed UDP checksum in
real TRex traffic, but the local smoke harness passes because these routed destinations bypass
grout's IPv6 local-delivery checksum validation.
Agent Prompt
## Issue description
`bench/ipv6.py`, the IPv6 stream in `bench/dualstack.py`, and `bench/srv6_transit.py` explicitly set zero UDP checksums on IPv6 packets and then vary the source port through `STLVM` without updating the checksum. Zero UDP checksums are invalid for IPv6, and every source-port mutation requires checksum recomputation.

## Fix Focus Areas
- bench/ipv6.py[23-27]
- bench/ipv6.py[39-43]
- bench/dualstack.py[24-28]
- bench/dualstack.py[42-50]
- bench/srv6_transit.py[34-38]
- bench/srv6_transit.py[50-56]

## Recommended Fix
Stop forcing zero UDP checksums for the affected IPv6 packets and add an IPv6-capable TRex checksum-fix VM instruction after each source-port write, such as the existing `fix_chksum_hw` pattern used by the VXLAN profiles. Ensure every generated IPv6 packet has a valid UDP checksum after mutation, while leaving the IPv4 streams' zero-checksum behavior unchanged.

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

@rjarry
rjarry force-pushed the bench branch 2 times, most recently from db8eb65 to ea7a1e3 Compare September 15, 2026 08:31
Comment thread bench/srv6_l3vpn.py
# inner IPv4 out p0.
#
# Ingress direction 0 is a 64-byte IPv4 frame; ingress direction 1 is
# Ether(14) + IPv6(40) + SRH(8 + 16) + IPv4(20) + UDP(8) = 106 bytes.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The code only show this:
Ether(14) + IPv6(40) + IPv4(20) + UDP(8) = 82 bytes

Comment thread GNUmakefile
if [ -n "$$failed" ]; then \
echo "FAILED: $$failed"; \
fi; \
exit "$$fail"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

exit $$(( fail > 0 )) is a bit more secure even if I don't know if we are going to have more than 125 scenarios :D

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 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 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. See bench/README.md.

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>
@rjarry
rjarry marked this pull request as draft September 17, 2026 14:19
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