1 /* Copyright (c) 2002-2009 InMon Corp. Licensed under the terms of the InMon sFlow licence: */
2 /* http://www.inmon.com/technology/sflowlicense.txt */
7 /*_________________--------------------------__________________
8 _________________ sfl_sampler_init __________________
9 -----------------__________________________------------------
12 void sfl_sampler_init(SFLSampler *sampler, SFLAgent *agent, SFLDataSource_instance *pdsi)
14 /* copy the dsi in case it points to sampler->dsi, which we are about to clear.
15 (Thanks to Jagjit Choudray of Force 10 Networks for pointing out this bug) */
16 SFLDataSource_instance dsi = *pdsi;
18 /* preserve the *nxt pointer too, in case we are resetting this poller and it is
19 already part of the agent's linked list (thanks to Matt Woodly for pointing this out) */
20 SFLSampler *nxtPtr = sampler->nxt;
22 /* clear everything */
23 memset(sampler, 0, sizeof(*sampler));
25 /* restore the linked list ptr */
26 sampler->nxt = nxtPtr;
28 /* now copy in the parameters */
29 sampler->agent = agent;
33 sampler->sFlowFsMaximumHeaderSize = SFL_DEFAULT_HEADER_SIZE;
34 sampler->sFlowFsPacketSamplingRate = SFL_DEFAULT_SAMPLING_RATE;
37 /*_________________--------------------------__________________
38 _________________ reset __________________
39 -----------------__________________________------------------
42 static void reset(SFLSampler *sampler)
44 SFLDataSource_instance dsi = sampler->dsi;
45 sfl_sampler_init(sampler, sampler->agent, &dsi);
48 /*_________________---------------------------__________________
49 _________________ MIB access __________________
50 -----------------___________________________------------------
52 u_int32_t sfl_sampler_get_sFlowFsReceiver(SFLSampler *sampler) {
53 return sampler->sFlowFsReceiver;
55 void sfl_sampler_set_sFlowFsReceiver(SFLSampler *sampler, u_int32_t sFlowFsReceiver) {
56 sampler->sFlowFsReceiver = sFlowFsReceiver;
57 if(sFlowFsReceiver == 0) reset(sampler);
59 /* retrieve and cache a direct pointer to my receiver */
60 sampler->myReceiver = sfl_agent_getReceiver(sampler->agent, sampler->sFlowFsReceiver);
63 u_int32_t sfl_sampler_get_sFlowFsPacketSamplingRate(SFLSampler *sampler) {
64 return sampler->sFlowFsPacketSamplingRate;
66 void sfl_sampler_set_sFlowFsPacketSamplingRate(SFLSampler *sampler, u_int32_t sFlowFsPacketSamplingRate) {
67 sampler->sFlowFsPacketSamplingRate = sFlowFsPacketSamplingRate;
69 u_int32_t sfl_sampler_get_sFlowFsMaximumHeaderSize(SFLSampler *sampler) {
70 return sampler->sFlowFsMaximumHeaderSize;
72 void sfl_sampler_set_sFlowFsMaximumHeaderSize(SFLSampler *sampler, u_int32_t sFlowFsMaximumHeaderSize) {
73 sampler->sFlowFsMaximumHeaderSize = sFlowFsMaximumHeaderSize;
76 /* call this to set a maximum samples-per-second threshold. If the sampler reaches this
77 threshold it will automatically back off the sampling rate. A value of 0 disables the
79 void sfl_sampler_set_backoffThreshold(SFLSampler *sampler, u_int32_t samplesPerSecond) {
80 sampler->backoffThreshold = samplesPerSecond;
82 u_int32_t sfl_sampler_get_backoffThreshold(SFLSampler *sampler) {
83 return sampler->backoffThreshold;
85 u_int32_t sfl_sampler_get_samplesLastTick(SFLSampler *sampler) {
86 return sampler->samplesLastTick;
89 /*_________________---------------------------------__________________
90 _________________ sequence number reset __________________
91 -----------------_________________________________------------------
92 Used by the agent to indicate a samplePool discontinuity
93 so that the sflow collector will know to ignore the next delta.
95 void sfl_sampler_resetFlowSeqNo(SFLSampler *sampler) { sampler->flowSampleSeqNo = 0; }
98 /*_________________---------------------------__________________
99 _________________ sfl_sampler_tick __________________
100 -----------------___________________________------------------
103 void sfl_sampler_tick(SFLSampler *sampler, time_t now)
105 if(sampler->backoffThreshold && sampler->samplesThisTick > sampler->backoffThreshold) {
106 /* automatic backoff. If using hardware sampling then this is where you have to
107 * call out to change the sampling rate and make sure that any other registers/variables
108 * that hold this value are updated.
110 sampler->sFlowFsPacketSamplingRate *= 2;
112 sampler->samplesLastTick = sampler->samplesThisTick;
113 sampler->samplesThisTick = 0;
118 /*_________________------------------------------__________________
119 _________________ sfl_sampler_writeFlowSample __________________
120 -----------------______________________________------------------
123 void sfl_sampler_writeFlowSample(SFLSampler *sampler, SFL_FLOW_SAMPLE_TYPE *fs)
125 if(fs == NULL) return;
126 sampler->samplesThisTick++;
127 /* increment the sequence number */
128 fs->sequence_number = ++sampler->flowSampleSeqNo;
129 /* copy the other header fields in */
130 #ifdef SFL_USE_32BIT_INDEX
131 fs->ds_class = SFL_DS_CLASS(sampler->dsi);
132 fs->ds_index = SFL_DS_INDEX(sampler->dsi);
134 fs->source_id = SFL_DS_DATASOURCE(sampler->dsi);
136 /* the sampling rate may have been set already. */
137 if(fs->sampling_rate == 0) fs->sampling_rate = sampler->sFlowFsPacketSamplingRate;
138 /* the samplePool may be maintained upstream too. */
139 if( fs->sample_pool == 0) fs->sample_pool = sampler->samplePool;
140 /* sent to my receiver */
141 if(sampler->myReceiver) sfl_receiver_writeFlowSample(sampler->myReceiver, fs);
144 #ifdef SFLOW_SOFTWARE_SAMPLING
146 /* ================== software sampling ========================*/
148 /*_________________---------------------------__________________
149 _________________ nextRandomSkip __________________
150 -----------------___________________________------------------
153 inline static u_int32_t nextRandomSkip(u_int32_t mean)
155 if(mean == 0 || mean == 1) return 1;
156 return ((random() % ((2 * mean) - 1)) + 1);
159 /*_________________---------------------------__________________
160 _________________ sfl_sampler_takeSample __________________
161 -----------------___________________________------------------
164 int sfl_sampler_takeSample(SFLSampler *sampler)
166 if(sampler->skip == 0) {
167 /* first time - seed the random number generator */
168 srandom(SFL_DS_INDEX(sampler->dsi));
169 sampler->skip = nextRandomSkip(sampler->sFlowFsPacketSamplingRate);
172 /* increment the samplePool */
173 sampler->samplePool++;
175 if(--sampler->skip == 0) {
176 /* reached zero. Set the next skip and return true. */
177 sampler->skip = nextRandomSkip(sampler->sFlowFsPacketSamplingRate);
183 #endif /* SFLOW_SOFTWARE_SAMPLING */