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