mirror of
https://github.com/openvswitch/ovs
synced 2025-09-05 08:45:23 +00:00
Add InMon's sFlow Agent library to the build system.
The C source and header files added in this commit is covered under the InMon sFlow license at http://www.inmon.com/technology/sflowlicense.txt The library requires -Wno-unused to compile without warnings, so this commit adds that for building the sFlow code only. Automake can only change compiler flags on a per-library or per-program basis, so sFlow is built as a separate library. The library will be used in upcoming commits.
This commit is contained in:
340
lib/sflow_api.h
Normal file
340
lib/sflow_api.h
Normal file
@@ -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 */
|
||||
|
||||
|
Reference in New Issue
Block a user