summaryrefslogtreecommitdiff
path: root/lib/sflow_sampler.c
diff options
context:
space:
mode:
authorBen Pfaff <blp@nicira.com>2009-11-20 09:45:26 -0800
committerBen Pfaff <blp@nicira.com>2009-12-21 13:18:35 -0800
commitc72e245a0e2c979f4c14279b56183e2200905c6c (patch)
tree5df768afcb9e5f0d51dcd8e69727bea331b626cd /lib/sflow_sampler.c
parente4bfff8f0d2c01009759acb8adcab070327b5747 (diff)
downloadopenvswitch-c72e245a0e2c979f4c14279b56183e2200905c6c.tar.gz
Add InMon's sFlow Agent library to the build system.
The C source and header files added in this commit is covered under the InMon sFlow license at http://www.inmon.com/technology/sflowlicense.txt The library requires -Wno-unused to compile without warnings, so this commit adds that for building the sFlow code only. Automake can only change compiler flags on a per-library or per-program basis, so sFlow is built as a separate library. The library will be used in upcoming commits.
Diffstat (limited to 'lib/sflow_sampler.c')
-rw-r--r--lib/sflow_sampler.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/lib/sflow_sampler.c b/lib/sflow_sampler.c
new file mode 100644
index 000000000..759b5a22c
--- /dev/null
+++ b/lib/sflow_sampler.c
@@ -0,0 +1,183 @@
+/* Copyright (c) 2002-2009 InMon Corp. Licensed under the terms of the InMon sFlow licence: */
+/* http://www.inmon.com/technology/sflowlicense.txt */
+
+#include "sflow_api.h"
+
+
+/*_________________--------------------------__________________
+ _________________ sfl_sampler_init __________________
+ -----------------__________________________------------------
+*/
+
+void sfl_sampler_init(SFLSampler *sampler, SFLAgent *agent, SFLDataSource_instance *pdsi)
+{
+ /* copy the dsi in case it points to sampler->dsi, which we are about to clear.
+ (Thanks to Jagjit Choudray of Force 10 Networks for pointing out this bug) */
+ SFLDataSource_instance dsi = *pdsi;
+
+ /* preserve the *nxt pointer too, in case we are resetting this poller and it is
+ already part of the agent's linked list (thanks to Matt Woodly for pointing this out) */
+ SFLSampler *nxtPtr = sampler->nxt;
+
+ /* clear everything */
+ memset(sampler, 0, sizeof(*sampler));
+
+ /* restore the linked list ptr */
+ sampler->nxt = nxtPtr;
+
+ /* now copy in the parameters */
+ sampler->agent = agent;
+ sampler->dsi = dsi;
+
+ /* set defaults */
+ sampler->sFlowFsMaximumHeaderSize = SFL_DEFAULT_HEADER_SIZE;
+ sampler->sFlowFsPacketSamplingRate = SFL_DEFAULT_SAMPLING_RATE;
+}
+
+/*_________________--------------------------__________________
+ _________________ reset __________________
+ -----------------__________________________------------------
+*/
+
+static void reset(SFLSampler *sampler)
+{
+ SFLDataSource_instance dsi = sampler->dsi;
+ sfl_sampler_init(sampler, sampler->agent, &dsi);
+}
+
+/*_________________---------------------------__________________
+ _________________ MIB access __________________
+ -----------------___________________________------------------
+*/
+u_int32_t sfl_sampler_get_sFlowFsReceiver(SFLSampler *sampler) {
+ return sampler->sFlowFsReceiver;
+}
+void sfl_sampler_set_sFlowFsReceiver(SFLSampler *sampler, u_int32_t sFlowFsReceiver) {
+ sampler->sFlowFsReceiver = sFlowFsReceiver;
+ if(sFlowFsReceiver == 0) reset(sampler);
+ else {
+ /* retrieve and cache a direct pointer to my receiver */
+ sampler->myReceiver = sfl_agent_getReceiver(sampler->agent, sampler->sFlowFsReceiver);
+ }
+}
+u_int32_t sfl_sampler_get_sFlowFsPacketSamplingRate(SFLSampler *sampler) {
+ return sampler->sFlowFsPacketSamplingRate;
+}
+void sfl_sampler_set_sFlowFsPacketSamplingRate(SFLSampler *sampler, u_int32_t sFlowFsPacketSamplingRate) {
+ sampler->sFlowFsPacketSamplingRate = sFlowFsPacketSamplingRate;
+}
+u_int32_t sfl_sampler_get_sFlowFsMaximumHeaderSize(SFLSampler *sampler) {
+ return sampler->sFlowFsMaximumHeaderSize;
+}
+void sfl_sampler_set_sFlowFsMaximumHeaderSize(SFLSampler *sampler, u_int32_t sFlowFsMaximumHeaderSize) {
+ sampler->sFlowFsMaximumHeaderSize = sFlowFsMaximumHeaderSize;
+}
+
+/* call this to set a maximum samples-per-second threshold. If the sampler reaches this
+ threshold it will automatically back off the sampling rate. A value of 0 disables the
+ mechanism */
+void sfl_sampler_set_backoffThreshold(SFLSampler *sampler, u_int32_t samplesPerSecond) {
+ sampler->backoffThreshold = samplesPerSecond;
+}
+u_int32_t sfl_sampler_get_backoffThreshold(SFLSampler *sampler) {
+ return sampler->backoffThreshold;
+}
+u_int32_t sfl_sampler_get_samplesLastTick(SFLSampler *sampler) {
+ return sampler->samplesLastTick;
+}
+
+/*_________________---------------------------------__________________
+ _________________ sequence number reset __________________
+ -----------------_________________________________------------------
+ Used by the agent to indicate a samplePool discontinuity
+ so that the sflow collector will know to ignore the next delta.
+*/
+void sfl_sampler_resetFlowSeqNo(SFLSampler *sampler) { sampler->flowSampleSeqNo = 0; }
+
+
+/*_________________---------------------------__________________
+ _________________ sfl_sampler_tick __________________
+ -----------------___________________________------------------
+*/
+
+void sfl_sampler_tick(SFLSampler *sampler, time_t now)
+{
+ if(sampler->backoffThreshold && sampler->samplesThisTick > sampler->backoffThreshold) {
+ /* automatic backoff. If using hardware sampling then this is where you have to
+ * call out to change the sampling rate and make sure that any other registers/variables
+ * that hold this value are updated.
+ */
+ sampler->sFlowFsPacketSamplingRate *= 2;
+ }
+ sampler->samplesLastTick = sampler->samplesThisTick;
+ sampler->samplesThisTick = 0;
+}
+
+
+
+/*_________________------------------------------__________________
+ _________________ sfl_sampler_writeFlowSample __________________
+ -----------------______________________________------------------
+*/
+
+void sfl_sampler_writeFlowSample(SFLSampler *sampler, SFL_FLOW_SAMPLE_TYPE *fs)
+{
+ if(fs == NULL) return;
+ sampler->samplesThisTick++;
+ /* increment the sequence number */
+ fs->sequence_number = ++sampler->flowSampleSeqNo;
+ /* copy the other header fields in */
+#ifdef SFL_USE_32BIT_INDEX
+ fs->ds_class = SFL_DS_CLASS(sampler->dsi);
+ fs->ds_index = SFL_DS_INDEX(sampler->dsi);
+#else
+ fs->source_id = SFL_DS_DATASOURCE(sampler->dsi);
+#endif
+ /* the sampling rate may have been set already. */
+ if(fs->sampling_rate == 0) fs->sampling_rate = sampler->sFlowFsPacketSamplingRate;
+ /* the samplePool may be maintained upstream too. */
+ if( fs->sample_pool == 0) fs->sample_pool = sampler->samplePool;
+ /* sent to my receiver */
+ if(sampler->myReceiver) sfl_receiver_writeFlowSample(sampler->myReceiver, fs);
+}
+
+#ifdef SFLOW_SOFTWARE_SAMPLING
+
+/* ================== software sampling ========================*/
+
+/*_________________---------------------------__________________
+ _________________ nextRandomSkip __________________
+ -----------------___________________________------------------
+*/
+
+inline static u_int32_t nextRandomSkip(u_int32_t mean)
+{
+ if(mean == 0 || mean == 1) return 1;
+ return ((random() % ((2 * mean) - 1)) + 1);
+}
+
+/*_________________---------------------------__________________
+ _________________ sfl_sampler_takeSample __________________
+ -----------------___________________________------------------
+*/
+
+int sfl_sampler_takeSample(SFLSampler *sampler)
+{
+ if(sampler->skip == 0) {
+ /* first time - seed the random number generator */
+ srandom(SFL_DS_INDEX(sampler->dsi));
+ sampler->skip = nextRandomSkip(sampler->sFlowFsPacketSamplingRate);
+ }
+
+ /* increment the samplePool */
+ sampler->samplePool++;
+
+ if(--sampler->skip == 0) {
+ /* reached zero. Set the next skip and return true. */
+ sampler->skip = nextRandomSkip(sampler->sFlowFsPacketSamplingRate);
+ return 1;
+ }
+ return 0;
+}
+
+#endif /* SFLOW_SOFTWARE_SAMPLING */