@cryptotaxi247 / netdata-1 / commits / 1c8127820

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