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