]> git.proxmox.com Git - mirror_ovs.git/blob - lib/sflow_poller.c
Merge "sflow" into "master".
[mirror_ovs.git] / lib / sflow_poller.c
1 /* Copyright (c) 2002-2009 InMon Corp. Licensed under the terms of the InMon sFlow licence: */
2 /* http://www.inmon.com/technology/sflowlicense.txt */
3
4 #include "sflow_api.h"
5
6 /*_________________--------------------------__________________
7 _________________ sfl_poller_init __________________
8 -----------------__________________________------------------
9 */
10
11 void sfl_poller_init(SFLPoller *poller,
12 SFLAgent *agent,
13 SFLDataSource_instance *pdsi,
14 void *magic, /* ptr to pass back in getCountersFn() */
15 getCountersFn_t getCountersFn)
16 {
17 /* copy the dsi in case it points to poller->dsi, which we are about to clear */
18 SFLDataSource_instance dsi = *pdsi;
19
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;
23
24 /* clear everything */
25 memset(poller, 0, sizeof(*poller));
26
27 /* restore the linked list ptr */
28 poller->nxt = nxtPtr;
29
30 /* now copy in the parameters */
31 poller->agent = agent;
32 poller->dsi = dsi; /* structure copy */
33 poller->magic = magic;
34 poller->getCountersFn = getCountersFn;
35 }
36
37 /*_________________--------------------------__________________
38 _________________ reset __________________
39 -----------------__________________________------------------
40 */
41
42 static void reset(SFLPoller *poller)
43 {
44 SFLDataSource_instance dsi = poller->dsi;
45 sfl_poller_init(poller, poller->agent, &dsi, poller->magic, poller->getCountersFn);
46 }
47
48 /*_________________---------------------------__________________
49 _________________ MIB access __________________
50 -----------------___________________________------------------
51 */
52 u_int32_t sfl_poller_get_sFlowCpReceiver(SFLPoller *poller) {
53 return poller->sFlowCpReceiver;
54 }
55
56 void sfl_poller_set_sFlowCpReceiver(SFLPoller *poller, u_int32_t sFlowCpReceiver) {
57 poller->sFlowCpReceiver = sFlowCpReceiver;
58 if(sFlowCpReceiver == 0) reset(poller);
59 else {
60 /* retrieve and cache a direct pointer to my receiver */
61 poller->myReceiver = sfl_agent_getReceiver(poller->agent, poller->sFlowCpReceiver);
62 }
63 }
64
65 u_int32_t sfl_poller_get_sFlowCpInterval(SFLPoller *poller) {
66 return poller->sFlowCpInterval;
67 }
68
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);
75 }
76
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.
82 */
83
84 void sfl_poller_set_bridgePort(SFLPoller *poller, u_int32_t port_no) {
85 poller->bridgePort = port_no;
86 }
87
88 u_int32_t sfl_poller_get_bridgePort(SFLPoller *poller) {
89 return poller->bridgePort;
90 }
91
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.
97 */
98 void sfl_poller_resetCountersSeqNo(SFLPoller *poller) { poller->countersSampleSeqNo = 0; }
99
100 /*_________________---------------------------__________________
101 _________________ sfl_poller_tick __________________
102 -----------------___________________________------------------
103 */
104
105 void sfl_poller_tick(SFLPoller *poller, time_t now)
106 {
107 if(poller->countersCountdown == 0) return; /* counters retrieval was not enabled */
108 if(poller->sFlowCpReceiver == 0) return;
109
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); */
118 }
119 /* reset the countdown */
120 poller->countersCountdown = poller->sFlowCpInterval;
121 }
122 }
123
124 /*_________________---------------------------------__________________
125 _________________ sfl_poller_writeCountersSample __________________
126 -----------------_________________________________------------------
127 */
128
129 void sfl_poller_writeCountersSample(SFLPoller *poller, SFL_COUNTERS_SAMPLE_TYPE *cs)
130 {
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);
136 #else
137 cs->source_id = SFL_DS_DATASOURCE(poller->dsi);
138 #endif
139 /* sent to my receiver */
140 if(poller->myReceiver) sfl_receiver_writeCountersSample(poller->myReceiver, cs);
141 }
142