1 /* Copyright (c) 2002-2009 InMon Corp. Licensed under the terms of the InMon sFlow licence: */
2 /* http://www.inmon.com/technology/sflowlicense.txt */
7 /* define SFLOW_DO_SOCKET to 1 if you want the agent
8 to send the packets itself, otherwise set the sendFn
9 callback in sfl_agent_init.*/
10 /* #define SFLOW_DO_SOCKET */
17 #include <sys/types.h>
18 #include <arpa/inet.h> /* for htonl */
20 #ifdef SFLOW_DO_SOCKET
21 #include <sys/socket.h>
22 #include <netinet/in_systm.h>
23 #include <netinet/in.h>
24 #include <netinet/ip.h>
29 /* define SFLOW_SOFTWARE_SAMPLING to 1 if you need to use the
30 sfl_sampler_takeSample routine and give it every packet */
31 /* #define SFLOW_SOFTWARE_SAMPLING */
34 uncomment this preprocessor flag (or compile with -DSFL_USE_32BIT_INDEX)
35 if your ds_index numbers can ever be >= 2^30-1 (i.e. >= 0x3FFFFFFF)
37 /* #define SFL_USE_32BIT_INDEX */
40 /* Used to combine ds_class, ds_index and instance into
41 a single 64-bit number like this:
42 __________________________________
43 | cls| index | instance |
44 ----------------------------------
46 but now is opened up to a 12-byte struct to ensure
47 that ds_index has a full 32-bit field, and to make
48 accessing the components simpler. The macros have
49 the same behavior as before, so this change should
50 be transparent. The only difference is that these
51 objects are now passed around by reference instead
52 of by value, and the comparison is done using a fn.
55 typedef struct _SFLDataSource_instance {
58 u_int32_t ds_instance;
59 } SFLDataSource_instance;
61 #ifdef SFL_USE_32BIT_INDEX
62 #define SFL_FLOW_SAMPLE_TYPE SFLFlow_sample_expanded
63 #define SFL_COUNTERS_SAMPLE_TYPE SFLCounters_sample_expanded
65 #define SFL_FLOW_SAMPLE_TYPE SFLFlow_sample
66 #define SFL_COUNTERS_SAMPLE_TYPE SFLCounters_sample
67 /* if index numbers are not going to use all 32 bits, then we can use
68 the more compact encoding, with the dataSource class and index merged */
69 #define SFL_DS_DATASOURCE(dsi) (((dsi).ds_class << 24) + (dsi).ds_index)
72 #define SFL_DS_INSTANCE(dsi) (dsi).ds_instance
73 #define SFL_DS_CLASS(dsi) (dsi).ds_class
74 #define SFL_DS_INDEX(dsi) (dsi).ds_index
75 #define SFL_DS_SET(dsi,clss,indx,inst) \
77 (dsi).ds_class = (clss); \
78 (dsi).ds_index = (indx); \
79 (dsi).ds_instance = (inst); \
82 typedef struct _SFLSampleCollector {
83 u_int32_t data[(SFL_MAX_DATAGRAM_SIZE + SFL_DATA_PAD) / sizeof(u_int32_t)];
84 u_int32_t *datap; /* packet fill pointer */
85 u_int32_t pktlen; /* accumulated size */
86 u_int32_t packetSeqNo;
90 struct _SFLAgent; /* forward decl */
92 typedef struct _SFLReceiver {
93 struct _SFLReceiver *nxt;
96 time_t sFlowRcvrTimeout;
97 u_int32_t sFlowRcvrMaximumDatagramSize;
98 SFLAddress sFlowRcvrAddress;
99 u_int32_t sFlowRcvrPort;
100 u_int32_t sFlowRcvrDatagramVersion;
102 struct _SFLAgent *agent; /* pointer to my agent */
104 SFLSampleCollector sampleCollector;
105 #ifdef SFLOW_DO_SOCKET
106 struct sockaddr_in receiver4;
107 struct sockaddr_in6 receiver6;
111 typedef struct _SFLSampler {
112 /* for linked list */
113 struct _SFLSampler *nxt;
114 /* for hash lookup table */
115 struct _SFLSampler *hash_nxt;
117 SFLDataSource_instance dsi;
118 u_int32_t sFlowFsReceiver;
119 u_int32_t sFlowFsPacketSamplingRate;
120 u_int32_t sFlowFsMaximumHeaderSize;
122 struct _SFLAgent *agent; /* pointer to my agent */
124 SFLReceiver *myReceiver;
126 u_int32_t samplePool;
127 u_int32_t flowSampleSeqNo;
129 u_int32_t samplesThisTick;
130 u_int32_t samplesLastTick;
131 u_int32_t backoffThreshold;
137 typedef void (*getCountersFn_t)(void *magic, /* callback to get counters */
138 struct _SFLPoller *sampler, /* called with self */
139 SFL_COUNTERS_SAMPLE_TYPE *cs); /* struct to fill in */
141 typedef struct _SFLPoller {
142 /* for linked list */
143 struct _SFLPoller *nxt;
145 SFLDataSource_instance dsi;
146 u_int32_t sFlowCpReceiver;
147 time_t sFlowCpInterval;
149 struct _SFLAgent *agent; /* pointer to my agent */
150 void *magic; /* ptr to pass back in getCountersFn() */
151 getCountersFn_t getCountersFn;
152 u_int32_t bridgePort; /* port number local to bridge */
154 SFLReceiver *myReceiver;
155 time_t countersCountdown;
156 u_int32_t countersSampleSeqNo;
159 typedef void *(*allocFn_t)(void *magic, /* callback to allocate space on heap */
160 struct _SFLAgent *agent, /* called with self */
161 size_t bytes); /* bytes requested */
163 typedef int (*freeFn_t)(void *magic, /* callback to free space on heap */
164 struct _SFLAgent *agent, /* called with self */
165 void *obj); /* obj to free */
167 typedef void (*errorFn_t)(void *magic, /* callback to log error message */
168 struct _SFLAgent *agent, /* called with self */
169 char *msg); /* error message */
171 typedef void (*sendFn_t)(void *magic, /* optional override fn to send packet */
172 struct _SFLAgent *agent,
173 SFLReceiver *receiver,
178 /* prime numbers are good for hash tables */
179 #define SFL_HASHTABLE_SIZ 199
181 typedef struct _SFLAgent {
182 SFLSampler *jumpTable[SFL_HASHTABLE_SIZ]; /* fast lookup table for samplers (by ifIndex) */
183 SFLSampler *samplers; /* the list of samplers */
184 SFLPoller *pollers; /* the list of samplers */
185 SFLReceiver *receivers; /* the array of receivers */
186 time_t bootTime; /* time when we booted or started */
187 time_t now; /* time now */
188 SFLAddress myIP; /* IP address of this node */
189 u_int32_t subId; /* sub_agent_id */
190 void *magic; /* ptr to pass back in logging and alloc fns */
195 #ifdef SFLOW_DO_SOCKET
201 /* call this at the start with a newly created agent */
202 void sfl_agent_init(SFLAgent *agent,
203 SFLAddress *myIP, /* IP address of this agent */
204 u_int32_t subId, /* agent_sub_id */
205 time_t bootTime, /* agent boot time */
206 time_t now, /* time now */
207 void *magic, /* ptr to pass back in logging and alloc fns */
213 /* call this to create samplers */
214 SFLSampler *sfl_agent_addSampler(SFLAgent *agent, SFLDataSource_instance *pdsi);
216 /* call this to create pollers */
217 SFLPoller *sfl_agent_addPoller(SFLAgent *agent,
218 SFLDataSource_instance *pdsi,
219 void *magic, /* ptr to pass back in getCountersFn() */
220 getCountersFn_t getCountersFn);
222 /* call this to create receivers */
223 SFLReceiver *sfl_agent_addReceiver(SFLAgent *agent);
225 /* call this to remove samplers */
226 int sfl_agent_removeSampler(SFLAgent *agent, SFLDataSource_instance *pdsi);
228 /* call this to remove pollers */
229 int sfl_agent_removePoller(SFLAgent *agent, SFLDataSource_instance *pdsi);
231 /* note: receivers should not be removed. Typically the receivers
232 list will be created at init time and never changed */
234 /* call these fns to retrieve sampler, poller or receiver (e.g. for SNMP GET or GETNEXT operation) */
235 SFLSampler *sfl_agent_getSampler(SFLAgent *agent, SFLDataSource_instance *pdsi);
236 SFLSampler *sfl_agent_getNextSampler(SFLAgent *agent, SFLDataSource_instance *pdsi);
237 SFLPoller *sfl_agent_getPoller(SFLAgent *agent, SFLDataSource_instance *pdsi);
238 SFLPoller *sfl_agent_getNextPoller(SFLAgent *agent, SFLDataSource_instance *pdsi);
239 SFLReceiver *sfl_agent_getReceiver(SFLAgent *agent, u_int32_t receiverIndex);
240 SFLReceiver *sfl_agent_getNextReceiver(SFLAgent *agent, u_int32_t receiverIndex);
242 /* jump table access - for performance */
243 SFLSampler *sfl_agent_getSamplerByIfIndex(SFLAgent *agent, u_int32_t ifIndex);
245 /* call these functions to GET and SET MIB values */
248 char * sfl_receiver_get_sFlowRcvrOwner(SFLReceiver *receiver);
249 void sfl_receiver_set_sFlowRcvrOwner(SFLReceiver *receiver, char *sFlowRcvrOwner);
250 time_t sfl_receiver_get_sFlowRcvrTimeout(SFLReceiver *receiver);
251 void sfl_receiver_set_sFlowRcvrTimeout(SFLReceiver *receiver, time_t sFlowRcvrTimeout);
252 u_int32_t sfl_receiver_get_sFlowRcvrMaximumDatagramSize(SFLReceiver *receiver);
253 void sfl_receiver_set_sFlowRcvrMaximumDatagramSize(SFLReceiver *receiver, u_int32_t sFlowRcvrMaximumDatagramSize);
254 SFLAddress *sfl_receiver_get_sFlowRcvrAddress(SFLReceiver *receiver);
255 void sfl_receiver_set_sFlowRcvrAddress(SFLReceiver *receiver, SFLAddress *sFlowRcvrAddress);
256 u_int32_t sfl_receiver_get_sFlowRcvrPort(SFLReceiver *receiver);
257 void sfl_receiver_set_sFlowRcvrPort(SFLReceiver *receiver, u_int32_t sFlowRcvrPort);
259 u_int32_t sfl_sampler_get_sFlowFsReceiver(SFLSampler *sampler);
260 void sfl_sampler_set_sFlowFsReceiver(SFLSampler *sampler, u_int32_t sFlowFsReceiver);
261 u_int32_t sfl_sampler_get_sFlowFsPacketSamplingRate(SFLSampler *sampler);
262 void sfl_sampler_set_sFlowFsPacketSamplingRate(SFLSampler *sampler, u_int32_t sFlowFsPacketSamplingRate);
263 u_int32_t sfl_sampler_get_sFlowFsMaximumHeaderSize(SFLSampler *sampler);
264 void sfl_sampler_set_sFlowFsMaximumHeaderSize(SFLSampler *sampler, u_int32_t sFlowFsMaximumHeaderSize);
265 u_int32_t sfl_sampler_get_samplesLastTick(SFLSampler *sampler);
267 u_int32_t sfl_poller_get_sFlowCpReceiver(SFLPoller *poller);
268 void sfl_poller_set_sFlowCpReceiver(SFLPoller *poller, u_int32_t sFlowCpReceiver);
269 u_int32_t sfl_poller_get_sFlowCpInterval(SFLPoller *poller);
270 void sfl_poller_set_sFlowCpInterval(SFLPoller *poller, u_int32_t sFlowCpInterval);
272 /* fns to set the sflow agent address or sub-id */
273 void sfl_agent_set_agentAddress(SFLAgent *agent, SFLAddress *addr);
274 void sfl_agent_set_agentSubId(SFLAgent *agent, u_int32_t subId);
276 /* The poller may need a separate number to reference the local bridge port
277 to get counters if it is not the same as the global ifIndex */
278 void sfl_poller_set_bridgePort(SFLPoller *poller, u_int32_t port_no);
279 u_int32_t sfl_poller_get_bridgePort(SFLPoller *poller);
281 /* call this to indicate a discontinuity with a counter like samplePool so that the
282 sflow collector will ignore the next delta */
283 void sfl_sampler_resetFlowSeqNo(SFLSampler *sampler);
285 /* call this to indicate a discontinuity with one or more of the counters so that the
286 sflow collector will ignore the next delta */
287 void sfl_poller_resetCountersSeqNo(SFLPoller *poller);
289 #ifdef SFLOW_SOFTWARE_SAMLING
290 /* software sampling: call this with every packet - returns non-zero if the packet
291 should be sampled (in which case you then call sfl_sampler_writeFlowSample()) */
292 int sfl_sampler_takeSample(SFLSampler *sampler);
295 /* call this to set a maximum samples-per-second threshold. If the sampler reaches this
296 threshold it will automatically back off the sampling rate. A value of 0 disables the
298 void sfl_sampler_set_backoffThreshold(SFLSampler *sampler, u_int32_t samplesPerSecond);
299 u_int32_t sfl_sampler_get_backoffThreshold(SFLSampler *sampler);
301 /* call this once per second (N.B. not on interrupt stack i.e. not hard real-time) */
302 void sfl_agent_tick(SFLAgent *agent, time_t now);
304 /* call this with each flow sample */
305 void sfl_sampler_writeFlowSample(SFLSampler *sampler, SFL_FLOW_SAMPLE_TYPE *fs);
307 /* call this to push counters samples (usually done in the getCountersFn callback) */
308 void sfl_poller_writeCountersSample(SFLPoller *poller, SFL_COUNTERS_SAMPLE_TYPE *cs);
310 /* call this to deallocate resources */
311 void sfl_agent_release(SFLAgent *agent);
316 void sfl_receiver_init(SFLReceiver *receiver, SFLAgent *agent);
317 void sfl_sampler_init(SFLSampler *sampler, SFLAgent *agent, SFLDataSource_instance *pdsi);
318 void sfl_poller_init(SFLPoller *poller, SFLAgent *agent, SFLDataSource_instance *pdsi, void *magic, getCountersFn_t getCountersFn);
321 void sfl_receiver_tick(SFLReceiver *receiver, time_t now);
322 void sfl_poller_tick(SFLPoller *poller, time_t now);
323 void sfl_sampler_tick(SFLSampler *sampler, time_t now);
325 int sfl_receiver_writeFlowSample(SFLReceiver *receiver, SFL_FLOW_SAMPLE_TYPE *fs);
326 int sfl_receiver_writeCountersSample(SFLReceiver *receiver, SFL_COUNTERS_SAMPLE_TYPE *cs);
328 void sfl_agent_resetReceiver(SFLAgent *agent, SFLReceiver *receiver);
330 void sfl_agent_error(SFLAgent *agent, char *modName, char *msg);
331 void sfl_agent_sysError(SFLAgent *agent, char *modName, char *msg);
333 u_int32_t sfl_receiver_samplePacketsSent(SFLReceiver *receiver);
335 #define SFL_ALLOC malloc
336 #define SFL_FREE free
338 #endif /* SFLOW_API_H */