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