]>
Commit | Line | Data |
---|---|---|
7dd32dff NM |
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 | |
6 | */ | |
c72e245a BP |
7 | |
8 | #ifndef SFLOW_API_H | |
9 | #define SFLOW_API_H 1 | |
10 | ||
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 */ | |
15 | ||
16 | #include <stdio.h> | |
17 | #include <stdlib.h> | |
18 | #include <unistd.h> | |
19 | #include <errno.h> | |
20 | #include <string.h> | |
21 | #include <sys/types.h> | |
22 | #include <arpa/inet.h> /* for htonl */ | |
23 | ||
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> | |
29 | #endif | |
30 | ||
31 | #include "sflow.h" | |
d295e8e9 | 32 | |
c72e245a BP |
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 */ | |
36 | ||
37 | /* | |
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) | |
40 | */ | |
41 | /* #define SFL_USE_32BIT_INDEX */ | |
42 | ||
43 | ||
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 | ---------------------------------- | |
d295e8e9 | 49 | |
c72e245a BP |
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. | |
57 | */ | |
58 | ||
59 | typedef struct _SFLDataSource_instance { | |
60 | u_int32_t ds_class; | |
61 | u_int32_t ds_index; | |
62 | u_int32_t ds_instance; | |
63 | } SFLDataSource_instance; | |
64 | ||
65 | #ifdef SFL_USE_32BIT_INDEX | |
66 | #define SFL_FLOW_SAMPLE_TYPE SFLFlow_sample_expanded | |
67 | #define SFL_COUNTERS_SAMPLE_TYPE SFLCounters_sample_expanded | |
68 | #else | |
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) | |
74 | #endif | |
75 | ||
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) \ | |
80 | do { \ | |
81 | (dsi).ds_class = (clss); \ | |
82 | (dsi).ds_index = (indx); \ | |
83 | (dsi).ds_instance = (inst); \ | |
84 | } while(0) | |
85 | ||
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; | |
91 | u_int32_t numSamples; | |
92 | } SFLSampleCollector; | |
93 | ||
94 | struct _SFLAgent; /* forward decl */ | |
95 | ||
96 | typedef struct _SFLReceiver { | |
97 | struct _SFLReceiver *nxt; | |
98 | /* MIB fields */ | |
99 | char *sFlowRcvrOwner; | |
100 | time_t sFlowRcvrTimeout; | |
101 | u_int32_t sFlowRcvrMaximumDatagramSize; | |
102 | SFLAddress sFlowRcvrAddress; | |
103 | u_int32_t sFlowRcvrPort; | |
104 | u_int32_t sFlowRcvrDatagramVersion; | |
105 | /* public fields */ | |
106 | struct _SFLAgent *agent; /* pointer to my agent */ | |
107 | /* private fields */ | |
108 | SFLSampleCollector sampleCollector; | |
109 | #ifdef SFLOW_DO_SOCKET | |
110 | struct sockaddr_in receiver4; | |
111 | struct sockaddr_in6 receiver6; | |
112 | #endif | |
113 | } SFLReceiver; | |
114 | ||
115 | typedef struct _SFLSampler { | |
116 | /* for linked list */ | |
117 | struct _SFLSampler *nxt; | |
118 | /* for hash lookup table */ | |
119 | struct _SFLSampler *hash_nxt; | |
120 | /* MIB fields */ | |
121 | SFLDataSource_instance dsi; | |
122 | u_int32_t sFlowFsReceiver; | |
123 | u_int32_t sFlowFsPacketSamplingRate; | |
124 | u_int32_t sFlowFsMaximumHeaderSize; | |
125 | /* public fields */ | |
126 | struct _SFLAgent *agent; /* pointer to my agent */ | |
127 | /* private fields */ | |
128 | SFLReceiver *myReceiver; | |
129 | u_int32_t skip; | |
130 | u_int32_t samplePool; | |
131 | u_int32_t flowSampleSeqNo; | |
132 | /* rate checking */ | |
133 | u_int32_t samplesThisTick; | |
134 | u_int32_t samplesLastTick; | |
135 | u_int32_t backoffThreshold; | |
136 | } SFLSampler; | |
137 | ||
138 | /* declare */ | |
139 | struct _SFLPoller; | |
140 | ||
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 */ | |
144 | ||
145 | typedef struct _SFLPoller { | |
146 | /* for linked list */ | |
147 | struct _SFLPoller *nxt; | |
148 | /* MIB fields */ | |
149 | SFLDataSource_instance dsi; | |
150 | u_int32_t sFlowCpReceiver; | |
151 | time_t sFlowCpInterval; | |
152 | /* public fields */ | |
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 */ | |
157 | /* private fields */ | |
158 | SFLReceiver *myReceiver; | |
159 | time_t countersCountdown; | |
160 | u_int32_t countersSampleSeqNo; | |
161 | } SFLPoller; | |
162 | ||
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 */ | |
166 | ||
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 */ | |
170 | ||
171 | typedef void (*errorFn_t)(void *magic, /* callback to log error message */ | |
172 | struct _SFLAgent *agent, /* called with self */ | |
173 | char *msg); /* error message */ | |
174 | ||
175 | typedef void (*sendFn_t)(void *magic, /* optional override fn to send packet */ | |
176 | struct _SFLAgent *agent, | |
177 | SFLReceiver *receiver, | |
178 | u_char *pkt, | |
179 | u_int32_t pktLen); | |
180 | ||
181 | ||
182 | /* prime numbers are good for hash tables */ | |
183 | #define SFL_HASHTABLE_SIZ 199 | |
184 | ||
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 */ | |
195 | allocFn_t allocFn; | |
196 | freeFn_t freeFn; | |
197 | errorFn_t errorFn; | |
198 | sendFn_t sendFn; | |
199 | #ifdef SFLOW_DO_SOCKET | |
200 | int receiverSocket4; | |
201 | int receiverSocket6; | |
202 | #endif | |
203 | } SFLAgent; | |
204 | ||
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 */ | |
212 | allocFn_t allocFn, | |
213 | freeFn_t freeFn, | |
214 | errorFn_t errorFn, | |
215 | sendFn_t sendFn); | |
216 | ||
217 | /* call this to create samplers */ | |
218 | SFLSampler *sfl_agent_addSampler(SFLAgent *agent, SFLDataSource_instance *pdsi); | |
219 | ||
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); | |
225 | ||
226 | /* call this to create receivers */ | |
227 | SFLReceiver *sfl_agent_addReceiver(SFLAgent *agent); | |
228 | ||
229 | /* call this to remove samplers */ | |
230 | int sfl_agent_removeSampler(SFLAgent *agent, SFLDataSource_instance *pdsi); | |
231 | ||
232 | /* call this to remove pollers */ | |
233 | int sfl_agent_removePoller(SFLAgent *agent, SFLDataSource_instance *pdsi); | |
234 | ||
235 | /* note: receivers should not be removed. Typically the receivers | |
236 | list will be created at init time and never changed */ | |
237 | ||
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); | |
245 | ||
246 | /* jump table access - for performance */ | |
247 | SFLSampler *sfl_agent_getSamplerByIfIndex(SFLAgent *agent, u_int32_t ifIndex); | |
248 | ||
249 | /* call these functions to GET and SET MIB values */ | |
250 | ||
251 | /* receiver */ | |
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); | |
262 | /* sampler */ | |
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); | |
270 | /* poller */ | |
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); | |
275 | ||
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); | |
279 | ||
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); | |
50b9699f | 284 | SFLPoller *sfl_agent_getPollerByBridgePort(SFLAgent *agent, u_int32_t port_no); |
c72e245a BP |
285 | |
286 | /* call this to indicate a discontinuity with a counter like samplePool so that the | |
287 | sflow collector will ignore the next delta */ | |
288 | void sfl_sampler_resetFlowSeqNo(SFLSampler *sampler); | |
289 | ||
290 | /* call this to indicate a discontinuity with one or more of the counters so that the | |
291 | sflow collector will ignore the next delta */ | |
292 | void sfl_poller_resetCountersSeqNo(SFLPoller *poller); | |
293 | ||
294 | #ifdef SFLOW_SOFTWARE_SAMLING | |
295 | /* software sampling: call this with every packet - returns non-zero if the packet | |
296 | should be sampled (in which case you then call sfl_sampler_writeFlowSample()) */ | |
297 | int sfl_sampler_takeSample(SFLSampler *sampler); | |
298 | #endif | |
299 | ||
300 | /* call this to set a maximum samples-per-second threshold. If the sampler reaches this | |
301 | threshold it will automatically back off the sampling rate. A value of 0 disables the | |
302 | mechanism */ | |
303 | void sfl_sampler_set_backoffThreshold(SFLSampler *sampler, u_int32_t samplesPerSecond); | |
304 | u_int32_t sfl_sampler_get_backoffThreshold(SFLSampler *sampler); | |
305 | ||
306 | /* call this once per second (N.B. not on interrupt stack i.e. not hard real-time) */ | |
307 | void sfl_agent_tick(SFLAgent *agent, time_t now); | |
308 | ||
309 | /* call this with each flow sample */ | |
310 | void sfl_sampler_writeFlowSample(SFLSampler *sampler, SFL_FLOW_SAMPLE_TYPE *fs); | |
311 | ||
312 | /* call this to push counters samples (usually done in the getCountersFn callback) */ | |
313 | void sfl_poller_writeCountersSample(SFLPoller *poller, SFL_COUNTERS_SAMPLE_TYPE *cs); | |
314 | ||
315 | /* call this to deallocate resources */ | |
316 | void sfl_agent_release(SFLAgent *agent); | |
317 | ||
318 | ||
319 | /* internal fns */ | |
320 | ||
321 | void sfl_receiver_init(SFLReceiver *receiver, SFLAgent *agent); | |
322 | void sfl_sampler_init(SFLSampler *sampler, SFLAgent *agent, SFLDataSource_instance *pdsi); | |
323 | void sfl_poller_init(SFLPoller *poller, SFLAgent *agent, SFLDataSource_instance *pdsi, void *magic, getCountersFn_t getCountersFn); | |
324 | ||
325 | ||
326 | void sfl_receiver_tick(SFLReceiver *receiver, time_t now); | |
327 | void sfl_poller_tick(SFLPoller *poller, time_t now); | |
328 | void sfl_sampler_tick(SFLSampler *sampler, time_t now); | |
329 | ||
330 | int sfl_receiver_writeFlowSample(SFLReceiver *receiver, SFL_FLOW_SAMPLE_TYPE *fs); | |
331 | int sfl_receiver_writeCountersSample(SFLReceiver *receiver, SFL_COUNTERS_SAMPLE_TYPE *cs); | |
332 | ||
333 | void sfl_agent_resetReceiver(SFLAgent *agent, SFLReceiver *receiver); | |
334 | ||
335 | void sfl_agent_error(SFLAgent *agent, char *modName, char *msg); | |
336 | void sfl_agent_sysError(SFLAgent *agent, char *modName, char *msg); | |
337 | ||
338 | u_int32_t sfl_receiver_samplePacketsSent(SFLReceiver *receiver); | |
339 | ||
340 | #define SFL_ALLOC malloc | |
341 | #define SFL_FREE free | |
342 | ||
343 | #endif /* SFLOW_API_H */ | |
344 | ||
345 |