Skip to content

[Nexthop][fboss2-dev] Move a QoS ingress codepoint between traffic classes instead of duplicating it - #1763

Open
hillol-nexthop wants to merge 1 commit into
meta:mainfrom
nexthop-ai:qos-ingress-codepoint-move
Open

hillol-nexthop wants to merge 1 commit into
meta:mainfrom
nexthop-ai:qos-ingress-codepoint-move

Conversation

@hillol-nexthop

@hillol-nexthop hillol-nexthop commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Pre-submission checklist

  • I've ran the linters locally and fixed lint errors related to the files I modified in this PR. You can install the linters by running pip install -r requirements-dev.txt && pre-commit install
  • pre-commit run

Summary

fboss2-dev config qos policy <P> map dscp <D> traffic-class <T> accepted a DSCP that another traffic class already carried and simply appended it to the new class's fromDscpToTrafficClass list. The staged config then mapped one DSCP to two traffic classes, the CLI reported success, and the commit was classified hitless. The agent builds its DscpMap from that list without validation and SaiQosMapManager hands both rows to SAI, so which class a packet with that DSCP actually lands in is SDK-defined. The only way to move a DSCP correctly was delete qos policy <P> map dscp <D> followed by the add.

A DSCP (and likewise an MPLS EXP or DOT1P codepoint) classifies to exactly one traffic class, so re-mapping it must move it. The same updateQosMapEntry helper serves mpls-exp and dot1p, so they had the identical defect.

What changed

  • The ingress add (<type> <value> traffic-class <tc>) now detaches the codepoint from any other class before attaching it, drops an entry left with no ingress codepoints and no egress rewrite, and leaves the target class's own list untouched, so re-issuing a mapping is a no-op while a duplicate left behind by the old CLI still gets cleaned up. The user sees the usual success message, since the result is exactly what was asked for.
  • The detach logic is the eraseCodepoint helper that delete qos policy map already used. It moved into QosPolicyUtils as eraseQosMapCodepoint with eraseDscp/eraseExp/erasePcp wrappers, so add and delete share one definition and cannot drift.
  • Egress rewrites (traffic-class <tc> <type> <value>) are untouched. Several classes may legitimately rewrite to the same codepoint.
  • Stale "additive" wording in the command's header and parser comments is corrected.

Not in this PR: agent-side rejection of a config that already carries a duplicated ingress codepoint (ApplyThriftConfig). That would turn a config the agent accepts today into a reload failure on upgrade, so it should be a separate decision.

Test Plan

New unit test fboss/cli/fboss2/test/config/CmdConfigQosPolicyMapTest.cpp (11 cases): move between classes, a tc0→tc2→tc4 move sequence, re-add is a no-op, re-add heals a duplicate an older CLI left behind, moving the last codepoint drops the entry unless it has an egress rewrite, egress rewrites are not moved, mpls-exp and dot1p moves, dot1p on a policy with no pcpMaps, and add-then-delete agreeing on ownership.

./fboss2_cmd_config_test --gtest_filter='CmdConfigQosPolicyMapTestFixture.*:CmdDeleteQosPolicyTestFixture.*'
[  PASSED  ] 35 tests.

New integration test ConfigQosPolicyMapTest.DscpMoveBetweenTrafficClasses mirrors the field repro end to end (seed under tc 0, commit, move to tc 2, commit, move to tc 4, commit, assert a single owner after each step and that the emptied tc 2 entry is gone). Full ConfigQosPolicyMapTest.* suite run on an NH-4010-F via run_test.py fboss2_integration:

[       OK ] ConfigQosPolicyMapTest.DscpMoveBetweenTrafficClasses (276 ms)
   PASSED : 7
   FAILED : 0

Manual repro of the original commands on the same device with the new fboss2-dev, staged config after dscp 9 tc 0, dscp 8 tc 0, dscp 9 tc 2, dscp 9 tc 4:

[{"fromDscpToTrafficClass":[8],"internalTrafficClass":0},{"fromDscpToTrafficClass":[9],"internalTrafficClass":4}]

clang-tidy and clang-format clean on all changed files.

…cating it

`config qos policy <p> map dscp <v> traffic-class <tc>` appended the
codepoint to the target class's ingress list without removing it from
the class that already carried it, so the staged config mapped one DSCP
to two traffic classes. The agent and SAI accept that silently and the
resulting classification is SDK-defined. The same helper serves mpls-exp
and dot1p, so they had the same defect.

The ingress add now detaches the codepoint from any other class first,
dropping an entry left with no ingress codepoints and no egress rewrite,
and leaves the target class untouched, so re-issuing a mapping is a
no-op while a duplicate an older CLI left behind still gets cleaned up. The
detach logic is the one `delete qos policy map` already used, moved into
QosPolicyUtils so add and delete cannot drift. Egress rewrites are
untouched: several classes may legitimately rewrite to one codepoint.
@hillol-nexthop
hillol-nexthop requested review from a team as code owners October 13, 2026 11:09
@meta-cla meta-cla Bot added the CLA Signed label Oct 13, 2026
@github-actions github-actions Bot added nexthop project:fboss2-dev FBOSS project: fboss2-dev labels Oct 30, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant