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 */