]> arthur.barton.de Git - netdata.git/blob - src/freebsd_sysctl.c
Separate getmntinfo module with simple patterns adopted
[netdata.git] / src / freebsd_sysctl.c
1 #include "common.h"
2
3 #include <sys/vmmeter.h>
4 #include <sys/devicestat.h>
5 #include <sys/mount.h>
6 #include <vm/vm_param.h>
7
8 #define _KERNEL
9 #include <sys/sem.h>
10 #include <sys/shm.h>
11 #include <sys/msg.h>
12 #undef _KERNEL
13
14 #include <net/netisr.h>
15 #include <net/if.h>
16 #include <ifaddrs.h>
17
18 #include <netinet/ip.h>
19 #include <netinet/ip_var.h>
20 #include <netinet/ip_icmp.h>
21 #include <netinet/icmp_var.h>
22 #include <netinet6/ip6_var.h>
23 #include <netinet/icmp6.h>
24 #include <netinet/tcp_var.h>
25 #include <netinet/tcp_fsm.h>
26 #include <netinet/udp.h>
27 #include <netinet/udp_var.h>
28
29 // --------------------------------------------------------------------------------------------------------------------
30 // common definitions and variables
31
32 #define KILO_FACTOR 1024
33 #define MEGA_FACTOR 1048576     // 1024 * 1024
34 #define GIGA_FACTOR 1073741824  // 1024 * 1024 * 1024
35
36 #define MAX_INT_DIGITS 10 // maximum number of digits for int
37
38 int system_pagesize = PAGE_SIZE;
39 int number_of_cpus = 1;
40
41 // --------------------------------------------------------------------------------------------------------------------
42 // FreeBSD plugin initialization
43
44 int freebsd_plugin_init()
45 {
46     system_pagesize = getpagesize();
47     if (system_pagesize <= 0) {
48         error("FREEBSD: can't get system page size");
49         return 1;
50     }
51
52     if (unlikely(GETSYSCTL_BY_NAME("kern.smp.cpus", number_of_cpus))) {
53         error("FREEBSD: can't get number of cpus");
54         return 1;
55     }
56
57     if (unlikely(!number_of_cpus)) {
58         error("FREEBSD: wrong number of cpus");
59         return 1;
60     }
61
62     return 0;
63 }
64
65 // --------------------------------------------------------------------------------------------------------------------
66 // vm.loadavg
67
68 // FreeBSD calculates load averages once every 5 seconds
69 #define MIN_LOADAVG_UPDATE_EVERY 5
70
71 int do_vm_loadavg(int update_every, usec_t dt){
72     static usec_t next_loadavg_dt = 0;
73
74     if (next_loadavg_dt <= dt) {
75         static int mib[2] = {0, 0};
76         struct loadavg sysload;
77
78         if (unlikely(GETSYSCTL_SIMPLE("vm.loadavg", mib, sysload))) {
79             error("DISABLED: system.load chart");
80             error("DISABLED: vm.loadavg module");
81             return 1;
82         } else {
83
84             // --------------------------------------------------------------------
85
86             static RRDSET *st = NULL;
87             static RRDDIM *rd_load1 = NULL, *rd_load2 = NULL, *rd_load3 = NULL;
88
89             if (unlikely(!st)) {
90                 st = rrdset_create_localhost("system",
91                                              "load",
92                                              NULL,
93                                              "load",
94                                              NULL,
95                                              "System Load Average",
96                                              "load",
97                                              100,
98                                              (update_every < MIN_LOADAVG_UPDATE_EVERY) ?
99                                              MIN_LOADAVG_UPDATE_EVERY : update_every, RRDSET_TYPE_LINE
100                 );
101                 rd_load1 = rrddim_add(st, "load1", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
102                 rd_load2 = rrddim_add(st, "load5", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
103                 rd_load3 = rrddim_add(st, "load15", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
104             } else
105                 rrdset_next(st);
106
107             rrddim_set_by_pointer(st, rd_load1, (collected_number) ((double) sysload.ldavg[0] / sysload.fscale * 1000));
108             rrddim_set_by_pointer(st, rd_load2, (collected_number) ((double) sysload.ldavg[1] / sysload.fscale * 1000));
109             rrddim_set_by_pointer(st, rd_load3, (collected_number) ((double) sysload.ldavg[2] / sysload.fscale * 1000));
110             rrdset_done(st);
111
112             next_loadavg_dt = st->update_every * USEC_PER_SEC;
113         }
114     }
115     else
116         next_loadavg_dt -= dt;
117
118     return 0;
119 }
120
121 // --------------------------------------------------------------------------------------------------------------------
122 // vm.vmtotal
123
124 int do_vm_vmtotal(int update_every, usec_t dt) {
125     static int do_all_processes = -1, do_processes = -1, do_committed = -1;
126
127     if (unlikely(do_all_processes == -1)) {
128         do_all_processes    = config_get_boolean("plugin:freebsd:vm.vmtotal", "enable total processes", 1);
129         do_processes        = config_get_boolean("plugin:freebsd:vm.vmtotal", "processes running", 1);
130         do_committed        = config_get_boolean("plugin:freebsd:vm.vmtotal", "committed memory", 1);
131     }
132
133     if (likely(do_all_processes | do_processes | do_committed)) {
134         static int mib[2] = {0, 0};
135         struct vmtotal vmtotal_data;
136
137         if (unlikely(GETSYSCTL_SIMPLE("vm.vmtotal", mib, vmtotal_data))) {
138             do_all_processes = 0;
139             error("DISABLED: system.active_processes chart");
140             do_processes = 0;
141             error("DISABLED: system.processes chart");
142             do_committed = 0;
143             error("DISABLED: mem.committed chart");
144             error("DISABLED: vm.vmtotal module");
145             return 1;
146         } else {
147
148             // --------------------------------------------------------------------
149
150             if (likely(do_all_processes)) {
151                 static RRDSET *st = NULL;
152                 static RRDDIM *rd = NULL;
153
154                 if (unlikely(!st)) {
155                     st = rrdset_create_localhost("system",
156                                                  "active_processes",
157                                                  NULL,
158                                                  "processes",
159                                                  NULL,
160                                                  "System Active Processes",
161                                                  "processes",
162                                                  750,
163                                                  update_every,
164                                                  RRDSET_TYPE_LINE
165                     );
166                     rd = rrddim_add(st, "active", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
167                 }
168                 else rrdset_next(st);
169
170                 rrddim_set_by_pointer(st, rd, (vmtotal_data.t_rq + vmtotal_data.t_dw + vmtotal_data.t_pw + vmtotal_data.t_sl + vmtotal_data.t_sw));
171                 rrdset_done(st);
172             }
173
174             // --------------------------------------------------------------------
175
176             if (likely(do_processes)) {
177                 static RRDSET *st = NULL;
178                 static RRDDIM *rd_running = NULL, *rd_blocked = NULL;
179
180                 if (unlikely(!st)) {
181                     st = rrdset_create_localhost("system",
182                                                  "processes",
183                                                  NULL,
184                                                  "processes",
185                                                  NULL,
186                                                  "System Processes",
187                                                  "processes",
188                                                  600,
189                                                  update_every,
190                                                  RRDSET_TYPE_LINE
191                     );
192
193                     rd_running = rrddim_add(st, "running", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
194                     rd_blocked = rrddim_add(st, "blocked", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE);
195                 }
196                 else rrdset_next(st);
197
198                 rrddim_set_by_pointer(st, rd_running, vmtotal_data.t_rq);
199                 rrddim_set_by_pointer(st, rd_blocked, (vmtotal_data.t_dw + vmtotal_data.t_pw));
200                 rrdset_done(st);
201             }
202
203             // --------------------------------------------------------------------
204
205             if (likely(do_committed)) {
206                 static RRDSET *st = NULL;
207                 static RRDDIM *rd = NULL;
208
209                 if (unlikely(!st)) {
210                     st = rrdset_create_localhost("mem",
211                                                  "committed",
212                                                  NULL,
213                                                  "system",
214                                                  NULL,
215                                                  "Committed (Allocated) Memory",
216                                                  "MB",
217                                                  5000,
218                                                  update_every,
219                                                  RRDSET_TYPE_AREA
220                     );
221                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
222
223                     rd = rrddim_add(st, "Committed_AS", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
224                 }
225                 else rrdset_next(st);
226
227                 rrddim_set_by_pointer(st, rd, vmtotal_data.t_rm);
228                 rrdset_done(st);
229             }
230         }
231     } else {
232         error("DISABLED: vm.vmtotal module");
233         return 1;
234     }
235
236     return 0;
237 }
238
239 // --------------------------------------------------------------------------------------------------------------------
240 // kern.cp_time
241
242 int do_kern_cp_time(int update_every, usec_t dt) {
243     if (unlikely(CPUSTATES != 5)) {
244         error("FREEBSD: There are %d CPU states (5 was expected)", CPUSTATES);
245         error("DISABLED: system.cpu chart");
246         error("DISABLED: kern.cp_time module");
247         return 1;
248     } else {
249         static int mib[2] = {0, 0};
250         long cp_time[CPUSTATES];
251
252         if (unlikely(GETSYSCTL_SIMPLE("kern.cp_time", mib, cp_time))) {
253             error("DISABLED: system.cpu chart");
254             error("DISABLED: kern.cp_time module");
255             return 1;
256         } else {
257
258             // --------------------------------------------------------------------
259
260             static RRDSET *st = NULL;
261             static RRDDIM *rd_nice = NULL, *rd_system = NULL, *rd_user = NULL, *rd_interrupt = NULL, *rd_idle = NULL;
262
263             if (unlikely(!st)) {
264                 st = rrdset_create_localhost("system",
265                                              "cpu",
266                                              NULL,
267                                              "cpu",
268                                              "system.cpu",
269                                              "Total CPU utilization",
270                                              "percentage",
271                                              100, update_every,
272                                              RRDSET_TYPE_STACKED
273                 );
274
275                 rd_nice         = rrddim_add(st, "nice", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
276                 rd_system       = rrddim_add(st, "system", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
277                 rd_user         = rrddim_add(st, "user", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
278                 rd_interrupt    = rrddim_add(st, "interrupt", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
279                 rd_idle         = rrddim_add(st, "idle", NULL, 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
280                 rrddim_hide(st, "idle");
281             }
282             else rrdset_next(st);
283
284             rrddim_set_by_pointer(st, rd_nice, cp_time[1]);
285             rrddim_set_by_pointer(st, rd_system, cp_time[2]);
286             rrddim_set_by_pointer(st, rd_user, cp_time[0]);
287             rrddim_set_by_pointer(st, rd_interrupt, cp_time[3]);
288             rrddim_set_by_pointer(st, rd_idle, cp_time[4]);
289             rrdset_done(st);
290         }
291     }
292
293     return 0;
294 }
295
296 // --------------------------------------------------------------------------------------------------------------------
297 // kern.cp_times
298
299 int do_kern_cp_times(int update_every, usec_t dt) {
300     if (unlikely(CPUSTATES != 5)) {
301         error("FREEBSD: There are %d CPU states (5 was expected)", CPUSTATES);
302         error("DISABLED: cpu.cpuXX charts");
303         error("DISABLED: kern.cp_times module");
304         return 1;
305     } else {
306         static int mib[2] = {0, 0};
307         long cp_time[CPUSTATES];
308         static long *pcpu_cp_time = NULL;
309
310         pcpu_cp_time = reallocz(pcpu_cp_time, sizeof(cp_time) * number_of_cpus);
311         if (unlikely(GETSYSCTL_WSIZE("kern.cp_times", mib, pcpu_cp_time, sizeof(cp_time) * number_of_cpus))) {
312             error("DISABLED: cpu.cpuXX charts");
313             error("DISABLED: kern.cp_times module");
314             return 1;
315         } else {
316
317             // --------------------------------------------------------------------
318
319             int i;
320             static struct cpu_chart {
321                 char cpuid[MAX_INT_DIGITS + 4];
322                 RRDSET *st;
323                 RRDDIM *rd_user;
324                 RRDDIM *rd_nice;
325                 RRDDIM *rd_system;
326                 RRDDIM *rd_interrupt;
327                 RRDDIM *rd_idle;
328             } *all_cpu_charts = NULL;
329
330             all_cpu_charts = reallocz(all_cpu_charts, sizeof(struct cpu_chart) * number_of_cpus);
331
332             for (i = 0; i < number_of_cpus; i++) {
333                 if (unlikely(!all_cpu_charts[i].st)) {
334                     snprintfz(all_cpu_charts[i].cpuid, MAX_INT_DIGITS, "cpu%d", i);
335                     all_cpu_charts[i].st = rrdset_create_localhost("cpu",
336                                                                    all_cpu_charts[i].cpuid,
337                                                                    NULL,
338                                                                    "utilization",
339                                                                    "cpu.cpu",
340                                                                    "Core utilization",
341                                                                    "percentage",
342                                                                    1000,
343                                                                    update_every,
344                                                                    RRDSET_TYPE_STACKED
345                     );
346
347                     all_cpu_charts[i].rd_nice       = rrddim_add(all_cpu_charts[i].st, "nice", NULL, 1, 1,
348                                                                  RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
349                     all_cpu_charts[i].rd_system     = rrddim_add(all_cpu_charts[i].st, "system", NULL, 1, 1,
350                                                                  RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
351                     all_cpu_charts[i].rd_user       = rrddim_add(all_cpu_charts[i].st, "user", NULL, 1, 1,
352                                                                  RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
353                     all_cpu_charts[i].rd_interrupt  = rrddim_add(all_cpu_charts[i].st, "interrupt", NULL, 1, 1,
354                                                                  RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
355                     all_cpu_charts[i].rd_idle       = rrddim_add(all_cpu_charts[i].st, "idle", NULL, 1, 1,
356                                                                  RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
357                     rrddim_hide(all_cpu_charts[i].st, "idle");
358                 } else rrdset_next(all_cpu_charts[i].st);
359
360                 rrddim_set_by_pointer(all_cpu_charts[i].st, all_cpu_charts[i].rd_nice, pcpu_cp_time[i * 5 + 1]);
361                 rrddim_set_by_pointer(all_cpu_charts[i].st, all_cpu_charts[i].rd_system, pcpu_cp_time[i * 5 + 2]);
362                 rrddim_set_by_pointer(all_cpu_charts[i].st, all_cpu_charts[i].rd_user, pcpu_cp_time[i * 5 + 0]);
363                 rrddim_set_by_pointer(all_cpu_charts[i].st, all_cpu_charts[i].rd_interrupt, pcpu_cp_time[i * 5 + 3]);
364                 rrddim_set_by_pointer(all_cpu_charts[i].st, all_cpu_charts[i].rd_idle, pcpu_cp_time[i * 5 + 4]);
365                 rrdset_done(all_cpu_charts[i].st);
366             }
367         }
368     }
369
370     return 0;
371 }
372
373 // --------------------------------------------------------------------------------------------------------------------
374 // hw.intrcnt
375
376 int do_hw_intcnt(int update_every, usec_t dt) {
377     static int mib_hw_intrcnt[2] = {0, 0};
378     size_t intrcnt_size;
379     int i;
380
381     if (unlikely(GETSYSCTL_SIZE("hw.intrcnt", mib_hw_intrcnt, intrcnt_size))) {
382         error("DISABLED: system.intr chart");
383         error("DISABLED: system.interrupts chart");
384         error("DISABLED: hw.intrcnt module");
385         return 1;
386     } else {
387         unsigned long nintr = 0;
388         static unsigned long *intrcnt = NULL;
389         unsigned long long totalintr = 0;
390
391         nintr = intrcnt_size / sizeof(u_long);
392         intrcnt = reallocz(intrcnt, nintr * sizeof(u_long));
393         if (unlikely(GETSYSCTL_WSIZE("hw.intrcnt", mib_hw_intrcnt, intrcnt, nintr * sizeof(u_long)))) {
394             error("DISABLED: system.intr chart");
395             error("DISABLED: system.interrupts chart");
396             error("DISABLED: hw.intrcnt module");
397             return 1;
398         } else {
399             for (i = 0; i < nintr; i++)
400                 totalintr += intrcnt[i];
401
402             // --------------------------------------------------------------------
403
404             static RRDSET *st_intr = NULL;
405             static RRDDIM *rd_intr = NULL;
406
407             if (unlikely(!st_intr)) {
408                 st_intr = rrdset_create_localhost("system",
409                                                   "intr",
410                                                   NULL,
411                                                   "interrupts",
412                                                   NULL,
413                                                   "Total Hardware Interrupts",
414                                                   "interrupts/s",
415                                                   900,
416                                                   update_every,
417                                                   RRDSET_TYPE_LINE
418                 );
419                 rrdset_flag_set(st_intr, RRDSET_FLAG_DETAIL);
420
421                 rd_intr = rrddim_add(st_intr, "interrupts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
422             } else
423                 rrdset_next(st_intr);
424
425             rrddim_set_by_pointer(st_intr, rd_intr, totalintr);
426             rrdset_done(st_intr);
427
428             // --------------------------------------------------------------------
429
430             size_t size;
431             static int mib_hw_intrnames[2] = {0, 0};
432             static char *intrnames = NULL;
433
434             size = nintr * (MAXCOMLEN + 1);
435             intrnames = reallocz(intrnames, size);
436             if (unlikely(GETSYSCTL_WSIZE("hw.intrnames", mib_hw_intrnames, intrnames, size))) {
437                 error("DISABLED: system.intr chart");
438                 error("DISABLED: system.interrupts chart");
439                 error("DISABLED: hw.intrcnt module");
440                 return 1;
441             } else {
442
443                 // --------------------------------------------------------------------
444
445                 static RRDSET *st_interrupts = NULL;
446                 RRDDIM *rd_interrupts = NULL;
447                 void *p;
448
449                 if (unlikely(!st_interrupts))
450                     st_interrupts = rrdset_create_localhost("system",
451                                                             "interrupts",
452                                                             NULL,
453                                                             "interrupts",
454                                                             NULL,
455                                                             "System interrupts",
456                                                             "interrupts/s",
457                                                             1000,
458                                                             update_every,
459                                                             RRDSET_TYPE_STACKED
460                     );
461                 else
462                     rrdset_next(st_interrupts);
463
464                 for (i = 0; i < nintr; i++) {
465                     p = intrnames + i * (MAXCOMLEN + 1);
466                     if (unlikely((intrcnt[i] != 0) && (*(char *) p != 0))) {
467                         rd_interrupts = rrddim_find(st_interrupts, p);
468                         if (unlikely(!rd_interrupts))
469                             rd_interrupts = rrddim_add(st_interrupts, p, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
470                         rrddim_set_by_pointer(st_interrupts, rd_interrupts, intrcnt[i]);
471                     }
472                 }
473                 rrdset_done(st_interrupts);
474             }
475         }
476     }
477
478     return 0;
479 }
480
481 // --------------------------------------------------------------------------------------------------------------------
482 // vm.stats.sys.v_intr
483
484 int do_vm_stats_sys_v_intr(int update_every, usec_t dt) {
485     static int mib[4] = {0, 0, 0, 0};
486     u_int int_number;
487
488     if (unlikely(GETSYSCTL_SIMPLE("vm.stats.sys.v_intr", mib, int_number))) {
489         error("DISABLED: system.dev_intr chart");
490         error("DISABLED: vm.stats.sys.v_intr module");
491         return 1;
492     } else {
493
494         // --------------------------------------------------------------------
495
496         static RRDSET *st = NULL;
497         static RRDDIM *rd = NULL;
498
499         if (unlikely(!st)) {
500             st = rrdset_create_localhost("system",
501                                          "dev_intr",
502                                          NULL,
503                                          "interrupts",
504                                          NULL,
505                                          "Device Interrupts",
506                                          "interrupts/s",
507                                          1000,
508                                          update_every,
509                                          RRDSET_TYPE_LINE
510             );
511
512             rd = rrddim_add(st, "interrupts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
513         }
514         else rrdset_next(st);
515
516         rrddim_set_by_pointer(st, rd, int_number);
517         rrdset_done(st);
518     }
519
520     return 0;
521 }
522
523 // --------------------------------------------------------------------------------------------------------------------
524 // vm.stats.sys.v_soft
525
526 int do_vm_stats_sys_v_soft(int update_every, usec_t dt) {
527     static int mib[4] = {0, 0, 0, 0};
528     u_int soft_intr_number;
529
530     if (unlikely(GETSYSCTL_SIMPLE("vm.stats.sys.v_soft", mib, soft_intr_number))) {
531         error("DISABLED: system.dev_intr chart");
532         error("DISABLED: vm.stats.sys.v_soft module");
533         return 1;
534     } else {
535
536         // --------------------------------------------------------------------
537
538         static RRDSET *st = NULL;
539         static RRDDIM *rd = NULL;
540
541         if (unlikely(!st)) {
542             st = rrdset_create_localhost("system",
543                                          "soft_intr",
544                                          NULL,
545                                          "interrupts",
546                                          NULL,
547                                          "Software Interrupts",
548                                          "interrupts/s",
549                                          1100,
550                                          update_every,
551                                          RRDSET_TYPE_LINE
552             );
553
554             rd = rrddim_add(st, "interrupts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
555         }
556         else rrdset_next(st);
557
558         rrddim_set_by_pointer(st, rd, soft_intr_number);
559         rrdset_done(st);
560     }
561
562     return 0;
563 }
564
565 // --------------------------------------------------------------------------------------------------------------------
566 // vm.stats.sys.v_swtch
567
568 int do_vm_stats_sys_v_swtch(int update_every, usec_t dt) {
569     static int mib[4] = {0, 0, 0, 0};
570     u_int ctxt_number;
571
572     if (unlikely(GETSYSCTL_SIMPLE("vm.stats.sys.v_swtch", mib, ctxt_number))) {
573         error("DISABLED: system.ctxt chart");
574         error("DISABLED: vm.stats.sys.v_swtch module");
575         return 1;
576     } else {
577
578         // --------------------------------------------------------------------
579
580         static RRDSET *st = NULL;
581         static RRDDIM *rd = NULL;
582
583         if (unlikely(!st)) {
584             st = rrdset_create_localhost("system",
585                                          "ctxt",
586                                          NULL,
587                                          "processes",
588                                          NULL,
589                                          "CPU Context Switches",
590                                          "context switches/s",
591                                          800,
592                                          update_every,
593                                          RRDSET_TYPE_LINE
594             );
595
596             rd = rrddim_add(st, "switches", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
597         }
598         else rrdset_next(st);
599
600         rrddim_set_by_pointer(st, rd, ctxt_number);
601         rrdset_done(st);
602     }
603
604     return 0;
605 }
606
607 // --------------------------------------------------------------------------------------------------------------------
608 // vm.stats.vm.v_forks
609
610 int do_vm_stats_sys_v_forks(int update_every, usec_t dt) {
611     static int mib[4] = {0, 0, 0, 0};
612     u_int forks_number;
613
614     if (unlikely(GETSYSCTL_SIMPLE("vm.stats.vm.v_forks", mib, forks_number))) {
615         error("DISABLED: system.forks chart");
616         error("DISABLED: vm.stats.sys.v_swtch module");
617         return 1;
618     } else {
619
620         // --------------------------------------------------------------------
621
622         static RRDSET *st = NULL;
623         static RRDDIM *rd = NULL;
624
625         if (unlikely(!st)) {
626             st = rrdset_create_localhost("system",
627                                          "forks",
628                                          NULL,
629                                          "processes",
630                                          NULL,
631                                          "Started Processes",
632                                          "processes/s",
633                                          700,
634                                          update_every,
635                                          RRDSET_TYPE_LINE
636             );
637
638             rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
639
640             rd = rrddim_add(st, "started", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
641         }
642         else rrdset_next(st);
643
644         rrddim_set_by_pointer(st, rd, forks_number);
645         rrdset_done(st);
646     }
647
648     return 0;
649 }
650
651 // --------------------------------------------------------------------------------------------------------------------
652 // vm.swap_info
653
654 int do_vm_swap_info(int update_every, usec_t dt) {
655     static int mib[3] = {0, 0, 0};
656
657     if (unlikely(getsysctl_mib("vm.swap_info", mib, 2))) {
658         error("DISABLED: system.swap chart");
659         error("DISABLED: vm.swap_info module");
660         return 1;
661     } else {
662         int i;
663         struct xswdev xsw;
664         struct total_xsw {
665             collected_number bytes_used;
666             collected_number bytes_total;
667         } total_xsw = {0, 0};
668
669         for (i = 0; ; i++) {
670             size_t size;
671
672             mib[2] = i;
673             size = sizeof(xsw);
674             if (unlikely(sysctl(mib, 3, &xsw, &size, NULL, 0) == -1 )) {
675                 if (unlikely(errno != ENOENT)) {
676                     error("FREEBSD: sysctl(%s...) failed: %s", "vm.swap_info", strerror(errno));
677                     error("DISABLED: system.swap chart");
678                     error("DISABLED: vm.swap_info module");
679                     return 1;
680                 } else {
681                     if (unlikely(size != sizeof(xsw))) {
682                         error("FREEBSD: sysctl(%s...) expected %lu, got %lu", "vm.swap_info", (unsigned long)sizeof(xsw), (unsigned long)size);
683                         error("DISABLED: system.swap chart");
684                         error("DISABLED: vm.swap_info module");
685                         return 1;
686                     } else break;
687                 }
688             }
689             total_xsw.bytes_used += xsw.xsw_used;
690             total_xsw.bytes_total += xsw.xsw_nblks;
691         }
692
693         // --------------------------------------------------------------------
694
695         static RRDSET *st = NULL;
696         static RRDDIM *rd_free = NULL, *rd_used = NULL;
697
698         if (unlikely(!st)) {
699             st = rrdset_create_localhost("system",
700                                          "swap",
701                                          NULL,
702                                          "swap",
703                                          NULL,
704                                          "System Swap",
705                                          "MB",
706                                          201,
707                                          update_every,
708                                          RRDSET_TYPE_STACKED
709             );
710
711             rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
712
713             rd_free = rrddim_add(st, "free",    NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
714             rd_used = rrddim_add(st, "used",    NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
715         }
716         else rrdset_next(st);
717
718         rrddim_set_by_pointer(st, rd_free, total_xsw.bytes_total - total_xsw.bytes_used);
719         rrddim_set_by_pointer(st, rd_used, total_xsw.bytes_used);
720         rrdset_done(st);
721     }
722
723     return 0;
724 }
725
726 // --------------------------------------------------------------------------------------------------------------------
727 // system.ram
728
729 int do_system_ram(int update_every, usec_t dt) {
730     static int mib_active_count[4] = {0, 0, 0, 0}, mib_inactive_count[4] = {0, 0, 0, 0}, mib_wire_count[4] = {0, 0, 0, 0},
731                mib_cache_count[4] = {0, 0, 0, 0}, mib_vfs_bufspace[2] = {0, 0}, mib_free_count[4] = {0, 0, 0, 0};
732     struct vmmeter vmmeter_data;
733     int vfs_bufspace_count;
734
735     if (unlikely(GETSYSCTL_SIMPLE("vm.stats.vm.v_active_count",   mib_active_count,   vmmeter_data.v_active_count) ||
736                  GETSYSCTL_SIMPLE("vm.stats.vm.v_inactive_count", mib_inactive_count, vmmeter_data.v_inactive_count) ||
737                  GETSYSCTL_SIMPLE("vm.stats.vm.v_wire_count",     mib_wire_count,     vmmeter_data.v_wire_count) ||
738 #if __FreeBSD_version < 1200016
739                  GETSYSCTL_SIMPLE("vm.stats.vm.v_cache_count",    mib_cache_count,    vmmeter_data.v_cache_count) ||
740 #endif
741                  GETSYSCTL_SIMPLE("vfs.bufspace",                 mib_vfs_bufspace,     vfs_bufspace_count) ||
742                  GETSYSCTL_SIMPLE("vm.stats.vm.v_free_count",     mib_free_count,     vmmeter_data.v_free_count))) {
743         error("DISABLED: system.ram chart");
744         error("DISABLED: System.ram module");
745         return 1;
746     } else {
747
748         // --------------------------------------------------------------------
749
750         static RRDSET *st = NULL;
751         static RRDDIM *rd_free = NULL, *rd_active = NULL, *rd_inactive = NULL,
752                       *rd_wired = NULL, *rd_cache = NULL, *rd_buffers = NULL;
753
754         st = rrdset_find_localhost("system.ram");
755         if (unlikely(!st)) {
756             st = rrdset_create_localhost("system",
757                                          "ram",
758                                          NULL,
759                                          "ram",
760                                          NULL,
761                                          "System RAM",
762                                          "MB",
763                                          200,
764                                          update_every,
765                                          RRDSET_TYPE_STACKED
766             );
767
768             rd_free     = rrddim_add(st, "free",     NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
769             rd_active   = rrddim_add(st, "active",   NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
770             rd_inactive = rrddim_add(st, "inactive", NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
771             rd_wired    = rrddim_add(st, "wired",    NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
772 #if __FreeBSD_version < 1200016
773             rd_cache    = rrddim_add(st, "cache",    NULL, system_pagesize, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
774 #endif
775             rd_buffers  = rrddim_add(st, "buffers",  NULL, 1, MEGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
776         }
777         else rrdset_next(st);
778
779         rrddim_set_by_pointer(st, rd_free,     vmmeter_data.v_free_count);
780         rrddim_set_by_pointer(st, rd_active,   vmmeter_data.v_active_count);
781         rrddim_set_by_pointer(st, rd_inactive, vmmeter_data.v_inactive_count);
782         rrddim_set_by_pointer(st, rd_wired,    vmmeter_data.v_wire_count);
783 #if __FreeBSD_version < 1200016
784         rrddim_set_by_pointer(st, rd_cache,    vmmeter_data.v_cache_count);
785 #endif
786         rrddim_set_by_pointer(st, rd_buffers,  vfs_bufspace_count);
787         rrdset_done(st);
788     }
789
790     return 0;
791 }
792
793 // --------------------------------------------------------------------------------------------------------------------
794 // vm.stats.vm.v_swappgs
795
796 int do_vm_stats_sys_v_swappgs(int update_every, usec_t dt) {
797     static int mib_swappgsin[4] = {0, 0, 0, 0}, mib_swappgsout[4] = {0, 0, 0, 0};
798     struct vmmeter vmmeter_data;
799
800     if (unlikely(GETSYSCTL_SIMPLE("vm.stats.vm.v_swappgsin", mib_swappgsin, vmmeter_data.v_swappgsin) ||
801                  GETSYSCTL_SIMPLE("vm.stats.vm.v_swappgsout", mib_swappgsout, vmmeter_data.v_swappgsout))) {
802         error("DISABLED: system.swapio chart");
803         error("DISABLED: vm.stats.vm.v_swappgs module");
804         return 1;
805     } else {
806
807         // --------------------------------------------------------------------
808
809         static RRDSET *st = NULL;
810         static RRDDIM *rd_in = NULL, *rd_out = NULL;
811
812         if (unlikely(!st)) {
813             st = rrdset_create_localhost("system",
814                                          "swapio",
815                                          NULL,
816                                          "swap",
817                                          NULL,
818                                          "Swap I/O",
819                                          "kilobytes/s",
820                                          250,
821                                          update_every,
822                                          RRDSET_TYPE_AREA
823             );
824
825             rd_in = rrddim_add(st, "in",  NULL, system_pagesize, KILO_FACTOR, RRD_ALGORITHM_INCREMENTAL);
826             rd_out = rrddim_add(st, "out", NULL, -system_pagesize, KILO_FACTOR, RRD_ALGORITHM_INCREMENTAL);
827         }
828         else rrdset_next(st);
829
830         rrddim_set_by_pointer(st, rd_in, vmmeter_data.v_swappgsin);
831         rrddim_set_by_pointer(st, rd_out, vmmeter_data.v_swappgsout);
832         rrdset_done(st);
833     }
834
835     return 0;
836 }
837
838 // --------------------------------------------------------------------------------------------------------------------
839 // vm.stats.vm.v_pgfaults
840
841 int do_vm_stats_sys_v_pgfaults(int update_every, usec_t dt) {
842     static int mib_vm_faults[4] = {0, 0, 0, 0}, mib_io_faults[4] = {0, 0, 0, 0}, mib_cow_faults[4] = {0, 0, 0, 0},
843                mib_cow_optim[4] = {0, 0, 0, 0}, mib_intrans[4] = {0, 0, 0, 0};
844     struct vmmeter vmmeter_data;
845
846     if (unlikely(GETSYSCTL_SIMPLE("vm.stats.vm.v_vm_faults",  mib_vm_faults,  vmmeter_data.v_vm_faults) ||
847                  GETSYSCTL_SIMPLE("vm.stats.vm.v_io_faults",  mib_io_faults,  vmmeter_data.v_io_faults) ||
848                  GETSYSCTL_SIMPLE("vm.stats.vm.v_cow_faults", mib_cow_faults, vmmeter_data.v_cow_faults) ||
849                  GETSYSCTL_SIMPLE("vm.stats.vm.v_cow_optim",  mib_cow_optim,  vmmeter_data.v_cow_optim) ||
850                  GETSYSCTL_SIMPLE("vm.stats.vm.v_intrans",    mib_intrans,    vmmeter_data.v_intrans))) {
851         error("DISABLED: mem.pgfaults chart");
852         error("DISABLED: vm.stats.vm.v_pgfaults module");
853         return 1;
854     } else {
855
856         // --------------------------------------------------------------------
857
858         static RRDSET *st = NULL;
859         static RRDDIM *rd_memory = NULL, *rd_io_requiring = NULL, *rd_cow = NULL,
860                       *rd_cow_optimized = NULL, *rd_in_transit = NULL;
861
862         if (unlikely(!st)) {
863             st = rrdset_create_localhost("mem",
864                                          "pgfaults",
865                                          NULL,
866                                          "system",
867                                          NULL,
868                                          "Memory Page Faults",
869                                          "page faults/s",
870                                          500,
871                                          update_every,
872                                          RRDSET_TYPE_LINE
873             );
874
875             rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
876
877             rd_memory        = rrddim_add(st, "memory",        NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
878             rd_io_requiring  = rrddim_add(st, "io_requiring",  NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
879             rd_cow           = rrddim_add(st, "cow",           NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
880             rd_cow_optimized = rrddim_add(st, "cow_optimized", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
881             rd_in_transit    = rrddim_add(st, "in_transit",    NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
882         }
883         else rrdset_next(st);
884
885         rrddim_set_by_pointer(st, rd_memory,        vmmeter_data.v_vm_faults);
886         rrddim_set_by_pointer(st, rd_io_requiring,  vmmeter_data.v_io_faults);
887         rrddim_set_by_pointer(st, rd_cow,           vmmeter_data.v_cow_faults);
888         rrddim_set_by_pointer(st, rd_cow_optimized, vmmeter_data.v_cow_optim);
889         rrddim_set_by_pointer(st, rd_in_transit,    vmmeter_data.v_intrans);
890         rrdset_done(st);
891     }
892
893     return 0;
894 }
895
896 // --------------------------------------------------------------------------------------------------------------------
897 // kern.ipc.sem
898
899 int do_kern_ipc_sem(int update_every, usec_t dt) {
900     static int mib_semmni[3] = {0, 0, 0}, mib_sema[3] = {0, 0, 0};
901     struct ipc_sem {
902         int semmni;
903         collected_number sets;
904         collected_number semaphores;
905     } ipc_sem = {0, 0, 0};
906
907     if (unlikely(GETSYSCTL_SIMPLE("kern.ipc.semmni", mib_semmni, ipc_sem.semmni))) {
908         error("DISABLED: system.ipc_semaphores chart");
909         error("DISABLED: system.ipc_semaphore_arrays chart");
910         error("DISABLED: kern.ipc.sem module");
911         return 1;
912     } else {
913         static struct semid_kernel *ipc_sem_data = NULL;
914
915         ipc_sem_data = reallocz(ipc_sem_data, sizeof(struct semid_kernel) * ipc_sem.semmni);
916         if (unlikely(GETSYSCTL_WSIZE("kern.ipc.sema", mib_sema, ipc_sem_data, sizeof(struct semid_kernel) * ipc_sem.semmni))) {
917             error("DISABLED: system.ipc_semaphores chart");
918             error("DISABLED: system.ipc_semaphore_arrays chart");
919             error("DISABLED: kern.ipc.sem module");
920             return 1;
921         } else {
922             int i;
923
924             for (i = 0; i < ipc_sem.semmni; i++) {
925                 if (unlikely(ipc_sem_data[i].u.sem_perm.mode & SEM_ALLOC)) {
926                     ipc_sem.sets += 1;
927                     ipc_sem.semaphores += ipc_sem_data[i].u.sem_nsems;
928                 }
929             }
930
931             // --------------------------------------------------------------------
932
933             static RRDSET *st_semaphores = NULL, *st_semaphore_arrays = NULL;
934             static RRDDIM *rd_semaphores = NULL, *rd_semaphore_arrays = NULL;
935
936             if (unlikely(!st_semaphores)) {
937                 st_semaphores = rrdset_create_localhost("system",
938                                                         "ipc_semaphores",
939                                                         NULL,
940                                                         "ipc semaphores",
941                                                         NULL,
942                                                         "IPC Semaphores",
943                                                         "semaphores",
944                                                         1000,
945                                                         localhost->rrd_update_every,
946                                                         RRDSET_TYPE_AREA
947                 );
948
949                 rd_semaphores = rrddim_add(st_semaphores, "semaphores", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
950             }
951             else rrdset_next(st_semaphores);
952
953             rrddim_set_by_pointer(st_semaphores, rd_semaphores, ipc_sem.semaphores);
954             rrdset_done(st_semaphores);
955
956             // --------------------------------------------------------------------
957
958             if (unlikely(!st_semaphore_arrays)) {
959                 st_semaphore_arrays = rrdset_create_localhost("system",
960                                                               "ipc_semaphore_arrays",
961                                                               NULL,
962                                                               "ipc semaphores",
963                                                               NULL,
964                                                               "IPC Semaphore Arrays",
965                                                               "arrays",
966                                                               1000,
967                                                               localhost->rrd_update_every,
968                                                               RRDSET_TYPE_AREA
969                 );
970
971                 rd_semaphore_arrays = rrddim_add(st_semaphore_arrays, "arrays", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
972             }
973             else rrdset_next(st_semaphore_arrays);
974
975             rrddim_set_by_pointer(st_semaphore_arrays, rd_semaphore_arrays, ipc_sem.sets);
976             rrdset_done(st_semaphore_arrays);
977         }
978     }
979
980     return 0;
981 }
982
983 // --------------------------------------------------------------------------------------------------------------------
984 // kern.ipc.shm
985
986 int do_kern_ipc_shm(int update_every, usec_t dt) {
987     static int mib_shmmni[3] = {0, 0, 0}, mib_shmsegs[3] = {0, 0, 0};
988     struct ipc_shm {
989         u_long shmmni;
990         collected_number segs;
991         collected_number segsize;
992     } ipc_shm = {0, 0, 0};
993
994     if (unlikely(GETSYSCTL_SIMPLE("kern.ipc.shmmni", mib_shmmni, ipc_shm.shmmni))) {
995         error("DISABLED: system.ipc_shared_mem_segs chart");
996         error("DISABLED: system.ipc_shared_mem_size chart");
997         error("DISABLED: kern.ipc.shmmodule");
998         return 1;
999     } else {
1000         static struct shmid_kernel *ipc_shm_data = NULL;
1001
1002         ipc_shm_data = reallocz(ipc_shm_data, sizeof(struct shmid_kernel) * ipc_shm.shmmni);
1003         if (unlikely(
1004                 GETSYSCTL_WSIZE("kern.ipc.shmsegs", mib_shmsegs, ipc_shm_data, sizeof(struct shmid_kernel) * ipc_shm.shmmni))) {
1005             error("DISABLED: system.ipc_shared_mem_segs chart");
1006             error("DISABLED: system.ipc_shared_mem_size chart");
1007             error("DISABLED: kern.ipc.shmmodule");
1008             return 1;
1009         } else {
1010             int i;
1011
1012             for (i = 0; i < ipc_shm.shmmni; i++) {
1013                 if (unlikely(ipc_shm_data[i].u.shm_perm.mode & 0x0800)) {
1014                     ipc_shm.segs += 1;
1015                     ipc_shm.segsize += ipc_shm_data[i].u.shm_segsz;
1016                 }
1017             }
1018
1019             // --------------------------------------------------------------------
1020
1021             static RRDSET *st_segs = NULL, *st_size = NULL;
1022             static RRDDIM *rd_segments = NULL, *rd_allocated = NULL;
1023
1024             if (unlikely(!st_segs)) {
1025                 st_segs = rrdset_create_localhost("system",
1026                                              "ipc_shared_mem_segs",
1027                                              NULL,
1028                                              "ipc shared memory",
1029                                              NULL,
1030                                              "IPC Shared Memory Segments",
1031                                              "segments",
1032                                              1000,
1033                                              localhost->rrd_update_every,
1034                                              RRDSET_TYPE_AREA
1035                 );
1036
1037                 rd_segments = rrddim_add(st_segs, "segments", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1038             }
1039             else rrdset_next(st_segs);
1040
1041             rrddim_set_by_pointer(st_segs, rd_segments, ipc_shm.segs);
1042             rrdset_done(st_segs);
1043
1044             // --------------------------------------------------------------------
1045
1046             if (unlikely(!st_size)) {
1047                 st_size = rrdset_create_localhost("system",
1048                                              "ipc_shared_mem_size",
1049                                              NULL,
1050                                              "ipc shared memory",
1051                                              NULL,
1052                                              "IPC Shared Memory Segments Size",
1053                                              "kilobytes",
1054                                              1000,
1055                                              localhost->rrd_update_every,
1056                                              RRDSET_TYPE_AREA
1057                 );
1058
1059                 rd_allocated = rrddim_add(st_size, "allocated", NULL, 1, KILO_FACTOR, RRD_ALGORITHM_ABSOLUTE);
1060             }
1061             else rrdset_next(st_size);
1062
1063             rrddim_set_by_pointer(st_size, rd_allocated, ipc_shm.segsize);
1064             rrdset_done(st_size);
1065         }
1066     }
1067
1068     return 0;
1069 }
1070
1071 // --------------------------------------------------------------------------------------------------------------------
1072 // kern.ipc.msq
1073
1074 int do_kern_ipc_msq(int update_every, usec_t dt) {
1075     static int mib_msgmni[3] = {0, 0, 0}, mib_msqids[3] = {0, 0, 0};
1076     struct ipc_msq {
1077         int msgmni;
1078         collected_number queues;
1079         collected_number messages;
1080         collected_number usedsize;
1081         collected_number allocsize;
1082     } ipc_msq = {0, 0, 0, 0, 0};
1083
1084     if (unlikely(GETSYSCTL_SIMPLE("kern.ipc.msgmni", mib_msgmni, ipc_msq.msgmni))) {
1085         error("DISABLED: system.ipc_msq_queues chart");
1086         error("DISABLED: system.ipc_msq_messages chart");
1087         error("DISABLED: system.ipc_msq_size chart");
1088         error("DISABLED: kern.ipc.msg module");
1089         return 1;
1090     } else {
1091         static struct msqid_kernel *ipc_msq_data = NULL;
1092
1093         ipc_msq_data = reallocz(ipc_msq_data, sizeof(struct msqid_kernel) * ipc_msq.msgmni);
1094         if (unlikely(
1095                 GETSYSCTL_WSIZE("kern.ipc.msqids", mib_msqids, ipc_msq_data, sizeof(struct msqid_kernel) * ipc_msq.msgmni))) {
1096             error("DISABLED: system.ipc_msq_queues chart");
1097             error("DISABLED: system.ipc_msq_messages chart");
1098             error("DISABLED: system.ipc_msq_size chart");
1099             error("DISABLED: kern.ipc.msg module");
1100             return 1;
1101         } else {
1102             int i;
1103
1104             for (i = 0; i < ipc_msq.msgmni; i++) {
1105                 if (unlikely(ipc_msq_data[i].u.msg_qbytes != 0)) {
1106                     ipc_msq.queues += 1;
1107                     ipc_msq.messages += ipc_msq_data[i].u.msg_qnum;
1108                     ipc_msq.usedsize += ipc_msq_data[i].u.msg_cbytes;
1109                     ipc_msq.allocsize += ipc_msq_data[i].u.msg_qbytes;
1110                 }
1111             }
1112
1113             // --------------------------------------------------------------------
1114
1115             static RRDSET *st_queues = NULL, *st_messages = NULL, *st_size = NULL;
1116             static RRDDIM *rd_queues = NULL, *rd_messages = NULL, *rd_allocated = NULL, *rd_used = NULL;
1117
1118             if (unlikely(!st_queues)) {
1119                 st_queues = rrdset_create_localhost("system",
1120                                                     "ipc_msq_queues",
1121                                                     NULL,
1122                                                     "ipc message queues",
1123                                                     NULL,
1124                                                     "Number of IPC Message Queues",
1125                                                     "queues",
1126                                                     990,
1127                                                     localhost->rrd_update_every,
1128                                                     RRDSET_TYPE_AREA
1129                 );
1130
1131                 rd_queues = rrddim_add(st_queues, "queues", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1132             }
1133             else rrdset_next(st_queues);
1134
1135             rrddim_set_by_pointer(st_queues, rd_queues, ipc_msq.queues);
1136             rrdset_done(st_queues);
1137
1138             // --------------------------------------------------------------------
1139
1140             if (unlikely(!st_messages)) {
1141                 st_messages = rrdset_create_localhost("system",
1142                                                       "ipc_msq_messages",
1143                                                       NULL,
1144                                                       "ipc message queues",
1145                                                       NULL,
1146                                                       "Number of Messages in IPC Message Queues",
1147                                                       "messages",
1148                                                       1000,
1149                                                       localhost->rrd_update_every,
1150                                                       RRDSET_TYPE_AREA
1151                 );
1152
1153                 rd_messages = rrddim_add(st_messages, "messages", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1154             }
1155             else rrdset_next(st_messages);
1156
1157             rrddim_set_by_pointer(st_messages, rd_messages, ipc_msq.messages);
1158             rrdset_done(st_messages);
1159
1160             // --------------------------------------------------------------------
1161
1162             if (unlikely(!st_size)) {
1163                 st_size = rrdset_create_localhost("system",
1164                                              "ipc_msq_size",
1165                                              NULL,
1166                                              "ipc message queues",
1167                                              NULL,
1168                                              "Size of IPC Message Queues",
1169                                              "bytes",
1170                                              1100,
1171                                              localhost->rrd_update_every,
1172                                              RRDSET_TYPE_LINE
1173                 );
1174
1175                 rd_allocated = rrddim_add(st_size, "allocated", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1176                 rd_used = rrddim_add(st_size, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1177             }
1178             else rrdset_next(st_size);
1179
1180             rrddim_set_by_pointer(st_size, rd_allocated, ipc_msq.allocsize);
1181             rrddim_set_by_pointer(st_size, rd_used, ipc_msq.usedsize);
1182             rrdset_done(st_size);
1183         }
1184     }
1185
1186     return 0;
1187 }
1188
1189 // --------------------------------------------------------------------------------------------------------------------
1190 // uptime
1191
1192 int do_uptime(int update_every, usec_t dt) {
1193     struct timespec up_time;
1194
1195     clock_gettime(CLOCK_UPTIME, &up_time);
1196
1197     // --------------------------------------------------------------------
1198
1199     static RRDSET *st = NULL;
1200     static RRDDIM *rd = NULL;
1201
1202     if(unlikely(!st)) {
1203         st = rrdset_create_localhost("system",
1204                                      "uptime",
1205                                      NULL,
1206                                      "uptime",
1207                                      NULL,
1208                                      "System Uptime",
1209                                      "seconds",
1210                                      1000,
1211                                      update_every,
1212                                      RRDSET_TYPE_LINE
1213         );
1214
1215         rd = rrddim_add(st, "uptime", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
1216     }
1217     else rrdset_next(st);
1218
1219     rrddim_set_by_pointer(st, rd, up_time.tv_sec);
1220     rrdset_done(st);
1221
1222     return 0;
1223 }
1224
1225 // --------------------------------------------------------------------------------------------------------------------
1226 // net.isr
1227
1228 int do_net_isr(int update_every, usec_t dt) {
1229     static int do_netisr = -1, do_netisr_per_core = -1;
1230
1231     if (unlikely(do_netisr == -1)) {
1232         do_netisr =          config_get_boolean("plugin:freebsd:sysctl", "netisr",          1);
1233         do_netisr_per_core = config_get_boolean("plugin:freebsd:sysctl", "netisr per core", 1);
1234     }
1235
1236     static int mib_workstream[3] = {0, 0, 0}, mib_work[3] = {0, 0, 0};
1237     int common_error = 0;
1238     int i, n;
1239     size_t netisr_workstream_size, netisr_work_size;
1240     unsigned long num_netisr_workstreams = 0, num_netisr_works = 0;
1241     static struct sysctl_netisr_workstream *netisr_workstream = NULL;
1242     static struct sysctl_netisr_work *netisr_work = NULL;
1243     static struct netisr_stats {
1244         collected_number dispatched;
1245         collected_number hybrid_dispatched;
1246         collected_number qdrops;
1247         collected_number queued;
1248     } *netisr_stats = NULL;
1249
1250     if (likely(do_netisr || do_netisr_per_core)) {
1251         if (unlikely(GETSYSCTL_SIZE("net.isr.workstream", mib_workstream, netisr_workstream_size))) {
1252             common_error = 1;
1253         } else if (unlikely(GETSYSCTL_SIZE("net.isr.work", mib_work, netisr_work_size))) {
1254             common_error = 1;
1255         } else {
1256             num_netisr_workstreams = netisr_workstream_size / sizeof(struct sysctl_netisr_workstream);
1257             netisr_workstream = reallocz(netisr_workstream, num_netisr_workstreams * sizeof(struct sysctl_netisr_workstream));
1258             if (unlikely(GETSYSCTL_WSIZE("net.isr.workstream", mib_workstream, netisr_workstream,
1259                                            num_netisr_workstreams * sizeof(struct sysctl_netisr_workstream)))){
1260                 common_error = 1;
1261             } else {
1262                 num_netisr_works = netisr_work_size / sizeof(struct sysctl_netisr_work);
1263                 netisr_work = reallocz(netisr_work, num_netisr_works * sizeof(struct sysctl_netisr_work));
1264                 if (unlikely(GETSYSCTL_WSIZE("net.isr.work", mib_work, netisr_work,
1265                                                num_netisr_works * sizeof(struct sysctl_netisr_work)))){
1266                     common_error = 1;
1267                 }
1268             }
1269         }
1270         if (unlikely(common_error)) {
1271             do_netisr = 0;
1272             error("DISABLED: system.softnet_stat chart");
1273             do_netisr_per_core = 0;
1274             error("DISABLED: system.cpuX_softnet_stat chart");
1275             common_error = 0;
1276             error("DISABLED: net.isr module");
1277             return 1;
1278         } else {
1279             netisr_stats = reallocz(netisr_stats, (number_of_cpus + 1) * sizeof(struct netisr_stats));
1280             bzero(netisr_stats, (number_of_cpus + 1) * sizeof(struct netisr_stats));
1281             for (i = 0; i < num_netisr_workstreams; i++) {
1282                 for (n = 0; n < num_netisr_works; n++) {
1283                     if (netisr_workstream[i].snws_wsid == netisr_work[n].snw_wsid) {
1284                         netisr_stats[netisr_workstream[i].snws_cpu].dispatched += netisr_work[n].snw_dispatched;
1285                         netisr_stats[netisr_workstream[i].snws_cpu].hybrid_dispatched += netisr_work[n].snw_hybrid_dispatched;
1286                         netisr_stats[netisr_workstream[i].snws_cpu].qdrops += netisr_work[n].snw_qdrops;
1287                         netisr_stats[netisr_workstream[i].snws_cpu].queued += netisr_work[n].snw_queued;
1288                     }
1289                 }
1290             }
1291             for (i = 0; i < number_of_cpus; i++) {
1292                 netisr_stats[number_of_cpus].dispatched += netisr_stats[i].dispatched;
1293                 netisr_stats[number_of_cpus].hybrid_dispatched += netisr_stats[i].hybrid_dispatched;
1294                 netisr_stats[number_of_cpus].qdrops += netisr_stats[i].qdrops;
1295                 netisr_stats[number_of_cpus].queued += netisr_stats[i].queued;
1296             }
1297         }
1298     } else {
1299         error("DISABLED: net.isr module");
1300         return 1;
1301     }
1302
1303     // --------------------------------------------------------------------
1304
1305     if (likely(do_netisr)) {
1306         static RRDSET *st = NULL;
1307         static RRDDIM *rd_dispatched = NULL, *rd_hybrid_dispatched = NULL, *rd_qdrops = NULL, *rd_queued = NULL;
1308
1309         if (unlikely(!st)) {
1310             st = rrdset_create_localhost("system",
1311                                          "softnet_stat",
1312                                          NULL,
1313                                          "softnet_stat",
1314                                          NULL,
1315                                          "System softnet_stat",
1316                                          "events/s",
1317                                          955,
1318                                          update_every,
1319                                          RRDSET_TYPE_LINE
1320             );
1321
1322             rd_dispatched        = rrddim_add(st, "dispatched",        NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1323             rd_hybrid_dispatched = rrddim_add(st, "hybrid_dispatched", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1324             rd_qdrops            = rrddim_add(st, "qdrops",            NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1325             rd_queued            = rrddim_add(st, "queued",            NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1326         }
1327         else rrdset_next(st);
1328
1329         rrddim_set_by_pointer(st, rd_dispatched,        netisr_stats[number_of_cpus].dispatched);
1330         rrddim_set_by_pointer(st, rd_hybrid_dispatched, netisr_stats[number_of_cpus].hybrid_dispatched);
1331         rrddim_set_by_pointer(st, rd_qdrops,            netisr_stats[number_of_cpus].qdrops);
1332         rrddim_set_by_pointer(st, rd_queued,            netisr_stats[number_of_cpus].queued);
1333         rrdset_done(st);
1334     }
1335
1336     // --------------------------------------------------------------------
1337
1338     if (likely(do_netisr_per_core)) {
1339         static struct softnet_chart {
1340             char netisr_cpuid[MAX_INT_DIGITS + 17];
1341             RRDSET *st;
1342             RRDDIM *rd_dispatched;
1343             RRDDIM *rd_hybrid_dispatched;
1344             RRDDIM *rd_qdrops;
1345             RRDDIM *rd_queued;
1346         } *all_softnet_charts = NULL;
1347
1348         all_softnet_charts = reallocz(all_softnet_charts, sizeof(struct softnet_chart) * number_of_cpus);
1349
1350         for (i = 0; i < number_of_cpus ;i++) {
1351             snprintfz(all_softnet_charts[i].netisr_cpuid, MAX_INT_DIGITS + 17, "cpu%d_softnet_stat", i);
1352
1353             if (unlikely(!all_softnet_charts[i].st)) {
1354                 all_softnet_charts[i].st = rrdset_create_localhost("cpu",
1355                                                                    all_softnet_charts[i].netisr_cpuid,
1356                                                                    NULL,
1357                                                                    "softnet_stat",
1358                                                                    NULL,
1359                                                                    "Per CPU netisr statistics",
1360                                                                    "events/s",
1361                                                                    1101 + i,
1362                                                                    update_every,
1363                                                                    RRDSET_TYPE_LINE
1364                 );
1365
1366                 all_softnet_charts[i].rd_dispatched        = rrddim_add(all_softnet_charts[i].st, "dispatched",
1367                                                                 NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1368                 all_softnet_charts[i].rd_hybrid_dispatched = rrddim_add(all_softnet_charts[i].st, "hybrid_dispatched",
1369                                                                 NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1370                 all_softnet_charts[i].rd_qdrops            = rrddim_add(all_softnet_charts[i].st, "qdrops",
1371                                                                 NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1372                 all_softnet_charts[i].rd_queued            = rrddim_add(all_softnet_charts[i].st, "queued",
1373                                                                 NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1374             }
1375             else rrdset_next(all_softnet_charts[i].st);
1376
1377             rrddim_set_by_pointer(all_softnet_charts[i].st, all_softnet_charts[i].rd_dispatched,
1378                                   netisr_stats[i].dispatched);
1379             rrddim_set_by_pointer(all_softnet_charts[i].st, all_softnet_charts[i].rd_hybrid_dispatched,
1380                                   netisr_stats[i].hybrid_dispatched);
1381             rrddim_set_by_pointer(all_softnet_charts[i].st, all_softnet_charts[i].rd_qdrops,
1382                                   netisr_stats[i].qdrops);
1383             rrddim_set_by_pointer(all_softnet_charts[i].st, all_softnet_charts[i].rd_queued,
1384                                   netisr_stats[i].queued);
1385             rrdset_done(all_softnet_charts[i].st);
1386         }
1387     }
1388
1389     return 0;
1390 }
1391
1392 // --------------------------------------------------------------------------------------------------------------------
1393 // net.inet.tcp.states
1394
1395 int do_net_inet_tcp_states(int update_every, usec_t dt) {
1396     static int mib[4] = {0, 0, 0, 0};
1397     uint64_t tcps_states[TCP_NSTATES];
1398
1399     // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html
1400     if (unlikely(GETSYSCTL_SIMPLE("net.inet.tcp.states", mib, tcps_states))) {
1401         error("DISABLED: ipv4.tcpsock chart");
1402         error("DISABLED: net.inet.tcp.states module");
1403         return 1;
1404     } else {
1405
1406         // --------------------------------------------------------------------
1407
1408         static RRDSET *st = NULL;
1409         static RRDDIM *rd = NULL;
1410
1411         if (unlikely(!st)) {
1412             st = rrdset_create_localhost("ipv4",
1413                                          "tcpsock",
1414                                          NULL,
1415                                          "tcp",
1416                                          NULL,
1417                                          "IPv4 TCP Connections",
1418                                          "active connections",
1419                                          2500,
1420                                          update_every,
1421                                          RRDSET_TYPE_LINE
1422             );
1423
1424             rd = rrddim_add(st, "CurrEstab", "connections", 1, 1, RRD_ALGORITHM_ABSOLUTE);
1425         } else
1426             rrdset_next(st);
1427
1428         rrddim_set_by_pointer(st, rd, tcps_states[TCPS_ESTABLISHED]);
1429         rrdset_done(st);
1430     }
1431
1432     return 0;
1433 }
1434
1435 // --------------------------------------------------------------------------------------------------------------------
1436 // net.inet.tcp.stats
1437
1438 int do_net_inet_tcp_stats(int update_every, usec_t dt) {
1439     static int do_tcp_packets = -1, do_tcp_errors = -1, do_tcp_handshake = -1, do_tcpext_connaborts = -1, do_tcpext_ofo = -1, do_tcpext_syncookies = -1, do_ecn = -1;
1440
1441     if (unlikely(do_tcp_packets == -1)) {
1442         do_tcp_packets       = config_get_boolean("plugin:freebsd:sysctl", "ipv4 TCP packets",          1);
1443         do_tcp_errors        = config_get_boolean("plugin:freebsd:sysctl", "ipv4 TCP errors",           1);
1444         do_tcp_handshake     = config_get_boolean("plugin:freebsd:sysctl", "ipv4 TCP handshake issues", 1);
1445         do_tcpext_connaborts = config_get_boolean_ondemand("plugin:freebsd:sysctl", "TCP connection aborts",
1446                                                            CONFIG_BOOLEAN_AUTO);
1447         do_tcpext_ofo        = config_get_boolean_ondemand("plugin:freebsd:sysctl", "TCP out-of-order queue",
1448                                                            CONFIG_BOOLEAN_AUTO);
1449         do_tcpext_syncookies = config_get_boolean_ondemand("plugin:freebsd:sysctl", "TCP SYN cookies",
1450                                                            CONFIG_BOOLEAN_AUTO);
1451         do_ecn               = config_get_boolean_ondemand("plugin:freebsd:sysctl", "ECN packets",
1452                                                            CONFIG_BOOLEAN_AUTO);
1453     }
1454
1455     // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html
1456     if (likely(do_tcp_packets || do_tcp_errors || do_tcp_handshake || do_tcpext_connaborts || do_tcpext_ofo || do_tcpext_syncookies || do_ecn)) {
1457         static int mib[4] = {0, 0, 0, 0};
1458         struct tcpstat tcpstat;
1459
1460         if (unlikely(GETSYSCTL_SIMPLE("net.inet.tcp.stats", mib, tcpstat))) {
1461             do_tcp_packets = 0;
1462             error("DISABLED: ipv4.tcppackets chart");
1463             do_tcp_errors = 0;
1464             error("DISABLED: ipv4.tcperrors  chart");
1465             do_tcp_handshake = 0;
1466             error("DISABLED: ipv4.tcphandshake  chart");
1467             do_tcpext_connaborts = 0;
1468             error("DISABLED: ipv4.tcpconnaborts  chart");
1469             do_tcpext_ofo = 0;
1470             error("DISABLED: ipv4.tcpofo chart");
1471             do_tcpext_syncookies = 0;
1472             error("DISABLED: ipv4.tcpsyncookies chart");
1473             do_ecn = 0;
1474             error("DISABLED: ipv4.ecnpkts chart");
1475             error("DISABLED: net.inet.tcp.stats module");
1476             return 1;
1477         } else {
1478
1479             // --------------------------------------------------------------------
1480
1481             if (likely(do_tcp_packets)) {
1482                 static RRDSET *st = NULL;
1483                 static RRDDIM *rd_in_segs = NULL, *rd_out_segs = NULL;
1484
1485                 if (unlikely(!st)) {
1486                     st = rrdset_create_localhost("ipv4",
1487                                                  "tcppackets",
1488                                                  NULL,
1489                                                  "tcp",
1490                                                  NULL,
1491                                                  "IPv4 TCP Packets",
1492                                                  "packets/s",
1493                                                  2600,
1494                                                  update_every,
1495                                                  RRDSET_TYPE_LINE
1496                     );
1497
1498                     rd_in_segs  = rrddim_add(st, "InSegs",  "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
1499                     rd_out_segs = rrddim_add(st, "OutSegs", "sent",    -1, 1, RRD_ALGORITHM_INCREMENTAL);
1500                 } else
1501                     rrdset_next(st);
1502
1503                 rrddim_set_by_pointer(st, rd_in_segs,  tcpstat.tcps_rcvtotal);
1504                 rrddim_set_by_pointer(st, rd_out_segs, tcpstat.tcps_sndtotal);
1505                 rrdset_done(st);
1506             }
1507
1508             // --------------------------------------------------------------------
1509
1510             if (likely(do_tcp_errors)) {
1511                 static RRDSET *st = NULL;
1512                 static RRDDIM *rd_in_errs = NULL, *rd_in_csum_errs = NULL, *rd_retrans_segs = NULL;
1513
1514                 if (unlikely(!st)) {
1515                     st = rrdset_create_localhost("ipv4",
1516                                                  "tcperrors",
1517                                                  NULL,
1518                                                  "tcp",
1519                                                  NULL,
1520                                                  "IPv4 TCP Errors",
1521                                                  "packets/s",
1522                                                  2700,
1523                                                  update_every,
1524                                                  RRDSET_TYPE_LINE
1525                     );
1526
1527                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
1528
1529                     rd_in_errs      = rrddim_add(st, "InErrs",       NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1530                     rd_in_csum_errs = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1531                     rd_retrans_segs = rrddim_add(st, "RetransSegs",  NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1532                 } else
1533                     rrdset_next(st);
1534
1535 #if __FreeBSD__ >= 11
1536                 rrddim_set_by_pointer(st, rd_in_errs,      tcpstat.tcps_rcvbadoff + tcpstat.tcps_rcvreassfull +
1537                                                            tcpstat.tcps_rcvshort);
1538 #else
1539                 rrddim_set_by_pointer(st, rd_in_errs,      tcpstat.tcps_rcvbadoff + tcpstat.tcps_rcvshort);
1540 #endif
1541                 rrddim_set_by_pointer(st, rd_in_csum_errs, tcpstat.tcps_rcvbadsum);
1542                 rrddim_set_by_pointer(st, rd_retrans_segs, tcpstat.tcps_sndrexmitpack);
1543                 rrdset_done(st);
1544             }
1545
1546             // --------------------------------------------------------------------
1547
1548             if (likely(do_tcp_handshake)) {
1549                 static RRDSET *st = NULL;
1550                 static RRDDIM *rd_estab_resets = NULL, *rd_active_opens = NULL, *rd_passive_opens = NULL,
1551                               *rd_attempt_fails = NULL;
1552
1553                 if (unlikely(!st)) {
1554                     st = rrdset_create_localhost("ipv4",
1555                                                  "tcphandshake",
1556                                                  NULL,
1557                                                  "tcp",
1558                                                  NULL,
1559                                                  "IPv4 TCP Handshake Issues",
1560                                                  "events/s",
1561                                                  2900,
1562                                                  update_every,
1563                                                  RRDSET_TYPE_LINE
1564                     );
1565
1566                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
1567
1568                     rd_estab_resets  = rrddim_add(st, "EstabResets",  NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1569                     rd_active_opens  = rrddim_add(st, "ActiveOpens",  NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1570                     rd_passive_opens = rrddim_add(st, "PassiveOpens", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1571                     rd_attempt_fails = rrddim_add(st, "AttemptFails", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1572                 } else
1573                     rrdset_next(st);
1574
1575                 rrddim_set_by_pointer(st, rd_estab_resets,  tcpstat.tcps_drops);
1576                 rrddim_set_by_pointer(st, rd_active_opens,  tcpstat.tcps_connattempt);
1577                 rrddim_set_by_pointer(st, rd_passive_opens, tcpstat.tcps_accepts);
1578                 rrddim_set_by_pointer(st, rd_attempt_fails, tcpstat.tcps_conndrops);
1579                 rrdset_done(st);
1580             }
1581
1582             // --------------------------------------------------------------------
1583
1584             if (do_tcpext_connaborts == CONFIG_BOOLEAN_YES || (do_tcpext_connaborts == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_rcvpackafterwin || tcpstat.tcps_rcvafterclose || tcpstat.tcps_rcvmemdrop || tcpstat.tcps_persistdrop || tcpstat.tcps_finwait2_drops))) {
1585                 do_tcpext_connaborts = CONFIG_BOOLEAN_YES;
1586
1587                 static RRDSET *st = NULL;
1588                 static RRDDIM *rd_on_data = NULL, *rd_on_close = NULL, *rd_on_memory = NULL,
1589                               *rd_on_timeout = NULL, *rd_on_linger = NULL;
1590
1591                 if (unlikely(!st)) {
1592                     st = rrdset_create_localhost("ipv4",
1593                                                  "tcpconnaborts",
1594                                                  NULL,
1595                                                  "tcp",
1596                                                  NULL,
1597                                                  "TCP Connection Aborts",
1598                                                  "connections/s",
1599                                                  3010,
1600                                                  update_every,
1601                                                  RRDSET_TYPE_LINE
1602                     );
1603
1604                     rd_on_data    = rrddim_add(st, "TCPAbortOnData",    "baddata",     1, 1, RRD_ALGORITHM_INCREMENTAL);
1605                     rd_on_close   = rrddim_add(st, "TCPAbortOnClose",   "userclosed",  1, 1, RRD_ALGORITHM_INCREMENTAL);
1606                     rd_on_memory  = rrddim_add(st, "TCPAbortOnMemory",  "nomemory",    1, 1, RRD_ALGORITHM_INCREMENTAL);
1607                     rd_on_timeout = rrddim_add(st, "TCPAbortOnTimeout", "timeout",     1, 1, RRD_ALGORITHM_INCREMENTAL);
1608                     rd_on_linger  = rrddim_add(st, "TCPAbortOnLinger",  "linger",      1, 1, RRD_ALGORITHM_INCREMENTAL);
1609                 }
1610                 else rrdset_next(st);
1611
1612                 rrddim_set_by_pointer(st, rd_on_data,    tcpstat.tcps_rcvpackafterwin);
1613                 rrddim_set_by_pointer(st, rd_on_close,   tcpstat.tcps_rcvafterclose);
1614                 rrddim_set_by_pointer(st, rd_on_memory,  tcpstat.tcps_rcvmemdrop);
1615                 rrddim_set_by_pointer(st, rd_on_timeout, tcpstat.tcps_persistdrop);
1616                 rrddim_set_by_pointer(st, rd_on_linger,  tcpstat.tcps_finwait2_drops);
1617                 rrdset_done(st);
1618             }
1619
1620             // --------------------------------------------------------------------
1621
1622             if (do_tcpext_ofo == CONFIG_BOOLEAN_YES || (do_tcpext_ofo == CONFIG_BOOLEAN_AUTO && tcpstat.tcps_rcvoopack)) {
1623                 do_tcpext_ofo = CONFIG_BOOLEAN_YES;
1624
1625                 static RRDSET *st = NULL;
1626                 static RRDDIM *rd_ofo_queue = NULL;
1627
1628                 if (unlikely(!st)) {
1629                     st = rrdset_create_localhost("ipv4",
1630                                                  "tcpofo",
1631                                                  NULL,
1632                                                  "tcp",
1633                                                  NULL,
1634                                                  "TCP Out-Of-Order Queue",
1635                                                  "packets/s",
1636                                                  3050,
1637                                                  update_every,
1638                                                  RRDSET_TYPE_LINE
1639                     );
1640
1641                     rd_ofo_queue = rrddim_add(st, "TCPOFOQueue", "inqueue",  1, 1, RRD_ALGORITHM_INCREMENTAL);
1642                 }
1643                 else rrdset_next(st);
1644
1645                 rrddim_set_by_pointer(st, rd_ofo_queue,   tcpstat.tcps_rcvoopack);
1646                 rrdset_done(st);
1647             }
1648
1649             // --------------------------------------------------------------------
1650
1651             if (do_tcpext_syncookies == CONFIG_BOOLEAN_YES || (do_tcpext_syncookies == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_sc_sendcookie || tcpstat.tcps_sc_recvcookie || tcpstat.tcps_sc_zonefail))) {
1652                 do_tcpext_syncookies = CONFIG_BOOLEAN_YES;
1653
1654                 static RRDSET *st = NULL;
1655                 static RRDDIM *rd_recv = NULL, *rd_send = NULL, *rd_failed = NULL;
1656
1657                 if (unlikely(!st)) {
1658                     st = rrdset_create_localhost("ipv4",
1659                                                  "tcpsyncookies",
1660                                                  NULL,
1661                                                  "tcp",
1662                                                  NULL,
1663                                                  "TCP SYN Cookies",
1664                                                  "packets/s",
1665                                                  3100,
1666                                                  update_every,
1667                                                  RRDSET_TYPE_LINE
1668                     );
1669
1670                     rd_recv   = rrddim_add(st, "SyncookiesRecv",   "received",  1, 1, RRD_ALGORITHM_INCREMENTAL);
1671                     rd_send   = rrddim_add(st, "SyncookiesSent",   "sent",     -1, 1, RRD_ALGORITHM_INCREMENTAL);
1672                     rd_failed = rrddim_add(st, "SyncookiesFailed", "failed",   -1, 1, RRD_ALGORITHM_INCREMENTAL);
1673                 }
1674                 else rrdset_next(st);
1675
1676                 rrddim_set_by_pointer(st, rd_recv,   tcpstat.tcps_sc_recvcookie);
1677                 rrddim_set_by_pointer(st, rd_send,   tcpstat.tcps_sc_sendcookie);
1678                 rrddim_set_by_pointer(st, rd_failed, tcpstat.tcps_sc_zonefail);
1679                 rrdset_done(st);
1680             }
1681
1682             // --------------------------------------------------------------------
1683
1684             if (do_ecn == CONFIG_BOOLEAN_YES || (do_ecn == CONFIG_BOOLEAN_AUTO && (tcpstat.tcps_ecn_ce || tcpstat.tcps_ecn_ect0 || tcpstat.tcps_ecn_ect1))) {
1685                 do_ecn = CONFIG_BOOLEAN_YES;
1686
1687                 static RRDSET *st = NULL;
1688                 static RRDDIM *rd_ce = NULL, *rd_no_ect = NULL, *rd_ect0 = NULL, *rd_ect1 = NULL;
1689
1690                 if (unlikely(!st)) {
1691                     st = rrdset_create_localhost("ipv4",
1692                                                  "ecnpkts",
1693                                                  NULL,
1694                                                  "ecn",
1695                                                  NULL,
1696                                                  "IPv4 ECN Statistics",
1697                                                  "packets/s",
1698                                                  8700,
1699                                                  update_every,
1700                                                  RRDSET_TYPE_LINE
1701                     );
1702
1703                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
1704
1705                     rd_ce     = rrddim_add(st, "InCEPkts", "CEP", 1, 1, RRD_ALGORITHM_INCREMENTAL);
1706                     rd_no_ect = rrddim_add(st, "InNoECTPkts", "NoECTP", -1, 1, RRD_ALGORITHM_INCREMENTAL);
1707                     rd_ect0   = rrddim_add(st, "InECT0Pkts", "ECTP0", 1, 1, RRD_ALGORITHM_INCREMENTAL);
1708                     rd_ect1   = rrddim_add(st, "InECT1Pkts", "ECTP1", 1, 1, RRD_ALGORITHM_INCREMENTAL);
1709                 }
1710                 else rrdset_next(st);
1711
1712                 rrddim_set_by_pointer(st, rd_ce,     tcpstat.tcps_ecn_ce);
1713                 rrddim_set_by_pointer(st, rd_no_ect, tcpstat.tcps_ecn_ce - (tcpstat.tcps_ecn_ect0 +
1714                                                                             tcpstat.tcps_ecn_ect1));
1715                 rrddim_set_by_pointer(st, rd_ect0,   tcpstat.tcps_ecn_ect0);
1716                 rrddim_set_by_pointer(st, rd_ect1,   tcpstat.tcps_ecn_ect1);
1717                 rrdset_done(st);
1718             }
1719
1720         }
1721     } else {
1722         error("DISABLED: net.inet.tcp.stats module");
1723         return 1;
1724     }
1725
1726     return 0;
1727 }
1728
1729 // --------------------------------------------------------------------------------------------------------------------
1730 // net.inet.udp.stats
1731
1732 int do_net_inet_udp_stats(int update_every, usec_t dt) {
1733     static int do_udp_packets = -1, do_udp_errors = -1;
1734
1735     if (unlikely(do_udp_packets == -1)) {
1736         do_udp_packets = config_get_boolean("plugin:freebsd:sysctl", "ipv4 UDP packets", 1);
1737         do_udp_errors  = config_get_boolean("plugin:freebsd:sysctl", "ipv4 UDP errors", 1);
1738     }
1739
1740     // see http://net-snmp.sourceforge.net/docs/mibs/udp.html
1741     if (likely(do_udp_packets || do_udp_errors)) {
1742         static int mib[4] = {0, 0, 0, 0};
1743         struct udpstat udpstat;
1744
1745         if (unlikely(GETSYSCTL_SIMPLE("net.inet.udp.stats", mib, udpstat))) {
1746             do_udp_packets = 0;
1747             error("DISABLED: ipv4.udppackets chart");
1748             do_udp_errors = 0;
1749             error("DISABLED: ipv4.udperrors chart");
1750             error("DISABLED: net.inet.udp.stats module");
1751             return 1;
1752         } else {
1753
1754             // --------------------------------------------------------------------
1755
1756             if (likely(do_udp_packets)) {
1757                 static RRDSET *st = NULL;
1758                 static RRDDIM *rd_in = NULL, *rd_out = NULL;
1759
1760                 if (unlikely(!st)) {
1761                     st = rrdset_create_localhost("ipv4",
1762                                                  "udppackets",
1763                                                  NULL,
1764                                                  "udp",
1765                                                  NULL,
1766                                                  "IPv4 UDP Packets",
1767                                                  "packets/s",
1768                                                  2601,
1769                                                  update_every,
1770                                                  RRDSET_TYPE_LINE
1771                     );
1772
1773                     rd_in  = rrddim_add(st, "InDatagrams",  "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
1774                     rd_out = rrddim_add(st, "OutDatagrams", "sent",    -1, 1, RRD_ALGORITHM_INCREMENTAL);
1775                 } else
1776                     rrdset_next(st);
1777
1778                 rrddim_set_by_pointer(st, rd_in,  udpstat.udps_ipackets);
1779                 rrddim_set_by_pointer(st, rd_out, udpstat.udps_opackets);
1780                 rrdset_done(st);
1781             }
1782
1783             // --------------------------------------------------------------------
1784
1785             if (likely(do_udp_errors)) {
1786                 static RRDSET *st = NULL;
1787                 static RRDDIM *rd_in_errors = NULL, *rd_no_ports = NULL, *rd_recv_buf_errors = NULL,
1788                               *rd_in_csum_errors = NULL, *rd_ignored_multi = NULL;
1789
1790                 if (unlikely(!st)) {
1791                     st = rrdset_create_localhost("ipv4",
1792                                                  "udperrors",
1793                                                  NULL,
1794                                                  "udp",
1795                                                  NULL,
1796                                                  "IPv4 UDP Errors",
1797                                                  "events/s",
1798                                                  2701,
1799                                                  update_every,
1800                                                  RRDSET_TYPE_LINE
1801                     );
1802
1803                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
1804
1805                     rd_in_errors       = rrddim_add(st, "InErrors",     NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1806                     rd_no_ports        = rrddim_add(st, "NoPorts",      NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1807                     rd_recv_buf_errors = rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1808                     rd_in_csum_errors  = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1809                     rd_ignored_multi   = rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1810                 } else
1811                     rrdset_next(st);
1812
1813                 rrddim_set_by_pointer(st, rd_in_errors,       udpstat.udps_hdrops + udpstat.udps_badlen);
1814                 rrddim_set_by_pointer(st, rd_no_ports,        udpstat.udps_noport);
1815                 rrddim_set_by_pointer(st, rd_recv_buf_errors, udpstat.udps_fullsock);
1816                 rrddim_set_by_pointer(st, rd_in_csum_errors,  udpstat.udps_badsum + udpstat.udps_nosum);
1817                 rrddim_set_by_pointer(st, rd_ignored_multi,   udpstat.udps_filtermcast);
1818                 rrdset_done(st);
1819             }
1820         }
1821     } else {
1822         error("DISABLED: net.inet.udp.stats module");
1823         return 1;
1824     }
1825
1826     return 0;
1827 }
1828
1829 // --------------------------------------------------------------------------------------------------------------------
1830 // net.inet.icmp.stats
1831
1832 int do_net_inet_icmp_stats(int update_every, usec_t dt) {
1833     static int do_icmp_packets = -1, do_icmp_errors = -1, do_icmpmsg = -1;
1834
1835     if (unlikely(do_icmp_packets == -1)) {
1836         do_icmp_packets = config_get_boolean("plugin:freebsd:sysctl", "ipv4 ICMP packets",  1);
1837         do_icmp_errors  = config_get_boolean("plugin:freebsd:sysctl", "ipv4 ICMP errors",   1);
1838         do_icmpmsg      = config_get_boolean("plugin:freebsd:sysctl", "ipv4 ICMP messages", 1);
1839     }
1840
1841     if (likely(do_icmp_packets || do_icmp_errors || do_icmpmsg)) {
1842         static int mib[4] = {0, 0, 0, 0};
1843         struct icmpstat icmpstat;
1844         int i;
1845         struct icmp_total {
1846             u_long  msgs_in;
1847             u_long  msgs_out;
1848         } icmp_total = {0, 0};
1849
1850         if (unlikely(GETSYSCTL_SIMPLE("net.inet.icmp.stats", mib, icmpstat))) {
1851             do_icmp_packets = 0;
1852             error("DISABLED: ipv4.icmp chart");
1853             do_icmp_errors = 0;
1854             error("DISABLED: ipv4.icmp_errors chart");
1855             do_icmpmsg = 0;
1856             error("DISABLED: ipv4.icmpmsg chart");
1857             error("DISABLED: net.inet.icmp.stats module");
1858             return 1;
1859         } else {
1860             for (i = 0; i <= ICMP_MAXTYPE; i++) {
1861                 icmp_total.msgs_in += icmpstat.icps_inhist[i];
1862                 icmp_total.msgs_out += icmpstat.icps_outhist[i];
1863             }
1864             icmp_total.msgs_in += icmpstat.icps_badcode + icmpstat.icps_badlen + icmpstat.icps_checksum + icmpstat.icps_tooshort;
1865
1866             // --------------------------------------------------------------------
1867
1868             if (likely(do_icmp_packets)) {
1869                 static RRDSET *st = NULL;
1870                 static RRDDIM *rd_in = NULL, *rd_out = NULL;
1871
1872                 if (unlikely(!st)) {
1873                     st = rrdset_create_localhost("ipv4",
1874                                                  "icmp",
1875                                                  NULL,
1876                                                  "icmp",
1877                                                  NULL,
1878                                                  "IPv4 ICMP Packets",
1879                                                  "packets/s",
1880                                                  2602,
1881                                                  update_every,
1882                                                  RRDSET_TYPE_LINE
1883                     );
1884
1885                     rd_in  = rrddim_add(st, "InMsgs",  "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
1886                     rd_out = rrddim_add(st, "OutMsgs", "sent",    -1, 1, RRD_ALGORITHM_INCREMENTAL);
1887                 } else
1888                     rrdset_next(st);
1889
1890                 rrddim_set_by_pointer(st, rd_in,  icmp_total.msgs_in);
1891                 rrddim_set_by_pointer(st, rd_out, icmp_total.msgs_out);
1892
1893                 rrdset_done(st);
1894             }
1895
1896             // --------------------------------------------------------------------
1897
1898             if (likely(do_icmp_errors)) {
1899                 static RRDSET *st = NULL;
1900                 static RRDDIM *rd_in = NULL, *rd_out = NULL, *rd_in_csum = NULL;
1901
1902                 if (unlikely(!st)) {
1903                     st = rrdset_create_localhost("ipv4", "icmp_errors", NULL, "icmp", NULL, "IPv4 ICMP Errors",
1904                                                  "packets/s",
1905                                                  2603, update_every, RRDSET_TYPE_LINE);
1906
1907                     rd_in      = rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1908                     rd_out     = rrddim_add(st, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1909                     rd_in_csum = rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
1910                 } else
1911                     rrdset_next(st);
1912
1913                 rrddim_set_by_pointer(st, rd_in,      icmpstat.icps_badcode + icmpstat.icps_badlen +
1914                                                       icmpstat.icps_checksum + icmpstat.icps_tooshort);
1915                 rrddim_set_by_pointer(st, rd_out,     icmpstat.icps_error);
1916                 rrddim_set_by_pointer(st, rd_in_csum, icmpstat.icps_checksum);
1917
1918                 rrdset_done(st);
1919             }
1920
1921             // --------------------------------------------------------------------
1922
1923             if (likely(do_icmpmsg)) {
1924                 static RRDSET *st = NULL;
1925                 static RRDDIM *rd_in_reps = NULL, *rd_out_reps = NULL, *rd_in = NULL, *rd_out = NULL;
1926
1927                 if (unlikely(!st)) {
1928                     st = rrdset_create_localhost("ipv4", "icmpmsg", NULL, "icmp", NULL, "IPv4 ICMP Messsages",
1929                                                  "packets/s", 2604, update_every, RRDSET_TYPE_LINE);
1930
1931                     rd_in_reps  = rrddim_add(st, "InEchoReps",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
1932                     rd_out_reps = rrddim_add(st, "OutEchoReps", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1933                     rd_in       = rrddim_add(st, "InEchos",     NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
1934                     rd_out      = rrddim_add(st, "OutEchos",    NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
1935                 } else
1936                     rrdset_next(st);
1937
1938                 rrddim_set_by_pointer(st, rd_in_reps, icmpstat.icps_inhist[ICMP_ECHOREPLY]);
1939                 rrddim_set_by_pointer(st, rd_out_reps, icmpstat.icps_outhist[ICMP_ECHOREPLY]);
1940                 rrddim_set_by_pointer(st, rd_in, icmpstat.icps_inhist[ICMP_ECHO]);
1941                 rrddim_set_by_pointer(st, rd_out, icmpstat.icps_outhist[ICMP_ECHO]);
1942
1943                 rrdset_done(st);
1944             }
1945         }
1946     } else {
1947         error("DISABLED: net.inet.icmp.stats module");
1948         return 1;
1949     }
1950
1951     return 0;
1952 }
1953
1954 // --------------------------------------------------------------------------------------------------------------------
1955 // net.inet.ip.stats
1956
1957 int do_net_inet_ip_stats(int update_every, usec_t dt) {
1958     static int do_ip_packets = -1, do_ip_fragsout = -1, do_ip_fragsin = -1, do_ip_errors = -1;
1959
1960     if (unlikely(do_ip_packets == -1)) {
1961         do_ip_packets  = config_get_boolean("plugin:freebsd:sysctl", "ipv4 packets", 1);
1962         do_ip_fragsout = config_get_boolean("plugin:freebsd:sysctl", "ipv4 fragments sent", 1);
1963         do_ip_fragsin  = config_get_boolean("plugin:freebsd:sysctl", "ipv4 fragments assembly", 1);
1964         do_ip_errors   = config_get_boolean("plugin:freebsd:sysctl", "ipv4 errors", 1);
1965     }
1966
1967     // see also http://net-snmp.sourceforge.net/docs/mibs/ip.html
1968     if (likely(do_ip_packets || do_ip_fragsout || do_ip_fragsin || do_ip_errors)) {
1969         static int mib[4] = {0, 0, 0, 0};
1970         struct ipstat ipstat;
1971
1972         if (unlikely(GETSYSCTL_SIMPLE("net.inet.ip.stats", mib, ipstat))) {
1973             do_ip_packets = 0;
1974             error("DISABLED: ipv4.packets chart");
1975             do_ip_fragsout = 0;
1976             error("DISABLED: ipv4.fragsout chart");
1977             do_ip_fragsin = 0;
1978             error("DISABLED: ipv4.fragsin chart");
1979             do_ip_errors = 0;
1980             error("DISABLED: ipv4.errors chart");
1981             error("DISABLED: net.inet.ip.stats module");
1982             return 1;
1983         } else {
1984
1985             // --------------------------------------------------------------------
1986
1987             if (likely(do_ip_packets)) {
1988                 static RRDSET *st = NULL;
1989                 static RRDDIM *rd_in_receives = NULL, *rd_out_requests = NULL, *rd_forward_datagrams = NULL,
1990                               *rd_in_delivers = NULL;
1991
1992                 if (unlikely(!st)) {
1993                     st = rrdset_create_localhost("ipv4",
1994                                                  "packets",
1995                                                  NULL,
1996                                                  "packets",
1997                                                  NULL,
1998                                                  "IPv4 Packets",
1999                                                  "packets/s",
2000                                                  3000,
2001                                                  update_every,
2002                                                  RRDSET_TYPE_LINE
2003                     );
2004
2005                     rd_in_receives       = rrddim_add(st, "InReceives",    "received",  1, 1, RRD_ALGORITHM_INCREMENTAL);
2006                     rd_out_requests      = rrddim_add(st, "OutRequests",   "sent",     -1, 1, RRD_ALGORITHM_INCREMENTAL);
2007                     rd_forward_datagrams = rrddim_add(st, "ForwDatagrams", "forwarded", 1, 1, RRD_ALGORITHM_INCREMENTAL);
2008                     rd_in_delivers       = rrddim_add(st, "InDelivers",    "delivered", 1, 1, RRD_ALGORITHM_INCREMENTAL);
2009                 } else
2010                     rrdset_next(st);
2011
2012                 rrddim_set_by_pointer(st, rd_in_receives,       ipstat.ips_total);
2013                 rrddim_set_by_pointer(st, rd_out_requests,      ipstat.ips_localout);
2014                 rrddim_set_by_pointer(st, rd_forward_datagrams, ipstat.ips_forward);
2015                 rrddim_set_by_pointer(st, rd_in_delivers,       ipstat.ips_delivered);
2016                 rrdset_done(st);
2017             }
2018
2019             // --------------------------------------------------------------------
2020
2021             if (likely(do_ip_fragsout)) {
2022                 static RRDSET *st = NULL;
2023                 static RRDDIM *rd_ok = NULL, *rd_fails = NULL, *rd_created = NULL;
2024
2025                 if (unlikely(!st)) {
2026                     st = rrdset_create_localhost("ipv4",
2027                                                  "fragsout",
2028                                                  NULL,
2029                                                  "fragments",
2030                                                  NULL,
2031                                                  "IPv4 Fragments Sent",
2032                                                  "packets/s",
2033                                                  3010,
2034                                                  update_every,
2035                                                  RRDSET_TYPE_LINE
2036                     );
2037
2038                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
2039
2040                     rd_ok      = rrddim_add(st, "FragOKs",     "ok",      1, 1, RRD_ALGORITHM_INCREMENTAL);
2041                     rd_fails   = rrddim_add(st, "FragFails",   "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL);
2042                     rd_created = rrddim_add(st, "FragCreates", "created", 1, 1, RRD_ALGORITHM_INCREMENTAL);
2043                 } else
2044                     rrdset_next(st);
2045
2046                 rrddim_set_by_pointer(st, rd_ok,      ipstat.ips_fragmented);
2047                 rrddim_set_by_pointer(st, rd_fails,   ipstat.ips_cantfrag);
2048                 rrddim_set_by_pointer(st, rd_created, ipstat.ips_ofragments);
2049                 rrdset_done(st);
2050             }
2051
2052             // --------------------------------------------------------------------
2053
2054             if (likely(do_ip_fragsin)) {
2055                 static RRDSET *st = NULL;
2056                 static RRDDIM *rd_ok = NULL, *rd_failed = NULL, *rd_all = NULL;
2057
2058                 if (unlikely(!st)) {
2059                     st = rrdset_create_localhost("ipv4",
2060                                                  "fragsin",
2061                                                  NULL,
2062                                                  "fragments",
2063                                                  NULL,
2064                                                  "IPv4 Fragments Reassembly",
2065                                                  "packets/s",
2066                                                  3011,
2067                                                  update_every,
2068                                                  RRDSET_TYPE_LINE
2069                     );
2070
2071                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
2072
2073                     rd_ok     = rrddim_add(st, "ReasmOKs",   "ok",      1, 1, RRD_ALGORITHM_INCREMENTAL);
2074                     rd_failed = rrddim_add(st, "ReasmFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL);
2075                     rd_all    = rrddim_add(st, "ReasmReqds", "all",     1, 1, RRD_ALGORITHM_INCREMENTAL);
2076                 } else
2077                     rrdset_next(st);
2078
2079                 rrddim_set_by_pointer(st, rd_ok,     ipstat.ips_fragments);
2080                 rrddim_set_by_pointer(st, rd_failed, ipstat.ips_fragdropped);
2081                 rrddim_set_by_pointer(st, rd_all,    ipstat.ips_reassembled);
2082                 rrdset_done(st);
2083             }
2084
2085             // --------------------------------------------------------------------
2086
2087             if (likely(do_ip_errors)) {
2088                 static RRDSET *st = NULL;
2089                 static RRDDIM *rd_in_discards = NULL, *rd_out_discards = NULL,
2090                               *rd_in_hdr_errors = NULL, *rd_out_no_routes = NULL,
2091                               *rd_in_addr_errors = NULL, *rd_in_unknown_protos = NULL;
2092
2093                 if (unlikely(!st)) {
2094                     st = rrdset_create_localhost("ipv4",
2095                                                  "errors",
2096                                                  NULL,
2097                                                  "errors",
2098                                                  NULL,
2099                                                  "IPv4 Errors",
2100                                                  "packets/s",
2101                                                  3002,
2102                                                  update_every,
2103                                                  RRDSET_TYPE_LINE
2104                     );
2105
2106                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
2107
2108                     rd_in_discards       = rrddim_add(st, "InDiscards",      NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2109                     rd_out_discards      = rrddim_add(st, "OutDiscards",     NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2110                     rd_in_hdr_errors     = rrddim_add(st, "InHdrErrors",     NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2111                     rd_out_no_routes     = rrddim_add(st, "OutNoRoutes",     NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2112                     rd_in_addr_errors    = rrddim_add(st, "InAddrErrors",    NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2113                     rd_in_unknown_protos = rrddim_add(st, "InUnknownProtos", NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2114                 } else
2115                     rrdset_next(st);
2116
2117                 rrddim_set_by_pointer(st, rd_in_discards,       ipstat.ips_badsum + ipstat.ips_tooshort +
2118                                                                 ipstat.ips_toosmall + ipstat.ips_toolong);
2119                 rrddim_set_by_pointer(st, rd_out_discards,      ipstat.ips_odropped);
2120                 rrddim_set_by_pointer(st, rd_in_hdr_errors,     ipstat.ips_badhlen + ipstat.ips_badlen +
2121                                                                 ipstat.ips_badoptions + ipstat.ips_badvers);
2122                 rrddim_set_by_pointer(st, rd_out_no_routes,     ipstat.ips_noroute);
2123                 rrddim_set_by_pointer(st, rd_in_addr_errors,    ipstat.ips_badaddr);
2124                 rrddim_set_by_pointer(st, rd_in_unknown_protos, ipstat.ips_noproto);
2125                 rrdset_done(st);
2126             }
2127         }
2128     } else {
2129         error("DISABLED: net.inet.ip.stats module");
2130         return 1;
2131     }
2132
2133     return 0;
2134 }
2135
2136 // --------------------------------------------------------------------------------------------------------------------
2137 // net.inet6.ip6.stats
2138
2139 int do_net_inet6_ip6_stats(int update_every, usec_t dt) {
2140     static int do_ip6_packets = -1, do_ip6_fragsout = -1, do_ip6_fragsin = -1, do_ip6_errors = -1;
2141
2142     if (unlikely(do_ip6_packets == -1)) {
2143         do_ip6_packets  = config_get_boolean_ondemand("plugin:freebsd:sysctl", "ipv6 packets",        CONFIG_BOOLEAN_AUTO);
2144         do_ip6_fragsout = config_get_boolean_ondemand("plugin:freebsd:sysctl", "ipv6 fragments sent", CONFIG_BOOLEAN_AUTO);
2145         do_ip6_fragsin  = config_get_boolean_ondemand("plugin:freebsd:sysctl", "ipv6 fragments assembly",
2146                                                       CONFIG_BOOLEAN_AUTO);
2147         do_ip6_errors   = config_get_boolean_ondemand("plugin:freebsd:sysctl", "ipv6 errors",         CONFIG_BOOLEAN_AUTO);
2148     }
2149
2150     if (likely(do_ip6_packets || do_ip6_fragsout || do_ip6_fragsin || do_ip6_errors)) {
2151         static int mib[4] = {0, 0, 0, 0};
2152         struct ip6stat ip6stat;
2153
2154         if (unlikely(GETSYSCTL_SIMPLE("net.inet6.ip6.stats", mib, ip6stat))) {
2155             do_ip6_packets = 0;
2156             error("DISABLED: ipv6.packets chart");
2157             do_ip6_fragsout = 0;
2158             error("DISABLED: ipv6.fragsout chart");
2159             do_ip6_fragsin = 0;
2160             error("DISABLED: ipv6.fragsin chart");
2161             do_ip6_errors = 0;
2162             error("DISABLED: ipv6.errors chart");
2163             error("DISABLED: net.inet6.ip6.stats module");
2164             return 1;
2165         } else {
2166
2167             // --------------------------------------------------------------------
2168
2169             if (do_ip6_packets == CONFIG_BOOLEAN_YES || (do_ip6_packets == CONFIG_BOOLEAN_AUTO &&
2170                                                          (ip6stat.ip6s_localout || ip6stat.ip6s_total ||
2171                                                           ip6stat.ip6s_forward || ip6stat.ip6s_delivered))) {
2172                 do_ip6_packets = CONFIG_BOOLEAN_YES;
2173
2174                 static RRDSET *st = NULL;
2175                 static RRDDIM *rd_received = NULL, *rd_sent = NULL, *rd_forwarded = NULL, *rd_delivers = NULL;
2176
2177                 if (unlikely(!st)) {
2178                     st = rrdset_create_localhost("ipv6",
2179                                                  "packets",
2180                                                  NULL,
2181                                                  "packets",
2182                                                  NULL,
2183                                                  "IPv6 Packets",
2184                                                  "packets/s",
2185                                                  3000,
2186                                                  update_every,
2187                                                  RRDSET_TYPE_LINE
2188                     );
2189
2190                     rd_received  = rrddim_add(st, "received",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2191                     rd_sent      = rrddim_add(st, "sent",      NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2192                     rd_forwarded = rrddim_add(st, "forwarded", NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2193                     rd_delivers  = rrddim_add(st, "delivers",  NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2194                 } else
2195                     rrdset_next(st);
2196
2197                 rrddim_set_by_pointer(st, rd_sent,      ip6stat.ip6s_localout);
2198                 rrddim_set_by_pointer(st, rd_received,  ip6stat.ip6s_total);
2199                 rrddim_set_by_pointer(st, rd_forwarded, ip6stat.ip6s_forward);
2200                 rrddim_set_by_pointer(st, rd_delivers,  ip6stat.ip6s_delivered);
2201                 rrdset_done(st);
2202             }
2203
2204             // --------------------------------------------------------------------
2205
2206             if (do_ip6_fragsout == CONFIG_BOOLEAN_YES || (do_ip6_fragsout == CONFIG_BOOLEAN_AUTO &&
2207                                                           (ip6stat.ip6s_fragmented || ip6stat.ip6s_cantfrag ||
2208                                                            ip6stat.ip6s_ofragments))) {
2209                 do_ip6_fragsout = CONFIG_BOOLEAN_YES;
2210
2211                 static RRDSET *st = NULL;
2212                 static RRDDIM *rd_ok = NULL, *rd_failed = NULL, *rd_all = NULL;
2213
2214                 if (unlikely(!st)) {
2215                     st = rrdset_create_localhost("ipv6",
2216                                                  "fragsout",
2217                                                  NULL,
2218                                                  "fragments",
2219                                                  NULL,
2220                                                  "IPv6 Fragments Sent",
2221                                                  "packets/s",
2222                                                  3010,
2223                                                  update_every,
2224                                                  RRDSET_TYPE_LINE
2225                     );
2226
2227                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
2228
2229                     rd_ok     = rrddim_add(st, "ok",     NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2230                     rd_failed = rrddim_add(st, "failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2231                     rd_all    = rrddim_add(st, "all",    NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2232                 } else
2233                     rrdset_next(st);
2234
2235                 rrddim_set_by_pointer(st, rd_ok,     ip6stat.ip6s_fragmented);
2236                 rrddim_set_by_pointer(st, rd_failed, ip6stat.ip6s_cantfrag);
2237                 rrddim_set_by_pointer(st, rd_all,    ip6stat.ip6s_ofragments);
2238                 rrdset_done(st);
2239             }
2240
2241             // --------------------------------------------------------------------
2242
2243             if (do_ip6_fragsin == CONFIG_BOOLEAN_YES || (do_ip6_fragsin == CONFIG_BOOLEAN_AUTO &&
2244                                                          (ip6stat.ip6s_reassembled || ip6stat.ip6s_fragdropped ||
2245                                                           ip6stat.ip6s_fragtimeout || ip6stat.ip6s_fragments))) {
2246                 do_ip6_fragsin = CONFIG_BOOLEAN_YES;
2247
2248                 static RRDSET *st = NULL;
2249                 static RRDDIM *rd_ok = NULL, *rd_failed = NULL, *rd_timeout = NULL, *rd_all = NULL;
2250
2251                 if (unlikely(!st)) {
2252                     st = rrdset_create_localhost("ipv6",
2253                                                  "fragsin",
2254                                                  NULL,
2255                                                  "fragments",
2256                                                  NULL,
2257                                                  "IPv6 Fragments Reassembly",
2258                                                  "packets/s",
2259                                                  3011,
2260                                                  update_every,
2261                                                  RRDSET_TYPE_LINE
2262                     );
2263
2264                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
2265
2266                     rd_ok      = rrddim_add(st, "ok",      NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2267                     rd_failed  = rrddim_add(st, "failed",  NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2268                     rd_timeout = rrddim_add(st, "timeout", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2269                     rd_all     = rrddim_add(st, "all",     NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2270                 } else
2271                     rrdset_next(st);
2272
2273                 rrddim_set_by_pointer(st, rd_ok,      ip6stat.ip6s_reassembled);
2274                 rrddim_set_by_pointer(st, rd_failed,  ip6stat.ip6s_fragdropped);
2275                 rrddim_set_by_pointer(st, rd_timeout, ip6stat.ip6s_fragtimeout);
2276                 rrddim_set_by_pointer(st, rd_all,     ip6stat.ip6s_fragments);
2277                 rrdset_done(st);
2278             }
2279
2280             // --------------------------------------------------------------------
2281
2282             if (do_ip6_errors == CONFIG_BOOLEAN_YES || (do_ip6_errors == CONFIG_BOOLEAN_AUTO && (
2283                     ip6stat.ip6s_toosmall ||
2284                     ip6stat.ip6s_odropped ||
2285                     ip6stat.ip6s_badoptions ||
2286                     ip6stat.ip6s_badvers ||
2287                     ip6stat.ip6s_exthdrtoolong ||
2288                     ip6stat.ip6s_sources_none ||
2289                     ip6stat.ip6s_tooshort ||
2290                     ip6stat.ip6s_cantforward ||
2291                     ip6stat.ip6s_noroute))) {
2292                 do_ip6_errors = CONFIG_BOOLEAN_YES;
2293
2294                 static RRDSET *st = NULL;
2295                 static RRDDIM *rd_in_discards = NULL, *rd_out_discards = NULL,
2296                               *rd_in_hdr_errors = NULL, *rd_in_addr_errors = NULL, *rd_in_truncated_pkts = NULL,
2297                               *rd_in_no_routes = NULL, *rd_out_no_routes = NULL;
2298
2299                 if (unlikely(!st)) {
2300                     st = rrdset_create_localhost("ipv6",
2301                                                  "errors",
2302                                                  NULL,
2303                                                  "errors",
2304                                                  NULL,
2305                                                  "IPv6 Errors",
2306                                                  "packets/s",
2307                                                  3002,
2308                                                  update_every,
2309                                                  RRDSET_TYPE_LINE
2310                     );
2311
2312                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
2313
2314                     rd_in_discards       = rrddim_add(st, "InDiscards",      NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2315                     rd_out_discards      = rrddim_add(st, "OutDiscards",     NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2316                     rd_in_hdr_errors     = rrddim_add(st, "InHdrErrors",     NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2317                     rd_in_addr_errors    = rrddim_add(st, "InAddrErrors",    NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2318                     rd_in_truncated_pkts = rrddim_add(st, "InTruncatedPkts", NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2319                     rd_in_no_routes      = rrddim_add(st, "InNoRoutes",      NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2320                     rd_out_no_routes     = rrddim_add(st, "OutNoRoutes",     NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2321                 } else
2322                     rrdset_next(st);
2323
2324                 rrddim_set_by_pointer(st, rd_in_discards,       ip6stat.ip6s_toosmall);
2325                 rrddim_set_by_pointer(st, rd_out_discards,      ip6stat.ip6s_odropped);
2326                 rrddim_set_by_pointer(st, rd_in_hdr_errors,     ip6stat.ip6s_badoptions + ip6stat.ip6s_badvers +
2327                                                                 ip6stat.ip6s_exthdrtoolong);
2328                 rrddim_set_by_pointer(st, rd_in_addr_errors,    ip6stat.ip6s_sources_none);
2329                 rrddim_set_by_pointer(st, rd_in_truncated_pkts, ip6stat.ip6s_tooshort);
2330                 rrddim_set_by_pointer(st, rd_in_no_routes,      ip6stat.ip6s_cantforward);
2331                 rrddim_set_by_pointer(st, rd_out_no_routes,     ip6stat.ip6s_noroute);
2332                 rrdset_done(st);
2333             }
2334         }
2335     } else {
2336         error("DISABLED: net.inet6.ip6.stats module");
2337         return 1;
2338     }
2339
2340     return 0;
2341 }
2342
2343 // --------------------------------------------------------------------------------------------------------------------
2344 // net.inet6.icmp6.stats
2345
2346 int do_net_inet6_icmp6_stats(int update_every, usec_t dt) {
2347     static int do_icmp6 = -1, do_icmp6_redir = -1, do_icmp6_errors = -1, do_icmp6_echos = -1, do_icmp6_router = -1,
2348             do_icmp6_neighbor = -1, do_icmp6_types = -1;
2349
2350     if (unlikely(do_icmp6 == -1)) {
2351         do_icmp6          = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp",           CONFIG_BOOLEAN_AUTO);
2352         do_icmp6_redir    = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp redirects", CONFIG_BOOLEAN_AUTO);
2353         do_icmp6_errors   = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp errors",    CONFIG_BOOLEAN_AUTO);
2354         do_icmp6_echos    = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp echos",     CONFIG_BOOLEAN_AUTO);
2355         do_icmp6_router   = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp router",    CONFIG_BOOLEAN_AUTO);
2356         do_icmp6_neighbor = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp neighbor",  CONFIG_BOOLEAN_AUTO);
2357         do_icmp6_types    = config_get_boolean_ondemand("plugin:freebsd:sysctl", "icmp types",     CONFIG_BOOLEAN_AUTO);
2358     }
2359
2360     if (likely(do_icmp6 || do_icmp6_redir || do_icmp6_errors || do_icmp6_echos || do_icmp6_router || do_icmp6_neighbor || do_icmp6_types)) {
2361         static int mib[4] = {0, 0, 0, 0};
2362         struct icmp6stat icmp6stat;
2363
2364         if (unlikely(GETSYSCTL_SIMPLE("net.inet6.icmp6.stats", mib, icmp6stat))) {
2365             do_icmp6 = 0;
2366             error("DISABLED: ipv6.icmp chart");
2367             do_icmp6_redir = 0;
2368             error("DISABLED: ipv6.icmpredir chart");
2369             do_icmp6_errors = 0;
2370             error("DISABLED: ipv6.icmperrors chart");
2371             do_icmp6_echos = 0;
2372             error("DISABLED: ipv6.icmpechos chart");
2373             do_icmp6_router = 0;
2374             error("DISABLED: ipv6.icmprouter chart");
2375             do_icmp6_neighbor = 0;
2376             error("DISABLED: ipv6.icmpneighbor chart");
2377             do_icmp6_types = 0;
2378             error("DISABLED: ipv6.icmptypes chart");
2379             error("DISABLED: net.inet6.icmp6.stats module");
2380             return 1;
2381         } else {
2382             int i;
2383             struct icmp6_total {
2384                 u_long  msgs_in;
2385                 u_long  msgs_out;
2386             } icmp6_total = {0, 0};
2387
2388             for (i = 0; i <= ICMP6_MAXTYPE; i++) {
2389                 icmp6_total.msgs_in += icmp6stat.icp6s_inhist[i];
2390                 icmp6_total.msgs_out += icmp6stat.icp6s_outhist[i];
2391             }
2392             icmp6_total.msgs_in += icmp6stat.icp6s_badcode + icmp6stat.icp6s_badlen + icmp6stat.icp6s_checksum + icmp6stat.icp6s_tooshort;
2393
2394             // --------------------------------------------------------------------
2395
2396             if (do_icmp6 == CONFIG_BOOLEAN_YES || (do_icmp6 == CONFIG_BOOLEAN_AUTO && (icmp6_total.msgs_in || icmp6_total.msgs_out))) {
2397                 do_icmp6 = CONFIG_BOOLEAN_YES;
2398
2399                 static RRDSET *st = NULL;
2400                 static RRDDIM *rd_received = NULL, *rd_sent = NULL;
2401
2402                 if (unlikely(!st)) {
2403                     st = rrdset_create_localhost("ipv6",
2404                                                  "icmp",
2405                                                  NULL,
2406                                                  "icmp",
2407                                                  NULL,
2408                                                  "IPv6 ICMP Messages",
2409                                                  "messages/s",
2410                                                  10000,
2411                                                  update_every,
2412                                                  RRDSET_TYPE_LINE
2413                     );
2414
2415                     rd_received = rrddim_add(st, "received", NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2416                     rd_sent     = rrddim_add(st, "sent",     NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2417                 } else
2418                     rrdset_next(st);
2419
2420                 rrddim_set_by_pointer(st, rd_received, icmp6_total.msgs_out);
2421                 rrddim_set_by_pointer(st, rd_sent,     icmp6_total.msgs_in);
2422
2423                 rrdset_done(st);
2424             }
2425
2426             // --------------------------------------------------------------------
2427
2428             if (do_icmp6_redir == CONFIG_BOOLEAN_YES || (do_icmp6_redir == CONFIG_BOOLEAN_AUTO && (icmp6stat.icp6s_inhist[ND_REDIRECT] || icmp6stat.icp6s_outhist[ND_REDIRECT]))) {
2429                 do_icmp6_redir = CONFIG_BOOLEAN_YES;
2430
2431                 static RRDSET *st = NULL;
2432                 static RRDDIM *rd_received = NULL, *rd_sent = NULL;
2433
2434                 if (unlikely(!st)) {
2435                     st = rrdset_create_localhost("ipv6",
2436                                                  "icmpredir",
2437                                                  NULL,
2438                                                  "icmp",
2439                                                  NULL,
2440                                                  "IPv6 ICMP Redirects",
2441                                                  "redirects/s",
2442                                                  10050,
2443                                                  update_every,
2444                                                  RRDSET_TYPE_LINE
2445                     );
2446
2447                     rd_received = rrddim_add(st, "received", NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2448                     rd_sent     = rrddim_add(st, "sent",     NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2449                 } else
2450                     rrdset_next(st);
2451
2452                 rrddim_set_by_pointer(st, rd_received, icmp6stat.icp6s_outhist[ND_REDIRECT]);
2453                 rrddim_set_by_pointer(st, rd_sent, icmp6stat.icp6s_inhist[ND_REDIRECT]);
2454                 rrdset_done(st);
2455             }
2456
2457             // --------------------------------------------------------------------
2458
2459             if (do_icmp6_errors == CONFIG_BOOLEAN_YES || (do_icmp6_errors == CONFIG_BOOLEAN_AUTO && (
2460                     icmp6stat.icp6s_badcode ||
2461                     icmp6stat.icp6s_badlen ||
2462                     icmp6stat.icp6s_checksum ||
2463                     icmp6stat.icp6s_tooshort ||
2464                     icmp6stat.icp6s_error ||
2465                     icmp6stat.icp6s_inhist[ICMP6_DST_UNREACH] ||
2466                     icmp6stat.icp6s_inhist[ICMP6_TIME_EXCEEDED] ||
2467                     icmp6stat.icp6s_inhist[ICMP6_PARAM_PROB] ||
2468                     icmp6stat.icp6s_outhist[ICMP6_DST_UNREACH] ||
2469                     icmp6stat.icp6s_outhist[ICMP6_TIME_EXCEEDED] ||
2470                     icmp6stat.icp6s_outhist[ICMP6_PARAM_PROB]))) {
2471                 do_icmp6_errors = CONFIG_BOOLEAN_YES;
2472
2473                 static RRDSET *st = NULL;
2474                 static RRDDIM *rd_in_errors = NULL, *rd_out_errors = NULL, *rd_in_csum_errors = NULL,
2475                               *rd_in_dest_unreachs = NULL, *rd_in_pkt_too_bigs = NULL, *rd_in_time_excds = NULL,
2476                               *rd_in_parm_problems = NULL, *rd_out_dest_unreachs = NULL, *rd_out_time_excds = NULL,
2477                               *rd_out_parm_problems = NULL;
2478
2479                 if (unlikely(!st)) {
2480                     st = rrdset_create_localhost("ipv6",
2481                                                  "icmperrors",
2482                                                  NULL, "icmp",
2483                                                  NULL,
2484                                                  "IPv6 ICMP Errors",
2485                                                  "errors/s",
2486                                                  10100,
2487                                                  update_every,
2488                                                  RRDSET_TYPE_LINE
2489                     );
2490
2491                     rd_in_errors         = rrddim_add(st, "InErrors",        NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2492                     rd_out_errors        = rrddim_add(st, "OutErrors",       NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2493                     rd_in_csum_errors    = rrddim_add(st, "InCsumErrors",    NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2494                     rd_in_dest_unreachs  = rrddim_add(st, "InDestUnreachs",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2495                     rd_in_pkt_too_bigs   = rrddim_add(st, "InPktTooBigs",    NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2496                     rd_in_time_excds     = rrddim_add(st, "InTimeExcds",     NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2497                     rd_in_parm_problems  = rrddim_add(st, "InParmProblems",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2498                     rd_out_dest_unreachs = rrddim_add(st, "OutDestUnreachs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2499                     rd_out_time_excds    = rrddim_add(st, "OutTimeExcds",    NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2500                     rd_out_parm_problems = rrddim_add(st, "OutParmProblems", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2501                 } else
2502                     rrdset_next(st);
2503
2504                 rrddim_set_by_pointer(st, rd_in_errors,         icmp6stat.icp6s_badcode + icmp6stat.icp6s_badlen +
2505                                                                 icmp6stat.icp6s_checksum + icmp6stat.icp6s_tooshort);
2506                 rrddim_set_by_pointer(st, rd_out_errors,        icmp6stat.icp6s_error);
2507                 rrddim_set_by_pointer(st, rd_in_csum_errors,    icmp6stat.icp6s_checksum);
2508                 rrddim_set_by_pointer(st, rd_in_dest_unreachs,  icmp6stat.icp6s_inhist[ICMP6_DST_UNREACH]);
2509                 rrddim_set_by_pointer(st, rd_in_pkt_too_bigs,   icmp6stat.icp6s_badlen);
2510                 rrddim_set_by_pointer(st, rd_in_time_excds,     icmp6stat.icp6s_inhist[ICMP6_TIME_EXCEEDED]);
2511                 rrddim_set_by_pointer(st, rd_in_parm_problems,  icmp6stat.icp6s_inhist[ICMP6_PARAM_PROB]);
2512                 rrddim_set_by_pointer(st, rd_out_dest_unreachs, icmp6stat.icp6s_outhist[ICMP6_DST_UNREACH]);
2513                 rrddim_set_by_pointer(st, rd_out_time_excds,    icmp6stat.icp6s_outhist[ICMP6_TIME_EXCEEDED]);
2514                 rrddim_set_by_pointer(st, rd_out_parm_problems, icmp6stat.icp6s_outhist[ICMP6_PARAM_PROB]);
2515                 rrdset_done(st);
2516             }
2517
2518             // --------------------------------------------------------------------
2519
2520             if (do_icmp6_echos == CONFIG_BOOLEAN_YES || (do_icmp6_echos == CONFIG_BOOLEAN_AUTO && (
2521                     icmp6stat.icp6s_inhist[ICMP6_ECHO_REQUEST] ||
2522                     icmp6stat.icp6s_outhist[ICMP6_ECHO_REQUEST] ||
2523                     icmp6stat.icp6s_inhist[ICMP6_ECHO_REPLY] ||
2524                     icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]))) {
2525                 do_icmp6_echos = CONFIG_BOOLEAN_YES;
2526
2527                 static RRDSET *st = NULL;
2528                 static RRDDIM *rd_in = NULL, *rd_out = NULL, *rd_in_replies = NULL, *rd_out_replies = NULL;
2529
2530                 if (unlikely(!st)) {
2531                     st = rrdset_create_localhost("ipv6",
2532                                                  "icmpechos",
2533                                                  NULL,
2534                                                  "icmp",
2535                                                  NULL,
2536                                                  "IPv6 ICMP Echo",
2537                                                  "messages/s",
2538                                                  10200,
2539                                                  update_every,
2540                                                  RRDSET_TYPE_LINE
2541                     );
2542
2543                     rd_in          = rrddim_add(st, "InEchos",        NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2544                     rd_out         = rrddim_add(st, "OutEchos",       NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2545                     rd_in_replies  = rrddim_add(st, "InEchoReplies",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2546                     rd_out_replies = rrddim_add(st, "OutEchoReplies", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2547                 } else
2548                     rrdset_next(st);
2549
2550                 rrddim_set_by_pointer(st, rd_in,          icmp6stat.icp6s_inhist[ICMP6_ECHO_REQUEST]);
2551                 rrddim_set_by_pointer(st, rd_out,         icmp6stat.icp6s_outhist[ICMP6_ECHO_REQUEST]);
2552                 rrddim_set_by_pointer(st, rd_in_replies,  icmp6stat.icp6s_inhist[ICMP6_ECHO_REPLY]);
2553                 rrddim_set_by_pointer(st, rd_out_replies, icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]);
2554                 rrdset_done(st);
2555             }
2556
2557             // --------------------------------------------------------------------
2558
2559             if (do_icmp6_router == CONFIG_BOOLEAN_YES || (do_icmp6_router == CONFIG_BOOLEAN_AUTO && (
2560                     icmp6stat.icp6s_inhist[ND_ROUTER_SOLICIT] ||
2561                     icmp6stat.icp6s_outhist[ND_ROUTER_SOLICIT] ||
2562                     icmp6stat.icp6s_inhist[ND_ROUTER_ADVERT] ||
2563                     icmp6stat.icp6s_outhist[ND_ROUTER_ADVERT]))) {
2564                 do_icmp6_router = CONFIG_BOOLEAN_YES;
2565
2566                 static RRDSET *st = NULL;
2567                 static RRDDIM *rd_in_solicits = NULL, *rd_out_solicits = NULL,
2568                               *rd_in_advertisements = NULL, *rd_out_advertisements = NULL;
2569
2570                 if (unlikely(!st)) {
2571                     st = rrdset_create_localhost("ipv6",
2572                                                  "icmprouter",
2573                                                  NULL,
2574                                                  "icmp",
2575                                                  NULL,
2576                                                  "IPv6 Router Messages",
2577                                                  "messages/s",
2578                                                  10400,
2579                                                  update_every,
2580                                                  RRDSET_TYPE_LINE
2581                     );
2582
2583                     rd_in_solicits        = rrddim_add(st, "InSolicits",        NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2584                     rd_out_solicits       = rrddim_add(st, "OutSolicits",       NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2585                     rd_in_advertisements  = rrddim_add(st, "InAdvertisements",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2586                     rd_out_advertisements = rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2587                 } else
2588                     rrdset_next(st);
2589
2590                 rrddim_set_by_pointer(st, rd_in_solicits,        icmp6stat.icp6s_inhist[ND_ROUTER_SOLICIT]);
2591                 rrddim_set_by_pointer(st, rd_out_solicits,       icmp6stat.icp6s_outhist[ND_ROUTER_SOLICIT]);
2592                 rrddim_set_by_pointer(st, rd_in_advertisements,  icmp6stat.icp6s_inhist[ND_ROUTER_ADVERT]);
2593                 rrddim_set_by_pointer(st, rd_out_advertisements, icmp6stat.icp6s_outhist[ND_ROUTER_ADVERT]);
2594                 rrdset_done(st);
2595             }
2596
2597             // --------------------------------------------------------------------
2598
2599             if (do_icmp6_neighbor == CONFIG_BOOLEAN_YES || (do_icmp6_neighbor == CONFIG_BOOLEAN_AUTO && (
2600                     icmp6stat.icp6s_inhist[ND_NEIGHBOR_SOLICIT] ||
2601                     icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT] ||
2602                     icmp6stat.icp6s_inhist[ND_NEIGHBOR_ADVERT] ||
2603                     icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]))) {
2604                 do_icmp6_neighbor = CONFIG_BOOLEAN_YES;
2605
2606                 static RRDSET *st = NULL;
2607                 static RRDDIM *rd_in_solicits = NULL, *rd_out_solicits = NULL,
2608                               *rd_in_advertisements = NULL, *rd_out_advertisements = NULL;
2609
2610                 if (unlikely(!st)) {
2611                     st = rrdset_create_localhost("ipv6",
2612                                                  "icmpneighbor",
2613                                                  NULL,
2614                                                  "icmp",
2615                                                  NULL,
2616                                                  "IPv6 Neighbor Messages",
2617                                                  "messages/s",
2618                                                  10500,
2619                                                  update_every,
2620                                                  RRDSET_TYPE_LINE
2621                     );
2622
2623                     rd_in_solicits        = rrddim_add(st, "InSolicits",        NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2624                     rd_out_solicits       = rrddim_add(st, "OutSolicits",       NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2625                     rd_in_advertisements  = rrddim_add(st, "InAdvertisements",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2626                     rd_out_advertisements = rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2627                 } else
2628                     rrdset_next(st);
2629
2630                 rrddim_set_by_pointer(st, rd_in_solicits,        icmp6stat.icp6s_inhist[ND_NEIGHBOR_SOLICIT]);
2631                 rrddim_set_by_pointer(st, rd_out_solicits,       icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT]);
2632                 rrddim_set_by_pointer(st, rd_in_advertisements,  icmp6stat.icp6s_inhist[ND_NEIGHBOR_ADVERT]);
2633                 rrddim_set_by_pointer(st, rd_out_advertisements, icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]);
2634                 rrdset_done(st);
2635             }
2636
2637             // --------------------------------------------------------------------
2638
2639             if (do_icmp6_types == CONFIG_BOOLEAN_YES || (do_icmp6_types == CONFIG_BOOLEAN_AUTO && (
2640                     icmp6stat.icp6s_inhist[1] ||
2641                     icmp6stat.icp6s_inhist[128] ||
2642                     icmp6stat.icp6s_inhist[129] ||
2643                     icmp6stat.icp6s_inhist[136] ||
2644                     icmp6stat.icp6s_outhist[1] ||
2645                     icmp6stat.icp6s_outhist[128] ||
2646                     icmp6stat.icp6s_outhist[129] ||
2647                     icmp6stat.icp6s_outhist[133] ||
2648                     icmp6stat.icp6s_outhist[135] ||
2649                     icmp6stat.icp6s_outhist[136]))) {
2650                 do_icmp6_types = CONFIG_BOOLEAN_YES;
2651
2652                 static RRDSET *st = NULL;
2653                 static RRDDIM *rd_in_1 = NULL, *rd_in_128 = NULL, *rd_in_129 = NULL, *rd_in_136 = NULL,
2654                               *rd_out_1 = NULL, *rd_out_128 = NULL, *rd_out_129 = NULL, *rd_out_133 = NULL,
2655                               *rd_out_135 = NULL, *rd_out_143 = NULL;
2656
2657                 if (unlikely(!st)) {
2658                     st = rrdset_create_localhost("ipv6",
2659                                                  "icmptypes",
2660                                                  NULL,
2661                                                  "icmp",
2662                                                  NULL,
2663                                                  "IPv6 ICMP Types",
2664                                                  "messages/s",
2665                                                  10700,
2666                                                  update_every,
2667                                                  RRDSET_TYPE_LINE
2668                     );
2669
2670                     rd_in_1    = rrddim_add(st, "InType1",    NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2671                     rd_in_128  = rrddim_add(st, "InType128",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2672                     rd_in_129  = rrddim_add(st, "InType129",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2673                     rd_in_136  = rrddim_add(st, "InType136",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2674                     rd_out_1   = rrddim_add(st, "OutType1",   NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2675                     rd_out_128 = rrddim_add(st, "OutType128", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2676                     rd_out_129 = rrddim_add(st, "OutType129", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2677                     rd_out_133 = rrddim_add(st, "OutType133", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2678                     rd_out_135 = rrddim_add(st, "OutType135", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2679                     rd_out_143 = rrddim_add(st, "OutType143", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2680                 } else
2681                     rrdset_next(st);
2682
2683                 rrddim_set_by_pointer(st, rd_in_1,    icmp6stat.icp6s_inhist[1]);
2684                 rrddim_set_by_pointer(st, rd_in_128,  icmp6stat.icp6s_inhist[128]);
2685                 rrddim_set_by_pointer(st, rd_in_129,  icmp6stat.icp6s_inhist[129]);
2686                 rrddim_set_by_pointer(st, rd_in_136,  icmp6stat.icp6s_inhist[136]);
2687                 rrddim_set_by_pointer(st, rd_out_1,   icmp6stat.icp6s_outhist[1]);
2688                 rrddim_set_by_pointer(st, rd_out_128, icmp6stat.icp6s_outhist[128]);
2689                 rrddim_set_by_pointer(st, rd_out_129, icmp6stat.icp6s_outhist[129]);
2690                 rrddim_set_by_pointer(st, rd_out_133, icmp6stat.icp6s_outhist[133]);
2691                 rrddim_set_by_pointer(st, rd_out_135, icmp6stat.icp6s_outhist[135]);
2692                 rrddim_set_by_pointer(st, rd_out_143, icmp6stat.icp6s_outhist[143]);
2693                 rrdset_done(st);
2694             }
2695         }
2696     } else {
2697         error("DISABLED: net.inet6.icmp6.stats module");
2698         return 1;
2699     }
2700
2701     return 0;
2702 }
2703
2704 // --------------------------------------------------------------------------------------------------------------------
2705 // getmntinfo
2706
2707 int do_getmntinfo(int update_every, usec_t dt) {
2708
2709 #define DELAULT_EXLUDED_PATHS "/proc/*"
2710 // taken from gnulib/mountlist.c and shortened to FreeBSD related fstypes
2711 #define DEFAULT_EXCLUDED_FILESYSTEMS "autofs procfs subfs devfs none"
2712 #define CONFIG_SECTION_DISKSPACE "plugin:freebsd:getmntinfo"
2713
2714     static int do_space = -1, do_inodes = -1;
2715
2716     if (unlikely(do_space == -1)) {
2717         do_space  = config_get_boolean_ondemand(CONFIG_SECTION_DISKSPACE, "space usage for all disks",  CONFIG_BOOLEAN_AUTO);
2718         do_inodes = config_get_boolean_ondemand(CONFIG_SECTION_DISKSPACE, "inodes usage for all disks", CONFIG_BOOLEAN_AUTO);
2719     }
2720
2721     if (likely(do_space || do_inodes)) {
2722         struct statfs *mntbuf;
2723         int mntsize;
2724
2725         // there is no mount info in sysctl MIBs
2726         if (unlikely(!(mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)))) {
2727             error("FREEBSD: getmntinfo() failed");
2728             do_space = 0;
2729             error("DISABLED: disk_space.* charts");
2730             do_inodes = 0;
2731             error("DISABLED: disk_inodes.* charts");
2732             error("DISABLED: getmntinfo module");
2733             return 1;
2734         } else {
2735             // Data to be stored in DICTIONARY mount_points.
2736             // This DICTIONARY is used to lookup the settings of the mount point on each iteration.
2737             struct mount_point_metadata {
2738                 int do_space;
2739                 int do_inodes;
2740
2741                 size_t collected; // the number of times this has been collected
2742
2743                 RRDSET *st_space;
2744                 RRDDIM *rd_space_used;
2745                 RRDDIM *rd_space_avail;
2746                 RRDDIM *rd_space_reserved;
2747
2748                 RRDSET *st_inodes;
2749                 RRDDIM *rd_inodes_used;
2750                 RRDDIM *rd_inodes_avail;
2751             };
2752             static DICTIONARY *mount_points = NULL;
2753             static SIMPLE_PATTERN *excluded_mountpoints = NULL;
2754             static SIMPLE_PATTERN *excluded_filesystems = NULL;
2755             int i;
2756
2757             if(unlikely(!mount_points)) {
2758
2759                 excluded_mountpoints = simple_pattern_create(
2760                         config_get(CONFIG_SECTION_DISKSPACE, "exclude space metrics on paths",
2761                                    DELAULT_EXLUDED_PATHS),
2762                         SIMPLE_PATTERN_EXACT
2763                 );
2764
2765                 excluded_filesystems = simple_pattern_create(
2766                         config_get(CONFIG_SECTION_DISKSPACE, "exclude space metrics on filesystems",
2767                                    DEFAULT_EXCLUDED_FILESYSTEMS),
2768                         SIMPLE_PATTERN_EXACT
2769                 );
2770
2771                 mount_points = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED);
2772             }
2773
2774             for (i = 0; i < mntsize; i++) {
2775
2776                 char title[4096 + 1];
2777                 int def_space, def_inodes, iter_space, iter_inodes;
2778
2779                 struct mount_point_metadata *m = dictionary_get(mount_points, mntbuf[i].f_mntonname);
2780                 if(unlikely(!m)) {
2781                     char var_name[4096 + 1];
2782                     snprintfz(var_name, 4096, "plugin:freebsd:getmntinfo:%s", mntbuf[i].f_mntonname);
2783
2784                     def_space = do_space;
2785                     def_inodes = do_space;
2786
2787                     if(unlikely(simple_pattern_matches(excluded_mountpoints, mntbuf[i].f_mntonname))) {
2788                         def_space = CONFIG_BOOLEAN_NO;
2789                         def_inodes = CONFIG_BOOLEAN_NO;
2790                     }
2791
2792                     if(unlikely(simple_pattern_matches(excluded_filesystems, mntbuf[i].f_fstypename))) {
2793                         def_space = CONFIG_BOOLEAN_NO;
2794                         def_inodes = CONFIG_BOOLEAN_NO;
2795                     }
2796
2797                     iter_space  = config_get_boolean_ondemand(var_name, "space usage",  def_space);
2798                     iter_inodes = config_get_boolean_ondemand(var_name, "inodes usage", def_inodes);
2799
2800                     struct mount_point_metadata mp = {
2801                             .do_space = iter_space,
2802                             .do_inodes = iter_inodes,
2803
2804                             .collected = 0,
2805
2806                             .st_space = NULL,
2807                             .rd_space_avail = NULL,
2808                             .rd_space_used = NULL,
2809                             .rd_space_reserved = NULL,
2810
2811                             .st_inodes = NULL,
2812                             .rd_inodes_avail = NULL,
2813                             .rd_inodes_used = NULL,
2814                     };
2815
2816                     m = dictionary_set(mount_points, mntbuf[i].f_mntonname, &mp, sizeof(struct mount_point_metadata));
2817                 }
2818
2819                 if(unlikely(m->do_space == CONFIG_BOOLEAN_NO && m->do_inodes == CONFIG_BOOLEAN_NO))
2820                     continue;
2821
2822                 if(unlikely(mntbuf[i].f_flags & MNT_RDONLY && !m->collected))
2823                     continue;
2824
2825                 // --------------------------------------------------------------------------
2826
2827                 int rendered = 0;
2828
2829                 if (m->do_space == CONFIG_BOOLEAN_YES || (m->do_space == CONFIG_BOOLEAN_AUTO && (mntbuf[i].f_blocks > 2))) {
2830                     if (unlikely(!m->st_space)) {
2831                         snprintfz(title, 4096, "Disk Space Usage for %s [%s]",
2832                                   mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname);
2833                         m->st_space = rrdset_create_localhost("disk_space",
2834                                                               mntbuf[i].f_mntonname,
2835                                                               NULL,
2836                                                               mntbuf[i].f_mntonname,
2837                                                               "disk.space",
2838                                                               title,
2839                                                               "GB",
2840                                                               2023,
2841                                                               update_every,
2842                                                               RRDSET_TYPE_STACKED
2843                         );
2844
2845                         m->rd_space_avail    = rrddim_add(m->st_space, "avail", NULL,
2846                                                           mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
2847                         m->rd_space_used     = rrddim_add(m->st_space, "used", NULL,
2848                                                           mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
2849                         m->rd_space_reserved = rrddim_add(m->st_space, "reserved_for_root", "reserved for root",
2850                                                           mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
2851                     } else
2852                         rrdset_next(m->st_space);
2853
2854                     rrddim_set_by_pointer(m->st_space, m->rd_space_avail,    (collected_number) mntbuf[i].f_bavail);
2855                     rrddim_set_by_pointer(m->st_space, m->rd_space_used,     (collected_number) (mntbuf[i].f_blocks -
2856                                                                                                  mntbuf[i].f_bfree));
2857                     rrddim_set_by_pointer(m->st_space, m->rd_space_reserved, (collected_number) (mntbuf[i].f_bfree -
2858                                                                                                  mntbuf[i].f_bavail));
2859                     rrdset_done(m->st_space);
2860
2861                     rendered++;
2862                 }
2863
2864                 // --------------------------------------------------------------------------
2865
2866                 if (m->do_inodes == CONFIG_BOOLEAN_YES || (m->do_inodes == CONFIG_BOOLEAN_AUTO && (mntbuf[i].f_files > 1))) {
2867                     if (unlikely(!m->st_inodes)) {
2868                         snprintfz(title, 4096, "Disk Files (inodes) Usage for %s [%s]",
2869                                   mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname);
2870                         m->st_inodes = rrdset_create_localhost("disk_inodes",
2871                                                                mntbuf[i].f_mntonname,
2872                                                                NULL,
2873                                                                mntbuf[i].f_mntonname,
2874                                                                "disk.inodes",
2875                                                                title,
2876                                                                "Inodes",
2877                                                                2024,
2878                                                                update_every,
2879                                                                RRDSET_TYPE_STACKED
2880                         );
2881
2882                         m->rd_inodes_avail = rrddim_add(m->st_inodes, "avail", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2883                         m->rd_inodes_used  = rrddim_add(m->st_inodes, "used",  NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2884                     } else
2885                         rrdset_next(m->st_inodes);
2886
2887                     rrddim_set_by_pointer(m->st_inodes, m->rd_inodes_avail, (collected_number) mntbuf[i].f_ffree);
2888                     rrddim_set_by_pointer(m->st_inodes, m->rd_inodes_used,  (collected_number) (mntbuf[i].f_files -
2889                                                                                                 mntbuf[i].f_ffree));
2890                     rrdset_done(m->st_inodes);
2891
2892                     rendered++;
2893                 }
2894
2895                 if(likely(rendered))
2896                     m->collected++;
2897             }
2898         }
2899     } else {
2900         error("DISABLED: getmntinfo module");
2901         return 1;
2902     }
2903
2904     return 0;
2905 }
2906
2907 // --------------------------------------------------------------------------------------------------------------------
2908 // old sources
2909
2910 int do_freebsd_sysctl_old(int update_every, usec_t dt) {
2911     static int do_disk_io = -1, do_bandwidth = -1;
2912
2913     if (unlikely(do_disk_io == -1)) {
2914         do_disk_io = config_get_boolean("plugin:freebsd:sysctl", "stats for all disks", 1);
2915         do_bandwidth = config_get_boolean("plugin:freebsd:sysctl", "bandwidth", 1);
2916     }
2917
2918     RRDSET *st;
2919
2920     int i;
2921
2922     // NEEDED BY: do_disk_io
2923     #define RRD_TYPE_DISK "disk"
2924     #define BINTIME_SCALE 5.42101086242752217003726400434970855712890625e-17 // this is 1000/2^64
2925     int numdevs;
2926     static void *devstat_data = NULL;
2927     struct devstat *dstat;
2928     char disk[DEVSTAT_NAME_LEN + MAX_INT_DIGITS + 1];
2929     struct cur_dstat {
2930         collected_number duration_read_ms;
2931         collected_number duration_write_ms;
2932         collected_number busy_time_ms;
2933     } cur_dstat;
2934     struct prev_dstat {
2935         collected_number bytes_read;
2936         collected_number bytes_write;
2937         collected_number operations_read;
2938         collected_number operations_write;
2939         collected_number duration_read_ms;
2940         collected_number duration_write_ms;
2941         collected_number busy_time_ms;
2942     } prev_dstat;
2943
2944     // NEEDED BY: do_bandwidth
2945     #define IFA_DATA(s) (((struct if_data *)ifa->ifa_data)->ifi_ ## s)
2946     struct ifaddrs *ifa, *ifap;
2947     struct iftot {
2948         u_long  ift_ibytes;
2949         u_long  ift_obytes;
2950     } iftot = {0, 0};
2951
2952     // --------------------------------------------------------------------
2953
2954     if (likely(do_disk_io)) {
2955         if (unlikely(GETSYSCTL_BY_NAME("kern.devstat.numdevs", numdevs))) {
2956             do_disk_io = 0;
2957             error("DISABLED: disk.io");
2958         } else {
2959             devstat_data = reallocz(devstat_data, sizeof(long) + sizeof(struct devstat) * numdevs); // there is generation number before devstat structures
2960             if (unlikely(
2961                     getsysctl_by_name("kern.devstat.all", devstat_data, sizeof(long) + sizeof(struct devstat) * numdevs))) {
2962                 do_disk_io = 0;
2963                 error("DISABLED: disk.io");
2964             } else {
2965                 dstat = devstat_data + sizeof(long); // skip generation number
2966                 collected_number total_disk_kbytes_read = 0;
2967                 collected_number total_disk_kbytes_write = 0;
2968
2969                 for (i = 0; i < numdevs; i++) {
2970                     if (((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_DIRECT) || ((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_STORARRAY)) {
2971                         sprintf(disk, "%s%d", dstat[i].device_name, dstat[i].unit_number);
2972
2973                         // --------------------------------------------------------------------
2974
2975                         st = rrdset_find_bytype_localhost(RRD_TYPE_DISK, disk);
2976                         if (unlikely(!st)) {
2977                             st = rrdset_create_localhost(RRD_TYPE_DISK, disk, NULL, disk, "disk.io", "Disk I/O Bandwidth", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA);
2978
2979                             rrddim_add(st, "reads", NULL, 1, 1024, RRD_ALGORITHM_INCREMENTAL);
2980                             rrddim_add(st, "writes", NULL, -1, 1024, RRD_ALGORITHM_INCREMENTAL);
2981                         }
2982                         else rrdset_next(st);
2983
2984                         total_disk_kbytes_read += dstat[i].bytes[DEVSTAT_READ]/KILO_FACTOR;
2985                         total_disk_kbytes_write += dstat[i].bytes[DEVSTAT_WRITE]/KILO_FACTOR;
2986                         prev_dstat.bytes_read = rrddim_set(st, "reads", dstat[i].bytes[DEVSTAT_READ]);
2987                         prev_dstat.bytes_write = rrddim_set(st, "writes", dstat[i].bytes[DEVSTAT_WRITE]);
2988                         rrdset_done(st);
2989
2990                         // --------------------------------------------------------------------
2991
2992                         st = rrdset_find_bytype_localhost("disk_ops", disk);
2993                         if (unlikely(!st)) {
2994                             st = rrdset_create_localhost("disk_ops", disk, NULL, disk, "disk.ops", "Disk Completed I/O Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE);
2995                             rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
2996
2997                             rrddim_add(st, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
2998                             rrddim_add(st, "writes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2999                         }
3000                         else rrdset_next(st);
3001
3002                         prev_dstat.operations_read = rrddim_set(st, "reads", dstat[i].operations[DEVSTAT_READ]);
3003                         prev_dstat.operations_write = rrddim_set(st, "writes", dstat[i].operations[DEVSTAT_WRITE]);
3004                         rrdset_done(st);
3005
3006                         // --------------------------------------------------------------------
3007
3008                         st = rrdset_find_bytype_localhost("disk_qops", disk);
3009                         if (unlikely(!st)) {
3010                             st = rrdset_create_localhost("disk_qops", disk, NULL, disk, "disk.qops", "Disk Current I/O Operations", "operations", 2002, update_every, RRDSET_TYPE_LINE);
3011                             rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
3012
3013                             rrddim_add(st, "operations", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
3014                         }
3015                         else rrdset_next(st);
3016
3017                         rrddim_set(st, "operations", dstat[i].start_count - dstat[i].end_count);
3018                         rrdset_done(st);
3019
3020                         // --------------------------------------------------------------------
3021
3022                         st = rrdset_find_bytype_localhost("disk_util", disk);
3023                         if (unlikely(!st)) {
3024                             st = rrdset_create_localhost("disk_util", disk, NULL, disk, "disk.util", "Disk Utilization Time", "% of time working", 2004, update_every, RRDSET_TYPE_AREA);
3025                             rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
3026
3027                             rrddim_add(st, "utilization", NULL, 1, 10, RRD_ALGORITHM_INCREMENTAL);
3028                         }
3029                         else rrdset_next(st);
3030
3031                         cur_dstat.busy_time_ms = dstat[i].busy_time.sec * 1000 + dstat[i].busy_time.frac * BINTIME_SCALE;
3032                         prev_dstat.busy_time_ms = rrddim_set(st, "utilization", cur_dstat.busy_time_ms);
3033                         rrdset_done(st);
3034
3035                         // --------------------------------------------------------------------
3036
3037                         st = rrdset_find_bytype_localhost("disk_iotime", disk);
3038                         if (unlikely(!st)) {
3039                             st = rrdset_create_localhost("disk_iotime", disk, NULL, disk, "disk.iotime", "Disk Total I/O Time", "milliseconds/s", 2022, update_every, RRDSET_TYPE_LINE);
3040                             rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
3041
3042                             rrddim_add(st, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
3043                             rrddim_add(st, "writes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
3044                         }
3045                         else rrdset_next(st);
3046
3047                         cur_dstat.duration_read_ms = dstat[i].duration[DEVSTAT_READ].sec * 1000 + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
3048                         cur_dstat.duration_write_ms = dstat[i].duration[DEVSTAT_WRITE].sec * 1000 + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
3049                         prev_dstat.duration_read_ms = rrddim_set(st, "reads", cur_dstat.duration_read_ms);
3050                         prev_dstat.duration_write_ms = rrddim_set(st, "writes", cur_dstat.duration_write_ms);
3051                         rrdset_done(st);
3052
3053                         // --------------------------------------------------------------------
3054                         // calculate differential charts
3055                         // only if this is not the first time we run
3056
3057                         if (likely(dt)) {
3058
3059                             // --------------------------------------------------------------------
3060
3061                             st = rrdset_find_bytype_localhost("disk_await", disk);
3062                             if (unlikely(!st)) {
3063                                 st = rrdset_create_localhost("disk_await", disk, NULL, disk, "disk.await", "Average Completed I/O Operation Time", "ms per operation", 2005, update_every, RRDSET_TYPE_LINE);
3064                                 rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
3065
3066                                 rrddim_add(st, "reads", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
3067                                 rrddim_add(st, "writes", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE);
3068                             }
3069                             else rrdset_next(st);
3070
3071                             rrddim_set(st, "reads", (dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) ?
3072                                 (cur_dstat.duration_read_ms - prev_dstat.duration_read_ms) / (dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) : 0);
3073                             rrddim_set(st, "writes", (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write) ?
3074                                 (cur_dstat.duration_write_ms - prev_dstat.duration_write_ms) / (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write) : 0);
3075                             rrdset_done(st);
3076
3077                             // --------------------------------------------------------------------
3078
3079                             st = rrdset_find_bytype_localhost("disk_avgsz", disk);
3080                             if (unlikely(!st)) {
3081                                 st = rrdset_create_localhost("disk_avgsz", disk, NULL, disk, "disk.avgsz", "Average Completed I/O Operation Bandwidth", "kilobytes per operation", 2006, update_every, RRDSET_TYPE_AREA);
3082                                 rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
3083
3084                                 rrddim_add(st, "reads", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
3085                                 rrddim_add(st, "writes", NULL, -1, 1024, RRD_ALGORITHM_ABSOLUTE);
3086                             }
3087                             else rrdset_next(st);
3088
3089                             rrddim_set(st, "reads", (dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) ?
3090                                 (dstat[i].bytes[DEVSTAT_READ] - prev_dstat.bytes_read) / (dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) : 0);
3091                             rrddim_set(st, "writes", (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write) ?
3092                                 (dstat[i].bytes[DEVSTAT_WRITE] - prev_dstat.bytes_write) / (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write) : 0);
3093                             rrdset_done(st);
3094
3095                             // --------------------------------------------------------------------
3096
3097                             st = rrdset_find_bytype_localhost("disk_svctm", disk);
3098                             if (unlikely(!st)) {
3099                                 st = rrdset_create_localhost("disk_svctm", disk, NULL, disk, "disk.svctm", "Average Service Time", "ms per operation", 2007, update_every, RRDSET_TYPE_LINE);
3100                                 rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
3101
3102                                 rrddim_add(st, "svctm", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
3103                             }
3104                             else rrdset_next(st);
3105
3106                             rrddim_set(st, "svctm", ((dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) + (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write)) ?
3107                                 (cur_dstat.busy_time_ms - prev_dstat.busy_time_ms) / ((dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) + (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write)) : 0);
3108                             rrdset_done(st);
3109                         }
3110                     }
3111                 }
3112
3113                 // --------------------------------------------------------------------
3114
3115                 st = rrdset_find_bytype_localhost("system", "io");
3116                 if (unlikely(!st)) {
3117                     st = rrdset_create_localhost("system", "io", NULL, "disk", NULL, "Disk I/O", "kilobytes/s", 150, update_every, RRDSET_TYPE_AREA);
3118                     rrddim_add(st, "in",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
3119                     rrddim_add(st, "out", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
3120                 }
3121                 else rrdset_next(st);
3122
3123                 rrddim_set(st, "in", total_disk_kbytes_read);
3124                 rrddim_set(st, "out", total_disk_kbytes_write);
3125                 rrdset_done(st);
3126             }
3127         }
3128     }
3129
3130     // --------------------------------------------------------------------
3131
3132     if (likely(do_bandwidth)) {
3133         if (unlikely(getifaddrs(&ifap))) {
3134             error("FREEBSD: getifaddrs()");
3135             do_bandwidth = 0;
3136             error("DISABLED: system.ipv4");
3137         } else {
3138             iftot.ift_ibytes = iftot.ift_obytes = 0;
3139             for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
3140                 if (ifa->ifa_addr->sa_family != AF_INET)
3141                         continue;
3142                 iftot.ift_ibytes += IFA_DATA(ibytes);
3143                 iftot.ift_obytes += IFA_DATA(obytes);
3144             }
3145
3146             st = rrdset_find_localhost("system.ipv4");
3147             if (unlikely(!st)) {
3148                 st = rrdset_create_localhost("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA);
3149
3150                 rrddim_add(st, "InOctets", "received", 8, 1024, RRD_ALGORITHM_INCREMENTAL);
3151                 rrddim_add(st, "OutOctets", "sent", -8, 1024, RRD_ALGORITHM_INCREMENTAL);
3152             }
3153             else rrdset_next(st);
3154
3155             rrddim_set(st, "InOctets", iftot.ift_ibytes);
3156             rrddim_set(st, "OutOctets", iftot.ift_obytes);
3157             rrdset_done(st);
3158
3159             // --------------------------------------------------------------------
3160
3161             iftot.ift_ibytes = iftot.ift_obytes = 0;
3162             for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
3163                 if (ifa->ifa_addr->sa_family != AF_INET6)
3164                         continue;
3165                 iftot.ift_ibytes += IFA_DATA(ibytes);
3166                 iftot.ift_obytes += IFA_DATA(obytes);
3167             }
3168
3169             st = rrdset_find_localhost("system.ipv6");
3170             if (unlikely(!st)) {
3171                 st = rrdset_create_localhost("system", "ipv6", NULL, "network", NULL, "IPv6 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA);
3172
3173                 rrddim_add(st, "received", NULL, 8, 1024, RRD_ALGORITHM_INCREMENTAL);
3174                 rrddim_add(st, "sent", NULL, -8, 1024, RRD_ALGORITHM_INCREMENTAL);
3175             }
3176             else rrdset_next(st);
3177
3178             rrddim_set(st, "sent", iftot.ift_obytes);
3179             rrddim_set(st, "received", iftot.ift_ibytes);
3180             rrdset_done(st);
3181
3182             for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
3183                 if (ifa->ifa_addr->sa_family != AF_LINK)
3184                         continue;
3185
3186                 // --------------------------------------------------------------------
3187
3188                 st = rrdset_find_bytype_localhost("net", ifa->ifa_name);
3189                 if (unlikely(!st)) {
3190                     st = rrdset_create_localhost("net", ifa->ifa_name, NULL, ifa->ifa_name, "net.net", "Bandwidth", "kilobits/s", 7000, update_every, RRDSET_TYPE_AREA);
3191
3192                     rrddim_add(st, "received", NULL, 8, 1024, RRD_ALGORITHM_INCREMENTAL);
3193                     rrddim_add(st, "sent", NULL, -8, 1024, RRD_ALGORITHM_INCREMENTAL);
3194                 }
3195                 else rrdset_next(st);
3196
3197                 rrddim_set(st, "received", IFA_DATA(ibytes));
3198                 rrddim_set(st, "sent", IFA_DATA(obytes));
3199                 rrdset_done(st);
3200
3201                 // --------------------------------------------------------------------
3202
3203                 st = rrdset_find_bytype_localhost("net_packets", ifa->ifa_name);
3204                 if (unlikely(!st)) {
3205                     st = rrdset_create_localhost("net_packets", ifa->ifa_name, NULL, ifa->ifa_name, "net.packets", "Packets", "packets/s", 7001, update_every, RRDSET_TYPE_LINE);
3206                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
3207
3208                     rrddim_add(st, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
3209                     rrddim_add(st, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
3210                     rrddim_add(st, "multicast_received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
3211                     rrddim_add(st, "multicast_sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
3212                 }
3213                 else rrdset_next(st);
3214
3215                 rrddim_set(st, "received", IFA_DATA(ipackets));
3216                 rrddim_set(st, "sent", IFA_DATA(opackets));
3217                 rrddim_set(st, "multicast_received", IFA_DATA(imcasts));
3218                 rrddim_set(st, "multicast_sent", IFA_DATA(omcasts));
3219                 rrdset_done(st);
3220
3221                 // --------------------------------------------------------------------
3222
3223                 st = rrdset_find_bytype_localhost("net_errors", ifa->ifa_name);
3224                 if (unlikely(!st)) {
3225                     st = rrdset_create_localhost("net_errors", ifa->ifa_name, NULL, ifa->ifa_name, "net.errors", "Interface Errors", "errors/s", 7002, update_every, RRDSET_TYPE_LINE);
3226                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
3227
3228                     rrddim_add(st, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
3229                     rrddim_add(st, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
3230                 }
3231                 else rrdset_next(st);
3232
3233                 rrddim_set(st, "inbound", IFA_DATA(ierrors));
3234                 rrddim_set(st, "outbound", IFA_DATA(oerrors));
3235                 rrdset_done(st);
3236
3237                 // --------------------------------------------------------------------
3238
3239                 st = rrdset_find_bytype_localhost("net_drops", ifa->ifa_name);
3240                 if (unlikely(!st)) {
3241                     st = rrdset_create_localhost("net_drops", ifa->ifa_name, NULL, ifa->ifa_name, "net.drops", "Interface Drops", "drops/s", 7003, update_every, RRDSET_TYPE_LINE);
3242                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
3243
3244                     rrddim_add(st, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
3245 #if __FreeBSD__ >= 11
3246                     rrddim_add(st, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
3247 #endif
3248                 }
3249                 else rrdset_next(st);
3250
3251                 rrddim_set(st, "inbound", IFA_DATA(iqdrops));
3252 #if __FreeBSD__ >= 11
3253                 rrddim_set(st, "outbound", IFA_DATA(oqdrops));
3254 #endif
3255                 rrdset_done(st);
3256
3257                 // --------------------------------------------------------------------
3258
3259                 st = rrdset_find_bytype_localhost("net_events", ifa->ifa_name);
3260                 if (unlikely(!st)) {
3261                     st = rrdset_create_localhost("net_events", ifa->ifa_name, NULL, ifa->ifa_name, "net.events", "Network Interface Events", "events/s", 7006, update_every, RRDSET_TYPE_LINE);
3262                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
3263
3264                     rrddim_add(st, "frames", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
3265                     rrddim_add(st, "collisions", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
3266                     rrddim_add(st, "carrier", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
3267                 }
3268                 else rrdset_next(st);
3269
3270                 rrddim_set(st, "collisions", IFA_DATA(collisions));
3271                 rrdset_done(st);
3272             }
3273
3274             freeifaddrs(ifap);
3275         }
3276     }
3277
3278     return 0;
3279 }