nfacct plugin source files
Costa Tsaousis (ktsaou) committed
Mar 19, 2015 at 09:49 UTC
1c8127820ae57f5fe7c70b7c6bea68c34269a50d
3 files changed
+218
src/plugin_nfacct.c
new
+206
@@ -0,0 +1,206 @@
1
+#include <stdio.h>
2
+#include <stdlib.h>
3
+#include <string.h>
4
+#include <sys/types.h>
5
+#include <dirent.h>
6
+#include <sys/stat.h>
7
+#include <fcntl.h>
8
+#include <unistd.h>
9
+#include <time.h>
10
+#include <errno.h>
11
+
12
+#include <libmnl/libmnl.h>
13
+#include <libnetfilter_acct/libnetfilter_acct.h>
14
+
15
+#include "global_statistics.h"
16
+#include "common.h"
17
+#include "config.h"
18
+#include "log.h"
19
+#include "rrd.h"
20
+#include "plugin_proc.h"
21
+
22
+struct mynfacct {
23
+ const char *name;
24
+ uint64_t pkts;
25
+ uint64_t bytes;
26
+ struct nfacct *nfacct;
27
+};
28
+
29
+struct nfacct_list {
30
+ int size;
31
+ int len;
32
+ struct mynfacct data[];
33
+} *nfacct_list = NULL;
34
+
35
+static int nfacct_callback(const struct nlmsghdr *nlh, void *data) {
36
+ if(data) {};
37
+
38
+ if(!nfacct_list || nfacct_list->len == nfacct_list->size) {
39
+ int size = (nfacct_list) ? nfacct_list->size : 0;
40
+ int len = (nfacct_list) ? nfacct_list->len : 0;
41
+ size++;
42
+
43
+ info("nfacct.plugin: increasing nfacct_list to size %d", size);
44
+
45
+ nfacct_list = realloc(nfacct_list, sizeof(struct nfacct_list) + (sizeof(struct mynfacct) * size));
46
+ if(!nfacct_list) {
47
+ error("nfacct.plugin: cannot allocate nfacct_list.");
48
+ return MNL_CB_OK;
49
+ }
50
+
51
+ nfacct_list->data[len].nfacct = nfacct_alloc();
52
+ if(!nfacct_list->data[size - 1].nfacct) {
53
+ error("nfacct.plugin: nfacct_alloc() failed.");
54
+ free(nfacct_list);
55
+ nfacct_list = NULL;
56
+ return MNL_CB_OK;
57
+ }
58
+
59
+ nfacct_list->size = size;
60
+ nfacct_list->len = len;
61
+ }
62
+
63
+ if(nfacct_nlmsg_parse_payload(nlh, nfacct_list->data[nfacct_list->len].nfacct) < 0) {
64
+ error("nfacct.plugin: nfacct_nlmsg_parse_payload() failed.");
65
+ return MNL_CB_OK;
66
+ }
67
+
68
+ nfacct_list->data[nfacct_list->len].name = nfacct_attr_get_str(nfacct_list->data[nfacct_list->len].nfacct, NFACCT_ATTR_NAME);
69
+ nfacct_list->data[nfacct_list->len].pkts = nfacct_attr_get_u64(nfacct_list->data[nfacct_list->len].nfacct, NFACCT_ATTR_PKTS);
70
+ nfacct_list->data[nfacct_list->len].bytes = nfacct_attr_get_u64(nfacct_list->data[nfacct_list->len].nfacct, NFACCT_ATTR_BYTES);
71
+
72
+ nfacct_list->len++;
73
+ return MNL_CB_OK;
74
+}
75
+
76
+void *nfacct_main(void *ptr) {
77
+ if(ptr) { ; }
78
+
79
+ if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
80
+ error("nfacct.plugin: Cannot set pthread cancel type to DEFERRED.");
81
+
82
+ if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
83
+ error("nfacct.plugin: Cannot set pthread cancel state to ENABLE.");
84
+
85
+ char buf[MNL_SOCKET_BUFFER_SIZE];
86
+ struct mnl_socket *nl = NULL;
87
+ struct nlmsghdr *nlh = NULL;
88
+ unsigned int seq = 0, portid = 0;
89
+
90
+ seq = time(NULL) - 1;
91
+
92
+ nl = mnl_socket_open(NETLINK_NETFILTER);
93
+ if(!nl) {
94
+ error("nfacct.plugin: mnl_socket_open() failed");
95
+ return NULL;
96
+ }
97
+
98
+ if(mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
99
+ mnl_socket_close(nl);
100
+ error("nfacct.plugin: mnl_socket_bind() failed");
101
+ return NULL;
102
+ }
103
+ portid = mnl_socket_get_portid(nl);
104
+
105
+ // ------------------------------------------------------------------------
106
+
107
+ struct timeval last, now;
108
+ unsigned long long usec = 0, susec = 0;
109
+ RRD_STATS *st = NULL;
110
+
111
+ gettimeofday(&last, NULL);
112
+
113
+ // ------------------------------------------------------------------------
114
+
115
+ while(1) {
116
+ seq++;
117
+
118
+ nlh = nfacct_nlmsg_build_hdr(buf, NFNL_MSG_ACCT_GET, NLM_F_DUMP, seq);
119
+ if(!nlh) {
120
+ mnl_socket_close(nl);
121
+ error("nfacct.plugin: nfacct_nlmsg_build_hdr() failed");
122
+ return NULL;
123
+ }
124
+
125
+ if(mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
126
+ error("nfacct.plugin: mnl_socket_send");
127
+ return NULL;
128
+ }
129
+
130
+ if(nfacct_list) nfacct_list->len = 0;
131
+
132
+ int ret;
133
+ while((ret = mnl_socket_recvfrom(nl, buf, sizeof(buf))) > 0) {
134
+ if((ret = mnl_cb_run(buf, ret, seq, portid, nfacct_callback, NULL)) <= 0) break;
135
+ }
136
+
137
+ if (ret == -1) {
138
+ error("nfacct.plugin: error communicating with kernel.");
139
+ return NULL;
140
+ }
141
+
142
+ // --------------------------------------------------------------------
143
+
144
+ gettimeofday(&now, NULL);
145
+ usec = usecdiff(&now, &last) - susec;
146
+ debug(D_NFACCT_LOOP, "nfacct.plugin: last loop took %llu usec (worked for %llu, sleeped for %llu).", usec + susec, usec, susec);
147
+
148
+ if(usec < (update_every * 1000000ULL / 2ULL)) susec = (update_every * 1000000ULL) - usec;
149
+ else susec = update_every * 1000000ULL / 2ULL;
150
+
151
+
152
+ // --------------------------------------------------------------------
153
+
154
+ if(nfacct_list && nfacct_list->len) {
155
+ int i;
156
+
157
+ st = rrd_stats_find_bytype("nfacct", "packets");
158
+ if(!st) {
159
+ st = rrd_stats_create("nfacct", "packets", NULL, "netfilter", "Netfilter Accounting Packets", "packets/s", 1006, update_every, CHART_TYPE_STACKED);
160
+
161
+ for(i = 0; i < nfacct_list->len ; i++)
162
+ rrd_stats_dimension_add(st, nfacct_list->data[i].name, NULL, 1, update_every, RRD_DIMENSION_INCREMENTAL);
163
+ }
164
+ else rrd_stats_next(st);
165
+
166
+ for(i = 0; i < nfacct_list->len ; i++) {
167
+ RRD_DIMENSION *rd = rrd_stats_dimension_find(st, nfacct_list->data[i].name);
168
+
169
+ if(!rd) rd = rrd_stats_dimension_add(st, nfacct_list->data[i].name, NULL, 1, update_every, RRD_DIMENSION_INCREMENTAL);
170
+ if(rd) rrd_stats_dimension_set_by_pointer(st, rd, nfacct_list->data[i].pkts);
171
+ }
172
+
173
+ rrd_stats_done(st);
174
+
175
+ // ----------------------------------------------------------------
176
+
177
+ st = rrd_stats_find_bytype("nfacct", "bytes");
178
+ if(!st) {
179
+ st = rrd_stats_create("nfacct", "bytes", NULL, "netfilter", "Netfilter Accounting Bandwidth", "kilobytes/s", 1007, update_every, CHART_TYPE_STACKED);
180
+
181
+ for(i = 0; i < nfacct_list->len ; i++)
182
+ rrd_stats_dimension_add(st, nfacct_list->data[i].name, NULL, 1, 1000 * update_every, RRD_DIMENSION_INCREMENTAL);
183
+ }
184
+ else rrd_stats_next(st);
185
+
186
+ for(i = 0; i < nfacct_list->len ; i++) {
187
+ RRD_DIMENSION *rd = rrd_stats_dimension_find(st, nfacct_list->data[i].name);
188
+
189
+ if(!rd) rd = rrd_stats_dimension_add(st, nfacct_list->data[i].name, NULL, 1, 1000 * update_every, RRD_DIMENSION_INCREMENTAL);
190
+ if(rd) rrd_stats_dimension_set_by_pointer(st, rd, nfacct_list->data[i].bytes);
191
+ }
192
+
193
+ rrd_stats_done(st);
194
+ }
195
+
196
+ // --------------------------------------------------------------------
197
+
198
+ usleep(susec);
199
+
200
+ // copy current to last
201
+ bcopy(&now, &last, sizeof(struct timeval));
202
+ }
203
+
204
+ mnl_socket_close(nl);
205
+ return NULL;
206
+}
src/plugin_nfacct.h
new
+7
@@ -0,0 +1,7 @@
1
+#ifndef NETDATA_NFACCT_H
2
+#define NETDATA_NFACCT_H 1
3
+
4
+extern void *nfacct_main(void *ptr);
5
+
6
+#endif /* NETDATA_NFACCT_H */
7
+
src/rrd.c
+5
@@ -597,6 +597,11 @@ int rrd_stats_dimension_set(RRD_STATS *st, const char *id, collected_number valu
597
void rrd_stats_next_usec(RRD_STATS *st, unsigned long long microseconds)
598
{
599
if(st->debug) debug(D_RRD_STATS, "%s: NEXT: %llu microseconds", st->name, microseconds);
600
+ if(microseconds > st->entries * st->update_every * 1000000ULL) {
601
+ info("History of chart %s too old. Reseting chart.", st->name);
602
+ rrd_stats_reset(st);
603
+ microseconds = 0;
604
+ }
605
st->usec_since_last_update = microseconds;
606
}
607