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
11 /* define SFLOW_DO_SOCKET to 1 if you want the agent
12 to send the packets itself, otherwise set the sendFn
13 callback in sfl_agent_init.*/
14 /* #define SFLOW_DO_SOCKET */
21 #include <sys/types.h>
22 #include <arpa/inet.h> /* for htonl */
24 #ifdef SFLOW_DO_SOCKET
25 #include <sys/socket.h>
26 #include <netinet/in_systm.h>
27 #include <netinet/in.h>
28 #include <netinet/ip.h>
33 /* define SFLOW_SOFTWARE_SAMPLING to 1 if you need to use the
34 sfl_sampler_takeSample routine and give it every packet */
35 /* #define SFLOW_SOFTWARE_SAMPLING */
38 uncomment this preprocessor flag (or compile with -DSFL_USE_32BIT_INDEX)
39 if your ds_index numbers can ever be >= 2^30-1 (i.e. >= 0x3FFFFFFF)
41 /* #define SFL_USE_32BIT_INDEX */
44 /* Used to combine ds_class, ds_index and instance into
45 a single 64-bit number like this:
46 __________________________________
47 | cls| index | instance |
48 ----------------------------------
50 but now is opened up to a 12-byte struct to ensure
51 that ds_index has a full 32-bit field, and to make
52 accessing the components simpler. The macros have
53 the same behavior as before, so this change should
54 be transparent. The only difference is that these
55 objects are now passed around by reference instead
56 of by value, and the comparison is done using a fn.
59 typedef struct _SFLDataSource_instance {
62 u_int32_t ds_instance;
63 } SFLDataSource_instance;
65 #ifdef SFL_USE_32BIT_INDEX
66 #define SFL_FLOW_SAMPLE_TYPE SFLFlow_sample_expanded
67 #define SFL_COUNTERS_SAMPLE_TYPE SFLCounters_sample_expanded
69 #define SFL_FLOW_SAMPLE_TYPE SFLFlow_sample
70 #define SFL_COUNTERS_SAMPLE_TYPE SFLCounters_sample
71 /* if index numbers are not going to use all 32 bits, then we can use
72 the more compact encoding, with the dataSource class and index merged */
73 #define SFL_DS_DATASOURCE(dsi) (((dsi).ds_class << 24) + (dsi).ds_index)
76 #define SFL_DS_INSTANCE(dsi) (dsi).ds_instance
77 #define SFL_DS_CLASS(dsi) (dsi).ds_class
78 #define SFL_DS_INDEX(dsi) (dsi).ds_index
79 #define SFL_DS_SET(dsi,clss,indx,inst) \
81 (dsi).ds_class = (clss); \
82 (dsi).ds_index = (indx); \
83 (dsi).ds_instance = (inst); \
86 typedef struct _SFLSampleCollector {
87 u_int32_t data[(SFL_MAX_DATAGRAM_SIZE + SFL_DATA_PAD) / sizeof(u_int32_t)];
88 u_int32_t *datap; /* packet fill pointer */
89 u_int32_t pktlen; /* accumulated size */
90 u_int32_t packetSeqNo;
94 struct _SFLAgent; /* forward decl */
96 typedef struct _SFLReceiver {
97 struct _SFLReceiver *nxt;
100 time_t sFlowRcvrTimeout;
101 u_int32_t sFlowRcvrMaximumDatagramSize;
102 SFLAddress sFlowRcvrAddress;
103 u_int32_t sFlowRcvrPort;
104 u_int32_t sFlowRcvrDatagramVersion;
106 struct _SFLAgent *agent; /* pointer to my agent */
108 SFLSampleCollector sampleCollector;
109 #ifdef SFLOW_DO_SOCKET
110 struct sockaddr_in receiver4;
111 struct sockaddr_in6 receiver6;
115 typedef struct _SFLSampler {
116 /* for linked list */
117 struct _SFLSampler *nxt;
118 /* for hash lookup table */
119 struct _SFLSampler *hash_nxt;
121 SFLDataSource_instance dsi;
122 u_int32_t sFlowFsReceiver;
123 u_int32_t sFlowFsPacketSamplingRate;
124 u_int32_t sFlowFsMaximumHeaderSize;
126 struct _SFLAgent *agent; /* pointer to my agent */
128 SFLReceiver *myReceiver;
130 u_int32_t samplePool;
131 u_int32_t flowSampleSeqNo;
133 u_int32_t samplesThisTick;
134 u_int32_t samplesLastTick;
135 u_int32_t backoffThreshold;
141 typedef void (*getCountersFn_t)(void *magic, /* callback to get counters */
142 struct _SFLPoller *sampler, /* called with self */
143 SFL_COUNTERS_SAMPLE_TYPE *cs); /* struct to fill in */
145 typedef struct _SFLPoller {
146 /* for linked list */
147 struct _SFLPoller *nxt;
149 SFLDataSource_instance dsi;
150 u_int32_t sFlowCpReceiver;
151 time_t sFlowCpInterval;
153 struct _SFLAgent *agent; /* pointer to my agent */
154 void *magic; /* ptr to pass back in getCountersFn() */
155 getCountersFn_t getCountersFn;
156 u_int32_t bridgePort; /* port number local to bridge */
158 SFLReceiver *myReceiver;
159 time_t countersCountdown;
160 u_int32_t countersSampleSeqNo;
163 typedef void *(*allocFn_t)(void *magic, /* callback to allocate space on heap */
164 struct _SFLAgent *agent, /* called with self */
165 size_t bytes); /* bytes requested */
167 typedef int (*freeFn_t)(void *magic, /* callback to free space on heap */
168 struct _SFLAgent *agent, /* called with self */
169 void *obj); /* obj to free */
171 typedef void (*errorFn_t)(void *magic, /* callback to log error message */
172 struct _SFLAgent *agent, /* called with self */
173 char *msg); /* error message */
175 typedef void (*sendFn_t)(void *magic, /* optional override fn to send packet */
176 struct _SFLAgent *agent,
177 SFLReceiver *receiver,
182 /* prime numbers are good for hash tables */
183 #define SFL_HASHTABLE_SIZ 199
185 typedef struct _SFLAgent {
186 SFLSampler *jumpTable[SFL_HASHTABLE_SIZ]; /* fast lookup table for samplers (by ifIndex) */
187 SFLSampler *samplers; /* the list of samplers */
188 SFLPoller *pollers; /* the list of samplers */
189 SFLReceiver *receivers; /* the array of receivers */
190 time_t bootTime; /* time when we booted or started */
191 time_t now; /* time now */
192 SFLAddress myIP; /* IP address of this node */
193 u_int32_t subId; /* sub_agent_id */
194 void *magic; /* ptr to pass back in logging and alloc fns */
199 #ifdef SFLOW_DO_SOCKET
205 /* call this at the start with a newly created agent */
206 void sfl_agent_init(SFLAgent *agent,
207 SFLAddress *myIP, /* IP address of this agent */
208 u_int32_t subId, /* agent_sub_id */
209 time_t bootTime, /* agent boot time */
210 time_t now, /* time now */
211 void *magic, /* ptr to pass back in logging and alloc fns */
217 /* call this to create samplers */
218 SFLSampler *sfl_agent_addSampler(SFLAgent *agent, SFLDataSource_instance *pdsi);
220 /* call this to create pollers */
221 SFLPoller *sfl_agent_addPoller(SFLAgent *agent,
222 SFLDataSource_instance *pdsi,
223 void *magic, /* ptr to pass back in getCountersFn() */
224 getCountersFn_t getCountersFn);
226 /* call this to create receivers */
227 SFLReceiver *sfl_agent_addReceiver(SFLAgent *agent);
229 /* call this to remove samplers */
230 int sfl_agent_removeSampler(SFLAgent *agent, SFLDataSource_instance *pdsi);
232 /* call this to remove pollers */
233 int sfl_agent_removePoller(SFLAgent *agent, SFLDataSource_instance *pdsi);
235 /* note: receivers should not be removed. Typically the receivers
236 list will be created at init time and never changed */
238 /* call these fns to retrieve sampler, poller or receiver (e.g. for SNMP GET or GETNEXT operation) */
239 SFLSampler *sfl_agent_getSampler(SFLAgent *agent, SFLDataSource_instance *pdsi);
240 SFLSampler *sfl_agent_getNextSampler(SFLAgent *agent, SFLDataSource_instance *pdsi);
241 SFLPoller *sfl_agent_getPoller(SFLAgent *agent, SFLDataSource_instance *pdsi);
242 SFLPoller *sfl_agent_getNextPoller(SFLAgent *agent, SFLDataSource_instance *pdsi);
243 SFLReceiver *sfl_agent_getReceiver(SFLAgent *agent, u_int32_t receiverIndex);
244 SFLReceiver *sfl_agent_getNextReceiver(SFLAgent *agent, u_int32_t receiverIndex);
246 /* jump table access - for performance */
247 SFLSampler *sfl_agent_getSamplerByIfIndex(SFLAgent *agent, u_int32_t ifIndex);
249 /* call these functions to GET and SET MIB values */
252 char * sfl_receiver_get_sFlowRcvrOwner(SFLReceiver *receiver);
253 void sfl_receiver_set_sFlowRcvrOwner(SFLReceiver *receiver, char *sFlowRcvrOwner);
254 time_t sfl_receiver_get_sFlowRcvrTimeout(SFLReceiver *receiver);
255 void sfl_receiver_set_sFlowRcvrTimeout(SFLReceiver *receiver, time_t sFlowRcvrTimeout);
256 u_int32_t sfl_receiver_get_sFlowRcvrMaximumDatagramSize(SFLReceiver *receiver);
257 void sfl_receiver_set_sFlowRcvrMaximumDatagramSize(SFLReceiver *receiver, u_int32_t sFlowRcvrMaximumDatagramSize);
258 SFLAddress *sfl_receiver_get_sFlowRcvrAddress(SFLReceiver *receiver);
259 void sfl_receiver_set_sFlowRcvrAddress(SFLReceiver *receiver, SFLAddress *sFlowRcvrAddress);
260 u_int32_t sfl_receiver_get_sFlowRcvrPort(SFLReceiver *receiver);
261 void sfl_receiver_set_sFlowRcvrPort(SFLReceiver *receiver, u_int32_t sFlowRcvrPort);
263 u_int32_t sfl_sampler_get_sFlowFsReceiver(SFLSampler *sampler);
264 void sfl_sampler_set_sFlowFsReceiver(SFLSampler *sampler, u_int32_t sFlowFsReceiver);
265 u_int32_t sfl_sampler_get_sFlowFsPacketSamplingRate(SFLSampler *sampler);
266 void sfl_sampler_set_sFlowFsPacketSamplingRate(SFLSampler *sampler, u_int32_t sFlowFsPacketSamplingRate);
267 u_int32_t sfl_sampler_get_sFlowFsMaximumHeaderSize(SFLSampler *sampler);
268 void sfl_sampler_set_sFlowFsMaximumHeaderSize(SFLSampler *sampler, u_int32_t sFlowFsMaximumHeaderSize);
269 u_int32_t sfl_sampler_get_samplesLastTick(SFLSampler *sampler);
271 u_int32_t sfl_poller_get_sFlowCpReceiver(SFLPoller *poller);
272 void sfl_poller_set_sFlowCpReceiver(SFLPoller *poller, u_int32_t sFlowCpReceiver);
273 u_int32_t sfl_poller_get_sFlowCpInterval(SFLPoller *poller);
274 void sfl_poller_set_sFlowCpInterval(SFLPoller *poller, u_int32_t sFlowCpInterval);
276 /* fns to set the sflow agent address or sub-id */
277 void sfl_agent_set_agentAddress(SFLAgent *agent, SFLAddress *addr);
278 void sfl_agent_set_agentSubId(SFLAgent *agent, u_int32_t subId);
280 /* The poller may need a separate number to reference the local bridge port
281 to get counters if it is not the same as the global ifIndex */
282 void sfl_poller_set_bridgePort(SFLPoller *poller, u_int32_t port_no);
283 u_int32_t sfl_poller_get_bridgePort(SFLPoller *poller);
285 /* call this to indicate a discontinuity with a counter like samplePool so that the
286 sflow collector will ignore the next delta */
287 void sfl_sampler_resetFlowSeqNo(SFLSampler *sampler);
289 /* call this to indicate a discontinuity with one or more of the counters so that the
290 sflow collector will ignore the next delta */
291 void sfl_poller_resetCountersSeqNo(SFLPoller *poller);
293 #ifdef SFLOW_SOFTWARE_SAMLING
294 /* software sampling: call this with every packet - returns non-zero if the packet
295 should be sampled (in which case you then call sfl_sampler_writeFlowSample()) */
296 int sfl_sampler_takeSample(SFLSampler *sampler);
299 /* call this to set a maximum samples-per-second threshold. If the sampler reaches this
300 threshold it will automatically back off the sampling rate. A value of 0 disables the
302 void sfl_sampler_set_backoffThreshold(SFLSampler *sampler, u_int32_t samplesPerSecond);
303 u_int32_t sfl_sampler_get_backoffThreshold(SFLSampler *sampler);
305 /* call this once per second (N.B. not on interrupt stack i.e. not hard real-time) */
306 void sfl_agent_tick(SFLAgent *agent, time_t now);
308 /* call this with each flow sample */
309 void sfl_sampler_writeFlowSample(SFLSampler *sampler, SFL_FLOW_SAMPLE_TYPE *fs);
311 /* call this to push counters samples (usually done in the getCountersFn callback) */
312 void sfl_poller_writeCountersSample(SFLPoller *poller, SFL_COUNTERS_SAMPLE_TYPE *cs);
314 /* call this to deallocate resources */
315 void sfl_agent_release(SFLAgent *agent);
320 void sfl_receiver_init(SFLReceiver *receiver, SFLAgent *agent);
321 void sfl_sampler_init(SFLSampler *sampler, SFLAgent *agent, SFLDataSource_instance *pdsi);
322 void sfl_poller_init(SFLPoller *poller, SFLAgent *agent, SFLDataSource_instance *pdsi, void *magic, getCountersFn_t getCountersFn);
325 void sfl_receiver_tick(SFLReceiver *receiver, time_t now);
326 void sfl_poller_tick(SFLPoller *poller, time_t now);
327 void sfl_sampler_tick(SFLSampler *sampler, time_t now);
329 int sfl_receiver_writeFlowSample(SFLReceiver *receiver, SFL_FLOW_SAMPLE_TYPE *fs);
330 int sfl_receiver_writeCountersSample(SFLReceiver *receiver, SFL_COUNTERS_SAMPLE_TYPE *cs);
332 void sfl_agent_resetReceiver(SFLAgent *agent, SFLReceiver *receiver);
334 void sfl_agent_error(SFLAgent *agent, char *modName, char *msg);
335 void sfl_agent_sysError(SFLAgent *agent, char *modName, char *msg);
337 u_int32_t sfl_receiver_samplePacketsSent(SFLReceiver *receiver);
339 #define SFL_ALLOC malloc
340 #define SFL_FREE free
342 #endif /* SFLOW_API_H */