Skip to content

Add VPP patch 0010: opt-in inner-aware flow hash for IPinIP/GRE/NVGRE#234

Merged
yue-fred-gao merged 4 commits into
sonic-net:masterfrom
yejianquan:inner-aware-flow-hash
May 29, 2026
Merged

Add VPP patch 0010: opt-in inner-aware flow hash for IPinIP/GRE/NVGRE#234
yue-fred-gao merged 4 commits into
sonic-net:masterfrom
yejianquan:inner-aware-flow-hash

Conversation

@yejianquan

@yejianquan yejianquan commented May 18, 2026

Copy link
Copy Markdown
Contributor

Why

Support vpp inner packet hash compute aware for sonic-net/sonic-buildimage#25762

This patch makes VPP's IPv4/IPv6 ECMP and bond LAG load-balancers hash on the inner header of IPinIP / 6in4 / 4in6 / 6in6 / GRE / NVGRE transit tunnels, so distinct inner flows between the same two tunnel endpoints distribute across paths and bond members instead of collapsing onto asingle path.

Design

Behaviour is fully opt-in on both surfaces:

  • IP layer (ECMP) — a new flow-hash bit IP_FLOW_HASH_PEEK_INNER (1<<9, CLI keyword peek_inner) in flow_hash_config_t. IP_FLOW_HASH_DEFAULT stays at 0x9F; when the bit is not set, ip4_compute_flow_hash and ip6_compute_flow_hash behave exactly as upstream.

  • LAG — a new load-balance algorithm BOND_API_LB_ALGO_L34_INNER = 6 in src/vnet/bonding/bond.api (CLI keyword l34-inner), backed by a new registered Ethernet hash function hash-eth-l34-inner (priority 50) in src/vnet/hash/hash_eth.c. The existingBOND_API_LB_ALGO_L34 = 1 and hash-eth-l34 are byte-for-byte unchanged, so any LAG that does not explicitly select l34-inner sees zero behaviour change and zero extra cost. This replaces the earlier in-place "always-on with safe fallback" edit of hash-eth-l34 in response toupstream review (Fred Wang, lolyu).

  • ABI compatibility for the new enum value is preserved by the [backwards_compatible] annotation: vppapigen excludes the new member from the CRCs of bond_create / bond_create2 / sw_interface_bond_details / sw_bond_interface_details, so a libsaivs built without the newvalue continues to link and run against a VPP built with it. The same mechanism is used by enum sr_behavior in src/vnet/srv6/sr_types.api and enum ipsec_crypto_alg in src/vnet/ipsec/ipsec_types.api.

  • Shared helpersrc/vnet/ip/ip_inner_aware_hash.h houses the inner-peek inlines used identically by all three hash surfaces (ip4_compute_flow_hash, ip6_compute_flow_hash, hash_eth_l34_inner). Every entry point takes a u32 remaining bound; outer-fragment packets areskipped; IPv6 inner extension headers (HBH/DST/ROUTE) are walked, and Fragment / AH / ESP cause a fall-back to outer-only hashing.

  • Out of scope — VxLAN (RFC 7348 §4.2) and Geneve (RFC 8926 §3.3) place inner-flow entropy in the outer UDP source port; SRv6 (RFC 6437 / RFC 8754 §7) places it in the IPv6 flow label. The existing outer-only hash already distributes those classes when the ingress generates theprescribed outer entropy.

Test coverage

  • Unit teststest/test_inner_aware_hash.py covers IPv4/IPv6 outer × IPv4/IPv6 inner, NVGRE, fragmented outer, truncated outer, IPv6 inner extension headers, a determinism check, and a regression-safety class TestLagL34LegacyOuterOnly that pins down that BOND_API_LB_ALGO_L34 / hash-eth-l34 are byte-for-byte unchanged after this patch.

  • Perf harnesstest/test_inner_aware_perf.py provides three packet-generator + show runtime measurement classes: PEEK_INNER on/off on ECMP, the new L34_INNER LAG algorithm with peek on, and the legacy L34 LAG algorithm as a side-by-side A/B baseline.

What this PR changes in this repo

  • vppbld/patches/0010-sonic-inner-aware-flow-hash.patch (new, 2849 lines, 13 files inside VPP, +2326 / -52)
  • vppbld/patches/series — adds the new patch with a 5-line scope comment listing in-scope encapsulations (IPinIP / 6in4 / 4in6 / 6in6 / GRE / NVGRE), out-of-scope ones (VxLAN / Geneve / SRv6), and the byte-for-byte-unchanged guarantee.

How to verify

Full sonic-mgmt tests/fib/test_fib.py suite on vms-kvm-vpp-t1-lag (regression r13):

Test Pre-patch Post-patch
test_basic_fib, test_hash[ipv4]/[ipv6], test_ecmp_group_member_flap PASS PASS
test_ipinip_hash[ipv4] / [ipv6] FAIL (single path) PASS
test_nvgre_hash[ipv4-*] / [ipv6-*] FAIL (single path) PASS
test_vxlan_hash[ipv4-*] / [ipv6-*] FAIL (LAG collapse) PASS
test_ipinip_hash_negative[ipv4] / [ipv6] PASS PASS

Result: 16 passed, 698 warnings, 2 errors in 7264.48s (2:01:04) — the 2 errors are syncd-shutdown teardown analyzer matches unrelated to flow hashing (they occur with or without this patch).

Companion changes (separate PRs)

vpp upstream PR: https://gerrit.fd.io/r/c/vpp/+/45864

@mssonicbld

Copy link
Copy Markdown

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@yejianquan yejianquan force-pushed the inner-aware-flow-hash branch from 18032d1 to f2da5f6 Compare May 18, 2026 01:59
@mssonicbld

Copy link
Copy Markdown

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@yejianquan

Copy link
Copy Markdown
Contributor Author

Will create PR to VPP upstream later

@yejianquan yejianquan force-pushed the inner-aware-flow-hash branch from f2da5f6 to f2f9182 Compare May 19, 2026 08:12
@mssonicbld

Copy link
Copy Markdown

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@yejianquan

Copy link
Copy Markdown
Contributor Author

vpp upstream PR: https://gerrit.fd.io/r/c/vpp/+/45864

@lolyu lolyu left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📊 Overview

Files Changed: 2 (vppbld/patches/0010-sonic-inner-aware-flow-hash.patch, rename from 0011→0010; vppbld/patches/README.md implied)
Lines: ~1927 in the patch file

VPP core patch implementing the inner-aware flow hash feature: new IP_FLOW_HASH_PEEK_INNER flag, shared ip_inner_aware_hash.h helper, changes to ip4/ip6_compute_flow_hash, hash_eth_l34_inline, VPP unit tests, and RST developer documentation.

✅ Strengths

  • ip_inner_resolve bounds checking is thorough throughout — every byte access is gated against the remaining counter, and all failure paths (truncated packet, unknown inner IP version, fragmented inner, unsupported GRE protocol type, unrecognised IPv6 extension header) set inner.valid = 0 and let the caller fall back to the outer-only hash. No crash path.
  • Fragment safety: IPv4 outer fragments correctly skip peeking (ip4_is_fragment guard); IPv6 outer fragments set outer_fragmented = 1 which blocks the peek_inner else-branch via the !outer_fragmented guard.
  • IP_FLOW_HASH_DEFAULT unchanged (0x9F) — the new bit is at position 9, cleanly outside all existing defaults. Zero behaviour change for any FIB that does not explicitly request peek_inner.
  • ABI preserved: no new BOND_API_LB_ALGO_* enumerator is introduced; hash-eth-l34 is extended in place, so no enum regeneration or CRC bump is needed on the libsaivs side.
  • 30+ VPP unit tests covering the full tunnel matrix (IPv4/IPv6 outer × IPv4/IPv6 inner, NVGRE, fragmented outer, truncated outer, IPv6 extension-header walk, determinism) plus a perf harness — excellent coverage.

📝 Review Findings

📝 Minor Issues

!PREDICT_FALSE(ip4_is_fragment(ip4)) idiom in hash_eth_l34_inline

if (!PREDICT_FALSE (ip4_is_fragment (ip4)))
{
    ...
    ip_inner_resolve (...);
}

The negation of PREDICT_FALSE is semantically correct but idiomatically unusual in VPP. The conventional expression is PREDICT_TRUE(!ip4_is_fragment(ip4)) or simply if (!ip4_is_fragment(ip4)) — both carry the same prediction hint that the non-fragment path is hot. Not a functional issue; purely a style nit.

IPv6 outer in hash_eth_l34_inline does not check for outer fragmentation before calling ip_inner_resolve

For the IPv6 LAG path, ip_inner_resolve is called directly with ip6->protocol without checking whether the outer IPv6 packet is a fragment (NH=44). In practice this is safe — if the outer IPv6 has a fragment extension header as its first next-header, ip6->protocol is 44, and ip_inner_resolve returns valid=0 for that unknown protocol, falling back to the outer hash. However the IPv4 path does explicitly guard with ip4_is_fragment, so the asymmetry is slightly surprising. A comment noting why the IPv6 path omits the explicit guard (i.e., ip_inner_resolve handles NH=44 safely via the fallback) would help future readers.

💡 Suggestions

  • The RST developer doc (inner_aware_hash.rst) and the patch commit message mention SRv6 is not handled, but only implicitly (SRH/NH=43 is not listed in the "walk outer IPv6 extension headers" section). A one-line note in §Testing or the RST doc that SRv6 outer falls back to outer-only hash would complete the exclusion story documented in the accompanying HLD (PR #235).

🧪 Testing

30+ unit test cases covering the full functional matrix, plus a perf harness — this is more coverage than most VPP patches carry. No gaps found.

Status

✅ Approved — clean implementation, thorough safety guards, minor style nit and one documentation suggestion only.

…_INNER algo

This patch makes VPP's IPv4/IPv6 ECMP and bond LAG load-balancers
hash on the inner header of IPinIP / 6in4 / 4in6 / 6in6 / GRE / NVGRE
transit tunnels, so distinct inner flows between the same two tunnel
endpoints distribute across paths and bond members instead of
collapsing onto a single path.

Behaviour is fully opt-in on both surfaces:

  * IP layer (ECMP) — a new flow-hash bit IP_FLOW_HASH_PEEK_INNER
    (1<<9, CLI keyword 'peek_inner') in flow_hash_config_t.
    IP_FLOW_HASH_DEFAULT stays at 0x9F; when the bit is not set,
    ip4_compute_flow_hash and ip6_compute_flow_hash behave exactly
    as upstream.

  * LAG — a NEW load-balance algorithm BOND_API_LB_ALGO_L34_INNER = 6
    in src/vnet/bonding/bond.api (CLI keyword 'l34-inner'), backed
    by a NEW registered Ethernet hash function 'hash-eth-l34-inner'
    (priority 50) in src/vnet/hash/hash_eth.c.  The existing
    BOND_API_LB_ALGO_L34 (= 1) and 'hash-eth-l34' are byte-for-byte
    unchanged, so any LAG that does not explicitly select 'l34-inner'
    sees zero behaviour change and zero extra cost.  This replaces
    the earlier in-place 'always-on with safe fallback' edit of
    hash-eth-l34 in response to upstream review (Fred Wang, lolyu).

  * ABI compatibility for the new enum value is preserved by the
    [backwards_compatible] annotation: vppapigen excludes the new
    member from the CRCs of bond_create / bond_create2 /
    sw_interface_bond_details / sw_bond_interface_details, so a
    libsaivs built without the new value continues to link and run
    against a VPP built with it.  The same mechanism is used by
    enum sr_behavior in src/vnet/srv6/sr_types.api and
    enum ipsec_crypto_alg in src/vnet/ipsec/ipsec_types.api.

  * A new helper src/vnet/ip/ip_inner_aware_hash.h houses the
    inner-peek inlines used identically by all three hash surfaces
    (ip4_compute_flow_hash, ip6_compute_flow_hash,
    hash_eth_l34_inner).  Every entry point takes a u32 'remaining'
    bound; outer-fragment packets are skipped; IPv6 inner extension
    headers (HBH/DST/ROUTE) are walked, and Fragment / AH / ESP
    cause a fall-back to outer-only hashing.

  * VxLAN, Geneve and SRv6 are intentionally out of scope.  VxLAN
    (RFC 7348 §4.2) and Geneve (RFC 8926 §3.3) place inner-flow
    entropy in the outer UDP source port; SRv6 (RFC 6437 / RFC
    8754 §7) places it in the IPv6 flow label.  The existing
    outer-only hash already distributes those classes when the
    ingress generates the prescribed outer entropy.

  * New VPP unit tests (test/test_inner_aware_hash.py) cover the
    on/off paths, IPv4/IPv6 outer x IPv4/IPv6 inner, NVGRE,
    fragmented outer, truncated outer, IPv6 inner extension
    headers, a determinism check, and a regression-safety class
    TestLagL34LegacyOuterOnly that pins down that
    BOND_API_LB_ALGO_L34 / hash-eth-l34 are byte-for-byte
    unchanged after this patch.

  * A perf harness (test/test_inner_aware_perf.py) provides three
    packet-generator + show-runtime measurement classes: PEEK_INNER
    on/off on ECMP, the new L34_INNER LAG algorithm with peek on,
    and the legacy L34 LAG algorithm as a side-by-side A/B baseline.

The patch is a single squashed file vppbld/patches/0010-sonic-inner-aware-flow-hash.patch
(2849 lines, 13 files inside VPP, +2326 / -52).

vppbld/patches/series gets a 5-line scope comment listing in-scope
encapsulations (IPinIP / 6in4 / 4in6 / 6in6 / GRE / NVGRE),
out-of-scope ones (VxLAN / Geneve / SRv6), and the byte-for-byte
unchanged guarantee for hash-eth-l34 and IP_FLOW_HASH_DEFAULT.

Verified end-to-end on vlab-vpp-01 (vms-kvm-vpp-t1-lag): the full
sonic-mgmt tests/fib/test_fib.py suite is 16/16 PASS (regression
r13), including test_ipinip_hash, test_nvgre_hash and
test_vxlan_hash that were previously skipped on sonic-vpp.

HLD: docs/HLD/vpp-inner-aware-flow-hash.md (branch
inner-aware-flow-hash-hld, separate PR).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Jianquan Ye <jianquanye@microsoft.com>
@yejianquan yejianquan force-pushed the inner-aware-flow-hash branch from f2f9182 to c6ace30 Compare May 22, 2026 11:12
@mssonicbld

Copy link
Copy Markdown

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@mssonicbld

Copy link
Copy Markdown

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@yue-fred-gao

Copy link
Copy Markdown
Contributor

hi @yejianquan , have you run sonic-mgmt sanity with this change? Please share the test result to make sure no breakage.

Comment thread vppbld/patches/0010-sonic-inner-aware-flow-hash.patch Outdated
Comment thread vppbld/patches/0011-sonic-inner-aware-flow-hash.patch
In response to Fred Wang's review (PR sonic-net#234, comment 1 -- "frag fix
should hop to outer-only hash"), the inner-aware flow-hash patch
0010 still hit the outer TCP/UDP `tcp->src/dst` read on the
non-peek branch even when `outer_fragmented = 1`.  On a fragmented
IPv6 outer carrying TCP/UDP, the payload after the IPv6 header is
not an L4 header at all -- it is a fragment continuation -- so the
read returned garbage source/dest ports and the hash diverged from
the un-fragmented-first-fragment case.

The corresponding fix in upstream VPP (vpp-upstream HEAD, amended
into the squashed inner-aware-flow-hash commit) is the 1-line guard
`if (!outer_fragmented && ...)` on the non-peek branch in
`src/vnet/ip/ip6_inlines.h`, plus an explanatory comment block
above it documenting the invariant.  Same as the existing peek_inner
branch right below it which already had a `!outer_fragmented` guard.

The regression test `TestSafetyEdges::test_outer_v6_fragmented_falls_back`
in `test/test_inner_aware_hash.py` pins this down: it sends an
outer-fragmented IPv6 packet, captures it on the output interface,
and asserts the hash equals the hash of the same packet with the
fragment header removed (i.e., outer-fragmented and unfragmented
forms hash identically because both fall back to outer L3-only).
Without the guard the test fails on three forwarding paths
(pg1=97 / pg2=73 / pg3=87 packets vs the 64 expected from a balanced
fall-back); with the guard all paths converge.

Net delta on the patch file:

  * ip6_inlines.h hunk:   +9 net dest-side lines
    (1 deleted `+if (TCP||UDP)` line -> 10 added lines = comment
     block + `else if (!outer_fragmented && ...)`)
    hunk header  -66,29 +77,76  ->  -66,29 +77,85

  * test/test_inner_aware_hash.py hunk:   +53 dest-side lines
    (new method appended before final `if __name__`)
    hunk header  -0,0 +1,1005  ->  -0,0 +1,1058

  * diff --stat: ip6_inlines.h 84 -> 93, test 1005 -> 1058,
    grand total +2326 -> +2388 insertions

Validated by clean clone of VPP at the pinned commit
435fda042e68ef90734ef5b3530c0a5b911a3bf8 + `git apply` of patches
0001..0010 in series order: exit 0.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Jianquan Ye <jianquanye@microsoft.com>
@yejianquan yejianquan force-pushed the inner-aware-flow-hash branch from 3fea8cb to 05d9791 Compare May 26, 2026 13:04
@mssonicbld

Copy link
Copy Markdown

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@mssonicbld

Copy link
Copy Markdown

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment thread vppbld/patches/0011-sonic-inner-aware-flow-hash.patch
@yejianquan

Copy link
Copy Markdown
Contributor Author

hi @yejianquan , have you run sonic-mgmt sanity with this change? Please share the test result to make sure no breakage.
Hi @yue-fred-gao , yeah, all of them passed.

sonic-mgmt fib/test_fib.py results

PASS test_basic_fib[True-True-1514]
PASS test_hash[ipv4]
PASS test_hash[ipv6]
PASS test_ipinip_hash[ipv4]
PASS test_ipinip_hash[ipv6]
PASS test_ipinip_hash_negative[ipv4]
PASS test_ipinip_hash_negative[ipv6]
PASS test_vxlan_hash[ipv4-ipv4]
PASS test_vxlan_hash[ipv6-ipv6]
PASS test_vxlan_hash[ipv6-ipv4]
PASS test_nvgre_hash[ipv4-ipv4]
PASS test_nvgre_hash[ipv4-ipv6]
PASS test_nvgre_hash[ipv6-ipv6]
PASS test_nvgre_hash[ipv6-ipv4]
PASS test_vxlan_hash[ipv4-ipv6] (body PASS, teardown ERROR*)
PASS test_ecmp_group_member_flap[True-False-1514] (body PASS, teardown ERROR*)

16 testcase bodies passed, 0 failed, 0 skipped.

(*) Both teardown ERRORs are infra-only: loganalyzer's
parallel_run fixture failed because core_uploader.py could
not reach the corefile collector proxy (-
timeout) to upload a pre-existing core file
syncd.1778467508.68.core dated 2026-04-09 — well before
this patch was deployed. The patch under test did not
generate any new core files (no fresh entries in /var/core
during the 2-hour run). These errors are unrelated to the
patch and have been seen in prior unrelated runs on
vlab-vpp-01.

Post-test sanity check: 5 passed, 1 skipped, 0 failed (no DUT regressions).

DUT verification artifacts (collected immediately after r13):

  • vppctl show bond: 8 BondEthernets all on l34-inner ✓
  • vppctl show hash: both hash-eth-l34-inner (new) and hash-eth-l34 (legacy, unchanged) registered ✓
  • vppctl show ip fib: peek_inner set on VRF:0 v4 ✓
  • BGP: 24/24 Established ✓
  • No new cores in /var/core/ ✓

@yue-fred-gao

Copy link
Copy Markdown
Contributor

Have you created fd.io PR? I think this is a valuable contribution. If it is merged, we don't have to deal with merge conflicts in the future. Please add the fd.io PR to the description.

@yue-fred-gao

Copy link
Copy Markdown
Contributor

please resolve the conflicts

PR sonic-net#238 (no-class-e-drop) merged ahead of this PR and claimed the
0010-* patch-file slot.  Rename our patch
0010-sonic-inner-aware-flow-hash.patch -> 0011-sonic-inner-aware-flow-hash.patch
and update vppbld/patches/series so that 0010-no-class-e-drop applies
first, then 0011-sonic-inner-aware-flow-hash.

Also brings in two HLD-only PRs that merged after the previous master
merge on this branch (9fa4107):
  - PR sonic-net#216: docs/HLD/vpp-mirror.md
  - PR sonic-net#236: docs/HLD/vpp-route-flow-counter.md

The two competing patches touch disjoint VPP source trees, so there
is no source-level conflict, only the series-file slot collision:

  - 0010-no-class-e-drop:    src/vnet/fib/ip4_fib.{c,h}, test/test_ip4.py
  - 0011-inner-aware-flow:   src/vnet/{bonding,hash,ip}/, test/test_inner_aware_*.py, docs

Validated by clean checkout of VPP at the pinned commit
435fda042e68ef90734ef5b3530c0a5b911a3bf8 + `git apply` of all 11
patches in series order: every patch returns exit 0.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Jianquan Ye <jianquanye@microsoft.com>
@mssonicbld

Copy link
Copy Markdown

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@yejianquan

Copy link
Copy Markdown
Contributor Author

Have you created fd.io PR? I think this is a valuable contribution. If it is merged, we don't have to deal with merge conflicts in the future. Please add the fd.io PR to the description.

Hi @yue-fred-gao , yeah: https://gerrit.fd.io/r/c/vpp/+/45864 all the changes are cherry-picked to the PR.
have resolved the conflict

@yue-fred-gao yue-fred-gao merged commit 756648b into sonic-net:master May 29, 2026
3 checks passed
yejianquan added a commit that referenced this pull request Jun 1, 2026
PR #234 added vppbld/patches/0011-sonic-inner-aware-flow-hash.patch
(introducing BOND_API_LB_ALGO_L34_INNER = 6 and the inner-aware ECMP/LAG
hash) but did not bump VPP_VERSION. The vppbld/Makefile keys its cache
lookup on VPP_VERSION_SONIC, so downstream sonic-buildimage builds keep
pulling the 2026-04-15 0.3+b1sonic1 debs from buildkite -- which were
built before patch 0011 existed. As soon as the matching sairedis
(PR #1896) lands and starts sending lb=6 to bond_create, the stale VPP
rejects the algo, no BondEthernets are created, and all LAG-side BGP
sessions stay in Active/Connect (failure visible in sonic-buildimage
PR #27621 CI).

Bump the minor suffix to 0.4 to invalidate the cache; downstream builds
will fall back to build_locally until buildkite is repopulated for 0.4.
Add an inline comment documenting the cache-key convention so the next
patch contributor does not repeat the miss.

Signed-off-by: Jianquan Ye <jianquanye@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
yejianquan added a commit that referenced this pull request Jun 1, 2026
PR #234 added vppbld/patches/0011-sonic-inner-aware-flow-hash.patch (introducing BOND_API_LB_ALGO_L34_INNER = 6 and the inner-aware ECMP/LAG hash) but did not bump VPP_VERSION. The vppbld/Makefile keys its cache lookup on VPP_VERSION_SONIC, so downstream sonic-buildimage builds keep pulling the 2026-04-15 0.3+b1sonic1 debs from buildkite -- which were built before patch 0011 existed. As soon as the matching sairedis (PR #1896) lands and starts sending lb=6 to bond_create, the stale VPP rejects the algo, no BondEthernets are created, and all LAG-side BGP sessions stay in Active/Connect (failure visible in sonic-buildimage PR #27621 CI).

Bump the minor suffix to 0.4 to invalidate the cache; downstream builds will fall back to build_locally until buildkite is repopulated for 0.4. Add an inline comment documenting the cache-key convention so the next patch contributor does not repeat the miss.

vppbld: bump VPP_VERSION 0.3 -> 0.4 to invalidate stale buildkite cache

signed-off-by: jianquanye@microsoft.com
lunyue-ms pushed a commit to lunyue-ms/sonic-platform-vpp that referenced this pull request Jun 2, 2026
…sonic-net#234)

* Add VPP patch 0010: opt-in inner-aware flow hash (ECMP) + new LAG L34_INNER algo

This patch makes VPP's IPv4/IPv6 ECMP and bond LAG load-balancers
hash on the inner header of IPinIP / 6in4 / 4in6 / 6in6 / GRE / NVGRE
transit tunnels, so distinct inner flows between the same two tunnel
endpoints distribute across paths and bond members instead of
collapsing onto a single path.

Behaviour is fully opt-in on both surfaces:

  * IP layer (ECMP) — a new flow-hash bit IP_FLOW_HASH_PEEK_INNER
    (1<<9, CLI keyword 'peek_inner') in flow_hash_config_t.
    IP_FLOW_HASH_DEFAULT stays at 0x9F; when the bit is not set,
    ip4_compute_flow_hash and ip6_compute_flow_hash behave exactly
    as upstream.

  * LAG — a NEW load-balance algorithm BOND_API_LB_ALGO_L34_INNER = 6
    in src/vnet/bonding/bond.api (CLI keyword 'l34-inner'), backed
    by a NEW registered Ethernet hash function 'hash-eth-l34-inner'
    (priority 50) in src/vnet/hash/hash_eth.c.  The existing
    BOND_API_LB_ALGO_L34 (= 1) and 'hash-eth-l34' are byte-for-byte
    unchanged, so any LAG that does not explicitly select 'l34-inner'
    sees zero behaviour change and zero extra cost.  This replaces
    the earlier in-place 'always-on with safe fallback' edit of
    hash-eth-l34 in response to upstream review (Fred Wang, lolyu).

  * ABI compatibility for the new enum value is preserved by the
    [backwards_compatible] annotation: vppapigen excludes the new
    member from the CRCs of bond_create / bond_create2 /
    sw_interface_bond_details / sw_bond_interface_details, so a
    libsaivs built without the new value continues to link and run
    against a VPP built with it.  The same mechanism is used by
    enum sr_behavior in src/vnet/srv6/sr_types.api and
    enum ipsec_crypto_alg in src/vnet/ipsec/ipsec_types.api.

  * A new helper src/vnet/ip/ip_inner_aware_hash.h houses the
    inner-peek inlines used identically by all three hash surfaces
    (ip4_compute_flow_hash, ip6_compute_flow_hash,
    hash_eth_l34_inner).  Every entry point takes a u32 'remaining'
    bound; outer-fragment packets are skipped; IPv6 inner extension
    headers (HBH/DST/ROUTE) are walked, and Fragment / AH / ESP
    cause a fall-back to outer-only hashing.

  * VxLAN, Geneve and SRv6 are intentionally out of scope.  VxLAN
    (RFC 7348 §4.2) and Geneve (RFC 8926 §3.3) place inner-flow
    entropy in the outer UDP source port; SRv6 (RFC 6437 / RFC
    8754 §7) places it in the IPv6 flow label.  The existing
    outer-only hash already distributes those classes when the
    ingress generates the prescribed outer entropy.

  * New VPP unit tests (test/test_inner_aware_hash.py) cover the
    on/off paths, IPv4/IPv6 outer x IPv4/IPv6 inner, NVGRE,
    fragmented outer, truncated outer, IPv6 inner extension
    headers, a determinism check, and a regression-safety class
    TestLagL34LegacyOuterOnly that pins down that
    BOND_API_LB_ALGO_L34 / hash-eth-l34 are byte-for-byte
    unchanged after this patch.

  * A perf harness (test/test_inner_aware_perf.py) provides three
    packet-generator + show-runtime measurement classes: PEEK_INNER
    on/off on ECMP, the new L34_INNER LAG algorithm with peek on,
    and the legacy L34 LAG algorithm as a side-by-side A/B baseline.

The patch is a single squashed file vppbld/patches/0010-sonic-inner-aware-flow-hash.patch
(2849 lines, 13 files inside VPP, +2326 / -52).

vppbld/patches/series gets a 5-line scope comment listing in-scope
encapsulations (IPinIP / 6in4 / 4in6 / 6in6 / GRE / NVGRE),
out-of-scope ones (VxLAN / Geneve / SRv6), and the byte-for-byte
unchanged guarantee for hash-eth-l34 and IP_FLOW_HASH_DEFAULT.

Verified end-to-end on vlab-vpp-01 (vms-kvm-vpp-t1-lag): the full
sonic-mgmt tests/fib/test_fib.py suite is 16/16 PASS (regression
r13), including test_ipinip_hash, test_nvgre_hash and
test_vxlan_hash that were previously skipped on sonic-vpp.

HLD: docs/HLD/vpp-inner-aware-flow-hash.md (branch
inner-aware-flow-hash-hld, separate PR).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Jianquan Ye <jianquanye@microsoft.com>

* patch 0010: fix outer-fragmented IPv6 fall-back in flow hash

In response to Fred Wang's review (PR sonic-net#234, comment 1 -- "frag fix
should hop to outer-only hash"), the inner-aware flow-hash patch
0010 still hit the outer TCP/UDP `tcp->src/dst` read on the
non-peek branch even when `outer_fragmented = 1`.  On a fragmented
IPv6 outer carrying TCP/UDP, the payload after the IPv6 header is
not an L4 header at all -- it is a fragment continuation -- so the
read returned garbage source/dest ports and the hash diverged from
the un-fragmented-first-fragment case.

The corresponding fix in upstream VPP (vpp-upstream HEAD, amended
into the squashed inner-aware-flow-hash commit) is the 1-line guard
`if (!outer_fragmented && ...)` on the non-peek branch in
`src/vnet/ip/ip6_inlines.h`, plus an explanatory comment block
above it documenting the invariant.  Same as the existing peek_inner
branch right below it which already had a `!outer_fragmented` guard.

The regression test `TestSafetyEdges::test_outer_v6_fragmented_falls_back`
in `test/test_inner_aware_hash.py` pins this down: it sends an
outer-fragmented IPv6 packet, captures it on the output interface,
and asserts the hash equals the hash of the same packet with the
fragment header removed (i.e., outer-fragmented and unfragmented
forms hash identically because both fall back to outer L3-only).
Without the guard the test fails on three forwarding paths
(pg1=97 / pg2=73 / pg3=87 packets vs the 64 expected from a balanced
fall-back); with the guard all paths converge.

Net delta on the patch file:

  * ip6_inlines.h hunk:   +9 net dest-side lines
    (1 deleted `+if (TCP||UDP)` line -> 10 added lines = comment
     block + `else if (!outer_fragmented && ...)`)
    hunk header  -66,29 +77,76  ->  -66,29 +77,85

  * test/test_inner_aware_hash.py hunk:   +53 dest-side lines
    (new method appended before final `if __name__`)
    hunk header  -0,0 +1,1005  ->  -0,0 +1,1058

  * diff --stat: ip6_inlines.h 84 -> 93, test 1005 -> 1058,
    grand total +2326 -> +2388 insertions

Validated by clean clone of VPP at the pinned commit
435fda042e68ef90734ef5b3530c0a5b911a3bf8 + `git apply` of patches
0001..0010 in series order: exit 0.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Jianquan Ye <jianquanye@microsoft.com>

---------

Signed-off-by: Jianquan Ye <jianquanye@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
yejianquan added a commit to sonic-net/sonic-mgmt that referenced this pull request Jun 8, 2026
#24721)

### Description of PR

Summary: Re-enable the three previously skipped tunnel-hashing tests for
the `vpp` `asic_type` now that VPP has **opt-in** inner-aware ECMP / LAG
flow hashing.

The two prerequisite changes that make these tests actually pass on
`vms-kvm-vpp-t1-lag`:

-
[sonic-net/sonic-platform-vpp#234](sonic-net/sonic-platform-vpp#234)
— vendors VPP patch `0010-sonic-inner-aware-flow-hash.patch`, which
registers the **new** opt-in `hash-eth-l34-inner` bond load-balance
function, the new `BOND_API_LB_ALGO_L34_INNER = 6` bond algorithm, and
the new `FLOW_HASH_PEEK_INNER` ECMP FIB bit. Stock `hash-eth-l34` and
the legacy `BOND_API_LB_ALGO_L34 = 1` are byte-for-byte unchanged.
-
[sonic-net/sonic-sairedis#1896](sonic-net/sonic-sairedis#1896)
— opts the `vslib/vpp` adapter into the new path: selects
`BOND_API_LB_ALGO_L34_INNER` in `vpp_create_lag` and OR's
`VPP_IP_API_FLOW_HASH_PEEK_INNER` into `vpp_add_ip_vrf` for both
`AF_INET` and `AF_INET6` (default + non-default VRFs).
- `sonic-net/sonic-buildimage` submodule bump for sonic-sairedis is a
separate routine PR once #1896 lands.

Fixes [#25762](#25762)

### Type of change

- [ ] Bug fix
- [ ] Testbed and Framework(new/improvement)
- [ ] New Test case
    - [ ] Skipped for non-supported platforms
- [x] Test case improvement

### Back port request

- [ ] 202205
- [ ] 202305
- [ ] 202311
- [ ] 202405
- [ ] 202411
- [ ] 202505
- [ ] 202511

### Approach

#### What is the motivation for this PR?

`fib/test_fib.py::test_ipinip_hash`, `test_nvgre_hash`, and
`test_vxlan_hash` were unconditionally skipped on `asic_type == 'vpp'`
because the underlying VPP runtime hashed every transit tunnel (IPinIP /
6in4 / 4in6 / 6in6 / GRE / NVGRE) on its **outer** 5-tuple only. When
many distinct inner flows share an outer 5-tuple — the common case for
SONiC T1-LAG topologies — they collapse onto a single LAG member and a
single ECMP next-hop, and these three tests deviate by more than the 5%
balance threshold.

With the upstream VPP fix (`hash-eth-l34-inner` + `PEEK_INNER` bit) and
the libsaivs opt-in landed, the three tests now pass on
`vms-kvm-vpp-t1-lag` and there is no reason to keep them on the skip
list.

#### How did you do it?

Two small changes (total **2 files, +12 / −23**):

| File | Change |
|---|---|
|
`tests/common/plugins/conditional_mark/tests_mark_conditions_sonic_vpp.yaml`
| Remove the three unconditional `skip` entries for `test_ipinip_hash`,
`test_nvgre_hash`, and `test_vxlan_hash` on `asic_type == 'vpp'`.
Replace with a comment block that points to issue #25762 and lists the
three prerequisites (VPP patch + vslib/vpp opt-in + the
`test_nvgre_hash` hash-key override below). |
| `tests/fib/test_fib.py` | In `test_nvgre_hash`, add a `vpp`
`asic_type` branch that sets `hash_keys = ['src-ip', 'dst-ip',
'src-port', 'dst-port']`. VPP's new opt-in `hash-eth-l34-inner` bond LB
peeks into the inner IP/L4 of NVGRE encap but does **not** mix in the
inner Ethernet src/dst MAC — identical to the `marvell-teralynx` and
`mellanox` behavioural carve-outs already in this test. Without this
override, `NvgreHashTest` treats inner MAC variations as additional hash
keys and incorrectly flags the run as deviating > 5 %. |

#### How did you verify/test it?

End-to-end on `vms-kvm-vpp-t1-lag` (`vlab-vpp-01`) with both
prerequisite PRs (#234, #1896) applied:

```
cd sonic-mgmt/tests
pytest fib/test_fib.py --topology=t1-lag-vpp --testbed=vms-kvm-vpp-t1-lag
```

Result: full `tests/fib/test_fib.py` is **16 / 16 PASS** in 2:01:36 —
`test_basic_fib`, `test_hash[ipv4/ipv6]`, `test_ipinip_hash[ipv4/ipv6]`,
`test_ipinip_hash_negative[ipv4/ipv6]`, `test_vxlan_hash × 4`,
`test_nvgre_hash × 4`, `test_ecmp_group_member_flap`.

Re-validated after the `0011 → 0010` VPP patch squash on 2026-05-19.

#### Any platform specific information?

This PR only affects `asic_type == 'vpp'`:

- The `tests_mark_conditions_sonic_vpp.yaml` change is scoped to the
`sonic-vpp` conditional-mark file.
- The `test_fib.py` change is a new `if duthost.facts['asic_type'] in
["vpp"]:` branch inside `test_nvgre_hash`, parallel to the existing
`marvell-teralynx` carve-out. Other `asic_type`s are unaffected.

If a sonic-vpp image **without** the two prerequisite changes (PR #234,
PR #1896) is used, the three re-enabled tests will deviate > 5 % and
fail. This is the expected hard prerequisite — see the comment block in
the `tests_mark_conditions_sonic_vpp.yaml` change for details.

#### Supported testbed topology if it's a new test case?

N/A — this PR re-enables existing tests on an existing topology
(`t1-lag-vpp` / `vms-kvm-vpp-t1-lag`). No new test case, no new
topology.

### Documentation

HLD:
[sonic-net/SONiC#1860](sonic-net/SONiC#1860) —
*Inner-aware flow hash for VPP-based platforms* (v0.3, opt-in design).

---------

Signed-off-by: Jianquan Ye <jianquanye@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
selldinesh pushed a commit to selldinesh/sonic-mgmt that referenced this pull request Jun 11, 2026
sonic-net#24721)

### Description of PR

Summary: Re-enable the three previously skipped tunnel-hashing tests for
the `vpp` `asic_type` now that VPP has **opt-in** inner-aware ECMP / LAG
flow hashing.

The two prerequisite changes that make these tests actually pass on
`vms-kvm-vpp-t1-lag`:

-
[sonic-net/sonic-platform-vpp#234](sonic-net/sonic-platform-vpp#234)
— vendors VPP patch `0010-sonic-inner-aware-flow-hash.patch`, which
registers the **new** opt-in `hash-eth-l34-inner` bond load-balance
function, the new `BOND_API_LB_ALGO_L34_INNER = 6` bond algorithm, and
the new `FLOW_HASH_PEEK_INNER` ECMP FIB bit. Stock `hash-eth-l34` and
the legacy `BOND_API_LB_ALGO_L34 = 1` are byte-for-byte unchanged.
-
[sonic-net/sonic-sairedis#1896](sonic-net/sonic-sairedis#1896)
— opts the `vslib/vpp` adapter into the new path: selects
`BOND_API_LB_ALGO_L34_INNER` in `vpp_create_lag` and OR's
`VPP_IP_API_FLOW_HASH_PEEK_INNER` into `vpp_add_ip_vrf` for both
`AF_INET` and `AF_INET6` (default + non-default VRFs).
- `sonic-net/sonic-buildimage` submodule bump for sonic-sairedis is a
separate routine PR once sonic-net#1896 lands.

Fixes [sonic-net#25762](sonic-net#25762)

### Type of change

- [ ] Bug fix
- [ ] Testbed and Framework(new/improvement)
- [ ] New Test case
    - [ ] Skipped for non-supported platforms
- [x] Test case improvement

### Back port request

- [ ] 202205
- [ ] 202305
- [ ] 202311
- [ ] 202405
- [ ] 202411
- [ ] 202505
- [ ] 202511

### Approach

#### What is the motivation for this PR?

`fib/test_fib.py::test_ipinip_hash`, `test_nvgre_hash`, and
`test_vxlan_hash` were unconditionally skipped on `asic_type == 'vpp'`
because the underlying VPP runtime hashed every transit tunnel (IPinIP /
6in4 / 4in6 / 6in6 / GRE / NVGRE) on its **outer** 5-tuple only. When
many distinct inner flows share an outer 5-tuple — the common case for
SONiC T1-LAG topologies — they collapse onto a single LAG member and a
single ECMP next-hop, and these three tests deviate by more than the 5%
balance threshold.

With the upstream VPP fix (`hash-eth-l34-inner` + `PEEK_INNER` bit) and
the libsaivs opt-in landed, the three tests now pass on
`vms-kvm-vpp-t1-lag` and there is no reason to keep them on the skip
list.

#### How did you do it?

Two small changes (total **2 files, +12 / −23**):

| File | Change |
|---|---|
|
`tests/common/plugins/conditional_mark/tests_mark_conditions_sonic_vpp.yaml`
| Remove the three unconditional `skip` entries for `test_ipinip_hash`,
`test_nvgre_hash`, and `test_vxlan_hash` on `asic_type == 'vpp'`.
Replace with a comment block that points to issue sonic-net#25762 and lists the
three prerequisites (VPP patch + vslib/vpp opt-in + the
`test_nvgre_hash` hash-key override below). |
| `tests/fib/test_fib.py` | In `test_nvgre_hash`, add a `vpp`
`asic_type` branch that sets `hash_keys = ['src-ip', 'dst-ip',
'src-port', 'dst-port']`. VPP's new opt-in `hash-eth-l34-inner` bond LB
peeks into the inner IP/L4 of NVGRE encap but does **not** mix in the
inner Ethernet src/dst MAC — identical to the `marvell-teralynx` and
`mellanox` behavioural carve-outs already in this test. Without this
override, `NvgreHashTest` treats inner MAC variations as additional hash
keys and incorrectly flags the run as deviating > 5 %. |

#### How did you verify/test it?

End-to-end on `vms-kvm-vpp-t1-lag` (`vlab-vpp-01`) with both
prerequisite PRs (sonic-net#234, sonic-net#1896) applied:

```
cd sonic-mgmt/tests
pytest fib/test_fib.py --topology=t1-lag-vpp --testbed=vms-kvm-vpp-t1-lag
```

Result: full `tests/fib/test_fib.py` is **16 / 16 PASS** in 2:01:36 —
`test_basic_fib`, `test_hash[ipv4/ipv6]`, `test_ipinip_hash[ipv4/ipv6]`,
`test_ipinip_hash_negative[ipv4/ipv6]`, `test_vxlan_hash × 4`,
`test_nvgre_hash × 4`, `test_ecmp_group_member_flap`.

Re-validated after the `0011 → 0010` VPP patch squash on 2026-05-19.

#### Any platform specific information?

This PR only affects `asic_type == 'vpp'`:

- The `tests_mark_conditions_sonic_vpp.yaml` change is scoped to the
`sonic-vpp` conditional-mark file.
- The `test_fib.py` change is a new `if duthost.facts['asic_type'] in
["vpp"]:` branch inside `test_nvgre_hash`, parallel to the existing
`marvell-teralynx` carve-out. Other `asic_type`s are unaffected.

If a sonic-vpp image **without** the two prerequisite changes (PR sonic-net#234,
PR sonic-net#1896) is used, the three re-enabled tests will deviate > 5 % and
fail. This is the expected hard prerequisite — see the comment block in
the `tests_mark_conditions_sonic_vpp.yaml` change for details.

#### Supported testbed topology if it's a new test case?

N/A — this PR re-enables existing tests on an existing topology
(`t1-lag-vpp` / `vms-kvm-vpp-t1-lag`). No new test case, no new
topology.

### Documentation

HLD:
[sonic-net/SONiC#1860](sonic-net/SONiC#1860) —
*Inner-aware flow hash for VPP-based platforms* (v0.3, opt-in design).

---------

Signed-off-by: Jianquan Ye <jianquanye@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: selldinesh <dinesh.sellappan@keysight.com>
selldinesh pushed a commit to selldinesh/sonic-mgmt that referenced this pull request Jun 11, 2026
sonic-net#24721)

### Description of PR

Summary: Re-enable the three previously skipped tunnel-hashing tests for
the `vpp` `asic_type` now that VPP has **opt-in** inner-aware ECMP / LAG
flow hashing.

The two prerequisite changes that make these tests actually pass on
`vms-kvm-vpp-t1-lag`:

-
[sonic-net/sonic-platform-vpp#234](sonic-net/sonic-platform-vpp#234)
— vendors VPP patch `0010-sonic-inner-aware-flow-hash.patch`, which
registers the **new** opt-in `hash-eth-l34-inner` bond load-balance
function, the new `BOND_API_LB_ALGO_L34_INNER = 6` bond algorithm, and
the new `FLOW_HASH_PEEK_INNER` ECMP FIB bit. Stock `hash-eth-l34` and
the legacy `BOND_API_LB_ALGO_L34 = 1` are byte-for-byte unchanged.
-
[sonic-net/sonic-sairedis#1896](sonic-net/sonic-sairedis#1896)
— opts the `vslib/vpp` adapter into the new path: selects
`BOND_API_LB_ALGO_L34_INNER` in `vpp_create_lag` and OR's
`VPP_IP_API_FLOW_HASH_PEEK_INNER` into `vpp_add_ip_vrf` for both
`AF_INET` and `AF_INET6` (default + non-default VRFs).
- `sonic-net/sonic-buildimage` submodule bump for sonic-sairedis is a
separate routine PR once sonic-net#1896 lands.

Fixes [sonic-net#25762](sonic-net#25762)

### Type of change

- [ ] Bug fix
- [ ] Testbed and Framework(new/improvement)
- [ ] New Test case
    - [ ] Skipped for non-supported platforms
- [x] Test case improvement

### Back port request

- [ ] 202205
- [ ] 202305
- [ ] 202311
- [ ] 202405
- [ ] 202411
- [ ] 202505
- [ ] 202511

### Approach

#### What is the motivation for this PR?

`fib/test_fib.py::test_ipinip_hash`, `test_nvgre_hash`, and
`test_vxlan_hash` were unconditionally skipped on `asic_type == 'vpp'`
because the underlying VPP runtime hashed every transit tunnel (IPinIP /
6in4 / 4in6 / 6in6 / GRE / NVGRE) on its **outer** 5-tuple only. When
many distinct inner flows share an outer 5-tuple — the common case for
SONiC T1-LAG topologies — they collapse onto a single LAG member and a
single ECMP next-hop, and these three tests deviate by more than the 5%
balance threshold.

With the upstream VPP fix (`hash-eth-l34-inner` + `PEEK_INNER` bit) and
the libsaivs opt-in landed, the three tests now pass on
`vms-kvm-vpp-t1-lag` and there is no reason to keep them on the skip
list.

#### How did you do it?

Two small changes (total **2 files, +12 / −23**):

| File | Change |
|---|---|
|
`tests/common/plugins/conditional_mark/tests_mark_conditions_sonic_vpp.yaml`
| Remove the three unconditional `skip` entries for `test_ipinip_hash`,
`test_nvgre_hash`, and `test_vxlan_hash` on `asic_type == 'vpp'`.
Replace with a comment block that points to issue sonic-net#25762 and lists the
three prerequisites (VPP patch + vslib/vpp opt-in + the
`test_nvgre_hash` hash-key override below). |
| `tests/fib/test_fib.py` | In `test_nvgre_hash`, add a `vpp`
`asic_type` branch that sets `hash_keys = ['src-ip', 'dst-ip',
'src-port', 'dst-port']`. VPP's new opt-in `hash-eth-l34-inner` bond LB
peeks into the inner IP/L4 of NVGRE encap but does **not** mix in the
inner Ethernet src/dst MAC — identical to the `marvell-teralynx` and
`mellanox` behavioural carve-outs already in this test. Without this
override, `NvgreHashTest` treats inner MAC variations as additional hash
keys and incorrectly flags the run as deviating > 5 %. |

#### How did you verify/test it?

End-to-end on `vms-kvm-vpp-t1-lag` (`vlab-vpp-01`) with both
prerequisite PRs (sonic-net#234, sonic-net#1896) applied:

```
cd sonic-mgmt/tests
pytest fib/test_fib.py --topology=t1-lag-vpp --testbed=vms-kvm-vpp-t1-lag
```

Result: full `tests/fib/test_fib.py` is **16 / 16 PASS** in 2:01:36 —
`test_basic_fib`, `test_hash[ipv4/ipv6]`, `test_ipinip_hash[ipv4/ipv6]`,
`test_ipinip_hash_negative[ipv4/ipv6]`, `test_vxlan_hash × 4`,
`test_nvgre_hash × 4`, `test_ecmp_group_member_flap`.

Re-validated after the `0011 → 0010` VPP patch squash on 2026-05-19.

#### Any platform specific information?

This PR only affects `asic_type == 'vpp'`:

- The `tests_mark_conditions_sonic_vpp.yaml` change is scoped to the
`sonic-vpp` conditional-mark file.
- The `test_fib.py` change is a new `if duthost.facts['asic_type'] in
["vpp"]:` branch inside `test_nvgre_hash`, parallel to the existing
`marvell-teralynx` carve-out. Other `asic_type`s are unaffected.

If a sonic-vpp image **without** the two prerequisite changes (PR sonic-net#234,
PR sonic-net#1896) is used, the three re-enabled tests will deviate > 5 % and
fail. This is the expected hard prerequisite — see the comment block in
the `tests_mark_conditions_sonic_vpp.yaml` change for details.

#### Supported testbed topology if it's a new test case?

N/A — this PR re-enables existing tests on an existing topology
(`t1-lag-vpp` / `vms-kvm-vpp-t1-lag`). No new test case, no new
topology.

### Documentation

HLD:
[sonic-net/SONiC#1860](sonic-net/SONiC#1860) —
*Inner-aware flow hash for VPP-based platforms* (v0.3, opt-in design).

---------

Signed-off-by: Jianquan Ye <jianquanye@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: selldinesh <dinesh.sellappan@keysight.com>
selldinesh pushed a commit to selldinesh/sonic-mgmt that referenced this pull request Jun 11, 2026
sonic-net#24721)

### Description of PR

Summary: Re-enable the three previously skipped tunnel-hashing tests for
the `vpp` `asic_type` now that VPP has **opt-in** inner-aware ECMP / LAG
flow hashing.

The two prerequisite changes that make these tests actually pass on
`vms-kvm-vpp-t1-lag`:

-
[sonic-net/sonic-platform-vpp#234](sonic-net/sonic-platform-vpp#234)
— vendors VPP patch `0010-sonic-inner-aware-flow-hash.patch`, which
registers the **new** opt-in `hash-eth-l34-inner` bond load-balance
function, the new `BOND_API_LB_ALGO_L34_INNER = 6` bond algorithm, and
the new `FLOW_HASH_PEEK_INNER` ECMP FIB bit. Stock `hash-eth-l34` and
the legacy `BOND_API_LB_ALGO_L34 = 1` are byte-for-byte unchanged.
-
[sonic-net/sonic-sairedis#1896](sonic-net/sonic-sairedis#1896)
— opts the `vslib/vpp` adapter into the new path: selects
`BOND_API_LB_ALGO_L34_INNER` in `vpp_create_lag` and OR's
`VPP_IP_API_FLOW_HASH_PEEK_INNER` into `vpp_add_ip_vrf` for both
`AF_INET` and `AF_INET6` (default + non-default VRFs).
- `sonic-net/sonic-buildimage` submodule bump for sonic-sairedis is a
separate routine PR once sonic-net#1896 lands.

Fixes [sonic-net#25762](sonic-net#25762)

### Type of change

- [ ] Bug fix
- [ ] Testbed and Framework(new/improvement)
- [ ] New Test case
    - [ ] Skipped for non-supported platforms
- [x] Test case improvement

### Back port request

- [ ] 202205
- [ ] 202305
- [ ] 202311
- [ ] 202405
- [ ] 202411
- [ ] 202505
- [ ] 202511

### Approach

#### What is the motivation for this PR?

`fib/test_fib.py::test_ipinip_hash`, `test_nvgre_hash`, and
`test_vxlan_hash` were unconditionally skipped on `asic_type == 'vpp'`
because the underlying VPP runtime hashed every transit tunnel (IPinIP /
6in4 / 4in6 / 6in6 / GRE / NVGRE) on its **outer** 5-tuple only. When
many distinct inner flows share an outer 5-tuple — the common case for
SONiC T1-LAG topologies — they collapse onto a single LAG member and a
single ECMP next-hop, and these three tests deviate by more than the 5%
balance threshold.

With the upstream VPP fix (`hash-eth-l34-inner` + `PEEK_INNER` bit) and
the libsaivs opt-in landed, the three tests now pass on
`vms-kvm-vpp-t1-lag` and there is no reason to keep them on the skip
list.

#### How did you do it?

Two small changes (total **2 files, +12 / −23**):

| File | Change |
|---|---|
|
`tests/common/plugins/conditional_mark/tests_mark_conditions_sonic_vpp.yaml`
| Remove the three unconditional `skip` entries for `test_ipinip_hash`,
`test_nvgre_hash`, and `test_vxlan_hash` on `asic_type == 'vpp'`.
Replace with a comment block that points to issue sonic-net#25762 and lists the
three prerequisites (VPP patch + vslib/vpp opt-in + the
`test_nvgre_hash` hash-key override below). |
| `tests/fib/test_fib.py` | In `test_nvgre_hash`, add a `vpp`
`asic_type` branch that sets `hash_keys = ['src-ip', 'dst-ip',
'src-port', 'dst-port']`. VPP's new opt-in `hash-eth-l34-inner` bond LB
peeks into the inner IP/L4 of NVGRE encap but does **not** mix in the
inner Ethernet src/dst MAC — identical to the `marvell-teralynx` and
`mellanox` behavioural carve-outs already in this test. Without this
override, `NvgreHashTest` treats inner MAC variations as additional hash
keys and incorrectly flags the run as deviating > 5 %. |

#### How did you verify/test it?

End-to-end on `vms-kvm-vpp-t1-lag` (`vlab-vpp-01`) with both
prerequisite PRs (sonic-net#234, sonic-net#1896) applied:

```
cd sonic-mgmt/tests
pytest fib/test_fib.py --topology=t1-lag-vpp --testbed=vms-kvm-vpp-t1-lag
```

Result: full `tests/fib/test_fib.py` is **16 / 16 PASS** in 2:01:36 —
`test_basic_fib`, `test_hash[ipv4/ipv6]`, `test_ipinip_hash[ipv4/ipv6]`,
`test_ipinip_hash_negative[ipv4/ipv6]`, `test_vxlan_hash × 4`,
`test_nvgre_hash × 4`, `test_ecmp_group_member_flap`.

Re-validated after the `0011 → 0010` VPP patch squash on 2026-05-19.

#### Any platform specific information?

This PR only affects `asic_type == 'vpp'`:

- The `tests_mark_conditions_sonic_vpp.yaml` change is scoped to the
`sonic-vpp` conditional-mark file.
- The `test_fib.py` change is a new `if duthost.facts['asic_type'] in
["vpp"]:` branch inside `test_nvgre_hash`, parallel to the existing
`marvell-teralynx` carve-out. Other `asic_type`s are unaffected.

If a sonic-vpp image **without** the two prerequisite changes (PR sonic-net#234,
PR sonic-net#1896) is used, the three re-enabled tests will deviate > 5 % and
fail. This is the expected hard prerequisite — see the comment block in
the `tests_mark_conditions_sonic_vpp.yaml` change for details.

#### Supported testbed topology if it's a new test case?

N/A — this PR re-enables existing tests on an existing topology
(`t1-lag-vpp` / `vms-kvm-vpp-t1-lag`). No new test case, no new
topology.

### Documentation

HLD:
[sonic-net/SONiC#1860](sonic-net/SONiC#1860) —
*Inner-aware flow hash for VPP-based platforms* (v0.3, opt-in design).

---------

Signed-off-by: Jianquan Ye <jianquanye@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: selldinesh <dinesh.sellappan@keysight.com>
sdeotarse-msft pushed a commit to SoumyaMishra18/sonic-mgmt that referenced this pull request Jun 12, 2026
sonic-net#24721)

### Description of PR

Summary: Re-enable the three previously skipped tunnel-hashing tests for
the `vpp` `asic_type` now that VPP has **opt-in** inner-aware ECMP / LAG
flow hashing.

The two prerequisite changes that make these tests actually pass on
`vms-kvm-vpp-t1-lag`:

-
[sonic-net/sonic-platform-vpp#234](sonic-net/sonic-platform-vpp#234)
— vendors VPP patch `0010-sonic-inner-aware-flow-hash.patch`, which
registers the **new** opt-in `hash-eth-l34-inner` bond load-balance
function, the new `BOND_API_LB_ALGO_L34_INNER = 6` bond algorithm, and
the new `FLOW_HASH_PEEK_INNER` ECMP FIB bit. Stock `hash-eth-l34` and
the legacy `BOND_API_LB_ALGO_L34 = 1` are byte-for-byte unchanged.
-
[sonic-net/sonic-sairedis#1896](sonic-net/sonic-sairedis#1896)
— opts the `vslib/vpp` adapter into the new path: selects
`BOND_API_LB_ALGO_L34_INNER` in `vpp_create_lag` and OR's
`VPP_IP_API_FLOW_HASH_PEEK_INNER` into `vpp_add_ip_vrf` for both
`AF_INET` and `AF_INET6` (default + non-default VRFs).
- `sonic-net/sonic-buildimage` submodule bump for sonic-sairedis is a
separate routine PR once sonic-net#1896 lands.

Fixes [sonic-net#25762](sonic-net#25762)

### Type of change

- [ ] Bug fix
- [ ] Testbed and Framework(new/improvement)
- [ ] New Test case
    - [ ] Skipped for non-supported platforms
- [x] Test case improvement

### Back port request

- [ ] 202205
- [ ] 202305
- [ ] 202311
- [ ] 202405
- [ ] 202411
- [ ] 202505
- [ ] 202511

### Approach

#### What is the motivation for this PR?

`fib/test_fib.py::test_ipinip_hash`, `test_nvgre_hash`, and
`test_vxlan_hash` were unconditionally skipped on `asic_type == 'vpp'`
because the underlying VPP runtime hashed every transit tunnel (IPinIP /
6in4 / 4in6 / 6in6 / GRE / NVGRE) on its **outer** 5-tuple only. When
many distinct inner flows share an outer 5-tuple — the common case for
SONiC T1-LAG topologies — they collapse onto a single LAG member and a
single ECMP next-hop, and these three tests deviate by more than the 5%
balance threshold.

With the upstream VPP fix (`hash-eth-l34-inner` + `PEEK_INNER` bit) and
the libsaivs opt-in landed, the three tests now pass on
`vms-kvm-vpp-t1-lag` and there is no reason to keep them on the skip
list.

#### How did you do it?

Two small changes (total **2 files, +12 / −23**):

| File | Change |
|---|---|
|
`tests/common/plugins/conditional_mark/tests_mark_conditions_sonic_vpp.yaml`
| Remove the three unconditional `skip` entries for `test_ipinip_hash`,
`test_nvgre_hash`, and `test_vxlan_hash` on `asic_type == 'vpp'`.
Replace with a comment block that points to issue sonic-net#25762 and lists the
three prerequisites (VPP patch + vslib/vpp opt-in + the
`test_nvgre_hash` hash-key override below). |
| `tests/fib/test_fib.py` | In `test_nvgre_hash`, add a `vpp`
`asic_type` branch that sets `hash_keys = ['src-ip', 'dst-ip',
'src-port', 'dst-port']`. VPP's new opt-in `hash-eth-l34-inner` bond LB
peeks into the inner IP/L4 of NVGRE encap but does **not** mix in the
inner Ethernet src/dst MAC — identical to the `marvell-teralynx` and
`mellanox` behavioural carve-outs already in this test. Without this
override, `NvgreHashTest` treats inner MAC variations as additional hash
keys and incorrectly flags the run as deviating > 5 %. |

#### How did you verify/test it?

End-to-end on `vms-kvm-vpp-t1-lag` (`vlab-vpp-01`) with both
prerequisite PRs (sonic-net#234, sonic-net#1896) applied:

```
cd sonic-mgmt/tests
pytest fib/test_fib.py --topology=t1-lag-vpp --testbed=vms-kvm-vpp-t1-lag
```

Result: full `tests/fib/test_fib.py` is **16 / 16 PASS** in 2:01:36 —
`test_basic_fib`, `test_hash[ipv4/ipv6]`, `test_ipinip_hash[ipv4/ipv6]`,
`test_ipinip_hash_negative[ipv4/ipv6]`, `test_vxlan_hash × 4`,
`test_nvgre_hash × 4`, `test_ecmp_group_member_flap`.

Re-validated after the `0011 → 0010` VPP patch squash on 2026-05-19.

#### Any platform specific information?

This PR only affects `asic_type == 'vpp'`:

- The `tests_mark_conditions_sonic_vpp.yaml` change is scoped to the
`sonic-vpp` conditional-mark file.
- The `test_fib.py` change is a new `if duthost.facts['asic_type'] in
["vpp"]:` branch inside `test_nvgre_hash`, parallel to the existing
`marvell-teralynx` carve-out. Other `asic_type`s are unaffected.

If a sonic-vpp image **without** the two prerequisite changes (PR sonic-net#234,
PR sonic-net#1896) is used, the three re-enabled tests will deviate > 5 % and
fail. This is the expected hard prerequisite — see the comment block in
the `tests_mark_conditions_sonic_vpp.yaml` change for details.

#### Supported testbed topology if it's a new test case?

N/A — this PR re-enables existing tests on an existing topology
(`t1-lag-vpp` / `vms-kvm-vpp-t1-lag`). No new test case, no new
topology.

### Documentation

HLD:
[sonic-net/SONiC#1860](sonic-net/SONiC#1860) —
*Inner-aware flow hash for VPP-based platforms* (v0.3, opt-in design).

---------

Signed-off-by: Jianquan Ye <jianquanye@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
selldinesh pushed a commit to selldinesh/sonic-mgmt that referenced this pull request Jun 25, 2026
sonic-net#24721)

### Description of PR

Summary: Re-enable the three previously skipped tunnel-hashing tests for
the `vpp` `asic_type` now that VPP has **opt-in** inner-aware ECMP / LAG
flow hashing.

The two prerequisite changes that make these tests actually pass on
`vms-kvm-vpp-t1-lag`:

-
[sonic-net/sonic-platform-vpp#234](sonic-net/sonic-platform-vpp#234)
— vendors VPP patch `0010-sonic-inner-aware-flow-hash.patch`, which
registers the **new** opt-in `hash-eth-l34-inner` bond load-balance
function, the new `BOND_API_LB_ALGO_L34_INNER = 6` bond algorithm, and
the new `FLOW_HASH_PEEK_INNER` ECMP FIB bit. Stock `hash-eth-l34` and
the legacy `BOND_API_LB_ALGO_L34 = 1` are byte-for-byte unchanged.
-
[sonic-net/sonic-sairedis#1896](sonic-net/sonic-sairedis#1896)
— opts the `vslib/vpp` adapter into the new path: selects
`BOND_API_LB_ALGO_L34_INNER` in `vpp_create_lag` and OR's
`VPP_IP_API_FLOW_HASH_PEEK_INNER` into `vpp_add_ip_vrf` for both
`AF_INET` and `AF_INET6` (default + non-default VRFs).
- `sonic-net/sonic-buildimage` submodule bump for sonic-sairedis is a
separate routine PR once sonic-net#1896 lands.

Fixes [sonic-net#25762](sonic-net#25762)

### Type of change

- [ ] Bug fix
- [ ] Testbed and Framework(new/improvement)
- [ ] New Test case
    - [ ] Skipped for non-supported platforms
- [x] Test case improvement

### Back port request

- [ ] 202205
- [ ] 202305
- [ ] 202311
- [ ] 202405
- [ ] 202411
- [ ] 202505
- [ ] 202511

### Approach

#### What is the motivation for this PR?

`fib/test_fib.py::test_ipinip_hash`, `test_nvgre_hash`, and
`test_vxlan_hash` were unconditionally skipped on `asic_type == 'vpp'`
because the underlying VPP runtime hashed every transit tunnel (IPinIP /
6in4 / 4in6 / 6in6 / GRE / NVGRE) on its **outer** 5-tuple only. When
many distinct inner flows share an outer 5-tuple — the common case for
SONiC T1-LAG topologies — they collapse onto a single LAG member and a
single ECMP next-hop, and these three tests deviate by more than the 5%
balance threshold.

With the upstream VPP fix (`hash-eth-l34-inner` + `PEEK_INNER` bit) and
the libsaivs opt-in landed, the three tests now pass on
`vms-kvm-vpp-t1-lag` and there is no reason to keep them on the skip
list.

#### How did you do it?

Two small changes (total **2 files, +12 / −23**):

| File | Change |
|---|---|
|
`tests/common/plugins/conditional_mark/tests_mark_conditions_sonic_vpp.yaml`
| Remove the three unconditional `skip` entries for `test_ipinip_hash`,
`test_nvgre_hash`, and `test_vxlan_hash` on `asic_type == 'vpp'`.
Replace with a comment block that points to issue sonic-net#25762 and lists the
three prerequisites (VPP patch + vslib/vpp opt-in + the
`test_nvgre_hash` hash-key override below). |
| `tests/fib/test_fib.py` | In `test_nvgre_hash`, add a `vpp`
`asic_type` branch that sets `hash_keys = ['src-ip', 'dst-ip',
'src-port', 'dst-port']`. VPP's new opt-in `hash-eth-l34-inner` bond LB
peeks into the inner IP/L4 of NVGRE encap but does **not** mix in the
inner Ethernet src/dst MAC — identical to the `marvell-teralynx` and
`mellanox` behavioural carve-outs already in this test. Without this
override, `NvgreHashTest` treats inner MAC variations as additional hash
keys and incorrectly flags the run as deviating > 5 %. |

#### How did you verify/test it?

End-to-end on `vms-kvm-vpp-t1-lag` (`vlab-vpp-01`) with both
prerequisite PRs (sonic-net#234, sonic-net#1896) applied:

```
cd sonic-mgmt/tests
pytest fib/test_fib.py --topology=t1-lag-vpp --testbed=vms-kvm-vpp-t1-lag
```

Result: full `tests/fib/test_fib.py` is **16 / 16 PASS** in 2:01:36 —
`test_basic_fib`, `test_hash[ipv4/ipv6]`, `test_ipinip_hash[ipv4/ipv6]`,
`test_ipinip_hash_negative[ipv4/ipv6]`, `test_vxlan_hash × 4`,
`test_nvgre_hash × 4`, `test_ecmp_group_member_flap`.

Re-validated after the `0011 → 0010` VPP patch squash on 2026-05-19.

#### Any platform specific information?

This PR only affects `asic_type == 'vpp'`:

- The `tests_mark_conditions_sonic_vpp.yaml` change is scoped to the
`sonic-vpp` conditional-mark file.
- The `test_fib.py` change is a new `if duthost.facts['asic_type'] in
["vpp"]:` branch inside `test_nvgre_hash`, parallel to the existing
`marvell-teralynx` carve-out. Other `asic_type`s are unaffected.

If a sonic-vpp image **without** the two prerequisite changes (PR sonic-net#234,
PR sonic-net#1896) is used, the three re-enabled tests will deviate > 5 % and
fail. This is the expected hard prerequisite — see the comment block in
the `tests_mark_conditions_sonic_vpp.yaml` change for details.

#### Supported testbed topology if it's a new test case?

N/A — this PR re-enables existing tests on an existing topology
(`t1-lag-vpp` / `vms-kvm-vpp-t1-lag`). No new test case, no new
topology.

### Documentation

HLD:
[sonic-net/SONiC#1860](sonic-net/SONiC#1860) —
*Inner-aware flow hash for VPP-based platforms* (v0.3, opt-in design).

---------

Signed-off-by: Jianquan Ye <jianquanye@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: selldinesh <dinesh.sellappan@keysight.com>
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.

4 participants