1 /* Copyright (c) 2002-2014 InMon Corp. Licensed under the terms of the InMon sFlow licence: */ 2 /* http://www.inmon.com/technology/sflowlicense.txt */ 3 4 /* 5 sFlow Agent Library 6 =================== 7 sflow_api.h - API for sflow agent library. 8 sflow.h - structure definitions for sFlow. 9 sflow_api.c - Agent, Sampler, Poller and Receiver 10 11 Neil McKee 12 InMon Corp. 13 http://www.inmon.com 14 email: neil.mckee@inmon.com 15 */ 16 17 #ifndef SFLOW_API_H 18 #define SFLOW_API_H 1 19 20 #include "ngx_http_sflow.h" 21 22 /* 23 uncomment this preprocessor flag (or compile with -DSFL_USE_32BIT_INDEX) 24 if your ds_index numbers can ever be >= 2^30-1 (i.e. >= 0x3FFFFFFF) 25 */ 26 /* #define SFL_USE_32BIT_INDEX */ 27 28 29 /* Used to combine ds_class, ds_index and instance into 30 a single 64-bit number like this: 31 __________________________________ 32 | cls| index | instance | 33 ---------------------------------- 34 35 but now is opened up to a 12-byte struct to ensure 36 that ds_index has a full 32-bit field, and to make 37 accessing the components simpler. The macros have 38 the same behavior as before, so this change should 39 be transparent. The only difference is that these 40 objects are now passed around by reference instead 41 of by value, and the comparison is done using a fn. 42 */ 43 44 typedef struct _SFLDataSource_instance { 45 uint32_t ds_class; 46 uint32_t ds_index; 47 uint32_t ds_instance; 48 } SFLDataSource_instance; 49 50 #ifdef SFL_USE_32BIT_INDEX 51 #define SFL_FLOW_SAMPLE_TYPE SFLFlow_sample_expanded 52 #define SFL_COUNTERS_SAMPLE_TYPE SFLCounters_sample_expanded 53 #else 54 #define SFL_FLOW_SAMPLE_TYPE SFLFlow_sample 55 #define SFL_COUNTERS_SAMPLE_TYPE SFLCounters_sample 56 /* if index numbers are not going to use all 32 bits, then we can use 57 the more compact encoding, with the dataSource class and index merged */ 58 #define SFL_DS_DATASOURCE(dsi) (((dsi).ds_class << 24) + (dsi).ds_index) 59 #endif 60 61 #define SFL_DS_INSTANCE(dsi) (dsi).ds_instance 62 #define SFL_DS_CLASS(dsi) (dsi).ds_class 63 #define SFL_DS_INDEX(dsi) (dsi).ds_index 64 #define SFL_DS_SET(dsi,clss,indx,inst) \ 65 do { \ 66 (dsi).ds_class = (clss); \ 67 (dsi).ds_index = (indx); \ 68 (dsi).ds_instance = (inst); \ 69 } while(0) 70 71 #define SFL_SAMPLECOLLECTOR_DATA_QUADS (SFL_MAX_DATAGRAM_SIZE + SFL_DATA_PAD) / sizeof(uint32_t) 72 73 typedef struct _SFLSampleCollector { 74 uint32_t data[SFL_SAMPLECOLLECTOR_DATA_QUADS]; 75 uint32_t *datap; /* packet fill pointer */ 76 uint32_t pktlen; /* accumulated size */ 77 uint32_t packetSeqNo; 78 uint32_t numSamples; 79 } SFLSampleCollector; 80 81 struct _SFLAgent; /* forward decl */ 82 83 typedef struct _SFLReceiver { 84 struct _SFLReceiver *nxt; 85 /* MIB fields */ 86 char *sFlowRcvrOwner; 87 time_t sFlowRcvrTimeout; 88 uint32_t sFlowRcvrMaximumDatagramSize; 89 SFLAddress sFlowRcvrAddress; 90 uint32_t sFlowRcvrPort; 91 uint32_t sFlowRcvrDatagramVersion; 92 /* public fields */ 93 struct _SFLAgent *agent; /* pointer to my agent */ 94 /* private fields */ 95 SFLSampleCollector sampleCollector; 96 } SFLReceiver; 97 98 typedef struct _SFLSampler { 99 /* for linked list */ 100 struct _SFLSampler *nxt; 101 /* for hash lookup table */ 102 struct _SFLSampler *hash_nxt; 103 /* MIB fields */ 104 SFLDataSource_instance dsi; 105 uint32_t sFlowFsReceiver; 106 uint32_t sFlowFsPacketSamplingRate; 107 uint32_t sFlowFsMaximumHeaderSize; 108 /* public fields */ 109 struct _SFLAgent *agent; /* pointer to my agent */ 110 void *userData; /* can be useful to hang something else here */ 111 /* private fields */ 112 SFLReceiver *myReceiver; 113 uint32_t skip; 114 uint32_t samplePool; 115 uint32_t dropEvents; 116 uint32_t flowSampleSeqNo; 117 /* rate checking */ 118 uint32_t samplesThisTick; 119 uint32_t samplesLastTick; 120 uint32_t backoffThreshold; 121 } SFLSampler; 122 123 /* declare */ 124 struct _SFLPoller; 125 126 typedef void (*getCountersFn_t)(void *magic, /* callback to get counters */ 127 struct _SFLPoller *sampler, /* called with self */ 128 SFL_COUNTERS_SAMPLE_TYPE *cs); /* struct to fill in */ 129 130 typedef struct _SFLPoller { 131 /* for linked list */ 132 struct _SFLPoller *nxt; 133 /* MIB fields */ 134 SFLDataSource_instance dsi; 135 uint32_t sFlowCpReceiver; 136 time_t sFlowCpInterval; 137 /* public fields */ 138 struct _SFLAgent *agent; /* pointer to my agent */ 139 void *magic; /* ptr to pass back in getCountersFn() */ 140 void *userData; /* can be useful to hang something else here */ 141 getCountersFn_t getCountersFn; 142 /* private fields */ 143 SFLReceiver *myReceiver; 144 time_t countersCountdown; 145 uint32_t countersSampleSeqNo; 146 } SFLPoller; 147 148 typedef void (*errorFn_t)(void *magic, /* callback to log error message */ 149 struct _SFLAgent *agent, /* called with self */ 150 char *msg); /* error message */ 151 152 typedef void (*sendFn_t)(void *magic, /* optional override fn to send packet */ 153 struct _SFLAgent *agent, 154 SFLReceiver *receiver, 155 byte_t *pkt, 156 uint32_t pktLen); 157 158 159 /* prime numbers are good for hash tables */ 160 #define SFL_HASHTABLE_SIZ 199 161 162 typedef struct _SFLAgent { 163 SFLSampler *jumpTable[SFL_HASHTABLE_SIZ]; /* fast lookup table for samplers (by ifIndex) */ 164 SFLSampler *samplers; /* the list of samplers */ 165 SFLPoller *pollers; /* the list of samplers */ 166 SFLReceiver *receivers; /* the array of receivers */ 167 time_t bootTime; /* time when we booted or started */ 168 time_t now; /* time now */ 169 SFLAddress myIP; /* IP address of this node */ 170 uint32_t subId; /* sub_agent_id */ 171 void *magic; /* ptr to pass back */ 172 errorFn_t errorFn; 173 sendFn_t sendFn; 174 } SFLAgent; 175 176 /* call this at the start with a newly created agent */ 177 void sfl_agent_init(SFLAgent *agent, 178 SFLAddress *myIP, /* IP address of this agent */ 179 uint32_t subId, /* agent_sub_id */ 180 time_t bootTime, /* agent boot time */ 181 time_t now, /* time now */ 182 void *magic, /* ptr to pass back */ 183 errorFn_t errorFn, 184 sendFn_t sendFn); 185 186 /* call this to create samplers */ 187 SFLSampler *sfl_agent_addSampler(SFLAgent *agent, 188 SFLDataSource_instance *pdsi, 189 SFLSampler *newsm); 190 191 /* call this to create pollers */ 192 SFLPoller *sfl_agent_addPoller(SFLAgent *agent, 193 SFLDataSource_instance *pdsi, 194 void *magic, /* ptr to pass back in getCountersFn() */ 195 getCountersFn_t getCountersFn, 196 SFLPoller *newpl); 197 198 /* call this to create receivers */ 199 SFLReceiver *sfl_agent_addReceiver(SFLAgent *agent, SFLReceiver *rcv); 200 201 /* call these fns to retrieve sampler, poller or receiver (e.g. for SNMP GET or GETNEXT operation) */ 202 SFLSampler *sfl_agent_getSampler(SFLAgent *agent, SFLDataSource_instance *pdsi); 203 SFLSampler *sfl_agent_getNextSampler(SFLAgent *agent, SFLDataSource_instance *pdsi); 204 SFLPoller *sfl_agent_getPoller(SFLAgent *agent, SFLDataSource_instance *pdsi); 205 SFLPoller *sfl_agent_getNextPoller(SFLAgent *agent, SFLDataSource_instance *pdsi); 206 SFLReceiver *sfl_agent_getReceiver(SFLAgent *agent, uint32_t receiverIndex); 207 SFLReceiver *sfl_agent_getNextReceiver(SFLAgent *agent, uint32_t receiverIndex); 208 209 /* jump table access - for performance */ 210 SFLSampler *sfl_agent_getSamplerByIfIndex(SFLAgent *agent, uint32_t ifIndex); 211 212 /* random number generator - used by sampler and poller */ 213 uint32_t sfl_random(uint32_t mean); 214 void sfl_random_init(uint32_t seed); 215 216 /* call these functions to GET and SET MIB values */ 217 218 /* receiver */ 219 char * sfl_receiver_get_sFlowRcvrOwner(SFLReceiver *receiver); 220 void sfl_receiver_set_sFlowRcvrOwner(SFLReceiver *receiver, char *sFlowRcvrOwner); 221 time_t sfl_receiver_get_sFlowRcvrTimeout(SFLReceiver *receiver); 222 void sfl_receiver_set_sFlowRcvrTimeout(SFLReceiver *receiver, time_t sFlowRcvrTimeout); 223 uint32_t sfl_receiver_get_sFlowRcvrMaximumDatagramSize(SFLReceiver *receiver); 224 void sfl_receiver_set_sFlowRcvrMaximumDatagramSize(SFLReceiver *receiver, uint32_t sFlowRcvrMaximumDatagramSize); 225 SFLAddress *sfl_receiver_get_sFlowRcvrAddress(SFLReceiver *receiver); 226 void sfl_receiver_set_sFlowRcvrAddress(SFLReceiver *receiver, SFLAddress *sFlowRcvrAddress); 227 uint32_t sfl_receiver_get_sFlowRcvrPort(SFLReceiver *receiver); 228 void sfl_receiver_set_sFlowRcvrPort(SFLReceiver *receiver, uint32_t sFlowRcvrPort); 229 /* sampler */ 230 uint32_t sfl_sampler_get_sFlowFsReceiver(SFLSampler *sampler); 231 void sfl_sampler_set_sFlowFsReceiver(SFLSampler *sampler, uint32_t sFlowFsReceiver); 232 uint32_t sfl_sampler_get_sFlowFsPacketSamplingRate(SFLSampler *sampler); 233 void sfl_sampler_set_sFlowFsPacketSamplingRate(SFLSampler *sampler, uint32_t sFlowFsPacketSamplingRate); 234 uint32_t sfl_sampler_get_sFlowFsMaximumHeaderSize(SFLSampler *sampler); 235 void sfl_sampler_set_sFlowFsMaximumHeaderSize(SFLSampler *sampler, uint32_t sFlowFsMaximumHeaderSize); 236 /* poller */ 237 uint32_t sfl_poller_get_sFlowCpReceiver(SFLPoller *poller); 238 void sfl_poller_set_sFlowCpReceiver(SFLPoller *poller, uint32_t sFlowCpReceiver); 239 uint32_t sfl_poller_get_sFlowCpInterval(SFLPoller *poller); 240 void sfl_poller_set_sFlowCpInterval(SFLPoller *poller, uint32_t sFlowCpInterval); 241 242 /* call this to indicate a discontinuity with a counter like samplePool so that the 243 sflow collector will ignore the next delta */ 244 void sfl_sampler_resetFlowSeqNo(SFLSampler *sampler); 245 246 /* call this to indicate a discontinuity with one or more of the counters so that the 247 sflow collector will ignore the next delta */ 248 void sfl_poller_resetCountersSeqNo(SFLPoller *poller); 249 250 /* software sampling: call this with every packet - returns non-zero if the packet 251 should be sampled (in which case you then call sfl_sampler_writeFlowSample()) */ 252 int sfl_sampler_takeSample(SFLSampler *sampler); 253 254 /* You can use this one if you are managing the skip countdown elsewhere */ 255 uint32_t sfl_sampler_next_skip(SFLSampler *sampler); 256 257 /* call this to set a maximum samples-per-second threshold. If the sampler reaches this 258 threshold it will automatically back off the sampling rate. A value of 0 disables the 259 mechanism */ 260 void sfl_sampler_set_backoffThreshold(SFLSampler *sampler, uint32_t samplesPerSecond); 261 uint32_t sfl_sampler_get_backoffThreshold(SFLSampler *sampler); 262 uint32_t sfl_sampler_get_samplesLastTick(SFLSampler *sampler); 263 264 265 /* call this once per second (N.B. not on interrupt stack i.e. not hard real-time) */ 266 void sfl_agent_tick(SFLAgent *agent, time_t now); 267 268 /* call this with each flow sample */ 269 void sfl_sampler_writeFlowSample(SFLSampler *sampler, SFL_FLOW_SAMPLE_TYPE *fs); 270 void sfl_sampler_writeEncodedFlowSample(SFLSampler *sampler, char *xdrBytes, uint32_t len); 271 272 /* call this to push counters samples (usually done in the getCountersFn callback) */ 273 void sfl_poller_writeCountersSample(SFLPoller *poller, SFL_COUNTERS_SAMPLE_TYPE *cs); 274 275 /* internal fns */ 276 277 void sfl_receiver_init(SFLReceiver *receiver, SFLAgent *agent); 278 void sfl_sampler_init(SFLSampler *sampler, SFLAgent *agent, SFLDataSource_instance *pdsi); 279 void sfl_poller_init(SFLPoller *poller, SFLAgent *agent, SFLDataSource_instance *pdsi, void *magic, getCountersFn_t getCountersFn); 280 281 282 void sfl_receiver_tick(SFLReceiver *receiver, time_t now); 283 void sfl_poller_tick(SFLPoller *poller, time_t now); 284 void sfl_sampler_tick(SFLSampler *sampler, time_t now); 285 286 int sfl_receiver_writeFlowSample(SFLReceiver *receiver, SFL_FLOW_SAMPLE_TYPE *fs); 287 int sfl_receiver_writeEncodedFlowSample(SFLReceiver *receiver, SFL_FLOW_SAMPLE_TYPE *fs, char *xdrBytes, uint32_t packedSize); 288 int sfl_receiver_writeCountersSample(SFLReceiver *receiver, SFL_COUNTERS_SAMPLE_TYPE *cs); 289 290 void sfl_agent_resetReceiver(SFLAgent *agent, SFLReceiver *receiver); 291 292 void sfl_agent_error(SFLAgent *agent, char *modName, char *msg); 293 294 uint32_t sfl_receiver_samplePacketsSent(SFLReceiver *receiver); 295 296 297 /* If supported, give compiler hints for branch prediction. */ 298 #if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96) 299 #define __builtin_expect(x, expected_value) (x) 300 #endif 301 302 #define likely(x) __builtin_expect((x),1) 303 #define unlikely(x) __builtin_expect((x),0) 304 305 /* selective exposure of some internal hooks, just for this project */ 306 void sfl_receiver_put32(SFLReceiver *receiver, uint32_t val); 307 void sfl_receiver_putOpaque(SFLReceiver *receiver, char *val, int len); 308 void sfl_receiver_resetSampleCollector(SFLReceiver *receiver); 309 310 #endif /* SFLOW_API_H */ 311