Self-cleaning obsolete network interfaces in FreeBSD plugin
Vladimir Kobal committed
Mar 30, 2017 at 15:13 UTC
ac62dedef23d6fafd3f45843434d269c32eff1c7
5 files changed
+497
-418
CMakeLists.txt
+2
@@ -29,6 +29,8 @@ set(NETDATA_SOURCE_FILES
29
src/eval.c
30
src/eval.h
31
src/freebsd_sysctl.c
32
+ src/freebsd_getmntinfo.c
33
+ src/freebsd_getifaddrs.c
34
src/global_statistics.c
35
src/global_statistics.h
36
src/health.c
src/Makefile.am
+1
@@ -147,6 +147,7 @@ netdata_SOURCES += \
147
plugin_freebsd.h \
148
freebsd_sysctl.c \
149
freebsd_getmntinfo.c \
150
+ freebsd_getifaddrs.c \
151
$(NULL)
152
else
153
if MACOS
src/freebsd_getifaddrs.c
new
+494
@@ -0,0 +1,494 @@
1
+#include "common.h"
2
+
3
+#include <ifaddrs.h>
4
+
5
+struct network_interface {
6
+ char *name;
7
+ uint32_t hash;
8
+ size_t len;
9
+
10
+ // flags
11
+ int configured;
12
+ int enabled;
13
+ int updated;
14
+
15
+ int do_bandwidth;
16
+ int do_packets;
17
+ int do_errors;
18
+ int do_drops;
19
+ int do_events;
20
+
21
+ // charts and dimensions
22
+
23
+ RRDSET *st_bandwidth;
24
+ RRDDIM *rd_bandwidth_in;
25
+ RRDDIM *rd_bandwidth_out;
26
+
27
+ RRDSET *st_packets;
28
+ RRDDIM *rd_packets_in;
29
+ RRDDIM *rd_packets_out;
30
+ RRDDIM *rd_packets_m_in;
31
+ RRDDIM *rd_packets_m_out;
32
+
33
+ RRDSET *st_errors;
34
+ RRDDIM *rd_errors_in;
35
+ RRDDIM *rd_errors_out;
36
+
37
+ RRDSET *st_drops;
38
+ RRDDIM *rd_drops_in;
39
+ RRDDIM *rd_drops_out;
40
+
41
+ RRDSET *st_events;
42
+ RRDDIM *rd_events_coll;
43
+
44
+ struct network_interface *next;
45
+};
46
+
47
+static struct network_interface *network_interfaces_root = NULL, *network_interfaces_last_used = NULL;
48
+
49
+static size_t network_interfaces_added = 0, network_interfaces_found = 0;
50
+
51
+static void network_interface_free(struct network_interface *ifm) {
52
+ if (likely(ifm->st_bandwidth))
53
+ rrdset_flag_set(ifm->st_bandwidth, RRDSET_FLAG_OBSOLETE);
54
+ if (likely(ifm->st_packets))
55
+ rrdset_flag_set(ifm->st_packets, RRDSET_FLAG_OBSOLETE);
56
+ if (likely(ifm->st_errors))
57
+ rrdset_flag_set(ifm->st_errors, RRDSET_FLAG_OBSOLETE);
58
+ if (likely(ifm->st_drops))
59
+ rrdset_flag_set(ifm->st_drops, RRDSET_FLAG_OBSOLETE);
60
+ if (likely(ifm->st_events))
61
+ rrdset_flag_set(ifm->st_events, RRDSET_FLAG_OBSOLETE);
62
+
63
+ network_interfaces_added--;
64
+ freez(ifm->name);
65
+ freez(ifm);
66
+}
67
+
68
+static void network_interfaces_cleanup() {
69
+ if (likely(network_interfaces_found == network_interfaces_added)) return;
70
+
71
+ struct network_interface *ifm = network_interfaces_root, *last = NULL;
72
+ while(ifm) {
73
+ if (unlikely(!ifm->updated)) {
74
+ // info("Removing network interface '%s', linked after '%s'", ifm->name, last?last->name:"ROOT");
75
+
76
+ if (network_interfaces_last_used == ifm)
77
+ network_interfaces_last_used = last;
78
+
79
+ struct network_interface *t = ifm;
80
+
81
+ if (ifm == network_interfaces_root || !last)
82
+ network_interfaces_root = ifm = ifm->next;
83
+
84
+ else
85
+ last->next = ifm = ifm->next;
86
+
87
+ t->next = NULL;
88
+ network_interface_free(t);
89
+ }
90
+ else {
91
+ last = ifm;
92
+ ifm->updated = 0;
93
+ ifm = ifm->next;
94
+ }
95
+ }
96
+}
97
+
98
+static struct network_interface *get_network_interface(const char *name) {
99
+ struct network_interface *ifm;
100
+
101
+ uint32_t hash = simple_hash(name);
102
+
103
+ // search it, from the last position to the end
104
+ for(ifm = network_interfaces_last_used ; ifm ; ifm = ifm->next) {
105
+ if (unlikely(hash == ifm->hash && !strcmp(name, ifm->name))) {
106
+ network_interfaces_last_used = ifm->next;
107
+ return ifm;
108
+ }
109
+ }
110
+
111
+ // search it from the beginning to the last position we used
112
+ for(ifm = network_interfaces_root ; ifm != network_interfaces_last_used ; ifm = ifm->next) {
113
+ if (unlikely(hash == ifm->hash && !strcmp(name, ifm->name))) {
114
+ network_interfaces_last_used = ifm->next;
115
+ return ifm;
116
+ }
117
+ }
118
+
119
+ // create a new one
120
+ ifm = callocz(1, sizeof(struct network_interface));
121
+ ifm->name = strdupz(name);
122
+ ifm->hash = simple_hash(ifm->name);
123
+ ifm->len = strlen(ifm->name);
124
+ network_interfaces_added++;
125
+
126
+ // link it to the end
127
+ if (network_interfaces_root) {
128
+ struct network_interface *e;
129
+ for(e = network_interfaces_root; e->next ; e = e->next) ;
130
+ e->next = ifm;
131
+ }
132
+ else
133
+ network_interfaces_root = ifm;
134
+
135
+ return ifm;
136
+}
137
+
138
+// --------------------------------------------------------------------------------------------------------------------
139
+// getifaddrs
140
+
141
+int do_getifaddrs(int update_every, usec_t dt) {
142
+ (void)dt;
143
+
144
+#define DELAULT_EXLUDED_INTERFACES "lo*"
145
+#define CONFIG_SECTION_GETIFADDRS "plugin:freebsd:getifaddrs"
146
+
147
+ static int enable_new_interfaces = -1;
148
+ static int do_bandwidth_ipv4 = -1, do_bandwidth_ipv6 = -1, do_bandwidth = -1, do_packets = -1,
149
+ do_errors = -1, do_drops = -1, do_events = -1;
150
+ static SIMPLE_PATTERN *excluded_interfaces = NULL;
151
+
152
+ if (unlikely(enable_new_interfaces == -1)) {
153
+ enable_new_interfaces = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS,
154
+ "enable new interfaces detected at runtime",
155
+ CONFIG_BOOLEAN_AUTO);
156
+
157
+ do_bandwidth_ipv4 = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "total bandwidth for ipv4 interfaces",
158
+ CONFIG_BOOLEAN_AUTO);
159
+ do_bandwidth_ipv6 = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "total bandwidth for ipv6 interfaces",
160
+ CONFIG_BOOLEAN_AUTO);
161
+ do_bandwidth = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "bandwidth for all interfaces",
162
+ CONFIG_BOOLEAN_AUTO);
163
+ do_packets = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "packets for all interfaces",
164
+ CONFIG_BOOLEAN_AUTO);
165
+ do_errors = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "errors for all interfaces",
166
+ CONFIG_BOOLEAN_AUTO);
167
+ do_drops = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "drops for all interfaces",
168
+ CONFIG_BOOLEAN_AUTO);
169
+ do_events = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "collisions for all interfaces",
170
+ CONFIG_BOOLEAN_AUTO);
171
+
172
+ excluded_interfaces = simple_pattern_create(
173
+ config_get(CONFIG_SECTION_GETIFADDRS, "disable by default interfaces matching",
174
+ DELAULT_EXLUDED_INTERFACES)
175
+ , SIMPLE_PATTERN_EXACT
176
+ );
177
+ }
178
+
179
+ if (likely(do_bandwidth_ipv4 || do_bandwidth_ipv6 || do_bandwidth || do_packets || do_errors ||
180
+ do_drops || do_events)) {
181
+ struct ifaddrs *ifap;
182
+
183
+ if (unlikely(getifaddrs(&ifap))) {
184
+ error("FREEBSD: getifaddrs() failed");
185
+ do_bandwidth_ipv4 = 0;
186
+ error("DISABLED: system.ipv4 chart");
187
+ do_bandwidth_ipv6 = 0;
188
+ error("DISABLED: system.ipv6 chart");
189
+ do_bandwidth = 0;
190
+ error("DISABLED: net.* charts");
191
+ do_packets = 0;
192
+ error("DISABLED: net_packets.* charts");
193
+ do_errors = 0;
194
+ error("DISABLED: net_errors.* charts");
195
+ do_drops = 0;
196
+ error("DISABLED: net_drops.* charts");
197
+ do_events = 0;
198
+ error("DISABLED: net_events.* charts");
199
+ error("DISABLED: getifaddrs module");
200
+ return 1;
201
+ } else {
202
+#define IFA_DATA(s) (((struct if_data *)ifa->ifa_data)->ifi_ ## s)
203
+ struct ifaddrs *ifa;
204
+ struct iftot {
205
+ u_long ift_ibytes;
206
+ u_long ift_obytes;
207
+ } iftot = {0, 0};
208
+
209
+ // --------------------------------------------------------------------
210
+
211
+ if (likely(do_bandwidth_ipv4)) {
212
+ iftot.ift_ibytes = iftot.ift_obytes = 0;
213
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
214
+ if (ifa->ifa_addr->sa_family != AF_INET)
215
+ continue;
216
+ iftot.ift_ibytes += IFA_DATA(ibytes);
217
+ iftot.ift_obytes += IFA_DATA(obytes);
218
+ }
219
+
220
+ static RRDSET *st = NULL;
221
+ static RRDDIM *rd_in = NULL, *rd_out = NULL;
222
+
223
+ if (unlikely(!st)) {
224
+ st = rrdset_create_localhost("system",
225
+ "ipv4",
226
+ NULL,
227
+ "network",
228
+ NULL,
229
+ "IPv4 Bandwidth",
230
+ "kilobits/s",
231
+ 500,
232
+ update_every,
233
+ RRDSET_TYPE_AREA
234
+ );
235
+
236
+ rd_in = rrddim_add(st, "InOctets", "received", 8, KILO_FACTOR, RRD_ALGORITHM_INCREMENTAL);
237
+ rd_out = rrddim_add(st, "OutOctets", "sent", -8, KILO_FACTOR, RRD_ALGORITHM_INCREMENTAL);
238
+ } else
239
+ rrdset_next(st);
240
+
241
+ rrddim_set_by_pointer(st, rd_in, iftot.ift_ibytes);
242
+ rrddim_set_by_pointer(st, rd_out, iftot.ift_obytes);
243
+ rrdset_done(st);
244
+ }
245
+
246
+ // --------------------------------------------------------------------
247
+
248
+ if (likely(do_bandwidth_ipv6)) {
249
+ iftot.ift_ibytes = iftot.ift_obytes = 0;
250
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
251
+ if (ifa->ifa_addr->sa_family != AF_INET6)
252
+ continue;
253
+ iftot.ift_ibytes += IFA_DATA(ibytes);
254
+ iftot.ift_obytes += IFA_DATA(obytes);
255
+ }
256
+
257
+ static RRDSET *st = NULL;
258
+ static RRDDIM *rd_in = NULL, *rd_out = NULL;
259
+
260
+ if (unlikely(!st)) {
261
+ st = rrdset_create_localhost("system",
262
+ "ipv6",
263
+ NULL,
264
+ "network",
265
+ NULL,
266
+ "IPv6 Bandwidth",
267
+ "kilobits/s",
268
+ 500,
269
+ update_every,
270
+ RRDSET_TYPE_AREA
271
+ );
272
+
273
+ rd_in = rrddim_add(st, "received", NULL, 8, KILO_FACTOR, RRD_ALGORITHM_INCREMENTAL);
274
+ rd_out = rrddim_add(st, "sent", NULL, -8, KILO_FACTOR, RRD_ALGORITHM_INCREMENTAL);
275
+ } else
276
+ rrdset_next(st);
277
+
278
+ rrddim_set_by_pointer(st, rd_in, iftot.ift_ibytes);
279
+ rrddim_set_by_pointer(st, rd_out, iftot.ift_obytes);
280
+ rrdset_done(st);
281
+ }
282
+
283
+ // --------------------------------------------------------------------
284
+
285
+ network_interfaces_found = 0;
286
+
287
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
288
+ if (ifa->ifa_addr->sa_family != AF_LINK)
289
+ continue;
290
+
291
+ struct network_interface *ifm = get_network_interface(ifa->ifa_name);
292
+ ifm->updated = 1;
293
+ network_interfaces_found++;
294
+
295
+ if (unlikely(!ifm->configured)) {
296
+ char var_name[4096 + 1];
297
+
298
+ // this is the first time we see this network interface
299
+
300
+ // remember we configured it
301
+ ifm->configured = 1;
302
+
303
+ ifm->enabled = enable_new_interfaces;
304
+
305
+ if (likely(ifm->enabled))
306
+ ifm->enabled = !simple_pattern_matches(excluded_interfaces, ifa->ifa_name);
307
+
308
+ snprintfz(var_name, 4096, "%s:%s", CONFIG_SECTION_GETIFADDRS, ifa->ifa_name);
309
+ ifm->enabled = config_get_boolean_ondemand(var_name, "enabled", ifm->enabled);
310
+
311
+ if (unlikely(ifm->enabled == CONFIG_BOOLEAN_NO))
312
+ continue;
313
+
314
+ ifm->do_bandwidth = config_get_boolean_ondemand(var_name, "bandwidth", do_bandwidth);
315
+ ifm->do_packets = config_get_boolean_ondemand(var_name, "packets", do_packets);
316
+ ifm->do_errors = config_get_boolean_ondemand(var_name, "errors", do_errors);
317
+ ifm->do_drops = config_get_boolean_ondemand(var_name, "drops", do_drops);
318
+ ifm->do_events = config_get_boolean_ondemand(var_name, "events", do_events);
319
+ }
320
+
321
+ if (unlikely(!ifm->enabled))
322
+ continue;
323
+
324
+ // --------------------------------------------------------------------
325
+
326
+ if (ifm->do_bandwidth == CONFIG_BOOLEAN_YES || (ifm->do_bandwidth == CONFIG_BOOLEAN_AUTO &&
327
+ (IFA_DATA(ibytes) || IFA_DATA(obytes)))) {
328
+ if (unlikely(!ifm->st_bandwidth)) {
329
+ ifm->st_bandwidth = rrdset_create_localhost("net",
330
+ ifa->ifa_name,
331
+ NULL,
332
+ ifa->ifa_name,
333
+ "net.net",
334
+ "Bandwidth",
335
+ "kilobits/s",
336
+ 7000,
337
+ update_every,
338
+ RRDSET_TYPE_AREA
339
+ );
340
+
341
+ ifm->rd_bandwidth_in = rrddim_add(ifm->st_bandwidth, "received", NULL, 8, KILO_FACTOR,
342
+ RRD_ALGORITHM_INCREMENTAL);
343
+ ifm->rd_bandwidth_out = rrddim_add(ifm->st_bandwidth, "sent", NULL, -8, KILO_FACTOR,
344
+ RRD_ALGORITHM_INCREMENTAL);
345
+ } else
346
+ rrdset_next(ifm->st_bandwidth);
347
+
348
+ rrddim_set_by_pointer(ifm->st_bandwidth, ifm->rd_bandwidth_in, IFA_DATA(ibytes));
349
+ rrddim_set_by_pointer(ifm->st_bandwidth, ifm->rd_bandwidth_out, IFA_DATA(obytes));
350
+ rrdset_done(ifm->st_bandwidth);
351
+ }
352
+
353
+ // --------------------------------------------------------------------
354
+
355
+ if (ifm->do_packets == CONFIG_BOOLEAN_YES || (ifm->do_packets == CONFIG_BOOLEAN_AUTO &&
356
+ (IFA_DATA(ipackets) || IFA_DATA(opackets) || IFA_DATA(imcasts) || IFA_DATA(omcasts)))) {
357
+ if (unlikely(!ifm->st_packets)) {
358
+ ifm->st_packets = rrdset_create_localhost("net_packets",
359
+ ifa->ifa_name,
360
+ NULL,
361
+ ifa->ifa_name,
362
+ "net.packets",
363
+ "Packets",
364
+ "packets/s",
365
+ 7001,
366
+ update_every,
367
+ RRDSET_TYPE_LINE
368
+ );
369
+
370
+ rrdset_flag_set(ifm->st_packets, RRDSET_FLAG_DETAIL);
371
+
372
+ ifm->rd_packets_in = rrddim_add(ifm->st_packets, "received", NULL, 1, 1,
373
+ RRD_ALGORITHM_INCREMENTAL);
374
+ ifm->rd_packets_out = rrddim_add(ifm->st_packets, "sent", NULL, -1, 1,
375
+ RRD_ALGORITHM_INCREMENTAL);
376
+ ifm->rd_packets_m_in = rrddim_add(ifm->st_packets, "multicast_received", NULL, 1, 1,
377
+ RRD_ALGORITHM_INCREMENTAL);
378
+ ifm->rd_packets_m_out = rrddim_add(ifm->st_packets, "multicast_sent", NULL, -1, 1,
379
+ RRD_ALGORITHM_INCREMENTAL);
380
+ } else
381
+ rrdset_next(ifm->st_packets);
382
+
383
+ rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_in, IFA_DATA(ipackets));
384
+ rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_out, IFA_DATA(opackets));
385
+ rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_m_in, IFA_DATA(imcasts));
386
+ rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_m_out, IFA_DATA(omcasts));
387
+ rrdset_done(ifm->st_packets);
388
+ }
389
+
390
+ // --------------------------------------------------------------------
391
+
392
+ if (ifm->do_errors == CONFIG_BOOLEAN_YES || (ifm->do_errors == CONFIG_BOOLEAN_AUTO &&
393
+ (IFA_DATA(ierrors) || IFA_DATA(oerrors)))) {
394
+ if (unlikely(!ifm->st_errors)) {
395
+ ifm->st_errors = rrdset_create_localhost("net_errors",
396
+ ifa->ifa_name,
397
+ NULL,
398
+ ifa->ifa_name,
399
+ "net.errors",
400
+ "Interface Errors",
401
+ "errors/s",
402
+ 7002,
403
+ update_every,
404
+ RRDSET_TYPE_LINE
405
+ );
406
+
407
+ rrdset_flag_set(ifm->st_errors, RRDSET_FLAG_DETAIL);
408
+
409
+ ifm->rd_errors_in = rrddim_add(ifm->st_errors, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
410
+ ifm->rd_errors_out = rrddim_add(ifm->st_errors, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
411
+ } else
412
+ rrdset_next(ifm->st_errors);
413
+
414
+ rrddim_set_by_pointer(ifm->st_errors, ifm->rd_errors_in, IFA_DATA(ierrors));
415
+ rrddim_set_by_pointer(ifm->st_errors, ifm->rd_errors_out, IFA_DATA(oerrors));
416
+ rrdset_done(ifm->st_errors);
417
+ }
418
+ // --------------------------------------------------------------------
419
+
420
+ if (ifm->do_drops == CONFIG_BOOLEAN_YES || (ifm->do_drops == CONFIG_BOOLEAN_AUTO &&
421
+ (IFA_DATA(iqdrops)
422
+ #if __FreeBSD__ >= 11
423
+ || IFA_DATA(oqdrops)
424
+#endif
425
+ ))) {
426
+ if (unlikely(!ifm->st_drops)) {
427
+ ifm->st_drops = rrdset_create_localhost("net_drops",
428
+ ifa->ifa_name,
429
+ NULL,
430
+ ifa->ifa_name,
431
+ "net.drops",
432
+ "Interface Drops",
433
+ "drops/s",
434
+ 7003,
435
+ update_every,
436
+ RRDSET_TYPE_LINE
437
+ );
438
+
439
+ rrdset_flag_set(ifm->st_drops, RRDSET_FLAG_DETAIL);
440
+
441
+ ifm->rd_drops_in = rrddim_add(ifm->st_drops, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
442
+#if __FreeBSD__ >= 11
443
+ ifm->rd_drops_out = rrddim_add(ifm->st_drops, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
444
+#endif
445
+ } else
446
+ rrdset_next(ifm->st_drops);
447
+
448
+ rrddim_set_by_pointer(ifm->st_drops, ifm->rd_drops_in, IFA_DATA(iqdrops));
449
+#if __FreeBSD__ >= 11
450
+ rrddim_set_by_pointer(ifm->st_drops, ifm->rd_drops_out, IFA_DATA(oqdrops));
451
+#endif
452
+ rrdset_done(ifm->st_drops);
453
+ }
454
+
455
+ // --------------------------------------------------------------------
456
+
457
+ if (ifm->do_events == CONFIG_BOOLEAN_YES || (ifm->do_events == CONFIG_BOOLEAN_AUTO &&
458
+ IFA_DATA(collisions))) {
459
+ if (unlikely(!ifm->st_events)) {
460
+ ifm->st_events = rrdset_create_localhost("net_events",
461
+ ifa->ifa_name,
462
+ NULL,
463
+ ifa->ifa_name,
464
+ "net.events",
465
+ "Network Interface Events",
466
+ "events/s",
467
+ 7006,
468
+ update_every,
469
+ RRDSET_TYPE_LINE
470
+ );
471
+
472
+ rrdset_flag_set(ifm->st_events, RRDSET_FLAG_DETAIL);
473
+
474
+ ifm->rd_events_coll = rrddim_add(ifm->st_events, "collisions", NULL, -1, 1,
475
+ RRD_ALGORITHM_INCREMENTAL);
476
+ } else
477
+ rrdset_next(ifm->st_events);
478
+
479
+ rrddim_set_by_pointer(ifm->st_events, ifm->rd_events_coll, IFA_DATA(collisions));
480
+ rrdset_done(ifm->st_events);
481
+ }
482
+ }
483
+
484
+ freeifaddrs(ifap);
485
+ }
486
+ } else {
487
+ error("DISABLED: getifaddrs module");
488
+ return 1;
489
+ }
490
+
491
+ network_interfaces_cleanup();
492
+
493
+ return 0;
494
+}
src/freebsd_getmntinfo.c
-1
@@ -291,4 +291,3 @@ int do_getmntinfo(int update_every, usec_t dt) {
291
292
return 0;
293
}
294
-
src/freebsd_sysctl.c
-417
@@ -2,7 +2,6 @@
2
3
#include <sys/vmmeter.h>
4
#include <sys/devicestat.h>
5
-#include <sys/mount.h>
5
#include <vm/vm_param.h>
6
7
#define _KERNEL
@@ -13,7 +12,6 @@
12
13
#include <net/netisr.h>
14
#include <net/if.h>
16
-#include <ifaddrs.h>
15
16
#include <netinet/ip.h>
17
#include <netinet/ip_var.h>
@@ -2778,421 +2776,6 @@ int do_net_inet6_icmp6_stats(int update_every, usec_t dt) {
2776
return 0;
2777
}
2778
2781
-// --------------------------------------------------------------------------------------------------------------------
2782
-// getifaddrs
2783
-
2784
-int do_getifaddrs(int update_every, usec_t dt) {
2785
- (void)dt;
2786
-
2787
-#define DELAULT_EXLUDED_INTERFACES "lo*"
2788
-#define CONFIG_SECTION_GETIFADDRS "plugin:freebsd:getifaddrs"
2789
-
2790
- static int do_bandwidth_ipv4 = -1, do_bandwidth_ipv6 = -1, do_bandwidth = -1, do_packets = -1,
2791
- do_errors = -1, do_drops = -1, do_events = -1;
2792
-
2793
- if (unlikely(do_bandwidth_ipv4 == -1)) {
2794
- do_bandwidth_ipv4 = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "total bandwidth for ipv4 interfaces",
2795
- CONFIG_BOOLEAN_AUTO);
2796
- do_bandwidth_ipv6 = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "total bandwidth for ipv6 interfaces",
2797
- CONFIG_BOOLEAN_AUTO);
2798
- do_bandwidth = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "bandwidth for all interfaces",
2799
- CONFIG_BOOLEAN_AUTO);
2800
- do_packets = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "packets for all interfaces",
2801
- CONFIG_BOOLEAN_AUTO);
2802
- do_errors = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "errors for all interfaces",
2803
- CONFIG_BOOLEAN_AUTO);
2804
- do_drops = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "drops for all interfaces",
2805
- CONFIG_BOOLEAN_AUTO);
2806
- do_events = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "collisions for all interfaces",
2807
- CONFIG_BOOLEAN_AUTO);
2808
- }
2809
-
2810
- if (likely(do_bandwidth_ipv4 || do_bandwidth_ipv6 || do_bandwidth || do_packets || do_errors ||
2811
- do_drops || do_events)) {
2812
- struct ifaddrs *ifap;
2813
-
2814
- if (unlikely(getifaddrs(&ifap))) {
2815
- error("FREEBSD: getifaddrs() failed");
2816
- do_bandwidth_ipv4 = 0;
2817
- error("DISABLED: system.ipv4 chart");
2818
- do_bandwidth_ipv6 = 0;
2819
- error("DISABLED: system.ipv6 chart");
2820
- do_bandwidth = 0;
2821
- error("DISABLED: net.* charts");
2822
- do_packets = 0;
2823
- error("DISABLED: net_packets.* charts");
2824
- do_errors = 0;
2825
- error("DISABLED: net_errors.* charts");
2826
- do_drops = 0;
2827
- error("DISABLED: net_drops.* charts");
2828
- do_events = 0;
2829
- error("DISABLED: net_events.* charts");
2830
- error("DISABLED: getifaddrs module");
2831
- return 1;
2832
- } else {
2833
- #define IFA_DATA(s) (((struct if_data *)ifa->ifa_data)->ifi_ ## s)
2834
- struct ifaddrs *ifa;
2835
- struct iftot {
2836
- u_long ift_ibytes;
2837
- u_long ift_obytes;
2838
- } iftot = {0, 0};
2839
-
2840
- // --------------------------------------------------------------------
2841
-
2842
- if (likely(do_bandwidth_ipv4)) {
2843
- iftot.ift_ibytes = iftot.ift_obytes = 0;
2844
- for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
2845
- if (ifa->ifa_addr->sa_family != AF_INET)
2846
- continue;
2847
- iftot.ift_ibytes += IFA_DATA(ibytes);
2848
- iftot.ift_obytes += IFA_DATA(obytes);
2849
- }
2850
-
2851
- static RRDSET *st = NULL;
2852
- static RRDDIM *rd_in = NULL, *rd_out = NULL;
2853
-
2854
- if (unlikely(!st)) {
2855
- st = rrdset_create_localhost("system",
2856
- "ipv4",
2857
- NULL,
2858
- "network",
2859
- NULL,
2860
- "IPv4 Bandwidth",
2861
- "kilobits/s",
2862
- 500,
2863
- update_every,
2864
- RRDSET_TYPE_AREA
2865
- );
2866
-
2867
- rd_in = rrddim_add(st, "InOctets", "received", 8, KILO_FACTOR, RRD_ALGORITHM_INCREMENTAL);
2868
- rd_out = rrddim_add(st, "OutOctets", "sent", -8, KILO_FACTOR, RRD_ALGORITHM_INCREMENTAL);
2869
- } else
2870
- rrdset_next(st);
2871
-
2872
- rrddim_set_by_pointer(st, rd_in, iftot.ift_ibytes);
2873
- rrddim_set_by_pointer(st, rd_out, iftot.ift_obytes);
2874
- rrdset_done(st);
2875
- }
2876
-
2877
- // --------------------------------------------------------------------
2878
-
2879
- if (likely(do_bandwidth_ipv6)) {
2880
- iftot.ift_ibytes = iftot.ift_obytes = 0;
2881
- for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
2882
- if (ifa->ifa_addr->sa_family != AF_INET6)
2883
- continue;
2884
- iftot.ift_ibytes += IFA_DATA(ibytes);
2885
- iftot.ift_obytes += IFA_DATA(obytes);
2886
- }
2887
-
2888
- static RRDSET *st = NULL;
2889
- static RRDDIM *rd_in = NULL, *rd_out = NULL;
2890
-
2891
- if (unlikely(!st)) {
2892
- st = rrdset_create_localhost("system",
2893
- "ipv6",
2894
- NULL,
2895
- "network",
2896
- NULL,
2897
- "IPv6 Bandwidth",
2898
- "kilobits/s",
2899
- 500,
2900
- update_every,
2901
- RRDSET_TYPE_AREA
2902
- );
2903
-
2904
- rd_in = rrddim_add(st, "received", NULL, 8, KILO_FACTOR, RRD_ALGORITHM_INCREMENTAL);
2905
- rd_out = rrddim_add(st, "sent", NULL, -8, KILO_FACTOR, RRD_ALGORITHM_INCREMENTAL);
2906
- } else
2907
- rrdset_next(st);
2908
-
2909
- rrddim_set_by_pointer(st, rd_in, iftot.ift_ibytes);
2910
- rrddim_set_by_pointer(st, rd_out, iftot.ift_obytes);
2911
- rrdset_done(st);
2912
- }
2913
-
2914
- // --------------------------------------------------------------------
2915
-
2916
- // Data to be stored in DICTIONARY interfaces.
2917
- // This DICTIONARY is used to lookup the settings of the interfaces on each iteration.
2918
- struct interfaces_metadata {
2919
- int do_bandwidth;
2920
- int do_packets;
2921
- int do_errors;
2922
- int do_drops;
2923
- int do_events;
2924
-
2925
- // charts and dimensions
2926
-
2927
- RRDSET *st_bandwidth;
2928
- RRDDIM *rd_bandwidth_in;
2929
- RRDDIM *rd_bandwidth_out;
2930
-
2931
- RRDSET *st_packets;
2932
- RRDDIM *rd_packets_in;
2933
- RRDDIM *rd_packets_out;
2934
- RRDDIM *rd_packets_m_in;
2935
- RRDDIM *rd_packets_m_out;
2936
-
2937
- RRDSET *st_errors;
2938
- RRDDIM *rd_errors_in;
2939
- RRDDIM *rd_errors_out;
2940
-
2941
- RRDSET *st_drops;
2942
- RRDDIM *rd_drops_in;
2943
- RRDDIM *rd_drops_out;
2944
-
2945
- RRDSET *st_events;
2946
- RRDDIM *rd_events_coll;
2947
- };
2948
- static DICTIONARY *interfaces = NULL;
2949
- static SIMPLE_PATTERN *excluded_interfaces = NULL;
2950
-
2951
- if(unlikely(!interfaces)) {
2952
-
2953
- excluded_interfaces = simple_pattern_create(
2954
- config_get(CONFIG_SECTION_GETIFADDRS, "disable by default interfaces matching",
2955
- DELAULT_EXLUDED_INTERFACES)
2956
- , SIMPLE_PATTERN_EXACT
2957
- );
2958
-
2959
- interfaces = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED);
2960
- }
2961
-
2962
- for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
2963
- if (ifa->ifa_addr->sa_family != AF_LINK)
2964
- continue;
2965
-
2966
- int def_bandwidth, def_packets, def_errors, def_drops, def_events,
2967
- iter_bandwidth, iter_packets, iter_errors, iter_drops, iter_events;
2968
-
2969
- struct interfaces_metadata *ifm = dictionary_get(interfaces, ifa->ifa_name);
2970
- if(unlikely(!ifm)) {
2971
- char var_name[4096 + 1];
2972
- snprintfz(var_name, 4096, "%s:%s", CONFIG_SECTION_GETIFADDRS, ifa->ifa_name);
2973
-
2974
- def_bandwidth = do_bandwidth;
2975
- def_packets = do_packets;
2976
- def_errors = do_errors;
2977
- def_drops = do_drops;
2978
- def_events = do_events;
2979
-
2980
- if(unlikely(simple_pattern_matches(excluded_interfaces, ifa->ifa_name))) {
2981
- def_bandwidth = CONFIG_BOOLEAN_NO;
2982
- def_packets = CONFIG_BOOLEAN_NO;
2983
- def_errors = CONFIG_BOOLEAN_NO;
2984
- def_drops = CONFIG_BOOLEAN_NO;
2985
- def_events = CONFIG_BOOLEAN_NO;
2986
- }
2987
-
2988
- iter_bandwidth = config_get_boolean_ondemand(var_name, "bandwidth", def_bandwidth);
2989
- iter_packets = config_get_boolean_ondemand(var_name, "packets", def_packets);
2990
- iter_errors = config_get_boolean_ondemand(var_name, "errors", def_errors);
2991
- iter_drops = config_get_boolean_ondemand(var_name, "drops", def_drops);
2992
- iter_events = config_get_boolean_ondemand(var_name, "events", def_events);
2993
-
2994
- struct interfaces_metadata ifmp = {
2995
- .do_bandwidth = iter_bandwidth,
2996
- .do_packets = iter_packets,
2997
- .do_errors = iter_errors,
2998
- .do_drops = iter_drops,
2999
- .do_events = iter_events,
3000
-
3001
- .st_bandwidth = NULL,
3002
- .rd_bandwidth_in = NULL,
3003
- .rd_bandwidth_out = NULL,
3004
-
3005
- .st_packets = NULL,
3006
- .rd_packets_in = NULL,
3007
- .rd_packets_out = NULL,
3008
- .rd_packets_m_in = NULL,
3009
- .rd_packets_m_out = NULL,
3010
-
3011
- .st_errors = NULL,
3012
- .rd_errors_in = NULL,
3013
- .rd_errors_out = NULL,
3014
-
3015
- .st_drops = NULL,
3016
- .rd_drops_in = NULL,
3017
- .rd_drops_out = NULL,
3018
-
3019
- .st_events = NULL,
3020
- .rd_events_coll = NULL,
3021
- };
3022
-
3023
- ifm = dictionary_set(interfaces, ifa->ifa_name, &ifmp, sizeof(struct interfaces_metadata));
3024
- }
3025
-
3026
- // --------------------------------------------------------------------
3027
-
3028
- if (ifm->do_bandwidth == CONFIG_BOOLEAN_YES || (ifm->do_bandwidth == CONFIG_BOOLEAN_AUTO &&
3029
- (IFA_DATA(ibytes) || IFA_DATA(obytes)))) {
3030
- if (unlikely(!ifm->st_bandwidth)) {
3031
- ifm->st_bandwidth = rrdset_create_localhost("net",
3032
- ifa->ifa_name,
3033
- NULL,
3034
- ifa->ifa_name,
3035
- "net.net",
3036
- "Bandwidth",
3037
- "kilobits/s",
3038
- 7000,
3039
- update_every,
3040
- RRDSET_TYPE_AREA
3041
- );
3042
-
3043
- ifm->rd_bandwidth_in = rrddim_add(ifm->st_bandwidth, "received", NULL, 8, KILO_FACTOR,
3044
- RRD_ALGORITHM_INCREMENTAL);
3045
- ifm->rd_bandwidth_out = rrddim_add(ifm->st_bandwidth, "sent", NULL, -8, KILO_FACTOR,
3046
- RRD_ALGORITHM_INCREMENTAL);
3047
- } else
3048
- rrdset_next(ifm->st_bandwidth);
3049
-
3050
- rrddim_set_by_pointer(ifm->st_bandwidth, ifm->rd_bandwidth_in, IFA_DATA(ibytes));
3051
- rrddim_set_by_pointer(ifm->st_bandwidth, ifm->rd_bandwidth_out, IFA_DATA(obytes));
3052
- rrdset_done(ifm->st_bandwidth);
3053
- }
3054
-
3055
- // --------------------------------------------------------------------
3056
-
3057
- if (ifm->do_packets == CONFIG_BOOLEAN_YES || (ifm->do_packets == CONFIG_BOOLEAN_AUTO &&
3058
- (IFA_DATA(ipackets) || IFA_DATA(opackets) || IFA_DATA(imcasts) || IFA_DATA(omcasts)))) {
3059
- if (unlikely(!ifm->st_packets)) {
3060
- ifm->st_packets = rrdset_create_localhost("net_packets",
3061
- ifa->ifa_name,
3062
- NULL,
3063
- ifa->ifa_name,
3064
- "net.packets",
3065
- "Packets",
3066
- "packets/s",
3067
- 7001,
3068
- update_every,
3069
- RRDSET_TYPE_LINE
3070
- );
3071
-
3072
- rrdset_flag_set(ifm->st_packets, RRDSET_FLAG_DETAIL);
3073
-
3074
- ifm->rd_packets_in = rrddim_add(ifm->st_packets, "received", NULL, 1, 1,
3075
- RRD_ALGORITHM_INCREMENTAL);
3076
- ifm->rd_packets_out = rrddim_add(ifm->st_packets, "sent", NULL, -1, 1,
3077
- RRD_ALGORITHM_INCREMENTAL);
3078
- ifm->rd_packets_m_in = rrddim_add(ifm->st_packets, "multicast_received", NULL, 1, 1,
3079
- RRD_ALGORITHM_INCREMENTAL);
3080
- ifm->rd_packets_m_out = rrddim_add(ifm->st_packets, "multicast_sent", NULL, -1, 1,
3081
- RRD_ALGORITHM_INCREMENTAL);
3082
- } else
3083
- rrdset_next(ifm->st_packets);
3084
-
3085
- rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_in, IFA_DATA(ipackets));
3086
- rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_out, IFA_DATA(opackets));
3087
- rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_m_in, IFA_DATA(imcasts));
3088
- rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_m_out, IFA_DATA(omcasts));
3089
- rrdset_done(ifm->st_packets);
3090
- }
3091
-
3092
- // --------------------------------------------------------------------
3093
-
3094
- if (ifm->do_errors == CONFIG_BOOLEAN_YES || (ifm->do_errors == CONFIG_BOOLEAN_AUTO &&
3095
- (IFA_DATA(ierrors) || IFA_DATA(oerrors)))) {
3096
- if (unlikely(!ifm->st_errors)) {
3097
- ifm->st_errors = rrdset_create_localhost("net_errors",
3098
- ifa->ifa_name,
3099
- NULL,
3100
- ifa->ifa_name,
3101
- "net.errors",
3102
- "Interface Errors",
3103
- "errors/s",
3104
- 7002,
3105
- update_every,
3106
- RRDSET_TYPE_LINE
3107
- );
3108
-
3109
- rrdset_flag_set(ifm->st_errors, RRDSET_FLAG_DETAIL);
3110
-
3111
- ifm->rd_errors_in = rrddim_add(ifm->st_errors, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
3112
- ifm->rd_errors_out = rrddim_add(ifm->st_errors, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
3113
- } else
3114
- rrdset_next(ifm->st_errors);
3115
-
3116
- rrddim_set_by_pointer(ifm->st_errors, ifm->rd_errors_in, IFA_DATA(ierrors));
3117
- rrddim_set_by_pointer(ifm->st_errors, ifm->rd_errors_out, IFA_DATA(oerrors));
3118
- rrdset_done(ifm->st_errors);
3119
- }
3120
- // --------------------------------------------------------------------
3121
-
3122
- if (ifm->do_drops == CONFIG_BOOLEAN_YES || (ifm->do_drops == CONFIG_BOOLEAN_AUTO &&
3123
- (IFA_DATA(iqdrops)
3124
-#if __FreeBSD__ >= 11
3125
- || IFA_DATA(oqdrops)
3126
-#endif
3127
- ))) {
3128
- if (unlikely(!ifm->st_drops)) {
3129
- ifm->st_drops = rrdset_create_localhost("net_drops",
3130
- ifa->ifa_name,
3131
- NULL,
3132
- ifa->ifa_name,
3133
- "net.drops",
3134
- "Interface Drops",
3135
- "drops/s",
3136
- 7003,
3137
- update_every,
3138
- RRDSET_TYPE_LINE
3139
- );
3140
-
3141
- rrdset_flag_set(ifm->st_drops, RRDSET_FLAG_DETAIL);
3142
-
3143
- ifm->rd_drops_in = rrddim_add(ifm->st_drops, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
3144
-#if __FreeBSD__ >= 11
3145
- ifm->rd_drops_out = rrddim_add(ifm->st_drops, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
3146
-#endif
3147
- } else
3148
- rrdset_next(ifm->st_drops);
3149
-
3150
- rrddim_set_by_pointer(ifm->st_drops, ifm->rd_drops_in, IFA_DATA(iqdrops));
3151
-#if __FreeBSD__ >= 11
3152
- rrddim_set_by_pointer(ifm->st_drops, ifm->rd_drops_out, IFA_DATA(oqdrops));
3153
-#endif
3154
- rrdset_done(ifm->st_drops);
3155
- }
3156
-
3157
- // --------------------------------------------------------------------
3158
-
3159
- if (ifm->do_events == CONFIG_BOOLEAN_YES || (ifm->do_events == CONFIG_BOOLEAN_AUTO &&
3160
- IFA_DATA(collisions))) {
3161
- if (unlikely(!ifm->st_events)) {
3162
- ifm->st_events = rrdset_create_localhost("net_events",
3163
- ifa->ifa_name,
3164
- NULL,
3165
- ifa->ifa_name,
3166
- "net.events",
3167
- "Network Interface Events",
3168
- "events/s",
3169
- 7006,
3170
- update_every,
3171
- RRDSET_TYPE_LINE
3172
- );
3173
-
3174
- rrdset_flag_set(ifm->st_events, RRDSET_FLAG_DETAIL);
3175
-
3176
- ifm->rd_events_coll = rrddim_add(ifm->st_events, "collisions", NULL, -1, 1,
3177
- RRD_ALGORITHM_INCREMENTAL);
3178
- } else
3179
- rrdset_next(ifm->st_events);
3180
-
3181
- rrddim_set_by_pointer(ifm->st_events, ifm->rd_events_coll, IFA_DATA(collisions));
3182
- rrdset_done(ifm->st_events);
3183
- }
3184
- }
3185
-
3186
- freeifaddrs(ifap);
3187
- }
3188
- } else {
3189
- error("DISABLED: getifaddrs module");
3190
- return 1;
3191
- }
3192
-
3193
- return 0;
3194
-}
3195
-
2779
// --------------------------------------------------------------------------------------------------------------------
2780
// kern.devstat
2781