sFlow Phase Three Per Port Rate Patch - #261
Conversation
…, rate 0 inherits global. Setter added but API/CLI wiring lands in a follow-up PR. Signed-off-by: Ritvik Uppal <rituppal@cisco.com>
|
/azp run |
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
| memcpy (sample.header, en, hdr); | ||
| if (PREDICT_FALSE (!sflow_fifo_enqueue (&sfwk->fifo, &sample))) | ||
| - sfwk->drop++; | ||
| + sfwk->drop++; |
| skipping the rest. */ | ||
| - sfwk->skip -= pkts; | ||
| - sfwk->pool += pkts; | ||
| + sfif->skip -= pkts; |
| + u32 samplingN; | ||
| + u32 skip; | ||
| + u32 pool; | ||
| + u32 seed; |
There was a problem hiding this comment.
Now that skip/pool/seed are per-interface instead of per-thread, multiple VPP threads may touch the same interface at once, causing a data race and miscounts. Can these be indexed per-thread and per-interface so each thread keeps its own counters? samplingN can stay shared since it's only set on the CLI/API path.
503f954 to
b5491f4
Compare
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
Signed-off-by: Ritvik Uppal <rituppal@cisco.com>
0a4bece to
f60d134
Compare
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
|
Moving this comment from the commit thread to the PR thread and expanding it to include more explanation: This approach is assuming all packets in the frame/vector presented to the worker thread are ingressing from (or egressing to) just one interface. I don't believe this is a safe assumption. To apply sampling on a per-interface basis in the dataplane node would require testing each packet separately, and the extra instructions/branching this would entail is likely to hurt performance significantly. Per-interface sampling rates are not important enough to justify slowing down the forwarding performance of the switch. However I do think we can support it if we adopt a different approach... that will also be easier to implement and test. So the suggested alternative way to support per-interface sampling rates is as follows: (1) Leave the data plane as it was. Whole articles were written about that code(!) Best not to touch it. Anything extra you do here will negatively impact the forwarding performance of the switch. There is one possible drawback that I will address here - what if an aggressive sampling rate is configured on a low-speed port, and a more sparse sampling-rate is configured on a high-speed port? The data-plane will be forced to sample all traffic at the aggressive rate, and there is a risk that too many samples will be generated, so that forwarding performance is affected and the FIFOs carrying samples from worker threads to main thread will start dropping samples, most of which the main thread was about to throw away. The answer is that (a) it is not common for a production switch to be given more than one sampling rate, and if it ever happens the difference is likely to be a factor of 8 or less (e.g. 1-in-1024 on one port and 1-in-8192 on another), and (b) in tests, the mechanism of forwarding samples via dedicated lock-free FIFOs from workers to main thread was efficient, so that the overhead of sending 8x or 16x or even 32x more samples that are actually required for export is not too expensive to accommodate. So the implementation suggestion is to apply per-interface sub-sampling here: You'll need to index into a vector of per-interface state that includes two integers: a worker_samples counter and the sub-sampling rate that should be applied. The sub-sampling rates will need to be recomputed whenever any change is made to the sampling-rate settings in the configuration. You might choose to implement is as a binary mask. So if the sub-sampling rate for interface X is to be 1:8 then the mask will be decimal 8 - 1 = binary 0x0111 and the sub-sampling test will be something like: |
Adds native per-port sample rates to the VPP sflow plugin by moving the random-skip sampling state from per-worker-thread to per-interface.
samplingN == 0 means inherit the global rate, so unconfigured ports are unchanged (backward compatible). Each port's rate is independent — changing one port doesn't affect others. Pairs with 0013 (direction) and 0014 (API/CLI) to complete Phase 3.