]> git.proxmox.com Git - mirror_ovs.git/blob - lib/sflow_sampler.c
ovsdb-idl: Fix iteration over tracked rows with no actual data.
[mirror_ovs.git] / lib / sflow_sampler.c
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 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
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 SFLSampler *nxtPtr = sampler->nxt;
26 SFLSampler *hashPtr = sampler->hash_nxt;
27
28 /* clear everything */
29 memset(sampler, 0, sizeof(*sampler));
30
31 /* restore the linked list and hash-table ptr */
32 sampler->nxt = nxtPtr;
33 sampler->hash_nxt = hashPtr;
34
35 /* now copy in the parameters */
36 sampler->agent = agent;
37 sampler->dsi = dsi;
38
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);
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 */