Skip to content

[Nexthop][fboss2-dev] Add config and delete interface sflow sample-dest - #1522

Open
vybhav-nexthop wants to merge 3 commits into
facebook:mainfrom
nexthop-ai:sflow-sample-dest
Open

[Nexthop][fboss2-dev] Add config and delete interface sflow sample-dest#1522
vybhav-nexthop wants to merge 3 commits into
facebook:mainfrom
nexthop-ai:sflow-sample-dest

Conversation

@vybhav-nexthop

@vybhav-nexthop vybhav-nexthop commented Aug 17, 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

Background: what sFlow sampling is and what sample-dest chooses

A switch forwards far more traffic than it could ever copy for analysis, so sFlow samples instead: the ASIC picks one in N packets on a port (N is Port.sFlowIngressRate/sFlowEgressRate) and exports just those. Statistically that is enough to see top talkers, flow mix, and anomalies without touching line-rate forwarding.

Port.sampleDest chooses where each sampled copy goes, and the two options trade CPU cost against flexibility:

  • cpu: the ASIC punts the sample to the switch CPU, and the agent wraps it into sFlow datagrams for the configured collectors. Flexible, but each sample costs CPU and punt-path bandwidth.
  • mirror: the ASIC forwards the sample out the port's ingress mirror session straight to a remote collector box, encapsulated, with no CPU involvement. Line rate, but the collector does all the work, and it only exists for ingress sampling.

The field is a modifier: it takes effect once a port's sampling rate is nonzero, and an unset field leaves the ASIC default behavior.

What: Adds fboss2-dev config interface <ports> sflow sample-dest <cpu|mirror> and its delete counterpart delete interface <ports> sflow sample-dest.

  • config sets Port.sampleDest: sFlow samples are processed on-box (cpu) or sent to the port's ingress mirror (mirror).
  • delete clears the optional field, returning the port to its unset default.

Why: Port.sampleDest had no CLI coverage in either direction.

How: New sflow subcommand branch under config interface / delete interface, in the same tree shape as ipv6/switchport. The CLI refuses mirror when the port has a non-zero sFlowEgressRate. That is the constraint the agent enforces (ApplyThriftConfig: "Egress sampling to mirror destination is unsupported"), but the CLI catches it first with a targeted message, before the config is touched. Hitless: sampling is (re)programmed from the port delta at runtime (SaiPortManager::addSamplePacket/removeSamplePacket).

Sample usage

$ fboss2-dev config interface eth1/1/1 sflow sample-dest cpu
Successfully set sFlow sample destination for interface(s) eth1/1/1 to cpu
$ fboss2-dev config interface eth1/2/1 sflow sample-dest mirror
Port eth1/2/1: sample-dest mirror requires sFlowEgressRate 0 — egress sampling to a mirror destination is unsupported
$ fboss2-dev delete interface eth1/1/1 sflow sample-dest
Reset sFlow sample destination for interface(s) eth1/1/1

Test Plan

Unit tests (13 new, config + delete):

[==========] 13 tests from 1 test suite ran. (1034 ms total)
[  PASSED  ] 13 tests.

Full config suite: //fboss/cli/fboss2/test/config:cmd_config_test PASSED in 53.1s.

Integration test on an Nexthop DUT: set cpu, verify it lands in the running config, delete, verify the field is unset again.

[       OK ] ConfigSflowSampleDestTest.SetThenDeleteSampleDest (159 ms)
[  PASSED  ] 1 test.

All of the above ran against the internal tree this commit was cherry-picked from. The upstream tree was not built locally; this PR's CI is the build validation for the rebased commit.

Review Findings

Pre-publication review (5 reviewers + verifier) raised three findings, all fixed before push: mixed interface lists now report L3-only names as skipped in both commands (a 13th unit test covers it), and the integration test gained a best-effort TearDown that clears a committed sampleDest on failure.

config interface <ports> sflow sample-dest <cpu|mirror> sets
Port.sampleDest, choosing whether sFlow samples are processed on-box
(cpu) or sent to the port's ingress mirror (mirror). The CLI refuses
mirror while the port has a non-zero sFlowEgressRate, mirroring the
agent's own validation (egress sampling to a mirror destination is
unsupported) with a targeted message.

delete interface <ports> sflow sample-dest clears the optional field,
returning the port to its unset default.

Both are hitless: sampling is (re)programmed from the port delta at
runtime (SaiPortManager add/removeSamplePacket).

Mixed interface lists report L3-only names as skipped (sampleDest is a
Port attribute), and the integration test carries a best-effort
TearDown that clears a committed sampleDest on failure.
@vybhav-nexthop
vybhav-nexthop requested review from a team as code owners August 17, 2026 07:30
@meta-cla meta-cla Bot added the CLA Signed label Aug 17, 2026

@joseph5wu joseph5wu 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.

Let's follow how we handle multiple interface attributes in CmdConfigInterface and do the same thing for CmdConfigInterfaceSflow rather than create three different classes.

using RetType = std::string;
};

class CmdConfigInterfaceSflowSampleDest

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.

Instead of creating a standalone CmdConfigInterfaceSflowSampleDest, can we have CmdConfigInterfaceSflow to handle all sflow related attributes in the same class:

  • sample_dest
  • ingress_rate
  • egress_rate?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

will add these 3 here in this PR itself, since they seemed to be simple enough to implement

…eSflow

Per review, collapse the standalone CmdConfigInterfaceSflowSampleDest /
CmdDeleteInterfaceSflowSampleDest leaf classes into their
CmdConfigInterfaceSflow / CmdDeleteInterfaceSflow parents, dispatching
on attribute name the same way CmdConfigInterface handles its own
attributes. This keeps future sflow attributes (ingress-rate,
egress-rate) to a single class each, instead of a new leaf class and
CLI11 subcommand per attribute.

CLI surface is unchanged: `config interface <ports> sflow sample-dest
<cpu|mirror>` and `delete interface <ports> sflow sample-dest` behave
identically; only the C++ class structure and the CLI11 command-tree
registration changed.
Per review, CmdConfigInterfaceSflow / CmdDeleteInterfaceSflow should
handle all sflow attributes: sample_dest, ingress_rate, egress_rate.
Adds the two rate attributes as new branches in the same dispatch
already added for sample-dest, mapping to
Port.sFlowIngressRate/sFlowEgressRate:

  config interface <ports> sflow ingress-rate <N>
  config interface <ports> sflow egress-rate <N>
  delete interface <ports> sflow ingress-rate    (resets to 0)
  delete interface <ports> sflow egress-rate     (resets to 0)

Rate values must be a non-negative integer. egress-rate carries the
same MIRROR/sFlowEgressRate constraint sample-dest already enforces
(ApplyThriftConfig: "Egress sampling to mirror destination is
unsupported"), checked from the other direction: a port whose
sample-dest is already MIRROR refuses a non-zero egress-rate.

Unit tests: 6 new (setIngressRate, setEgressRate, rateValueInvalid,
egressRateRefusedWhenMirror, deleteClearsIngressRate,
deleteClearsEgressRate), plus fixed two existing tests that used
ingress-rate as a stand-in for an unrecognized attribute (now a real
one) to use a bogus attribute name instead.

Integration test (new file, minimal): ConfigSflowRateTest covers the
config/delete round trip for both rate attributes in one DUT run,
mirroring ConfigSflowSampleDestTest's shape. Run on an Nexthop DUT
(NH-4010-F): PASSED.
@vybhav-nexthop

Copy link
Copy Markdown
Contributor Author

Added ingress-rate and egress-rate too, in 0b89a7e: config/delete interface <ports> sflow ingress-rate|egress-rate <N>, mapping to Port.sFlowIngressRate/sFlowEgressRate, both handled by the same CmdConfigInterfaceSflow/CmdDeleteInterfaceSflow class as sample-dest. egress-rate carries the same MIRROR/egress-rate constraint sample-dest already enforces, checked from the other direction (refuses a non-zero egress-rate on a port whose sample-dest is already MIRROR).

All three attributes now go through one class each on the config/delete side, per your original comment.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants