diff options
| author | Ben Pfaff <blp@nicira.com> | 2009-11-20 09:45:26 -0800 |
|---|---|---|
| committer | Ben Pfaff <blp@nicira.com> | 2009-12-21 13:18:35 -0800 |
| commit | c72e245a0e2c979f4c14279b56183e2200905c6c (patch) | |
| tree | 5df768afcb9e5f0d51dcd8e69727bea331b626cd /lib/sflow_sampler.c | |
| parent | e4bfff8f0d2c01009759acb8adcab070327b5747 (diff) | |
| download | openvswitch-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.c | 183 |
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 */ |
