1 /* Copyright (c) 2002-2009 InMon Corp. Licensed under the terms of the InMon sFlow licence: */
2 /* http://www.inmon.com/technology/sflowlicense.txt */
6 /*_________________--------------------------__________________
7 _________________ sfl_poller_init __________________
8 -----------------__________________________------------------
11 void sfl_poller_init(SFLPoller *poller,
13 SFLDataSource_instance *pdsi,
14 void *magic, /* ptr to pass back in getCountersFn() */
15 getCountersFn_t getCountersFn)
17 /* copy the dsi in case it points to poller->dsi, which we are about to clear */
18 SFLDataSource_instance dsi = *pdsi;
20 /* preserve the *nxt pointer too, in case we are resetting this poller and it is
21 already part of the agent's linked list (thanks to Matt Woodly for pointing this out) */
22 SFLPoller *nxtPtr = poller->nxt;
24 /* clear everything */
25 memset(poller, 0, sizeof(*poller));
27 /* restore the linked list ptr */
30 /* now copy in the parameters */
31 poller->agent = agent;
32 poller->dsi = dsi; /* structure copy */
33 poller->magic = magic;
34 poller->getCountersFn = getCountersFn;
37 /*_________________--------------------------__________________
38 _________________ reset __________________
39 -----------------__________________________------------------
42 static void reset(SFLPoller *poller)
44 SFLDataSource_instance dsi = poller->dsi;
45 sfl_poller_init(poller, poller->agent, &dsi, poller->magic, poller->getCountersFn);
48 /*_________________---------------------------__________________
49 _________________ MIB access __________________
50 -----------------___________________________------------------
52 u_int32_t sfl_poller_get_sFlowCpReceiver(SFLPoller *poller) {
53 return poller->sFlowCpReceiver;
56 void sfl_poller_set_sFlowCpReceiver(SFLPoller *poller, u_int32_t sFlowCpReceiver) {
57 poller->sFlowCpReceiver = sFlowCpReceiver;
58 if(sFlowCpReceiver == 0) reset(poller);
60 /* retrieve and cache a direct pointer to my receiver */
61 poller->myReceiver = sfl_agent_getReceiver(poller->agent, poller->sFlowCpReceiver);
65 u_int32_t sfl_poller_get_sFlowCpInterval(SFLPoller *poller) {
66 return poller->sFlowCpInterval;
69 void sfl_poller_set_sFlowCpInterval(SFLPoller *poller, u_int32_t sFlowCpInterval) {
70 poller->sFlowCpInterval = sFlowCpInterval;
71 /* Set the countersCountdown to be a randomly selected value between 1 and
72 sFlowCpInterval. That way the counter polling would be desynchronised
73 (on a 200-port switch, polling all the counters in one second could be harmful). */
74 poller->countersCountdown = 1 + (random() % sFlowCpInterval);
77 /*_________________---------------------------------__________________
78 _________________ bridge port __________________
79 -----------------_________________________________------------------
80 May need a separate number to reference the local bridge port
81 to get counters if it is not the same as the global ifIndex.
84 void sfl_poller_set_bridgePort(SFLPoller *poller, u_int32_t port_no) {
85 poller->bridgePort = port_no;
88 u_int32_t sfl_poller_get_bridgePort(SFLPoller *poller) {
89 return poller->bridgePort;
92 /*_________________---------------------------------__________________
93 _________________ sequence number reset __________________
94 -----------------_________________________________------------------
95 Used to indicate a counter discontinuity
96 so that the sflow collector will know to ignore the next delta.
98 void sfl_poller_resetCountersSeqNo(SFLPoller *poller) { poller->countersSampleSeqNo = 0; }
100 /*_________________---------------------------__________________
101 _________________ sfl_poller_tick __________________
102 -----------------___________________________------------------
105 void sfl_poller_tick(SFLPoller *poller, time_t now)
107 if(poller->countersCountdown == 0) return; /* counters retrieval was not enabled */
108 if(poller->sFlowCpReceiver == 0) return;
110 if(--poller->countersCountdown == 0) {
111 if(poller->getCountersFn != NULL) {
112 /* call out for counters */
113 SFL_COUNTERS_SAMPLE_TYPE cs;
114 memset(&cs, 0, sizeof(cs));
115 poller->getCountersFn(poller->magic, poller, &cs);
116 /* this countersFn is expected to fill in some counter block elements
117 and then call sfl_poller_writeCountersSample(poller, &cs); */
119 /* reset the countdown */
120 poller->countersCountdown = poller->sFlowCpInterval;
124 /*_________________---------------------------------__________________
125 _________________ sfl_poller_writeCountersSample __________________
126 -----------------_________________________________------------------
129 void sfl_poller_writeCountersSample(SFLPoller *poller, SFL_COUNTERS_SAMPLE_TYPE *cs)
131 /* fill in the rest of the header fields, and send to the receiver */
132 cs->sequence_number = ++poller->countersSampleSeqNo;
133 #ifdef SFL_USE_32BIT_INDEX
134 cs->ds_class = SFL_DS_CLASS(poller->dsi);
135 cs->ds_index = SFL_DS_INDEX(poller->dsi);
137 cs->source_id = SFL_DS_DATASOURCE(poller->dsi);
139 /* sent to my receiver */
140 if(poller->myReceiver) sfl_receiver_writeCountersSample(poller->myReceiver, cs);