aboutsummaryrefslogtreecommitdiff
path: root/lib/sflow_api.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sflow_api.h')
-rw-r--r--lib/sflow_api.h340
1 files changed, 340 insertions, 0 deletions
diff --git a/lib/sflow_api.h b/lib/sflow_api.h
new file mode 100644
index 00000000..be8d9977
--- /dev/null
+++ b/lib/sflow_api.h
@@ -0,0 +1,340 @@
+/* Copyright (c) 2002-2009 InMon Corp. Licensed under the terms of the InMon sFlow licence: */
+/* http://www.inmon.com/technology/sflowlicense.txt */
+
+#ifndef SFLOW_API_H
+#define SFLOW_API_H 1
+
+/* define SFLOW_DO_SOCKET to 1 if you want the agent
+ to send the packets itself, otherwise set the sendFn
+ callback in sfl_agent_init.*/
+/* #define SFLOW_DO_SOCKET */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <arpa/inet.h> /* for htonl */
+
+#ifdef SFLOW_DO_SOCKET
+#include <sys/socket.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#endif
+
+#include "sflow.h"
+
+/* define SFLOW_SOFTWARE_SAMPLING to 1 if you need to use the
+ sfl_sampler_takeSample routine and give it every packet */
+/* #define SFLOW_SOFTWARE_SAMPLING */
+
+/*
+ uncomment this preprocessor flag (or compile with -DSFL_USE_32BIT_INDEX)
+ if your ds_index numbers can ever be >= 2^30-1 (i.e. >= 0x3FFFFFFF)
+*/
+/* #define SFL_USE_32BIT_INDEX */
+
+
+/* Used to combine ds_class, ds_index and instance into
+ a single 64-bit number like this:
+ __________________________________
+ | cls| index | instance |
+ ----------------------------------
+
+ but now is opened up to a 12-byte struct to ensure
+ that ds_index has a full 32-bit field, and to make
+ accessing the components simpler. The macros have
+ the same behavior as before, so this change should
+ be transparent. The only difference is that these
+ objects are now passed around by reference instead
+ of by value, and the comparison is done using a fn.
+*/
+
+typedef struct _SFLDataSource_instance {
+ u_int32_t ds_class;
+ u_int32_t ds_index;
+ u_int32_t ds_instance;
+} SFLDataSource_instance;
+
+#ifdef SFL_USE_32BIT_INDEX
+#define SFL_FLOW_SAMPLE_TYPE SFLFlow_sample_expanded
+#define SFL_COUNTERS_SAMPLE_TYPE SFLCounters_sample_expanded
+#else
+#define SFL_FLOW_SAMPLE_TYPE SFLFlow_sample
+#define SFL_COUNTERS_SAMPLE_TYPE SFLCounters_sample
+/* if index numbers are not going to use all 32 bits, then we can use
+ the more compact encoding, with the dataSource class and index merged */
+#define SFL_DS_DATASOURCE(dsi) (((dsi).ds_class << 24) + (dsi).ds_index)
+#endif
+
+#define SFL_DS_INSTANCE(dsi) (dsi).ds_instance
+#define SFL_DS_CLASS(dsi) (dsi).ds_class
+#define SFL_DS_INDEX(dsi) (dsi).ds_index
+#define SFL_DS_SET(dsi,clss,indx,inst) \
+ do { \
+ (dsi).ds_class = (clss); \
+ (dsi).ds_index = (indx); \
+ (dsi).ds_instance = (inst); \
+ } while(0)
+
+typedef struct _SFLSampleCollector {
+ u_int32_t data[(SFL_MAX_DATAGRAM_SIZE + SFL_DATA_PAD) / sizeof(u_int32_t)];
+ u_int32_t *datap; /* packet fill pointer */
+ u_int32_t pktlen; /* accumulated size */
+ u_int32_t packetSeqNo;
+ u_int32_t numSamples;
+} SFLSampleCollector;
+
+struct _SFLAgent; /* forward decl */
+
+typedef struct _SFLReceiver {
+ struct _SFLReceiver *nxt;
+ /* MIB fields */
+ char *sFlowRcvrOwner;
+ time_t sFlowRcvrTimeout;
+ u_int32_t sFlowRcvrMaximumDatagramSize;
+ SFLAddress sFlowRcvrAddress;
+ u_int32_t sFlowRcvrPort;
+ u_int32_t sFlowRcvrDatagramVersion;
+ /* public fields */
+ struct _SFLAgent *agent; /* pointer to my agent */
+ /* private fields */
+ SFLSampleCollector sampleCollector;
+#ifdef SFLOW_DO_SOCKET
+ struct sockaddr_in receiver4;
+ struct sockaddr_in6 receiver6;
+#endif
+} SFLReceiver;
+
+typedef struct _SFLSampler {
+ /* for linked list */
+ struct _SFLSampler *nxt;
+ /* for hash lookup table */
+ struct _SFLSampler *hash_nxt;
+ /* MIB fields */
+ SFLDataSource_instance dsi;
+ u_int32_t sFlowFsReceiver;
+ u_int32_t sFlowFsPacketSamplingRate;
+ u_int32_t sFlowFsMaximumHeaderSize;
+ /* public fields */
+ struct _SFLAgent *agent; /* pointer to my agent */
+ /* private fields */
+ SFLReceiver *myReceiver;
+ u_int32_t skip;
+ u_int32_t samplePool;
+ u_int32_t flowSampleSeqNo;
+ /* rate checking */
+ u_int32_t samplesThisTick;
+ u_int32_t samplesLastTick;
+ u_int32_t backoffThreshold;
+} SFLSampler;
+
+/* declare */
+struct _SFLPoller;
+
+typedef void (*getCountersFn_t)(void *magic, /* callback to get counters */
+ struct _SFLPoller *sampler, /* called with self */
+ SFL_COUNTERS_SAMPLE_TYPE *cs); /* struct to fill in */
+
+typedef struct _SFLPoller {
+ /* for linked list */
+ struct _SFLPoller *nxt;
+ /* MIB fields */
+ SFLDataSource_instance dsi;
+ u_int32_t sFlowCpReceiver;
+ time_t sFlowCpInterval;
+ /* public fields */
+ struct _SFLAgent *agent; /* pointer to my agent */
+ void *magic; /* ptr to pass back in getCountersFn() */
+ getCountersFn_t getCountersFn;
+ u_int32_t bridgePort; /* port number local to bridge */
+ /* private fields */
+ SFLReceiver *myReceiver;
+ time_t countersCountdown;
+ u_int32_t countersSampleSeqNo;
+} SFLPoller;
+
+typedef void *(*allocFn_t)(void *magic, /* callback to allocate space on heap */
+ struct _SFLAgent *agent, /* called with self */
+ size_t bytes); /* bytes requested */
+
+typedef int (*freeFn_t)(void *magic, /* callback to free space on heap */
+ struct _SFLAgent *agent, /* called with self */
+ void *obj); /* obj to free */
+
+typedef void (*errorFn_t)(void *magic, /* callback to log error message */
+ struct _SFLAgent *agent, /* called with self */
+ char *msg); /* error message */
+
+typedef void (*sendFn_t)(void *magic, /* optional override fn to send packet */
+ struct _SFLAgent *agent,
+ SFLReceiver *receiver,
+ u_char *pkt,
+ u_int32_t pktLen);
+
+
+/* prime numbers are good for hash tables */
+#define SFL_HASHTABLE_SIZ 199
+
+typedef struct _SFLAgent {
+ SFLSampler *jumpTable[SFL_HASHTABLE_SIZ]; /* fast lookup table for samplers (by ifIndex) */
+ SFLSampler *samplers; /* the list of samplers */
+ SFLPoller *pollers; /* the list of samplers */
+ SFLReceiver *receivers; /* the array of receivers */
+ time_t bootTime; /* time when we booted or started */
+ time_t now; /* time now */
+ SFLAddress myIP; /* IP address of this node */
+ u_int32_t subId; /* sub_agent_id */
+ void *magic; /* ptr to pass back in logging and alloc fns */
+ allocFn_t allocFn;
+ freeFn_t freeFn;
+ errorFn_t errorFn;
+ sendFn_t sendFn;
+#ifdef SFLOW_DO_SOCKET
+ int receiverSocket4;
+ int receiverSocket6;
+#endif
+} SFLAgent;
+
+/* call this at the start with a newly created agent */
+void sfl_agent_init(SFLAgent *agent,
+ SFLAddress *myIP, /* IP address of this agent */
+ u_int32_t subId, /* agent_sub_id */
+ time_t bootTime, /* agent boot time */
+ time_t now, /* time now */
+ void *magic, /* ptr to pass back in logging and alloc fns */
+ allocFn_t allocFn,
+ freeFn_t freeFn,
+ errorFn_t errorFn,
+ sendFn_t sendFn);
+
+/* call this to create samplers */
+SFLSampler *sfl_agent_addSampler(SFLAgent *agent, SFLDataSource_instance *pdsi);
+
+/* call this to create pollers */
+SFLPoller *sfl_agent_addPoller(SFLAgent *agent,
+ SFLDataSource_instance *pdsi,
+ void *magic, /* ptr to pass back in getCountersFn() */
+ getCountersFn_t getCountersFn);
+
+/* call this to create receivers */
+SFLReceiver *sfl_agent_addReceiver(SFLAgent *agent);
+
+/* call this to remove samplers */
+int sfl_agent_removeSampler(SFLAgent *agent, SFLDataSource_instance *pdsi);
+
+/* call this to remove pollers */
+int sfl_agent_removePoller(SFLAgent *agent, SFLDataSource_instance *pdsi);
+
+/* note: receivers should not be removed. Typically the receivers
+ list will be created at init time and never changed */
+
+/* call these fns to retrieve sampler, poller or receiver (e.g. for SNMP GET or GETNEXT operation) */
+SFLSampler *sfl_agent_getSampler(SFLAgent *agent, SFLDataSource_instance *pdsi);
+SFLSampler *sfl_agent_getNextSampler(SFLAgent *agent, SFLDataSource_instance *pdsi);
+SFLPoller *sfl_agent_getPoller(SFLAgent *agent, SFLDataSource_instance *pdsi);
+SFLPoller *sfl_agent_getNextPoller(SFLAgent *agent, SFLDataSource_instance *pdsi);
+SFLReceiver *sfl_agent_getReceiver(SFLAgent *agent, u_int32_t receiverIndex);
+SFLReceiver *sfl_agent_getNextReceiver(SFLAgent *agent, u_int32_t receiverIndex);
+
+/* jump table access - for performance */
+SFLSampler *sfl_agent_getSamplerByIfIndex(SFLAgent *agent, u_int32_t ifIndex);
+
+/* call these functions to GET and SET MIB values */
+
+/* receiver */
+char * sfl_receiver_get_sFlowRcvrOwner(SFLReceiver *receiver);
+void sfl_receiver_set_sFlowRcvrOwner(SFLReceiver *receiver, char *sFlowRcvrOwner);
+time_t sfl_receiver_get_sFlowRcvrTimeout(SFLReceiver *receiver);
+void sfl_receiver_set_sFlowRcvrTimeout(SFLReceiver *receiver, time_t sFlowRcvrTimeout);
+u_int32_t sfl_receiver_get_sFlowRcvrMaximumDatagramSize(SFLReceiver *receiver);
+void sfl_receiver_set_sFlowRcvrMaximumDatagramSize(SFLReceiver *receiver, u_int32_t sFlowRcvrMaximumDatagramSize);
+SFLAddress *sfl_receiver_get_sFlowRcvrAddress(SFLReceiver *receiver);
+void sfl_receiver_set_sFlowRcvrAddress(SFLReceiver *receiver, SFLAddress *sFlowRcvrAddress);
+u_int32_t sfl_receiver_get_sFlowRcvrPort(SFLReceiver *receiver);
+void sfl_receiver_set_sFlowRcvrPort(SFLReceiver *receiver, u_int32_t sFlowRcvrPort);
+/* sampler */
+u_int32_t sfl_sampler_get_sFlowFsReceiver(SFLSampler *sampler);
+void sfl_sampler_set_sFlowFsReceiver(SFLSampler *sampler, u_int32_t sFlowFsReceiver);
+u_int32_t sfl_sampler_get_sFlowFsPacketSamplingRate(SFLSampler *sampler);
+void sfl_sampler_set_sFlowFsPacketSamplingRate(SFLSampler *sampler, u_int32_t sFlowFsPacketSamplingRate);
+u_int32_t sfl_sampler_get_sFlowFsMaximumHeaderSize(SFLSampler *sampler);
+void sfl_sampler_set_sFlowFsMaximumHeaderSize(SFLSampler *sampler, u_int32_t sFlowFsMaximumHeaderSize);
+u_int32_t sfl_sampler_get_samplesLastTick(SFLSampler *sampler);
+/* poller */
+u_int32_t sfl_poller_get_sFlowCpReceiver(SFLPoller *poller);
+void sfl_poller_set_sFlowCpReceiver(SFLPoller *poller, u_int32_t sFlowCpReceiver);
+u_int32_t sfl_poller_get_sFlowCpInterval(SFLPoller *poller);
+void sfl_poller_set_sFlowCpInterval(SFLPoller *poller, u_int32_t sFlowCpInterval);
+
+/* fns to set the sflow agent address or sub-id */
+void sfl_agent_set_agentAddress(SFLAgent *agent, SFLAddress *addr);
+void sfl_agent_set_agentSubId(SFLAgent *agent, u_int32_t subId);
+
+/* The poller may need a separate number to reference the local bridge port
+ to get counters if it is not the same as the global ifIndex */
+void sfl_poller_set_bridgePort(SFLPoller *poller, u_int32_t port_no);
+u_int32_t sfl_poller_get_bridgePort(SFLPoller *poller);
+
+/* call this to indicate a discontinuity with a counter like samplePool so that the
+ sflow collector will ignore the next delta */
+void sfl_sampler_resetFlowSeqNo(SFLSampler *sampler);
+
+/* call this to indicate a discontinuity with one or more of the counters so that the
+ sflow collector will ignore the next delta */
+void sfl_poller_resetCountersSeqNo(SFLPoller *poller);
+
+#ifdef SFLOW_SOFTWARE_SAMLING
+/* software sampling: call this with every packet - returns non-zero if the packet
+ should be sampled (in which case you then call sfl_sampler_writeFlowSample()) */
+int sfl_sampler_takeSample(SFLSampler *sampler);
+#endif
+
+/* call this to set a maximum samples-per-second threshold. If the sampler reaches this
+ threshold it will automatically back off the sampling rate. A value of 0 disables the
+ mechanism */
+void sfl_sampler_set_backoffThreshold(SFLSampler *sampler, u_int32_t samplesPerSecond);
+u_int32_t sfl_sampler_get_backoffThreshold(SFLSampler *sampler);
+
+/* call this once per second (N.B. not on interrupt stack i.e. not hard real-time) */
+void sfl_agent_tick(SFLAgent *agent, time_t now);
+
+/* call this with each flow sample */
+void sfl_sampler_writeFlowSample(SFLSampler *sampler, SFL_FLOW_SAMPLE_TYPE *fs);
+
+/* call this to push counters samples (usually done in the getCountersFn callback) */
+void sfl_poller_writeCountersSample(SFLPoller *poller, SFL_COUNTERS_SAMPLE_TYPE *cs);
+
+/* call this to deallocate resources */
+void sfl_agent_release(SFLAgent *agent);
+
+
+/* internal fns */
+
+void sfl_receiver_init(SFLReceiver *receiver, SFLAgent *agent);
+void sfl_sampler_init(SFLSampler *sampler, SFLAgent *agent, SFLDataSource_instance *pdsi);
+void sfl_poller_init(SFLPoller *poller, SFLAgent *agent, SFLDataSource_instance *pdsi, void *magic, getCountersFn_t getCountersFn);
+
+
+void sfl_receiver_tick(SFLReceiver *receiver, time_t now);
+void sfl_poller_tick(SFLPoller *poller, time_t now);
+void sfl_sampler_tick(SFLSampler *sampler, time_t now);
+
+int sfl_receiver_writeFlowSample(SFLReceiver *receiver, SFL_FLOW_SAMPLE_TYPE *fs);
+int sfl_receiver_writeCountersSample(SFLReceiver *receiver, SFL_COUNTERS_SAMPLE_TYPE *cs);
+
+void sfl_agent_resetReceiver(SFLAgent *agent, SFLReceiver *receiver);
+
+void sfl_agent_error(SFLAgent *agent, char *modName, char *msg);
+void sfl_agent_sysError(SFLAgent *agent, char *modName, char *msg);
+
+u_int32_t sfl_receiver_samplePacketsSent(SFLReceiver *receiver);
+
+#define SFL_ALLOC malloc
+#define SFL_FREE free
+
+#endif /* SFLOW_API_H */
+
+