[Nexthop][fboss2-dev] Add config and delete interface sflow sample-dest - #1522
[Nexthop][fboss2-dev] Add config and delete interface sflow sample-dest#1522vybhav-nexthop wants to merge 4 commits into
Conversation
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.
joseph5wu
left a comment
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
|
Added ingress-rate and egress-rate too, in 0b89a7e: All three attributes now go through one class each on the config/delete side, per your original comment. |
joseph5wu
left a comment
There was a problem hiding this comment.
Overall it looks pretty good to me. Just make sure you can support setting multiple attributes at the same time like CmdConfigInterface.cpp
| if (attr == kAttrSampleDest) { | ||
| // The agent rejects egress sampling to a mirror destination | ||
| // (ApplyThriftConfig throws for MIRROR + sFlowEgressRate > 0); fail | ||
| // here with a targeted message before touching the config. | ||
| if (dest == cfg::SampleDestination::MIRROR && | ||
| *port->sFlowEgressRate() > 0) { | ||
| throw std::invalid_argument( | ||
| fmt::format( | ||
| "Port {}: sample-dest {} requires sFlowEgressRate 0 — egress " | ||
| "sampling to a mirror destination is unsupported", | ||
| *port->name(), | ||
| kSampleDestMirror)); | ||
| } | ||
| port->sampleDest() = dest; | ||
| } else if (attr == kAttrIngressRate) { | ||
| port->sFlowIngressRate() = rate; | ||
| } else { | ||
| // Same MIRROR/egress-rate constraint as above, checked from the other | ||
| // side: refuse a non-zero egress-rate on a port whose sampleDest is | ||
| // already MIRROR. | ||
| if (rate > 0 && port->sampleDest().has_value() && | ||
| *port->sampleDest() == cfg::SampleDestination::MIRROR) { | ||
| throw std::invalid_argument( | ||
| fmt::format( | ||
| "Port {}: egress-rate must be 0 while sample-dest is {} — " | ||
| "egress sampling to a mirror destination is unsupported", | ||
| *port->name(), | ||
| kSampleDestMirror)); | ||
| } | ||
| port->sFlowEgressRate() = rate; | ||
| } |
There was a problem hiding this comment.
Instead of using if-else, can you support just if independently for the three attributes?
This way we can support a combined command like fboss2-dev config interface XXX sflow sample-dest CPU ingress-rate XXX egress-rate YYY?
| std::string attrLabel = attr == kAttrSampleDest | ||
| ? "sample destination" | ||
| : (attr == kAttrIngressRate ? "ingress-rate" : "egress-rate"); | ||
| std::string message = fmt::format( | ||
| "Successfully set sFlow {} for interface(s) {} to {}", | ||
| attrLabel, | ||
| folly::join(", ", updatedNames), | ||
| displayValue); | ||
| if (!skippedNames.empty()) { | ||
| message += | ||
| fmt::format("; skipped (no port): {}", folly::join(", ", skippedNames)); | ||
| } |
There was a problem hiding this comment.
The benefit to have the same CmdConfigInterfaceSflow.cpp to control three attributes is to program the three attributes at the same time. Let's make sure we don't make it exclusive
There was a problem hiding this comment.
got it , will do it the next commit . Thanks
Per review, CmdConfigInterfaceSflow / CmdDeleteInterfaceSflow should be able to program sample-dest, ingress-rate, and egress-rate together in a single command, not mutually exclusive: config interface <ports> sflow sample-dest cpu ingress-rate 100 egress-rate 50 delete interface <ports> sflow sample-dest ingress-rate egress-rate SflowAttrArgs / SflowDeleteAttrArgs now parse repeated <attr> <value> pairs (config) / repeated <attr> names (delete) instead of exactly one, validating attribute names at construction (last occurrence of a repeated attribute wins). queryClient extracts an optional value for each of the three attributes up front, then applies whichever are present together per port. The mirror/egress-rate cross-check now evaluates the combined effective state -- the new value if given this call, else the port's existing value -- so "sample-dest mirror egress-rate 0" succeeds and "sample-dest mirror egress-rate 50" fails, regardless of token order. Unit tests: added configArgsMultiplePairsValid, deleteArgsMultipleValid, combinedAttributesAppliedTogether, combinedMirrorWithZeroEgressRateSucceeds, combinedMirrorWithNonzeroEgressRateFails, combinedRejectionIsOrderIndependent, repeatedAttributeLastValueWins, deleteClearsMultipleAttributesTogether. Renamed the two arity tests for clarity; unknownAttr/deleteUnknownAttrThrows now assert directly on the arg-type constructor (validation moved there). Integration test: ConfigSflowRateTest now issues one combined config command (ingress-rate + egress-rate) and one combined delete, instead of two separate commands each, to actually exercise the new capability end-to-end. Run on a hardware DUT: PASSED.
|
@joseph5wu has imported this pull request. If you are a Meta employee, you can view this in D117229194. |
|
@joseph5wu merged this pull request in 2c207c4. |
Pre-submission checklist
pip install -r requirements-dev.txt && pre-commit installpre-commit runSummary
Background: what sFlow sampling is and what these three attributes control
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 and exports just those. Statistically that is enough to see top talkers, flow mix, and anomalies without touching line-rate forwarding.
Three
Portfields control this:sFlowIngressRate/sFlowEgressRate: the sampling rate in each direction. Every 1/N packets is sampled; 0 disables sampling in that direction.sampleDest: where each sampled copy goes once sampling is enabled, trading 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 —mirroris invalid whilesFlowEgressRateis nonzero.What: Adds
fboss2-dev config interface <ports> sflow <attr> <value> [<attr> <value> ...]and its delete counterpart, for three attributes. Any combination can be set (or deleted) together in one command:sample-dest <cpu|mirror>Port.sampleDestingress-rate <N>Port.sFlowIngressRate0egress-rate <N>Port.sFlowEgressRate0Why: none of these three fields had CLI coverage in either direction.
How:
CmdConfigInterfaceSflow/CmdDeleteInterfaceSfloweach parse one or more<attr> <value>pairs (or<attr>names for delete) and apply every attribute present in the call together, the same wayCmdConfigInterfacehandles its own attributes (mtu,description, ...) — rather than a separate leaf class and CLI11 subcommand per attribute, and rather than an if/else chain that would only let one attribute take effect per call. Adding a future sflow attribute is one more branch in the same file.Validation: rate values must be a non-negative integer.
sample-dest mirroris refused when the port'ssFlowEgressRate— from this same command if given, else the port's current value — is nonzero, and symmetrically, a nonzeroegress-rateis refused when the port's effectivesample-destismirror. This is evaluated against the combined result of the whole command, sosample-dest mirror egress-rate 0succeeds andsample-dest mirror egress-rate 50fails regardless of which attribute is given first. It's the same constraint the agent enforces (ApplyThriftConfig: "Egress sampling to mirror destination is unsupported"), caught by the CLI before the config is touched. Hitless: sampling is (re)programmed from the port delta at runtime (SaiPortManager::addSamplePacket/removeSamplePacket).Sample usage
Changed files
commands/config/interface/sflow/CmdConfigInterfaceSflow.{h,cpp}<attr> <value>pairs, applies all attributes present togethercommands/delete/interface/sflow/CmdDeleteInterfaceSflow.{h,cpp}<attr>names, resets all present togetherCmdListConfig.cppsflowis now a leaf command (was a stub + one nested subcommand per attribute)test/config/CmdConfigInterfaceSflowSampleDestTest.cpptest/integration_test/ConfigSflowSampleDestTest.cppsample-destset/delete round triptest/integration_test/ConfigSflowRateTest.cppingress-rate+egress-rateset/delete round tripTest Plan
Unit tests (29, config + delete, covering all three attributes individually, combined in one call, and the order-independent cross-attribute mirror/egress-rate validation): all pass.
Full config suite:
//fboss/cli/fboss2/test/config:cmd_config_test PASSED.Integration tests on a hardware DUT —
sample-dest(set cpu, verify running config, delete, verify unset) and combinedingress-rate+egress-rate(set both in one command, verify running config, delete both in one command, verify reset to 0):Agents stayed active throughout; DUT config verified restored to its pre-test state.