Conversation
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
The "do not count policy denies as interface drops" change that used to sit on top of this branch has been split out into its own PR (sonic-net#280), where it takes patch slot 0018 and VPP version 2606-0.6. Renumber this patch to 0019 and bump to 2606-0.7 so the two series do not claim the same patch number or deb version, and can be merged in either order. Patch contents are unchanged - this is a rename plus the series and version bookkeeping. Signed-off-by: Longxiang Lyu <lolv@microsoft.com>
The "do not count policy denies as interface drops" change that used to sit on top of this branch has been split out into its own PR (sonic-net#280), where it takes patch slot 0018. Renumber this patch to 0019 so the two series do not claim the same patch number. Patch contents are unchanged - this is a rename plus the series bookkeeping. Signed-off-by: Longxiang Lyu <lolv@microsoft.com>
There was a problem hiding this comment.
🟢 Approval recommended
The patch cleanly scopes the counter semantic change to explicit ACL policy denies via a dedicated buffer flag while leaving resource-drop paths and existing observability intact.
Pull request overview
This PR adjusts how VPP accounts ACL deny traffic so intentional policy drops don’t inflate interface drop counters exported to SONiC as RX_DRP (SAI_PORT_STAT_IF_IN_DISCARDS), while preserving visibility via existing per-node/per-ACE error counters.
Changes:
- Add a new VPP buffer flag (
VNET_BUFFER_F_POLICY_DROP) and set it on the ACL deny path for true policy denies (not resource-exhaustion denies). - Update
interface_drop_punt()accounting to exclude flagged buffers from/if/drops(and still charge original member interfaces for rewritten RX sw_if_index where applicable). - Bump the VPP package minor version to ensure downstream builds don’t reuse cached/stale debs after patch content changes.
File summaries
| File | Description |
|---|---|
| vppbld/patches/series | Adds the new patch to the build patch series with rationale in comments. |
| vppbld/patches/0018-acl-do-not-count-policy-denies-as-interface-drops.patch | Implements VNET_BUFFER_F_POLICY_DROP, sets it for ACL policy denies, and discounts those buffers from interface drop counters. |
| rules/vpp.mk | Bumps VPP_VERSION from 2606-0.5 to 2606-0.6 to invalidate cached artifacts after patch updates. |
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
457c0e5 to
bb83e04
Compare
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
|
Renumbered this patch
The patch content is unchanged; this is the filename plus the Re-verified with The |
An ACL deny is an intentional forwarding decision, not an interface discard, but today the deny path sends the buffer to error-drop, which charges it to the ingress interface's drop counter (/if/drops). SONiC exports that counter as SAI_PORT_STAT_IF_IN_DISCARDS and displays it as RX_DRP, so a port doing exactly what it was configured to do reports a large and growing discard count. This is most visible on a dual-ToR standby mux port, where the standby ToR is *supposed* to drop the traffic it receives from the server: the port reports a ~99% RX_DRP rate while forwarding correctly. RFC 1213 defines ifInDiscards as packets discarded despite no error being detected, to free buffer space - i.e. resource exhaustion, not policy. SONiC itself already treats ACL drops as RX_ERR rather than RX_DRP. Add VNET_BUFFER_F_POLICY_DROP (bit 19, the first free bit) and set it at the ACL deny choke point in acl_fa_inner_node_fn(). interface_drop_punt() then discounts flagged buffers from the interface drop counter while still counting the per-node/per-ACE error, so denies remain fully observable via "show errors" and "show acl-plugin acl". The flag is set only for ACL_FA_ERROR_ACL_DROP. Drops caused by a lack of resources, such as ACL_FA_ERROR_ACL_TOO_MANY_SESSIONS, are genuine discards and continue to increment the interface counter. Verified on a KVM dual-ToR testbed running this patch: the standby ToR received 5762 packets on the mux port with RX_DRP=0 (previously RX_DRP tracked the full received count), while "show errors" still reported the denies against acl-plugin-in-ip4-l2. This makes dualtor_io/test_normal_op.py::test_upstream_standby_rx_drop_check pass. Bump VPP_VERSION to 2606-0.7. The suffix is the cache key vppbld/Makefile uses to fetch pre-built debs, so it has to move whenever the patch series changes content. 0.6 is already published by patch 0018, which merged as PR sonic-net#278 while this one was open; leaving it at 0.6 would make downstream sonic-buildimage builds pull the stale 0.6 debs that pre-date this patch. Note that git does not flag this: both branches bumped 0.5 to 0.6 independently, so the identical edits merge without a conflict. Signed-off-by: Longxiang Lyu <lolv@microsoft.com>
bb83e04 to
a35d580
Compare
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
|
Reviewed this against the pinned VPP source (commit 3f9e978d). The mechanism is correct and the targeting is precise. Nice, well-scoped fix. A few notes and one question. What I verified
Semantic scope (your flagged question)
Minor
Reviewed by AI agent on behalf of aaronber0614. |
|
Tracking issue filed: sonic-net/sonic-buildimage#29335. Also noting for reviewers that this branch has been rebased onto master since #278 merged. Full series re-verified against the pinned VPP commit |
|
If I understand this correctly, the port is reporting RX_DRP correctly, as it should because the packet was dropped (as opposed to RX_ERR). The description states the issue is that "SONiC itself already treats ACL drops as RX_ERR, not RX_DRP". Is the problem here in how SONiC treats the drops and should that be fixed rather than have VPP not report any drops when it does drop packets due to ACL match? |
| + continue; | ||
| + } | ||
| + | ||
| + orig = vnet_buffer2 (ob)->orig_rx_sw_if_index; |
There was a problem hiding this comment.
As far as I understand the original code, it added the count for regular interfaces and then down below also added same count for a super interface (like a bond) if it exists. Are we double counting by adding this code for sub-interfaces?
Also, since we skip this code if this is a policy drop, is the intention here to do this for sub-interfaces only when this is not a policy drop?
There was a problem hiding this comment.
Good question, and the diff is genuinely misleading here — sorry. That loop isn't new; I moved it.
It comes from patch 0008-bond-drop-stats-track-original-member-interface.patch. You can see it already present in the tree with only 0008 applied:
$ git apply .../0008-bond-drop-stats-track-original-member-interface.patch
$ sed -n '1052,1065p' src/vnet/interface_output.c
/* Also count against the original member interface if the
RX sw_if_index was rewritten (e.g. by bond-input). */
{
u32 orig_off = frame->n_vectors - n_left - count;
for (u32 j = 0; j < count; j++)
...
}The diff shows it as + at the top and - at the bottom because I merged it into my new loop, so the block is walked once instead of twice. Net effect on non-policy traffic: identical work, one pass.
On the double-counting concern specifically — these are two different mechanisms, and neither is about sub-interfaces in the same sense:
| what it charges | when it applies | |
|---|---|---|
sup_sw_if_index |
sub-interface → its parent (Ethernet0.100 → Ethernet0) |
when the RX interface is a sub-interface |
orig_rx_sw_if_index |
LAG member whose RX index was rewritten (BondEthernet0 → Ethernet0) |
bond traffic only |
orig_rx_sw_if_index is written in exactly one place — src/vnet/bonding/node.c, where bond-input rewrites sw_if_index[VLIB_RX] from the member to the bond — and is explicitly zeroed otherwise. It's also guarded by orig && orig != sw_if_index[0], so it can never charge the same interface twice.
The offsets are equivalent too: the original computed orig_off = frame->n_vectors - n_left - count after n_left -= count, which is the same value as my off = frame->n_vectors - n_left computed before the decrement.
is the intention here to do this for sub-interfaces only when this is not a policy drop?
Yes — intentional, and it applies to all three counters, not just this one:
- RX interface — via the reduced
count - super-interface — same reduced
count - original bond member — via the
continue
If the bond member were still charged for a policy drop, a mux port that happened to be a LAG member would keep reporting RX_DRP and the fix wouldn't work there. Suppressing it in one place and not the others would be the inconsistent option.
|
You're right to push on this, and you caught a real error in my PR description. Let me correct it, because the sentence you quoted was simply wrong. The claim you quoted is wrong — I've retracted it
That is not what SONiC does, and I shouldn't have written it. What upstream actually expects is that an ACL drop increments neither counter. From if acl_drops != pkt_number:
pytest.fail(...) # per-ACE ACL counter MUST increment
if not COMBINED_ACL_DROP_COUNTER:
executor.submit(ensure_no_l3_and_l2_drops, ...) # RX_DRP and RX_ERR must NOTSo an ACL drop belongs in the per-ACE ACL counter, and nowhere else. I've rewritten that section of the description. That correction doesn't change what the patch does — it only stops charging And you're right about the RFC tooI overstated it. The actual text is:
Buffer exhaustion is an example, not the definition. An ACL drop genuinely is "chosen to be discarded, no error detected" — so on a strict reading, your position is defensible and my "RFC says resource exhaustion only" framing was not. @aaronber0614 flagged the same thing. I've dropped that argument. Why the fix still belongs in VPP, not SONiCThe real justification is a SONiC-level convention that already exists — and which already names VPP specifically.
acl_l2:
- "x86_64-mlnx"
- "x86_64-dell.*"
- "x86_64-arista.*"
- "x86_64-cel_seastone.*"
- "x86_64-nokia.*"On those platforms, an ACL drop showing up in the L2 drop counter is expected and the test tolerates it. So this isn't VPP inventing a semantic, and it isn't a SONiC-side bug to fix: upstream has already declared that on VPP an ACL drop must not land in the L2/ The dual-ToR case was also called out explicitly and independently — sonic-mgmt#23577, which added the failing test, says:
That test carries no platform carve-out, so it applies to VPP as written. On "VPP not reporting any drops"Worth being clear that it still reports them — this only gates the interface discard counter. The denies remain fully visible where SONiC actually looks for them:
And only Thanks for the challenge — the description is materially more accurate for it. |
|
Thanks — and your read of the mechanism matches mine on every point, including the "Is anything consuming
|
|
Thanks for the response. Agreed on the double counting. I see how it won't get double counted. |
|
I found that drop_packets test_acl_drop and test_acl_egress_drop have been passing on VPP only by accident. There's a bug in the test that skips the drop-counter check instead of running it. Once I fix it, both tests FAIL on VPP t1-lag, confirming VPP counts ACL denies to RX_DRP, not just the dual-tor mux path. So VPP was never actually validated against the ACL/RX_DRP check, it just wasn't being checked. I put up a sonic-mgmt-side fix here (test bug fix + adding vpp to acl_l2): sonic-net/sonic-mgmt#27815. With these changes, the test now legitimately passes on sonic-vpp (tested it locally on t1-lag). Note though, the acl_l2 route of my fix conflicts with this PR's approach, and it doesn't fix dualtor_io test_upstream_standby_rx_drop_check either. |
|
I agree with @nhegde-microsoft and @AkeelAli, since many platforms in acl_l2 list are treating ACL drop as l2 drop, vpp can do the same. It is not 0 cost to behave like the other half, particularly the patch to maintain. |
What
An ACL deny is an intentional forwarding decision, not an interface discard, but
today the deny path sends the buffer to
error-drop, which charges it to theingress interface's drop counter (
/if/drops). SONiC exports that counter asSAI_PORT_STAT_IF_IN_DISCARDSand displays it asRX_DRP, so a port doingexactly what it was configured to do reports a large and growing discard count.
This adds
VNET_BUFFER_F_POLICY_DROPand stops charging policy denies to theinterface drop counter, while keeping them fully visible as per-node/per-ACE
errors.
Why
This is most visible on a dual-ToR standby mux port, where the standby ToR is
supposed to drop the traffic it receives from the server. The port reports a
~99%
RX_DRPrate while forwarding perfectly correctly:The counter semantics are the problem, not the drops themselves.
Where SONiC expects an ACL drop to be counted. Upstream
sonic-mgmtstatesthis directly. For
discard_group == "ACL",tests/drop_packets/test_drop_counters.pyasserts the per-ACE ACL rule counter increments, and then — on any platform not
listed as having combined counters — asserts that neither
RX_DRPnorRX_ERRmoved:So an ACL drop belongs in the per-ACE counter — not
RX_ERR, and notRX_DRP.VPP is already declared as such a platform.
tests/drop_packets/combined_drop_counters.ymllists the platforms where ACL and L2 drop counters legitimately are combined:
x86_64-kvm_x86_64-r0(VPP) appears in that file'sl2_l3list but deliberatelynot in
acl_l2— added by @AkeelAli insonic-mgmt#24031
("Enable test_drop_counters.py on Sonic-VPP"). Upstream has therefore already
declared that on VPP an ACL drop must not land in the L2/
RX_DRPcounter. TodayVPP contradicts that declaration; this patch makes it conform.
And the dual-ToR case was called out explicitly. The test that fails here was
added by a third party in
sonic-mgmt#23577, whose
description reads:
On RFC 1213. For completeness, the RFC does not settle this.
ifInDiscardsis "the number of inbound packets which were chosen to be discarded even though no
errors had been detected... One possible reason ... could be to free up
buffer space" — buffer exhaustion is an example, not the definition. A strict
reading leaves
RX_DRPdefensible for a policy drop. The justification for thischange is the SONiC-level convention above, not the RFC.
How
Three small changes:
src/vnet/buffer.h— allocateVNET_BUFFER_F_POLICY_DROPon bit 19, thefirst free bit. Per the in-tree convention comment,
AVAIL1..AVAIL9areredefined as
AVAIL1..AVAIL8andVNET_BUFFER_FLAGS_ALL_AVAILis updated.src/plugins/acl/dataplane_node.c— set the flag at the single ACL denychoke point in
acl_fa_inner_node_fn().src/vnet/interface_output.c—interface_drop_punt()discounts flaggedbuffers from the interface drop counter. It reuses the existing per-buffer
loop added by patch 0008, so there is no new pass over the frame.
The flag is set only for
ACL_FA_ERROR_ACL_DROP. Drops caused by a lack ofresources, such as
ACL_FA_ERROR_ACL_TOO_MANY_SESSIONS, are genuine discards andcontinue to increment the interface counter.
Denies remain fully observable — this suppresses one counter, not the visibility:
Verification
Built as VPP
2606-0.6and deployed to a KVM dual-ToR testbed(
vms-kvm-dual-vpp-t0-1,vlab-vpp-03/vlab-vpp-04).dualtor_io/test_normal_op.py::test_upstream_standby_rx_drop_checkpasses:Raw port counters on the standby mux port confirm the mechanism rather than just
the outcome — 5762 packets received and denied, none counted as interface drops:
RX_OKRX_DRPThe full patch series (
0001–0017plus this one) was also verified to applycleanly with
git applyagainst pinned VPP commit3f9e978d.Notes for reviewers
operator-configured DATAACL rules, not just the dual-ToR case. That matches the
upstream
discard_group == "ACL"expectation above, which is not dual-ToRspecific, and avoids the incoherent rule that a DATAACL deny would be an
interface discard on a normal port but not on a mux port. It is still a
deliberate semantic change and worth a second opinion.
ACL_ANYDEBUG_COUNTERand the per-ACEacl_factspackets_count, both untouched here.I found no consumer of
SAI_PORT_STAT_IF_IN_DISCARDS/RX_DRPinmonitorsonic-swss-commonthat keys on ACL denies.convention in
buffer.hexactly, andavail9is confirmed gone from the builtlibvnet.so.IN_PORTSsupport), where it originated. Thetwo changes are independent — they touch disjoint files — and [vpp][acl] match on ingress interface to support SAI ACL IN_PORTS #278 will be
rebased on top of whichever lands first.