Branch data Line data Source code
1 : : /* Copyright (c) 2002-2009 InMon Corp. Licensed under the terms of either the
2 : : * Sun Industry Standards Source License 1.1, that is available at:
3 : : * http://host-sflow.sourceforge.net/sissl.html
4 : : * or the InMon sFlow License, that is available at:
5 : : * http://www.inmon.com/technology/sflowlicense.txt
6 : : */
7 : :
8 : : #include "sflow_api.h"
9 : :
10 : :
11 : : /*_________________--------------------------__________________
12 : : _________________ sfl_sampler_init __________________
13 : : -----------------__________________________------------------
14 : : */
15 : :
16 : 6 : void sfl_sampler_init(SFLSampler *sampler, SFLAgent *agent, SFLDataSource_instance *pdsi)
17 : : {
18 : : /* copy the dsi in case it points to sampler->dsi, which we are about to clear.
19 : : (Thanks to Jagjit Choudray of Force 10 Networks for pointing out this bug) */
20 : 6 : SFLDataSource_instance dsi = *pdsi;
21 : :
22 : : /* preserve the *nxt pointer too, in case we are resetting this poller and it is
23 : : already part of the agent's linked list (thanks to Matt Woodly for pointing this out,
24 : : and to Andy Kitchingman for pointing out that it applies to the hash_nxt ptr too) */
25 : 6 : SFLSampler *nxtPtr = sampler->nxt;
26 : 6 : SFLSampler *hashPtr = sampler->hash_nxt;
27 : :
28 : : /* clear everything */
29 : 6 : memset(sampler, 0, sizeof(*sampler));
30 : :
31 : : /* restore the linked list and hash-table ptr */
32 : 6 : sampler->nxt = nxtPtr;
33 : 6 : sampler->hash_nxt = hashPtr;
34 : :
35 : : /* now copy in the parameters */
36 : 6 : sampler->agent = agent;
37 : 6 : sampler->dsi = dsi;
38 : :
39 : : /* set defaults */
40 : 6 : sampler->sFlowFsMaximumHeaderSize = SFL_DEFAULT_HEADER_SIZE;
41 : 6 : sampler->sFlowFsPacketSamplingRate = SFL_DEFAULT_SAMPLING_RATE;
42 : 6 : }
43 : :
44 : : /*_________________--------------------------__________________
45 : : _________________ reset __________________
46 : : -----------------__________________________------------------
47 : : */
48 : :
49 : 0 : static void reset(SFLSampler *sampler)
50 : : {
51 : 0 : SFLDataSource_instance dsi = sampler->dsi;
52 : 0 : sfl_sampler_init(sampler, sampler->agent, &dsi);
53 : 0 : }
54 : :
55 : : /*_________________---------------------------__________________
56 : : _________________ MIB access __________________
57 : : -----------------___________________________------------------
58 : : */
59 : 0 : u_int32_t sfl_sampler_get_sFlowFsReceiver(SFLSampler *sampler) {
60 : 0 : return sampler->sFlowFsReceiver;
61 : : }
62 : 6 : void sfl_sampler_set_sFlowFsReceiver(SFLSampler *sampler, u_int32_t sFlowFsReceiver) {
63 : 6 : sampler->sFlowFsReceiver = sFlowFsReceiver;
64 [ - + ]: 6 : if(sFlowFsReceiver == 0) reset(sampler);
65 : : else {
66 : : /* retrieve and cache a direct pointer to my receiver */
67 : 6 : sampler->myReceiver = sfl_agent_getReceiver(sampler->agent, sampler->sFlowFsReceiver);
68 : : }
69 : 6 : }
70 : 14 : u_int32_t sfl_sampler_get_sFlowFsPacketSamplingRate(SFLSampler *sampler) {
71 : 14 : return sampler->sFlowFsPacketSamplingRate;
72 : : }
73 : 6 : void sfl_sampler_set_sFlowFsPacketSamplingRate(SFLSampler *sampler, u_int32_t sFlowFsPacketSamplingRate) {
74 : 6 : sampler->sFlowFsPacketSamplingRate = sFlowFsPacketSamplingRate;
75 : 6 : }
76 : 0 : u_int32_t sfl_sampler_get_sFlowFsMaximumHeaderSize(SFLSampler *sampler) {
77 : 0 : return sampler->sFlowFsMaximumHeaderSize;
78 : : }
79 : 6 : void sfl_sampler_set_sFlowFsMaximumHeaderSize(SFLSampler *sampler, u_int32_t sFlowFsMaximumHeaderSize) {
80 : 6 : sampler->sFlowFsMaximumHeaderSize = sFlowFsMaximumHeaderSize;
81 : 6 : }
82 : :
83 : : /* call this to set a maximum samples-per-second threshold. If the sampler reaches this
84 : : threshold it will automatically back off the sampling rate. A value of 0 disables the
85 : : mechanism */
86 : 0 : void sfl_sampler_set_backoffThreshold(SFLSampler *sampler, u_int32_t samplesPerSecond) {
87 : 0 : sampler->backoffThreshold = samplesPerSecond;
88 : 0 : }
89 : 0 : u_int32_t sfl_sampler_get_backoffThreshold(SFLSampler *sampler) {
90 : 0 : return sampler->backoffThreshold;
91 : : }
92 : 0 : u_int32_t sfl_sampler_get_samplesLastTick(SFLSampler *sampler) {
93 : 0 : return sampler->samplesLastTick;
94 : : }
95 : :
96 : : /*_________________---------------------------------__________________
97 : : _________________ sequence number reset __________________
98 : : -----------------_________________________________------------------
99 : : Used by the agent to indicate a samplePool discontinuity
100 : : so that the sflow collector will know to ignore the next delta.
101 : : */
102 : 0 : void sfl_sampler_resetFlowSeqNo(SFLSampler *sampler) { sampler->flowSampleSeqNo = 0; }
103 : :
104 : :
105 : : /*_________________---------------------------__________________
106 : : _________________ sfl_sampler_tick __________________
107 : : -----------------___________________________------------------
108 : : */
109 : :
110 : 15 : void sfl_sampler_tick(SFLSampler *sampler, time_t now)
111 : : {
112 [ - + ][ # # ]: 15 : if(sampler->backoffThreshold && sampler->samplesThisTick > sampler->backoffThreshold) {
113 : : /* automatic backoff. If using hardware sampling then this is where you have to
114 : : * call out to change the sampling rate and make sure that any other registers/variables
115 : : * that hold this value are updated.
116 : : */
117 : 0 : sampler->sFlowFsPacketSamplingRate *= 2;
118 : : }
119 : 15 : sampler->samplesLastTick = sampler->samplesThisTick;
120 : 15 : sampler->samplesThisTick = 0;
121 : 15 : }
122 : :
123 : :
124 : :
125 : : /*_________________------------------------------__________________
126 : : _________________ sfl_sampler_writeFlowSample __________________
127 : : -----------------______________________________------------------
128 : : */
129 : :
130 : 14 : void sfl_sampler_writeFlowSample(SFLSampler *sampler, SFL_FLOW_SAMPLE_TYPE *fs)
131 : : {
132 [ - + ]: 14 : if(fs == NULL) return;
133 : 14 : sampler->samplesThisTick++;
134 : : /* increment the sequence number */
135 : 14 : fs->sequence_number = ++sampler->flowSampleSeqNo;
136 : : /* copy the other header fields in */
137 : : #ifdef SFL_USE_32BIT_INDEX
138 : : fs->ds_class = SFL_DS_CLASS(sampler->dsi);
139 : : fs->ds_index = SFL_DS_INDEX(sampler->dsi);
140 : : #else
141 : 14 : fs->source_id = SFL_DS_DATASOURCE(sampler->dsi);
142 : : #endif
143 : : /* the sampling rate may have been set already. */
144 [ + - ]: 14 : if(fs->sampling_rate == 0) fs->sampling_rate = sampler->sFlowFsPacketSamplingRate;
145 : : /* the samplePool may be maintained upstream too. */
146 [ + - ]: 14 : if( fs->sample_pool == 0) fs->sample_pool = sampler->samplePool;
147 : : /* sent to my receiver */
148 [ + - ]: 14 : if(sampler->myReceiver) sfl_receiver_writeFlowSample(sampler->myReceiver, fs);
149 : : }
150 : :
151 : : #ifdef SFLOW_SOFTWARE_SAMPLING
152 : :
153 : : /* ================== software sampling ========================*/
154 : :
155 : : /*_________________---------------------------__________________
156 : : _________________ nextRandomSkip __________________
157 : : -----------------___________________________------------------
158 : : */
159 : :
160 : : inline static u_int32_t nextRandomSkip(u_int32_t mean)
161 : : {
162 : : if(mean == 0 || mean == 1) return 1;
163 : : return ((random() % ((2 * mean) - 1)) + 1);
164 : : }
165 : :
166 : : /*_________________---------------------------__________________
167 : : _________________ sfl_sampler_takeSample __________________
168 : : -----------------___________________________------------------
169 : : */
170 : :
171 : : int sfl_sampler_takeSample(SFLSampler *sampler)
172 : : {
173 : : if(sampler->skip == 0) {
174 : : /* first time - seed the random number generator */
175 : : srandom(SFL_DS_INDEX(sampler->dsi));
176 : : sampler->skip = nextRandomSkip(sampler->sFlowFsPacketSamplingRate);
177 : : }
178 : :
179 : : /* increment the samplePool */
180 : : sampler->samplePool++;
181 : :
182 : : if(--sampler->skip == 0) {
183 : : /* reached zero. Set the next skip and return true. */
184 : : sampler->skip = nextRandomSkip(sampler->sFlowFsPacketSamplingRate);
185 : : return 1;
186 : : }
187 : : return 0;
188 : : }
189 : :
190 : : #endif /* SFLOW_SOFTWARE_SAMPLING */
|