]>
Commit | Line | Data |
---|---|---|
7dd32dff NM |
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 | */ | |
c72e245a BP |
7 | |
8 | #include "sflow_api.h" | |
9 | ||
10 | ||
11 | /*_________________--------------------------__________________ | |
12 | _________________ sfl_sampler_init __________________ | |
13 | -----------------__________________________------------------ | |
14 | */ | |
15 | ||
16 | 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 | SFLDataSource_instance dsi = *pdsi; | |
21 | ||
22 | /* preserve the *nxt pointer too, in case we are resetting this poller and it is | |
da0603cf NM |
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) */ | |
c72e245a | 25 | SFLSampler *nxtPtr = sampler->nxt; |
da0603cf | 26 | SFLSampler *hashPtr = sampler->hash_nxt; |
d295e8e9 | 27 | |
c72e245a BP |
28 | /* clear everything */ |
29 | memset(sampler, 0, sizeof(*sampler)); | |
d295e8e9 | 30 | |
da0603cf | 31 | /* restore the linked list and hash-table ptr */ |
c72e245a | 32 | sampler->nxt = nxtPtr; |
da0603cf | 33 | sampler->hash_nxt = hashPtr; |
d295e8e9 | 34 | |
c72e245a BP |
35 | /* now copy in the parameters */ |
36 | sampler->agent = agent; | |
37 | sampler->dsi = dsi; | |
d295e8e9 | 38 | |
c72e245a BP |
39 | /* set defaults */ |
40 | sampler->sFlowFsMaximumHeaderSize = SFL_DEFAULT_HEADER_SIZE; | |
41 | sampler->sFlowFsPacketSamplingRate = SFL_DEFAULT_SAMPLING_RATE; | |
42 | } | |
43 | ||
44 | /*_________________--------------------------__________________ | |
45 | _________________ reset __________________ | |
46 | -----------------__________________________------------------ | |
47 | */ | |
48 | ||
49 | static void reset(SFLSampler *sampler) | |
50 | { | |
51 | SFLDataSource_instance dsi = sampler->dsi; | |
52 | sfl_sampler_init(sampler, sampler->agent, &dsi); | |
53 | } | |
54 | ||
55 | /*_________________---------------------------__________________ | |
56 | _________________ MIB access __________________ | |
57 | -----------------___________________________------------------ | |
58 | */ | |
59 | u_int32_t sfl_sampler_get_sFlowFsReceiver(SFLSampler *sampler) { | |
60 | return sampler->sFlowFsReceiver; | |
61 | } | |
62 | void sfl_sampler_set_sFlowFsReceiver(SFLSampler *sampler, u_int32_t sFlowFsReceiver) { | |
63 | sampler->sFlowFsReceiver = sFlowFsReceiver; | |
64 | if(sFlowFsReceiver == 0) reset(sampler); | |
65 | else { | |
66 | /* retrieve and cache a direct pointer to my receiver */ | |
67 | sampler->myReceiver = sfl_agent_getReceiver(sampler->agent, sampler->sFlowFsReceiver); | |
68 | } | |
69 | } | |
70 | u_int32_t sfl_sampler_get_sFlowFsPacketSamplingRate(SFLSampler *sampler) { | |
71 | return sampler->sFlowFsPacketSamplingRate; | |
72 | } | |
73 | void sfl_sampler_set_sFlowFsPacketSamplingRate(SFLSampler *sampler, u_int32_t sFlowFsPacketSamplingRate) { | |
74 | sampler->sFlowFsPacketSamplingRate = sFlowFsPacketSamplingRate; | |
75 | } | |
76 | u_int32_t sfl_sampler_get_sFlowFsMaximumHeaderSize(SFLSampler *sampler) { | |
77 | return sampler->sFlowFsMaximumHeaderSize; | |
78 | } | |
79 | void sfl_sampler_set_sFlowFsMaximumHeaderSize(SFLSampler *sampler, u_int32_t sFlowFsMaximumHeaderSize) { | |
80 | sampler->sFlowFsMaximumHeaderSize = sFlowFsMaximumHeaderSize; | |
81 | } | |
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 | void sfl_sampler_set_backoffThreshold(SFLSampler *sampler, u_int32_t samplesPerSecond) { | |
87 | sampler->backoffThreshold = samplesPerSecond; | |
88 | } | |
89 | u_int32_t sfl_sampler_get_backoffThreshold(SFLSampler *sampler) { | |
90 | return sampler->backoffThreshold; | |
91 | } | |
92 | u_int32_t sfl_sampler_get_samplesLastTick(SFLSampler *sampler) { | |
93 | 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 | void sfl_sampler_resetFlowSeqNo(SFLSampler *sampler) { sampler->flowSampleSeqNo = 0; } | |
103 | ||
104 | ||
105 | /*_________________---------------------------__________________ | |
106 | _________________ sfl_sampler_tick __________________ | |
107 | -----------------___________________________------------------ | |
108 | */ | |
109 | ||
110 | void sfl_sampler_tick(SFLSampler *sampler, time_t now) | |
111 | { | |
112 | 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 | sampler->sFlowFsPacketSamplingRate *= 2; | |
118 | } | |
119 | sampler->samplesLastTick = sampler->samplesThisTick; | |
120 | sampler->samplesThisTick = 0; | |
121 | } | |
122 | ||
123 | ||
124 | ||
125 | /*_________________------------------------------__________________ | |
126 | _________________ sfl_sampler_writeFlowSample __________________ | |
127 | -----------------______________________________------------------ | |
128 | */ | |
129 | ||
130 | void sfl_sampler_writeFlowSample(SFLSampler *sampler, SFL_FLOW_SAMPLE_TYPE *fs) | |
131 | { | |
132 | if(fs == NULL) return; | |
133 | sampler->samplesThisTick++; | |
134 | /* increment the sequence number */ | |
135 | 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 | fs->source_id = SFL_DS_DATASOURCE(sampler->dsi); | |
142 | #endif | |
143 | /* the sampling rate may have been set already. */ | |
144 | if(fs->sampling_rate == 0) fs->sampling_rate = sampler->sFlowFsPacketSamplingRate; | |
145 | /* the samplePool may be maintained upstream too. */ | |
146 | if( fs->sample_pool == 0) fs->sample_pool = sampler->samplePool; | |
147 | /* sent to my receiver */ | |
148 | 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); | |
d295e8e9 | 164 | } |
c72e245a BP |
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 */ |