]> arthur.barton.de Git - netdata.git/blob - src/freebsd_sysctl.c
Separate kern.devstat 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:net.isr", "netisr",          1);
1233         do_netisr_per_core = config_get_boolean("plugin:freebsd:net.isr", "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:net.inet.tcp.stats", "ipv4 TCP packets",          1);
1443         do_tcp_errors        = config_get_boolean("plugin:freebsd:net.inet.tcp.stats", "ipv4 TCP errors",           1);
1444         do_tcp_handshake     = config_get_boolean("plugin:freebsd:net.inet.tcp.stats", "ipv4 TCP handshake issues", 1);
1445         do_tcpext_connaborts = config_get_boolean_ondemand("plugin:freebsd:net.inet.tcp.stats", "TCP connection aborts",
1446                                                            CONFIG_BOOLEAN_AUTO);
1447         do_tcpext_ofo        = config_get_boolean_ondemand("plugin:freebsd:net.inet.tcp.stats", "TCP out-of-order queue",
1448                                                            CONFIG_BOOLEAN_AUTO);
1449         do_tcpext_syncookies = config_get_boolean_ondemand("plugin:freebsd:net.inet.tcp.stats", "TCP SYN cookies",
1450                                                            CONFIG_BOOLEAN_AUTO);
1451         do_ecn               = config_get_boolean_ondemand("plugin:freebsd:net.inet.tcp.stats", "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:net.inet.udp.stats", "ipv4 UDP packets", 1);
1737         do_udp_errors  = config_get_boolean("plugin:freebsd:net.inet.udp.stats", "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:net.inet.icmp.stats", "ipv4 ICMP packets",  1);
1837         do_icmp_errors  = config_get_boolean("plugin:freebsd:net.inet.icmp.stats", "ipv4 ICMP errors",   1);
1838         do_icmpmsg      = config_get_boolean("plugin:freebsd:net.inet.icmp.stats", "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:net.inet.ip.stats", "ipv4 packets", 1);
1962         do_ip_fragsout = config_get_boolean("plugin:freebsd:net.inet.ip.stats", "ipv4 fragments sent", 1);
1963         do_ip_fragsin  = config_get_boolean("plugin:freebsd:net.inet.ip.stats", "ipv4 fragments assembly", 1);
1964         do_ip_errors   = config_get_boolean("plugin:freebsd:net.inet.ip.stats", "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:net.inet6.ip6.stats", "ipv6 packets",
2144                                                       CONFIG_BOOLEAN_AUTO);
2145         do_ip6_fragsout = config_get_boolean_ondemand("plugin:freebsd:net.inet6.ip6.stats", "ipv6 fragments sent",
2146                                                       CONFIG_BOOLEAN_AUTO);
2147         do_ip6_fragsin  = config_get_boolean_ondemand("plugin:freebsd:net.inet6.ip6.stats", "ipv6 fragments assembly",
2148                                                       CONFIG_BOOLEAN_AUTO);
2149         do_ip6_errors   = config_get_boolean_ondemand("plugin:freebsd:net.inet6.ip6.stats", "ipv6 errors",
2150                                                       CONFIG_BOOLEAN_AUTO);
2151     }
2152
2153     if (likely(do_ip6_packets || do_ip6_fragsout || do_ip6_fragsin || do_ip6_errors)) {
2154         static int mib[4] = {0, 0, 0, 0};
2155         struct ip6stat ip6stat;
2156
2157         if (unlikely(GETSYSCTL_SIMPLE("net.inet6.ip6.stats", mib, ip6stat))) {
2158             do_ip6_packets = 0;
2159             error("DISABLED: ipv6.packets chart");
2160             do_ip6_fragsout = 0;
2161             error("DISABLED: ipv6.fragsout chart");
2162             do_ip6_fragsin = 0;
2163             error("DISABLED: ipv6.fragsin chart");
2164             do_ip6_errors = 0;
2165             error("DISABLED: ipv6.errors chart");
2166             error("DISABLED: net.inet6.ip6.stats module");
2167             return 1;
2168         } else {
2169
2170             // --------------------------------------------------------------------
2171
2172             if (do_ip6_packets == CONFIG_BOOLEAN_YES || (do_ip6_packets == CONFIG_BOOLEAN_AUTO &&
2173                                                          (ip6stat.ip6s_localout || ip6stat.ip6s_total ||
2174                                                           ip6stat.ip6s_forward || ip6stat.ip6s_delivered))) {
2175                 do_ip6_packets = CONFIG_BOOLEAN_YES;
2176
2177                 static RRDSET *st = NULL;
2178                 static RRDDIM *rd_received = NULL, *rd_sent = NULL, *rd_forwarded = NULL, *rd_delivers = NULL;
2179
2180                 if (unlikely(!st)) {
2181                     st = rrdset_create_localhost("ipv6",
2182                                                  "packets",
2183                                                  NULL,
2184                                                  "packets",
2185                                                  NULL,
2186                                                  "IPv6 Packets",
2187                                                  "packets/s",
2188                                                  3000,
2189                                                  update_every,
2190                                                  RRDSET_TYPE_LINE
2191                     );
2192
2193                     rd_received  = rrddim_add(st, "received",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2194                     rd_sent      = rrddim_add(st, "sent",      NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2195                     rd_forwarded = rrddim_add(st, "forwarded", NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2196                     rd_delivers  = rrddim_add(st, "delivers",  NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2197                 } else
2198                     rrdset_next(st);
2199
2200                 rrddim_set_by_pointer(st, rd_sent,      ip6stat.ip6s_localout);
2201                 rrddim_set_by_pointer(st, rd_received,  ip6stat.ip6s_total);
2202                 rrddim_set_by_pointer(st, rd_forwarded, ip6stat.ip6s_forward);
2203                 rrddim_set_by_pointer(st, rd_delivers,  ip6stat.ip6s_delivered);
2204                 rrdset_done(st);
2205             }
2206
2207             // --------------------------------------------------------------------
2208
2209             if (do_ip6_fragsout == CONFIG_BOOLEAN_YES || (do_ip6_fragsout == CONFIG_BOOLEAN_AUTO &&
2210                                                           (ip6stat.ip6s_fragmented || ip6stat.ip6s_cantfrag ||
2211                                                            ip6stat.ip6s_ofragments))) {
2212                 do_ip6_fragsout = CONFIG_BOOLEAN_YES;
2213
2214                 static RRDSET *st = NULL;
2215                 static RRDDIM *rd_ok = NULL, *rd_failed = NULL, *rd_all = NULL;
2216
2217                 if (unlikely(!st)) {
2218                     st = rrdset_create_localhost("ipv6",
2219                                                  "fragsout",
2220                                                  NULL,
2221                                                  "fragments",
2222                                                  NULL,
2223                                                  "IPv6 Fragments Sent",
2224                                                  "packets/s",
2225                                                  3010,
2226                                                  update_every,
2227                                                  RRDSET_TYPE_LINE
2228                     );
2229
2230                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
2231
2232                     rd_ok     = rrddim_add(st, "ok",     NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2233                     rd_failed = rrddim_add(st, "failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2234                     rd_all    = rrddim_add(st, "all",    NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2235                 } else
2236                     rrdset_next(st);
2237
2238                 rrddim_set_by_pointer(st, rd_ok,     ip6stat.ip6s_fragmented);
2239                 rrddim_set_by_pointer(st, rd_failed, ip6stat.ip6s_cantfrag);
2240                 rrddim_set_by_pointer(st, rd_all,    ip6stat.ip6s_ofragments);
2241                 rrdset_done(st);
2242             }
2243
2244             // --------------------------------------------------------------------
2245
2246             if (do_ip6_fragsin == CONFIG_BOOLEAN_YES || (do_ip6_fragsin == CONFIG_BOOLEAN_AUTO &&
2247                                                          (ip6stat.ip6s_reassembled || ip6stat.ip6s_fragdropped ||
2248                                                           ip6stat.ip6s_fragtimeout || ip6stat.ip6s_fragments))) {
2249                 do_ip6_fragsin = CONFIG_BOOLEAN_YES;
2250
2251                 static RRDSET *st = NULL;
2252                 static RRDDIM *rd_ok = NULL, *rd_failed = NULL, *rd_timeout = NULL, *rd_all = NULL;
2253
2254                 if (unlikely(!st)) {
2255                     st = rrdset_create_localhost("ipv6",
2256                                                  "fragsin",
2257                                                  NULL,
2258                                                  "fragments",
2259                                                  NULL,
2260                                                  "IPv6 Fragments Reassembly",
2261                                                  "packets/s",
2262                                                  3011,
2263                                                  update_every,
2264                                                  RRDSET_TYPE_LINE
2265                     );
2266
2267                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
2268
2269                     rd_ok      = rrddim_add(st, "ok",      NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2270                     rd_failed  = rrddim_add(st, "failed",  NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2271                     rd_timeout = rrddim_add(st, "timeout", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2272                     rd_all     = rrddim_add(st, "all",     NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2273                 } else
2274                     rrdset_next(st);
2275
2276                 rrddim_set_by_pointer(st, rd_ok,      ip6stat.ip6s_reassembled);
2277                 rrddim_set_by_pointer(st, rd_failed,  ip6stat.ip6s_fragdropped);
2278                 rrddim_set_by_pointer(st, rd_timeout, ip6stat.ip6s_fragtimeout);
2279                 rrddim_set_by_pointer(st, rd_all,     ip6stat.ip6s_fragments);
2280                 rrdset_done(st);
2281             }
2282
2283             // --------------------------------------------------------------------
2284
2285             if (do_ip6_errors == CONFIG_BOOLEAN_YES || (do_ip6_errors == CONFIG_BOOLEAN_AUTO && (
2286                     ip6stat.ip6s_toosmall ||
2287                     ip6stat.ip6s_odropped ||
2288                     ip6stat.ip6s_badoptions ||
2289                     ip6stat.ip6s_badvers ||
2290                     ip6stat.ip6s_exthdrtoolong ||
2291                     ip6stat.ip6s_sources_none ||
2292                     ip6stat.ip6s_tooshort ||
2293                     ip6stat.ip6s_cantforward ||
2294                     ip6stat.ip6s_noroute))) {
2295                 do_ip6_errors = CONFIG_BOOLEAN_YES;
2296
2297                 static RRDSET *st = NULL;
2298                 static RRDDIM *rd_in_discards = NULL, *rd_out_discards = NULL,
2299                               *rd_in_hdr_errors = NULL, *rd_in_addr_errors = NULL, *rd_in_truncated_pkts = NULL,
2300                               *rd_in_no_routes = NULL, *rd_out_no_routes = NULL;
2301
2302                 if (unlikely(!st)) {
2303                     st = rrdset_create_localhost("ipv6",
2304                                                  "errors",
2305                                                  NULL,
2306                                                  "errors",
2307                                                  NULL,
2308                                                  "IPv6 Errors",
2309                                                  "packets/s",
2310                                                  3002,
2311                                                  update_every,
2312                                                  RRDSET_TYPE_LINE
2313                     );
2314
2315                     rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
2316
2317                     rd_in_discards       = rrddim_add(st, "InDiscards",      NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2318                     rd_out_discards      = rrddim_add(st, "OutDiscards",     NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2319                     rd_in_hdr_errors     = rrddim_add(st, "InHdrErrors",     NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2320                     rd_in_addr_errors    = rrddim_add(st, "InAddrErrors",    NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2321                     rd_in_truncated_pkts = rrddim_add(st, "InTruncatedPkts", NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2322                     rd_in_no_routes      = rrddim_add(st, "InNoRoutes",      NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2323                     rd_out_no_routes     = rrddim_add(st, "OutNoRoutes",     NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2324                 } else
2325                     rrdset_next(st);
2326
2327                 rrddim_set_by_pointer(st, rd_in_discards,       ip6stat.ip6s_toosmall);
2328                 rrddim_set_by_pointer(st, rd_out_discards,      ip6stat.ip6s_odropped);
2329                 rrddim_set_by_pointer(st, rd_in_hdr_errors,     ip6stat.ip6s_badoptions + ip6stat.ip6s_badvers +
2330                                                                 ip6stat.ip6s_exthdrtoolong);
2331                 rrddim_set_by_pointer(st, rd_in_addr_errors,    ip6stat.ip6s_sources_none);
2332                 rrddim_set_by_pointer(st, rd_in_truncated_pkts, ip6stat.ip6s_tooshort);
2333                 rrddim_set_by_pointer(st, rd_in_no_routes,      ip6stat.ip6s_cantforward);
2334                 rrddim_set_by_pointer(st, rd_out_no_routes,     ip6stat.ip6s_noroute);
2335                 rrdset_done(st);
2336             }
2337         }
2338     } else {
2339         error("DISABLED: net.inet6.ip6.stats module");
2340         return 1;
2341     }
2342
2343     return 0;
2344 }
2345
2346 // --------------------------------------------------------------------------------------------------------------------
2347 // net.inet6.icmp6.stats
2348
2349 int do_net_inet6_icmp6_stats(int update_every, usec_t dt) {
2350     static int do_icmp6 = -1, do_icmp6_redir = -1, do_icmp6_errors = -1, do_icmp6_echos = -1, do_icmp6_router = -1,
2351             do_icmp6_neighbor = -1, do_icmp6_types = -1;
2352
2353     if (unlikely(do_icmp6 == -1)) {
2354         do_icmp6          = config_get_boolean_ondemand("plugin:freebsd:net.inet6.icmp6.stats", "icmp",
2355                                                         CONFIG_BOOLEAN_AUTO);
2356         do_icmp6_redir    = config_get_boolean_ondemand("plugin:freebsd:net.inet6.icmp6.stats", "icmp redirects",
2357                                                         CONFIG_BOOLEAN_AUTO);
2358         do_icmp6_errors   = config_get_boolean_ondemand("plugin:freebsd:net.inet6.icmp6.stats", "icmp errors",
2359                                                         CONFIG_BOOLEAN_AUTO);
2360         do_icmp6_echos    = config_get_boolean_ondemand("plugin:freebsd:net.inet6.icmp6.stats", "icmp echos",
2361                                                         CONFIG_BOOLEAN_AUTO);
2362         do_icmp6_router   = config_get_boolean_ondemand("plugin:freebsd:net.inet6.icmp6.stats", "icmp router",
2363                                                         CONFIG_BOOLEAN_AUTO);
2364         do_icmp6_neighbor = config_get_boolean_ondemand("plugin:freebsd:net.inet6.icmp6.stats", "icmp neighbor",
2365                                                         CONFIG_BOOLEAN_AUTO);
2366         do_icmp6_types    = config_get_boolean_ondemand("plugin:freebsd:net.inet6.icmp6.stats", "icmp types",
2367                                                         CONFIG_BOOLEAN_AUTO);
2368     }
2369
2370     if (likely(do_icmp6 || do_icmp6_redir || do_icmp6_errors || do_icmp6_echos || do_icmp6_router || do_icmp6_neighbor || do_icmp6_types)) {
2371         static int mib[4] = {0, 0, 0, 0};
2372         struct icmp6stat icmp6stat;
2373
2374         if (unlikely(GETSYSCTL_SIMPLE("net.inet6.icmp6.stats", mib, icmp6stat))) {
2375             do_icmp6 = 0;
2376             error("DISABLED: ipv6.icmp chart");
2377             do_icmp6_redir = 0;
2378             error("DISABLED: ipv6.icmpredir chart");
2379             do_icmp6_errors = 0;
2380             error("DISABLED: ipv6.icmperrors chart");
2381             do_icmp6_echos = 0;
2382             error("DISABLED: ipv6.icmpechos chart");
2383             do_icmp6_router = 0;
2384             error("DISABLED: ipv6.icmprouter chart");
2385             do_icmp6_neighbor = 0;
2386             error("DISABLED: ipv6.icmpneighbor chart");
2387             do_icmp6_types = 0;
2388             error("DISABLED: ipv6.icmptypes chart");
2389             error("DISABLED: net.inet6.icmp6.stats module");
2390             return 1;
2391         } else {
2392             int i;
2393             struct icmp6_total {
2394                 u_long  msgs_in;
2395                 u_long  msgs_out;
2396             } icmp6_total = {0, 0};
2397
2398             for (i = 0; i <= ICMP6_MAXTYPE; i++) {
2399                 icmp6_total.msgs_in += icmp6stat.icp6s_inhist[i];
2400                 icmp6_total.msgs_out += icmp6stat.icp6s_outhist[i];
2401             }
2402             icmp6_total.msgs_in += icmp6stat.icp6s_badcode + icmp6stat.icp6s_badlen + icmp6stat.icp6s_checksum + icmp6stat.icp6s_tooshort;
2403
2404             // --------------------------------------------------------------------
2405
2406             if (do_icmp6 == CONFIG_BOOLEAN_YES || (do_icmp6 == CONFIG_BOOLEAN_AUTO && (icmp6_total.msgs_in || icmp6_total.msgs_out))) {
2407                 do_icmp6 = CONFIG_BOOLEAN_YES;
2408
2409                 static RRDSET *st = NULL;
2410                 static RRDDIM *rd_received = NULL, *rd_sent = NULL;
2411
2412                 if (unlikely(!st)) {
2413                     st = rrdset_create_localhost("ipv6",
2414                                                  "icmp",
2415                                                  NULL,
2416                                                  "icmp",
2417                                                  NULL,
2418                                                  "IPv6 ICMP Messages",
2419                                                  "messages/s",
2420                                                  10000,
2421                                                  update_every,
2422                                                  RRDSET_TYPE_LINE
2423                     );
2424
2425                     rd_received = rrddim_add(st, "received", NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2426                     rd_sent     = rrddim_add(st, "sent",     NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2427                 } else
2428                     rrdset_next(st);
2429
2430                 rrddim_set_by_pointer(st, rd_received, icmp6_total.msgs_out);
2431                 rrddim_set_by_pointer(st, rd_sent,     icmp6_total.msgs_in);
2432
2433                 rrdset_done(st);
2434             }
2435
2436             // --------------------------------------------------------------------
2437
2438             if (do_icmp6_redir == CONFIG_BOOLEAN_YES || (do_icmp6_redir == CONFIG_BOOLEAN_AUTO && (icmp6stat.icp6s_inhist[ND_REDIRECT] || icmp6stat.icp6s_outhist[ND_REDIRECT]))) {
2439                 do_icmp6_redir = CONFIG_BOOLEAN_YES;
2440
2441                 static RRDSET *st = NULL;
2442                 static RRDDIM *rd_received = NULL, *rd_sent = NULL;
2443
2444                 if (unlikely(!st)) {
2445                     st = rrdset_create_localhost("ipv6",
2446                                                  "icmpredir",
2447                                                  NULL,
2448                                                  "icmp",
2449                                                  NULL,
2450                                                  "IPv6 ICMP Redirects",
2451                                                  "redirects/s",
2452                                                  10050,
2453                                                  update_every,
2454                                                  RRDSET_TYPE_LINE
2455                     );
2456
2457                     rd_received = rrddim_add(st, "received", NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2458                     rd_sent     = rrddim_add(st, "sent",     NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2459                 } else
2460                     rrdset_next(st);
2461
2462                 rrddim_set_by_pointer(st, rd_received, icmp6stat.icp6s_outhist[ND_REDIRECT]);
2463                 rrddim_set_by_pointer(st, rd_sent, icmp6stat.icp6s_inhist[ND_REDIRECT]);
2464                 rrdset_done(st);
2465             }
2466
2467             // --------------------------------------------------------------------
2468
2469             if (do_icmp6_errors == CONFIG_BOOLEAN_YES || (do_icmp6_errors == CONFIG_BOOLEAN_AUTO && (
2470                     icmp6stat.icp6s_badcode ||
2471                     icmp6stat.icp6s_badlen ||
2472                     icmp6stat.icp6s_checksum ||
2473                     icmp6stat.icp6s_tooshort ||
2474                     icmp6stat.icp6s_error ||
2475                     icmp6stat.icp6s_inhist[ICMP6_DST_UNREACH] ||
2476                     icmp6stat.icp6s_inhist[ICMP6_TIME_EXCEEDED] ||
2477                     icmp6stat.icp6s_inhist[ICMP6_PARAM_PROB] ||
2478                     icmp6stat.icp6s_outhist[ICMP6_DST_UNREACH] ||
2479                     icmp6stat.icp6s_outhist[ICMP6_TIME_EXCEEDED] ||
2480                     icmp6stat.icp6s_outhist[ICMP6_PARAM_PROB]))) {
2481                 do_icmp6_errors = CONFIG_BOOLEAN_YES;
2482
2483                 static RRDSET *st = NULL;
2484                 static RRDDIM *rd_in_errors = NULL, *rd_out_errors = NULL, *rd_in_csum_errors = NULL,
2485                               *rd_in_dest_unreachs = NULL, *rd_in_pkt_too_bigs = NULL, *rd_in_time_excds = NULL,
2486                               *rd_in_parm_problems = NULL, *rd_out_dest_unreachs = NULL, *rd_out_time_excds = NULL,
2487                               *rd_out_parm_problems = NULL;
2488
2489                 if (unlikely(!st)) {
2490                     st = rrdset_create_localhost("ipv6",
2491                                                  "icmperrors",
2492                                                  NULL, "icmp",
2493                                                  NULL,
2494                                                  "IPv6 ICMP Errors",
2495                                                  "errors/s",
2496                                                  10100,
2497                                                  update_every,
2498                                                  RRDSET_TYPE_LINE
2499                     );
2500
2501                     rd_in_errors         = rrddim_add(st, "InErrors",        NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2502                     rd_out_errors        = rrddim_add(st, "OutErrors",       NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2503                     rd_in_csum_errors    = rrddim_add(st, "InCsumErrors",    NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2504                     rd_in_dest_unreachs  = rrddim_add(st, "InDestUnreachs",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2505                     rd_in_pkt_too_bigs   = rrddim_add(st, "InPktTooBigs",    NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2506                     rd_in_time_excds     = rrddim_add(st, "InTimeExcds",     NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2507                     rd_in_parm_problems  = rrddim_add(st, "InParmProblems",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2508                     rd_out_dest_unreachs = rrddim_add(st, "OutDestUnreachs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2509                     rd_out_time_excds    = rrddim_add(st, "OutTimeExcds",    NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2510                     rd_out_parm_problems = rrddim_add(st, "OutParmProblems", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2511                 } else
2512                     rrdset_next(st);
2513
2514                 rrddim_set_by_pointer(st, rd_in_errors,         icmp6stat.icp6s_badcode + icmp6stat.icp6s_badlen +
2515                                                                 icmp6stat.icp6s_checksum + icmp6stat.icp6s_tooshort);
2516                 rrddim_set_by_pointer(st, rd_out_errors,        icmp6stat.icp6s_error);
2517                 rrddim_set_by_pointer(st, rd_in_csum_errors,    icmp6stat.icp6s_checksum);
2518                 rrddim_set_by_pointer(st, rd_in_dest_unreachs,  icmp6stat.icp6s_inhist[ICMP6_DST_UNREACH]);
2519                 rrddim_set_by_pointer(st, rd_in_pkt_too_bigs,   icmp6stat.icp6s_badlen);
2520                 rrddim_set_by_pointer(st, rd_in_time_excds,     icmp6stat.icp6s_inhist[ICMP6_TIME_EXCEEDED]);
2521                 rrddim_set_by_pointer(st, rd_in_parm_problems,  icmp6stat.icp6s_inhist[ICMP6_PARAM_PROB]);
2522                 rrddim_set_by_pointer(st, rd_out_dest_unreachs, icmp6stat.icp6s_outhist[ICMP6_DST_UNREACH]);
2523                 rrddim_set_by_pointer(st, rd_out_time_excds,    icmp6stat.icp6s_outhist[ICMP6_TIME_EXCEEDED]);
2524                 rrddim_set_by_pointer(st, rd_out_parm_problems, icmp6stat.icp6s_outhist[ICMP6_PARAM_PROB]);
2525                 rrdset_done(st);
2526             }
2527
2528             // --------------------------------------------------------------------
2529
2530             if (do_icmp6_echos == CONFIG_BOOLEAN_YES || (do_icmp6_echos == CONFIG_BOOLEAN_AUTO && (
2531                     icmp6stat.icp6s_inhist[ICMP6_ECHO_REQUEST] ||
2532                     icmp6stat.icp6s_outhist[ICMP6_ECHO_REQUEST] ||
2533                     icmp6stat.icp6s_inhist[ICMP6_ECHO_REPLY] ||
2534                     icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]))) {
2535                 do_icmp6_echos = CONFIG_BOOLEAN_YES;
2536
2537                 static RRDSET *st = NULL;
2538                 static RRDDIM *rd_in = NULL, *rd_out = NULL, *rd_in_replies = NULL, *rd_out_replies = NULL;
2539
2540                 if (unlikely(!st)) {
2541                     st = rrdset_create_localhost("ipv6",
2542                                                  "icmpechos",
2543                                                  NULL,
2544                                                  "icmp",
2545                                                  NULL,
2546                                                  "IPv6 ICMP Echo",
2547                                                  "messages/s",
2548                                                  10200,
2549                                                  update_every,
2550                                                  RRDSET_TYPE_LINE
2551                     );
2552
2553                     rd_in          = rrddim_add(st, "InEchos",        NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2554                     rd_out         = rrddim_add(st, "OutEchos",       NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2555                     rd_in_replies  = rrddim_add(st, "InEchoReplies",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2556                     rd_out_replies = rrddim_add(st, "OutEchoReplies", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2557                 } else
2558                     rrdset_next(st);
2559
2560                 rrddim_set_by_pointer(st, rd_in,          icmp6stat.icp6s_inhist[ICMP6_ECHO_REQUEST]);
2561                 rrddim_set_by_pointer(st, rd_out,         icmp6stat.icp6s_outhist[ICMP6_ECHO_REQUEST]);
2562                 rrddim_set_by_pointer(st, rd_in_replies,  icmp6stat.icp6s_inhist[ICMP6_ECHO_REPLY]);
2563                 rrddim_set_by_pointer(st, rd_out_replies, icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]);
2564                 rrdset_done(st);
2565             }
2566
2567             // --------------------------------------------------------------------
2568
2569             if (do_icmp6_router == CONFIG_BOOLEAN_YES || (do_icmp6_router == CONFIG_BOOLEAN_AUTO && (
2570                     icmp6stat.icp6s_inhist[ND_ROUTER_SOLICIT] ||
2571                     icmp6stat.icp6s_outhist[ND_ROUTER_SOLICIT] ||
2572                     icmp6stat.icp6s_inhist[ND_ROUTER_ADVERT] ||
2573                     icmp6stat.icp6s_outhist[ND_ROUTER_ADVERT]))) {
2574                 do_icmp6_router = CONFIG_BOOLEAN_YES;
2575
2576                 static RRDSET *st = NULL;
2577                 static RRDDIM *rd_in_solicits = NULL, *rd_out_solicits = NULL,
2578                               *rd_in_advertisements = NULL, *rd_out_advertisements = NULL;
2579
2580                 if (unlikely(!st)) {
2581                     st = rrdset_create_localhost("ipv6",
2582                                                  "icmprouter",
2583                                                  NULL,
2584                                                  "icmp",
2585                                                  NULL,
2586                                                  "IPv6 Router Messages",
2587                                                  "messages/s",
2588                                                  10400,
2589                                                  update_every,
2590                                                  RRDSET_TYPE_LINE
2591                     );
2592
2593                     rd_in_solicits        = rrddim_add(st, "InSolicits",        NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2594                     rd_out_solicits       = rrddim_add(st, "OutSolicits",       NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2595                     rd_in_advertisements  = rrddim_add(st, "InAdvertisements",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2596                     rd_out_advertisements = rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2597                 } else
2598                     rrdset_next(st);
2599
2600                 rrddim_set_by_pointer(st, rd_in_solicits,        icmp6stat.icp6s_inhist[ND_ROUTER_SOLICIT]);
2601                 rrddim_set_by_pointer(st, rd_out_solicits,       icmp6stat.icp6s_outhist[ND_ROUTER_SOLICIT]);
2602                 rrddim_set_by_pointer(st, rd_in_advertisements,  icmp6stat.icp6s_inhist[ND_ROUTER_ADVERT]);
2603                 rrddim_set_by_pointer(st, rd_out_advertisements, icmp6stat.icp6s_outhist[ND_ROUTER_ADVERT]);
2604                 rrdset_done(st);
2605             }
2606
2607             // --------------------------------------------------------------------
2608
2609             if (do_icmp6_neighbor == CONFIG_BOOLEAN_YES || (do_icmp6_neighbor == CONFIG_BOOLEAN_AUTO && (
2610                     icmp6stat.icp6s_inhist[ND_NEIGHBOR_SOLICIT] ||
2611                     icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT] ||
2612                     icmp6stat.icp6s_inhist[ND_NEIGHBOR_ADVERT] ||
2613                     icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]))) {
2614                 do_icmp6_neighbor = CONFIG_BOOLEAN_YES;
2615
2616                 static RRDSET *st = NULL;
2617                 static RRDDIM *rd_in_solicits = NULL, *rd_out_solicits = NULL,
2618                               *rd_in_advertisements = NULL, *rd_out_advertisements = NULL;
2619
2620                 if (unlikely(!st)) {
2621                     st = rrdset_create_localhost("ipv6",
2622                                                  "icmpneighbor",
2623                                                  NULL,
2624                                                  "icmp",
2625                                                  NULL,
2626                                                  "IPv6 Neighbor Messages",
2627                                                  "messages/s",
2628                                                  10500,
2629                                                  update_every,
2630                                                  RRDSET_TYPE_LINE
2631                     );
2632
2633                     rd_in_solicits        = rrddim_add(st, "InSolicits",        NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2634                     rd_out_solicits       = rrddim_add(st, "OutSolicits",       NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2635                     rd_in_advertisements  = rrddim_add(st, "InAdvertisements",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2636                     rd_out_advertisements = rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2637                 } else
2638                     rrdset_next(st);
2639
2640                 rrddim_set_by_pointer(st, rd_in_solicits,        icmp6stat.icp6s_inhist[ND_NEIGHBOR_SOLICIT]);
2641                 rrddim_set_by_pointer(st, rd_out_solicits,       icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT]);
2642                 rrddim_set_by_pointer(st, rd_in_advertisements,  icmp6stat.icp6s_inhist[ND_NEIGHBOR_ADVERT]);
2643                 rrddim_set_by_pointer(st, rd_out_advertisements, icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]);
2644                 rrdset_done(st);
2645             }
2646
2647             // --------------------------------------------------------------------
2648
2649             if (do_icmp6_types == CONFIG_BOOLEAN_YES || (do_icmp6_types == CONFIG_BOOLEAN_AUTO && (
2650                     icmp6stat.icp6s_inhist[1] ||
2651                     icmp6stat.icp6s_inhist[128] ||
2652                     icmp6stat.icp6s_inhist[129] ||
2653                     icmp6stat.icp6s_inhist[136] ||
2654                     icmp6stat.icp6s_outhist[1] ||
2655                     icmp6stat.icp6s_outhist[128] ||
2656                     icmp6stat.icp6s_outhist[129] ||
2657                     icmp6stat.icp6s_outhist[133] ||
2658                     icmp6stat.icp6s_outhist[135] ||
2659                     icmp6stat.icp6s_outhist[136]))) {
2660                 do_icmp6_types = CONFIG_BOOLEAN_YES;
2661
2662                 static RRDSET *st = NULL;
2663                 static RRDDIM *rd_in_1 = NULL, *rd_in_128 = NULL, *rd_in_129 = NULL, *rd_in_136 = NULL,
2664                               *rd_out_1 = NULL, *rd_out_128 = NULL, *rd_out_129 = NULL, *rd_out_133 = NULL,
2665                               *rd_out_135 = NULL, *rd_out_143 = NULL;
2666
2667                 if (unlikely(!st)) {
2668                     st = rrdset_create_localhost("ipv6",
2669                                                  "icmptypes",
2670                                                  NULL,
2671                                                  "icmp",
2672                                                  NULL,
2673                                                  "IPv6 ICMP Types",
2674                                                  "messages/s",
2675                                                  10700,
2676                                                  update_every,
2677                                                  RRDSET_TYPE_LINE
2678                     );
2679
2680                     rd_in_1    = rrddim_add(st, "InType1",    NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2681                     rd_in_128  = rrddim_add(st, "InType128",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2682                     rd_in_129  = rrddim_add(st, "InType129",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2683                     rd_in_136  = rrddim_add(st, "InType136",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
2684                     rd_out_1   = rrddim_add(st, "OutType1",   NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2685                     rd_out_128 = rrddim_add(st, "OutType128", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2686                     rd_out_129 = rrddim_add(st, "OutType129", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2687                     rd_out_133 = rrddim_add(st, "OutType133", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2688                     rd_out_135 = rrddim_add(st, "OutType135", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2689                     rd_out_143 = rrddim_add(st, "OutType143", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
2690                 } else
2691                     rrdset_next(st);
2692
2693                 rrddim_set_by_pointer(st, rd_in_1,    icmp6stat.icp6s_inhist[1]);
2694                 rrddim_set_by_pointer(st, rd_in_128,  icmp6stat.icp6s_inhist[128]);
2695                 rrddim_set_by_pointer(st, rd_in_129,  icmp6stat.icp6s_inhist[129]);
2696                 rrddim_set_by_pointer(st, rd_in_136,  icmp6stat.icp6s_inhist[136]);
2697                 rrddim_set_by_pointer(st, rd_out_1,   icmp6stat.icp6s_outhist[1]);
2698                 rrddim_set_by_pointer(st, rd_out_128, icmp6stat.icp6s_outhist[128]);
2699                 rrddim_set_by_pointer(st, rd_out_129, icmp6stat.icp6s_outhist[129]);
2700                 rrddim_set_by_pointer(st, rd_out_133, icmp6stat.icp6s_outhist[133]);
2701                 rrddim_set_by_pointer(st, rd_out_135, icmp6stat.icp6s_outhist[135]);
2702                 rrddim_set_by_pointer(st, rd_out_143, icmp6stat.icp6s_outhist[143]);
2703                 rrdset_done(st);
2704             }
2705         }
2706     } else {
2707         error("DISABLED: net.inet6.icmp6.stats module");
2708         return 1;
2709     }
2710
2711     return 0;
2712 }
2713
2714 // --------------------------------------------------------------------------------------------------------------------
2715 // getmntinfo
2716
2717 int do_getmntinfo(int update_every, usec_t dt) {
2718
2719 #define DELAULT_EXLUDED_PATHS "/proc/*"
2720 // taken from gnulib/mountlist.c and shortened to FreeBSD related fstypes
2721 #define DEFAULT_EXCLUDED_FILESYSTEMS "autofs procfs subfs devfs none"
2722 #define CONFIG_SECTION_GETMNTINFO "plugin:freebsd:getmntinfo"
2723
2724     static int do_space = -1, do_inodes = -1;
2725
2726     if (unlikely(do_space == -1)) {
2727         do_space  = config_get_boolean_ondemand(CONFIG_SECTION_GETMNTINFO, "space usage for all disks",  CONFIG_BOOLEAN_AUTO);
2728         do_inodes = config_get_boolean_ondemand(CONFIG_SECTION_GETMNTINFO, "inodes usage for all disks", CONFIG_BOOLEAN_AUTO);
2729     }
2730
2731     if (likely(do_space || do_inodes)) {
2732         struct statfs *mntbuf;
2733         int mntsize;
2734
2735         // there is no mount info in sysctl MIBs
2736         if (unlikely(!(mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)))) {
2737             error("FREEBSD: getmntinfo() failed");
2738             do_space = 0;
2739             error("DISABLED: disk_space.* charts");
2740             do_inodes = 0;
2741             error("DISABLED: disk_inodes.* charts");
2742             error("DISABLED: getmntinfo module");
2743             return 1;
2744         } else {
2745             // Data to be stored in DICTIONARY mount_points.
2746             // This DICTIONARY is used to lookup the settings of the mount point on each iteration.
2747             struct mount_point_metadata {
2748                 int do_space;
2749                 int do_inodes;
2750
2751                 size_t collected; // the number of times this has been collected
2752
2753                 // charts and dimensions
2754
2755                 RRDSET *st_space;
2756                 RRDDIM *rd_space_used;
2757                 RRDDIM *rd_space_avail;
2758                 RRDDIM *rd_space_reserved;
2759
2760                 RRDSET *st_inodes;
2761                 RRDDIM *rd_inodes_used;
2762                 RRDDIM *rd_inodes_avail;
2763             };
2764             static DICTIONARY *mount_points = NULL;
2765             static SIMPLE_PATTERN *excluded_mountpoints = NULL;
2766             static SIMPLE_PATTERN *excluded_filesystems = NULL;
2767             int i;
2768
2769             if(unlikely(!mount_points)) {
2770
2771                 excluded_mountpoints = simple_pattern_create(
2772                         config_get(CONFIG_SECTION_GETMNTINFO, "exclude space metrics on paths",
2773                                    DELAULT_EXLUDED_PATHS),
2774                         SIMPLE_PATTERN_EXACT
2775                 );
2776
2777                 excluded_filesystems = simple_pattern_create(
2778                         config_get(CONFIG_SECTION_GETMNTINFO, "exclude space metrics on filesystems",
2779                                    DEFAULT_EXCLUDED_FILESYSTEMS),
2780                         SIMPLE_PATTERN_EXACT
2781                 );
2782
2783                 mount_points = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED);
2784             }
2785
2786             for (i = 0; i < mntsize; i++) {
2787
2788                 char title[4096 + 1];
2789                 int def_space, def_inodes, iter_space, iter_inodes;
2790
2791                 struct mount_point_metadata *m = dictionary_get(mount_points, mntbuf[i].f_mntonname);
2792                 if(unlikely(!m)) {
2793                     char var_name[4096 + 1];
2794                     snprintfz(var_name, 4096, "%s:%s", CONFIG_SECTION_GETMNTINFO, mntbuf[i].f_mntonname);
2795
2796                     def_space = do_space;
2797                     def_inodes = do_space;
2798
2799                     if(unlikely(simple_pattern_matches(excluded_mountpoints, mntbuf[i].f_mntonname))) {
2800                         def_space = CONFIG_BOOLEAN_NO;
2801                         def_inodes = CONFIG_BOOLEAN_NO;
2802                     }
2803
2804                     if(unlikely(simple_pattern_matches(excluded_filesystems, mntbuf[i].f_fstypename))) {
2805                         def_space = CONFIG_BOOLEAN_NO;
2806                         def_inodes = CONFIG_BOOLEAN_NO;
2807                     }
2808
2809                     iter_space  = config_get_boolean_ondemand(var_name, "space usage",  def_space);
2810                     iter_inodes = config_get_boolean_ondemand(var_name, "inodes usage", def_inodes);
2811
2812                     struct mount_point_metadata mp = {
2813                             .do_space = iter_space,
2814                             .do_inodes = iter_inodes,
2815
2816                             .collected = 0,
2817
2818                             .st_space = NULL,
2819                             .rd_space_avail = NULL,
2820                             .rd_space_used = NULL,
2821                             .rd_space_reserved = NULL,
2822
2823                             .st_inodes = NULL,
2824                             .rd_inodes_avail = NULL,
2825                             .rd_inodes_used = NULL,
2826                     };
2827
2828                     m = dictionary_set(mount_points, mntbuf[i].f_mntonname, &mp, sizeof(struct mount_point_metadata));
2829                 }
2830
2831                 if(unlikely(m->do_space == CONFIG_BOOLEAN_NO && m->do_inodes == CONFIG_BOOLEAN_NO))
2832                     continue;
2833
2834                 if(unlikely(mntbuf[i].f_flags & MNT_RDONLY && !m->collected))
2835                     continue;
2836
2837                 // --------------------------------------------------------------------------
2838
2839                 int rendered = 0;
2840
2841                 if (m->do_space == CONFIG_BOOLEAN_YES || (m->do_space == CONFIG_BOOLEAN_AUTO && (mntbuf[i].f_blocks > 2))) {
2842                     if (unlikely(!m->st_space)) {
2843                         snprintfz(title, 4096, "Disk Space Usage for %s [%s]",
2844                                   mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname);
2845                         m->st_space = rrdset_create_localhost("disk_space",
2846                                                               mntbuf[i].f_mntonname,
2847                                                               NULL,
2848                                                               mntbuf[i].f_mntonname,
2849                                                               "disk.space",
2850                                                               title,
2851                                                               "GB",
2852                                                               2023,
2853                                                               update_every,
2854                                                               RRDSET_TYPE_STACKED
2855                         );
2856
2857                         m->rd_space_avail    = rrddim_add(m->st_space, "avail", NULL,
2858                                                           mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
2859                         m->rd_space_used     = rrddim_add(m->st_space, "used", NULL,
2860                                                           mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
2861                         m->rd_space_reserved = rrddim_add(m->st_space, "reserved_for_root", "reserved for root",
2862                                                           mntbuf[i].f_bsize, GIGA_FACTOR, RRD_ALGORITHM_ABSOLUTE);
2863                     } else
2864                         rrdset_next(m->st_space);
2865
2866                     rrddim_set_by_pointer(m->st_space, m->rd_space_avail,    (collected_number) mntbuf[i].f_bavail);
2867                     rrddim_set_by_pointer(m->st_space, m->rd_space_used,     (collected_number) (mntbuf[i].f_blocks -
2868                                                                                                  mntbuf[i].f_bfree));
2869                     rrddim_set_by_pointer(m->st_space, m->rd_space_reserved, (collected_number) (mntbuf[i].f_bfree -
2870                                                                                                  mntbuf[i].f_bavail));
2871                     rrdset_done(m->st_space);
2872
2873                     rendered++;
2874                 }
2875
2876                 // --------------------------------------------------------------------------
2877
2878                 if (m->do_inodes == CONFIG_BOOLEAN_YES || (m->do_inodes == CONFIG_BOOLEAN_AUTO && (mntbuf[i].f_files > 1))) {
2879                     if (unlikely(!m->st_inodes)) {
2880                         snprintfz(title, 4096, "Disk Files (inodes) Usage for %s [%s]",
2881                                   mntbuf[i].f_mntonname, mntbuf[i].f_mntfromname);
2882                         m->st_inodes = rrdset_create_localhost("disk_inodes",
2883                                                                mntbuf[i].f_mntonname,
2884                                                                NULL,
2885                                                                mntbuf[i].f_mntonname,
2886                                                                "disk.inodes",
2887                                                                title,
2888                                                                "Inodes",
2889                                                                2024,
2890                                                                update_every,
2891                                                                RRDSET_TYPE_STACKED
2892                         );
2893
2894                         m->rd_inodes_avail = rrddim_add(m->st_inodes, "avail", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2895                         m->rd_inodes_used  = rrddim_add(m->st_inodes, "used",  NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
2896                     } else
2897                         rrdset_next(m->st_inodes);
2898
2899                     rrddim_set_by_pointer(m->st_inodes, m->rd_inodes_avail, (collected_number) mntbuf[i].f_ffree);
2900                     rrddim_set_by_pointer(m->st_inodes, m->rd_inodes_used,  (collected_number) (mntbuf[i].f_files -
2901                                                                                                 mntbuf[i].f_ffree));
2902                     rrdset_done(m->st_inodes);
2903
2904                     rendered++;
2905                 }
2906
2907                 if(likely(rendered))
2908                     m->collected++;
2909             }
2910         }
2911     } else {
2912         error("DISABLED: getmntinfo module");
2913         return 1;
2914     }
2915
2916     return 0;
2917 }
2918
2919 // --------------------------------------------------------------------------------------------------------------------
2920 // getifaddrs
2921
2922 int do_getifaddrs(int update_every, usec_t dt) {
2923
2924 #define DELAULT_EXLUDED_INTERFACES "lo*"
2925 #define CONFIG_SECTION_GETIFADDRS "plugin:freebsd:getifaddrs"
2926
2927     static int do_bandwidth_ipv4 = -1, do_bandwidth_ipv6 = -1, do_bandwidth = -1, do_packets = -1,
2928                do_errors = -1, do_drops = -1, do_events = -1;
2929
2930     if (unlikely(do_bandwidth_ipv4 == -1)) {
2931         do_bandwidth_ipv4 = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "total bandwidth for ipv4 interfaces",
2932                                                         CONFIG_BOOLEAN_AUTO);
2933         do_bandwidth_ipv6 = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "total bandwidth for ipv6 interfaces",
2934                                                         CONFIG_BOOLEAN_AUTO);
2935         do_bandwidth      = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "bandwidth for all interfaces",
2936                                                         CONFIG_BOOLEAN_AUTO);
2937         do_packets        = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "packets for all interfaces",
2938                                                         CONFIG_BOOLEAN_AUTO);
2939         do_errors         = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "errors for all interfaces",
2940                                                         CONFIG_BOOLEAN_AUTO);
2941         do_drops          = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "drops for all interfaces",
2942                                                         CONFIG_BOOLEAN_AUTO);
2943         do_events         = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "collisions for all interfaces",
2944                                                         CONFIG_BOOLEAN_AUTO);
2945     }
2946
2947     if (likely(do_bandwidth_ipv4 || do_bandwidth_ipv6 || do_bandwidth || do_packets || do_errors ||
2948                do_drops || do_events)) {
2949         struct ifaddrs *ifap;
2950
2951         if (unlikely(getifaddrs(&ifap))) {
2952             error("FREEBSD: getifaddrs() failed");
2953             do_bandwidth_ipv4 = 0;
2954             error("DISABLED: system.ipv4 chart");
2955             do_bandwidth_ipv6 = 0;
2956             error("DISABLED: system.ipv6 chart");
2957             do_bandwidth = 0;
2958             error("DISABLED: net.* charts");
2959             do_packets = 0;
2960             error("DISABLED: net_packets.* charts");
2961             do_errors = 0;
2962             error("DISABLED: net_errors.* charts");
2963             do_drops = 0;
2964             error("DISABLED: net_drops.* charts");
2965             do_events = 0;
2966             error("DISABLED: net_events.* charts");
2967             error("DISABLED: getifaddrs module");
2968             return 1;
2969         } else {
2970             #define IFA_DATA(s) (((struct if_data *)ifa->ifa_data)->ifi_ ## s)
2971             struct ifaddrs *ifa;
2972             struct iftot {
2973                 u_long  ift_ibytes;
2974                 u_long  ift_obytes;
2975             } iftot = {0, 0};
2976
2977             // --------------------------------------------------------------------
2978
2979             if (likely(do_bandwidth_ipv4)) {
2980                 iftot.ift_ibytes = iftot.ift_obytes = 0;
2981                 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
2982                     if (ifa->ifa_addr->sa_family != AF_INET)
2983                         continue;
2984                     iftot.ift_ibytes += IFA_DATA(ibytes);
2985                     iftot.ift_obytes += IFA_DATA(obytes);
2986                 }
2987
2988                 static RRDSET *st = NULL;
2989                 static RRDDIM *rd_in = NULL, *rd_out = NULL;
2990
2991                 if (unlikely(!st)) {
2992                     st = rrdset_create_localhost("system",
2993                                                  "ipv4",
2994                                                  NULL,
2995                                                  "network",
2996                                                  NULL,
2997                                                  "IPv4 Bandwidth",
2998                                                  "kilobits/s",
2999                                                  500,
3000                                                  update_every,
3001                                                  RRDSET_TYPE_AREA
3002                     );
3003
3004                     rd_in  = rrddim_add(st, "InOctets",  "received", 8, KILO_FACTOR, RRD_ALGORITHM_INCREMENTAL);
3005                     rd_out = rrddim_add(st, "OutOctets", "sent",    -8, KILO_FACTOR, RRD_ALGORITHM_INCREMENTAL);
3006                 } else
3007                     rrdset_next(st);
3008
3009                 rrddim_set_by_pointer(st, rd_in,  iftot.ift_ibytes);
3010                 rrddim_set_by_pointer(st, rd_out, iftot.ift_obytes);
3011                 rrdset_done(st);
3012             }
3013
3014             // --------------------------------------------------------------------
3015
3016             if (likely(do_bandwidth_ipv6)) {
3017                 iftot.ift_ibytes = iftot.ift_obytes = 0;
3018                 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
3019                     if (ifa->ifa_addr->sa_family != AF_INET6)
3020                         continue;
3021                     iftot.ift_ibytes += IFA_DATA(ibytes);
3022                     iftot.ift_obytes += IFA_DATA(obytes);
3023                 }
3024
3025                 static RRDSET *st = NULL;
3026                 static RRDDIM *rd_in = NULL, *rd_out = NULL;
3027
3028                 if (unlikely(!st)) {
3029                     st = rrdset_create_localhost("system",
3030                                                  "ipv6",
3031                                                  NULL,
3032                                                  "network",
3033                                                  NULL,
3034                                                  "IPv6 Bandwidth",
3035                                                  "kilobits/s",
3036                                                  500,
3037                                                  update_every,
3038                                                  RRDSET_TYPE_AREA
3039                     );
3040
3041                     rd_in  = rrddim_add(st, "received", NULL,  8, KILO_FACTOR, RRD_ALGORITHM_INCREMENTAL);
3042                     rd_out = rrddim_add(st, "sent",     NULL, -8, KILO_FACTOR, RRD_ALGORITHM_INCREMENTAL);
3043                 } else
3044                     rrdset_next(st);
3045
3046                 rrddim_set_by_pointer(st, rd_in,  iftot.ift_ibytes);
3047                 rrddim_set_by_pointer(st, rd_out, iftot.ift_obytes);
3048                 rrdset_done(st);
3049             }
3050
3051             // --------------------------------------------------------------------
3052
3053             // Data to be stored in DICTIONARY interfaces.
3054             // This DICTIONARY is used to lookup the settings of the interfaces on each iteration.
3055             struct interfaces_metadata {
3056                 int do_bandwidth;
3057                 int do_packets;
3058                 int do_errors;
3059                 int do_drops;
3060                 int do_events;
3061
3062                 // charts and dimensions
3063
3064                 RRDSET *st_bandwidth;
3065                 RRDDIM *rd_bandwidth_in;
3066                 RRDDIM *rd_bandwidth_out;
3067
3068                 RRDSET *st_packets;
3069                 RRDDIM *rd_packets_in;
3070                 RRDDIM *rd_packets_out;
3071                 RRDDIM *rd_packets_m_in;
3072                 RRDDIM *rd_packets_m_out;
3073
3074                 RRDSET *st_errors;
3075                 RRDDIM *rd_errors_in;
3076                 RRDDIM *rd_errors_out;
3077
3078                 RRDSET *st_drops;
3079                 RRDDIM *rd_drops_in;
3080                 RRDDIM *rd_drops_out;
3081
3082                 RRDSET *st_events;
3083                 RRDDIM *rd_events_coll;
3084             };
3085             static DICTIONARY *interfaces = NULL;
3086             static SIMPLE_PATTERN *excluded_interfaces = NULL;
3087
3088             if(unlikely(!interfaces)) {
3089
3090                 excluded_interfaces = simple_pattern_create(
3091                         config_get(CONFIG_SECTION_GETIFADDRS, "disable by default interfaces matching",
3092                                    DELAULT_EXLUDED_INTERFACES)
3093                         , SIMPLE_PATTERN_EXACT
3094                 );
3095
3096                 interfaces = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED);
3097             }
3098
3099             for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
3100                 if (ifa->ifa_addr->sa_family != AF_LINK)
3101                     continue;
3102
3103                 int def_bandwidth, def_packets, def_errors, def_drops, def_events,
3104                     iter_bandwidth, iter_packets, iter_errors, iter_drops, iter_events;
3105
3106                 struct interfaces_metadata *ifm = dictionary_get(interfaces, ifa->ifa_name);
3107                 if(unlikely(!ifm)) {
3108                     char var_name[4096 + 1];
3109                     snprintfz(var_name, 4096, "%s:%s", CONFIG_SECTION_GETIFADDRS, ifa->ifa_name);
3110
3111                     def_bandwidth = do_bandwidth;
3112                     def_packets   = do_packets;
3113                     def_errors    = do_errors;
3114                     def_drops     = do_drops;
3115                     def_events    = do_events;
3116
3117                     if(unlikely(simple_pattern_matches(excluded_interfaces, ifa->ifa_name))) {
3118                         def_bandwidth = CONFIG_BOOLEAN_NO;
3119                         def_packets   = CONFIG_BOOLEAN_NO;
3120                         def_errors    = CONFIG_BOOLEAN_NO;
3121                         def_drops     = CONFIG_BOOLEAN_NO;
3122                         def_events    = CONFIG_BOOLEAN_NO;
3123                     }
3124
3125                     iter_bandwidth = config_get_boolean_ondemand(var_name, "bandwidth", def_bandwidth);
3126                     iter_packets   = config_get_boolean_ondemand(var_name, "packets",   def_packets);
3127                     iter_errors    = config_get_boolean_ondemand(var_name, "errors",    def_errors);
3128                     iter_drops     = config_get_boolean_ondemand(var_name, "drops",     def_drops);
3129                     iter_events    = config_get_boolean_ondemand(var_name, "events",    def_events);
3130
3131                     struct interfaces_metadata ifmp = {
3132                             .do_bandwidth = iter_bandwidth,
3133                             .do_packets   = iter_packets,
3134                             .do_errors    = iter_errors,
3135                             .do_drops     = iter_drops,
3136                             .do_events    = iter_events,
3137
3138                             .st_bandwidth = NULL,
3139                             .rd_bandwidth_in = NULL,
3140                             .rd_bandwidth_out = NULL,
3141
3142                             .st_packets = NULL,
3143                             .rd_packets_in = NULL,
3144                             .rd_packets_out = NULL,
3145                             .rd_packets_m_in = NULL,
3146                             .rd_packets_m_out = NULL,
3147
3148                             .st_errors = NULL,
3149                             .rd_errors_in = NULL,
3150                             .rd_errors_out = NULL,
3151
3152                             .st_drops = NULL,
3153                             .rd_drops_in = NULL,
3154                             .rd_drops_out = NULL,
3155
3156                             .st_events = NULL,
3157                             .rd_events_coll = NULL,
3158                     };
3159
3160                     ifm = dictionary_set(interfaces, ifa->ifa_name, &ifmp, sizeof(struct interfaces_metadata));
3161                 }
3162
3163                 // --------------------------------------------------------------------
3164
3165                 if (ifm->do_bandwidth == CONFIG_BOOLEAN_YES || (ifm->do_bandwidth == CONFIG_BOOLEAN_AUTO &&
3166                         (IFA_DATA(ibytes) || IFA_DATA(obytes)))) {
3167                     if (unlikely(!ifm->st_bandwidth)) {
3168                         ifm->st_bandwidth = rrdset_create_localhost("net",
3169                                                                     ifa->ifa_name,
3170                                                                     NULL,
3171                                                                     ifa->ifa_name,
3172                                                                     "net.net",
3173                                                                     "Bandwidth",
3174                                                                     "kilobits/s",
3175                                                                     7000,
3176                                                                     update_every,
3177                                                                     RRDSET_TYPE_AREA
3178                         );
3179
3180                         ifm->rd_bandwidth_in  = rrddim_add(ifm->st_bandwidth, "received", NULL,  8, KILO_FACTOR,
3181                                                            RRD_ALGORITHM_INCREMENTAL);
3182                         ifm->rd_bandwidth_out = rrddim_add(ifm->st_bandwidth, "sent",     NULL, -8, KILO_FACTOR,
3183                                                            RRD_ALGORITHM_INCREMENTAL);
3184                     } else
3185                         rrdset_next(ifm->st_bandwidth);
3186
3187                     rrddim_set_by_pointer(ifm->st_bandwidth, ifm->rd_bandwidth_in,  IFA_DATA(ibytes));
3188                     rrddim_set_by_pointer(ifm->st_bandwidth, ifm->rd_bandwidth_out, IFA_DATA(obytes));
3189                     rrdset_done(ifm->st_bandwidth);
3190                 }
3191
3192                 // --------------------------------------------------------------------
3193
3194                 if (ifm->do_packets == CONFIG_BOOLEAN_YES || (ifm->do_packets == CONFIG_BOOLEAN_AUTO &&
3195                         (IFA_DATA(ipackets) || IFA_DATA(opackets) || IFA_DATA(imcasts) || IFA_DATA(omcasts)))) {
3196                     if (unlikely(!ifm->st_packets)) {
3197                         ifm->st_packets = rrdset_create_localhost("net_packets",
3198                                                                   ifa->ifa_name,
3199                                                                   NULL,
3200                                                                   ifa->ifa_name,
3201                                                                   "net.packets",
3202                                                                   "Packets",
3203                                                                   "packets/s",
3204                                                                   7001,
3205                                                                   update_every,
3206                                                                   RRDSET_TYPE_LINE
3207                         );
3208
3209                         rrdset_flag_set(ifm->st_packets, RRDSET_FLAG_DETAIL);
3210
3211                         ifm->rd_packets_in    = rrddim_add(ifm->st_packets, "received",           NULL,  1, 1,
3212                                                            RRD_ALGORITHM_INCREMENTAL);
3213                         ifm->rd_packets_out   = rrddim_add(ifm->st_packets, "sent",               NULL, -1, 1,
3214                                                            RRD_ALGORITHM_INCREMENTAL);
3215                         ifm->rd_packets_m_in  = rrddim_add(ifm->st_packets, "multicast_received", NULL,  1, 1,
3216                                                            RRD_ALGORITHM_INCREMENTAL);
3217                         ifm->rd_packets_m_out = rrddim_add(ifm->st_packets, "multicast_sent",     NULL, -1, 1,
3218                                                            RRD_ALGORITHM_INCREMENTAL);
3219                     } else
3220                         rrdset_next(ifm->st_packets);
3221
3222                     rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_in,    IFA_DATA(ipackets));
3223                     rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_out,   IFA_DATA(opackets));
3224                     rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_m_in,  IFA_DATA(imcasts));
3225                     rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_m_out, IFA_DATA(omcasts));
3226                     rrdset_done(ifm->st_packets);
3227                 }
3228
3229                 // --------------------------------------------------------------------
3230
3231                 if (ifm->do_errors == CONFIG_BOOLEAN_YES || (ifm->do_errors == CONFIG_BOOLEAN_AUTO &&
3232                         (IFA_DATA(ierrors) || IFA_DATA(oerrors)))) {
3233                     if (unlikely(!ifm->st_errors)) {
3234                         ifm->st_errors = rrdset_create_localhost("net_errors",
3235                                                                  ifa->ifa_name,
3236                                                                  NULL,
3237                                                                  ifa->ifa_name,
3238                                                                  "net.errors",
3239                                                                  "Interface Errors",
3240                                                                  "errors/s",
3241                                                                  7002,
3242                                                                  update_every,
3243                                                                  RRDSET_TYPE_LINE
3244                         );
3245
3246                         rrdset_flag_set(ifm->st_errors, RRDSET_FLAG_DETAIL);
3247
3248                         ifm->rd_errors_in  = rrddim_add(ifm->st_errors, "inbound",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
3249                         ifm->rd_errors_out = rrddim_add(ifm->st_errors, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
3250                     } else
3251                         rrdset_next(ifm->st_errors);
3252
3253                     rrddim_set_by_pointer(ifm->st_errors, ifm->rd_errors_in,  IFA_DATA(ierrors));
3254                     rrddim_set_by_pointer(ifm->st_errors, ifm->rd_errors_out, IFA_DATA(oerrors));
3255                     rrdset_done(ifm->st_errors);
3256                 }
3257                 // --------------------------------------------------------------------
3258
3259                 if (ifm->do_drops == CONFIG_BOOLEAN_YES || (ifm->do_drops == CONFIG_BOOLEAN_AUTO &&
3260                         (IFA_DATA(iqdrops) || IFA_DATA(oqdrops)))) {
3261                     if (unlikely(!ifm->st_drops)) {
3262                         ifm->st_drops = rrdset_create_localhost("net_drops",
3263                                                                 ifa->ifa_name,
3264                                                                 NULL,
3265                                                                 ifa->ifa_name,
3266                                                                 "net.drops",
3267                                                                 "Interface Drops",
3268                                                                 "drops/s",
3269                                                                 7003,
3270                                                                 update_every,
3271                                                                 RRDSET_TYPE_LINE
3272                         );
3273
3274                         rrdset_flag_set(ifm->st_drops, RRDSET_FLAG_DETAIL);
3275
3276                         ifm->rd_drops_in  = rrddim_add(ifm->st_drops, "inbound",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
3277 #if __FreeBSD__ >= 11
3278                         ifm->rd_drops_out = rrddim_add(ifm->st_drops, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
3279 #endif
3280                     } else
3281                         rrdset_next(ifm->st_drops);
3282
3283                     rrddim_set_by_pointer(ifm->st_drops, ifm->rd_drops_in,  IFA_DATA(iqdrops));
3284 #if __FreeBSD__ >= 11
3285                     rrddim_set_by_pointer(ifm->st_drops, ifm->rd_drops_out, IFA_DATA(oqdrops));
3286 #endif
3287                     rrdset_done(ifm->st_drops);
3288                 }
3289
3290                 // --------------------------------------------------------------------
3291
3292                 if (ifm->do_events == CONFIG_BOOLEAN_YES || (ifm->do_events == CONFIG_BOOLEAN_AUTO &&
3293                                                              IFA_DATA(collisions))) {
3294                     if (unlikely(!ifm->st_events)) {
3295                         ifm->st_events = rrdset_create_localhost("net_events",
3296                                                                  ifa->ifa_name,
3297                                                                  NULL,
3298                                                                  ifa->ifa_name,
3299                                                                  "net.events",
3300                                                                  "Network Interface Events",
3301                                                                  "events/s",
3302                                                                  7006,
3303                                                                  update_every,
3304                                                                  RRDSET_TYPE_LINE
3305                         );
3306
3307                         rrdset_flag_set(ifm->st_events, RRDSET_FLAG_DETAIL);
3308
3309                         ifm->rd_events_coll = rrddim_add(ifm->st_events, "collisions", NULL, -1, 1,
3310                                                          RRD_ALGORITHM_INCREMENTAL);
3311                     } else
3312                         rrdset_next(ifm->st_events);
3313
3314                     rrddim_set_by_pointer(ifm->st_events, ifm->rd_events_coll, IFA_DATA(collisions));
3315                     rrdset_done(ifm->st_events);
3316                 }
3317             }
3318
3319             freeifaddrs(ifap);
3320         }
3321     } else {
3322         error("DISABLED: getifaddrs module");
3323         return 1;
3324     }
3325
3326     return 0;
3327 }
3328
3329 // --------------------------------------------------------------------------------------------------------------------
3330 // kern.devstat
3331
3332 int do_kern_devstat(int update_every, usec_t dt) {
3333
3334 #define DELAULT_EXLUDED_DISKS ""
3335 #define CONFIG_SECTION_KERN_DEVSTAT "plugin:freebsd:kern.devstat"
3336 #define BINTIME_SCALE 5.42101086242752217003726400434970855712890625e-17 // this is 1000/2^64
3337
3338     static int enable_pass_devices = -1, do_system_io = -1, do_io = -1, do_ops = -1, do_qops = -1, do_util = -1,
3339                do_iotime = -1, do_await = -1, do_avagsz = -1, do_svctm = -1;
3340
3341     if (unlikely(enable_pass_devices == -1)) {
3342         enable_pass_devices = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT,
3343                                                           "performance metrics for pass devices", CONFIG_BOOLEAN_AUTO);
3344
3345         do_system_io = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "total bandwidth for all disks",
3346                                                    CONFIG_BOOLEAN_YES);
3347
3348         do_io     = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "bandwidth for all disks",
3349                                                 CONFIG_BOOLEAN_AUTO);
3350         do_ops    = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "operations for all disks",
3351                                                 CONFIG_BOOLEAN_AUTO);
3352         do_qops   = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "queued operations for all disks",
3353                                                 CONFIG_BOOLEAN_AUTO);
3354         do_util   = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "utilization percentage for all disks",
3355                                                 CONFIG_BOOLEAN_AUTO);
3356         do_iotime = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "i/o time for all disks",
3357                                                 CONFIG_BOOLEAN_AUTO);
3358         do_await  = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "average completed i/o time for all disks",
3359                                                 CONFIG_BOOLEAN_AUTO);
3360         do_avagsz = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "average completed i/o bandwidth for all disks",
3361                                                 CONFIG_BOOLEAN_AUTO);
3362         do_svctm  = config_get_boolean_ondemand(CONFIG_SECTION_KERN_DEVSTAT, "average service time for all disks",
3363                                                 CONFIG_BOOLEAN_AUTO);
3364     }
3365
3366     if (likely(do_system_io || do_io || do_ops || do_qops || do_util || do_iotime || do_await || do_avagsz || do_svctm)) {
3367         static int mib_numdevs[3] = {0, 0, 0};
3368         int numdevs;
3369         int common_error = 0;
3370
3371         if (unlikely(GETSYSCTL_SIMPLE("kern.devstat.numdevs", mib_numdevs, numdevs))) {
3372             common_error = 1;
3373         } else {
3374             static int mib_devstat[3] = {0, 0, 0};
3375             static void *devstat_data = NULL;
3376
3377             devstat_data = reallocz(devstat_data, sizeof(long) + sizeof(struct devstat) * numdevs); // there is generation number before devstat structures
3378             if (unlikely(GETSYSCTL_WSIZE("kern.devstat.all", mib_devstat, devstat_data,
3379                                          sizeof(long) + sizeof(struct devstat) * numdevs))) {
3380                 common_error = 1;
3381             } else {
3382                 struct devstat *dstat;
3383                 int i;
3384                 collected_number total_disk_kbytes_read = 0;
3385                 collected_number total_disk_kbytes_write = 0;
3386
3387                 // Data to be stored in DICTIONARY disks.
3388                 // This DICTIONARY is used to lookup the settings of the disks on each iteration.
3389                 struct disks_metadata {
3390                     int do_io;
3391                     int do_ops;
3392                     int do_qops;
3393                     int do_util;
3394                     int do_iotime;
3395                     int do_await;
3396                     int do_avagsz;
3397                     int do_svctm;
3398
3399
3400                     // data for differential charts
3401
3402                     struct prev_dstat {
3403                         collected_number bytes_read;
3404                         collected_number bytes_write;
3405                         collected_number operations_read;
3406                         collected_number operations_write;
3407                         collected_number duration_read_ms;
3408                         collected_number duration_write_ms;
3409                         collected_number busy_time_ms;
3410                     } prev_dstat;
3411
3412                     // charts and dimensions
3413
3414                     RRDSET *st_io;
3415                     RRDDIM *rd_io_in;
3416                     RRDDIM *rd_io_out;
3417
3418                     RRDSET *st_ops;
3419                     RRDDIM *rd_ops_in;
3420                     RRDDIM *rd_ops_out;
3421
3422                     RRDSET *st_qops;
3423                     RRDDIM *rd_qops;
3424
3425                     RRDSET *st_util;
3426                     RRDDIM *rd_util;
3427
3428                     RRDSET *st_iotime;
3429                     RRDDIM *rd_iotime_in;
3430                     RRDDIM *rd_iotime_out;
3431
3432                     RRDSET *st_await;
3433                     RRDDIM *rd_await_in;
3434                     RRDDIM *rd_await_out;
3435
3436                     RRDSET *st_avagsz;
3437                     RRDDIM *rd_avagsz_in;
3438                     RRDDIM *rd_avagsz_out;
3439
3440                     RRDSET *st_svctm;
3441                     RRDDIM *rd_svctm;
3442
3443                 };
3444                 static DICTIONARY *disks = NULL;
3445                 static SIMPLE_PATTERN *excluded_disks = NULL;
3446
3447                 if(unlikely(!disks)) {
3448
3449                     excluded_disks = simple_pattern_create(
3450                             config_get(CONFIG_SECTION_KERN_DEVSTAT, "disable by default disks matching",
3451                                        DELAULT_EXLUDED_DISKS)
3452                             , SIMPLE_PATTERN_EXACT
3453                     );
3454
3455                     disks = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED);
3456                 }
3457
3458                 dstat = devstat_data + sizeof(long); // skip generation number
3459
3460                 for (i = 0; i < numdevs; i++) {
3461                     if (unlikely(!do_system_io)) {
3462                         if (((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_DIRECT) || ((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_STORARRAY)) {
3463                             total_disk_kbytes_read += dstat[i].bytes[DEVSTAT_READ] / KILO_FACTOR;
3464                             total_disk_kbytes_write += dstat[i].bytes[DEVSTAT_WRITE] / KILO_FACTOR;
3465                         }
3466                     }
3467
3468                     if (unlikely(!enable_pass_devices))
3469                         if (dstat[i].device_type & DEVSTAT_TYPE_PASS == DEVSTAT_TYPE_PASS)
3470                             continue;
3471
3472                     if (((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_DIRECT) || ((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_STORARRAY)) {
3473                         char disk[DEVSTAT_NAME_LEN + MAX_INT_DIGITS + 1];
3474                         int def_io, def_ops, def_qops, def_util, def_iotime, def_await, def_avagsz, def_svctm,
3475                             iter_io, iter_ops, iter_qops, iter_util, iter_iotime, iter_await, iter_avagsz, iter_svctm;
3476                         struct cur_dstat {
3477                             collected_number duration_read_ms;
3478                             collected_number duration_write_ms;
3479                             collected_number busy_time_ms;
3480                         } cur_dstat;
3481
3482                         sprintf(disk, "%s%d", dstat[i].device_name, dstat[i].unit_number);
3483
3484                         struct disks_metadata *dm = dictionary_get(disks, disk);
3485                         if(unlikely(!dm)) {
3486                             char var_name[4096 + 1];
3487                             snprintfz(var_name, 4096, "%s:%s", CONFIG_SECTION_KERN_DEVSTAT, disk);
3488
3489                             def_io     = do_io;
3490                             def_ops    = do_ops;
3491                             def_qops   = do_qops;
3492                             def_util   = do_util;
3493                             def_iotime = do_iotime;
3494                             def_await  = do_await;
3495                             def_avagsz = do_avagsz;
3496                             def_svctm  = do_svctm;
3497
3498                             if(unlikely(simple_pattern_matches(excluded_disks, disk))) {
3499                                 def_io     = CONFIG_BOOLEAN_NO;
3500                                 def_ops    = CONFIG_BOOLEAN_NO;
3501                                 def_qops   = CONFIG_BOOLEAN_NO;
3502                                 def_util   = CONFIG_BOOLEAN_NO;
3503                                 def_iotime = CONFIG_BOOLEAN_NO;
3504                                 def_await  = CONFIG_BOOLEAN_NO;
3505                                 def_avagsz = CONFIG_BOOLEAN_NO;
3506                                 def_svctm  = CONFIG_BOOLEAN_NO;
3507                             }
3508
3509                             iter_io     = config_get_boolean_ondemand(var_name, "bandwidth",                  def_io);
3510                             iter_ops    = config_get_boolean_ondemand(var_name, "operations",                 def_ops);
3511                             iter_qops   = config_get_boolean_ondemand(var_name, "queued operations",          def_qops);
3512                             iter_util   = config_get_boolean_ondemand(var_name, "utilization percentage",     def_util);
3513                             iter_iotime = config_get_boolean_ondemand(var_name, "i/o time",                   def_iotime);
3514                             iter_await  = config_get_boolean_ondemand(var_name, "average completed i/o time", def_await);
3515                             iter_avagsz = config_get_boolean_ondemand(var_name, "average completed i/o bandwidth",
3516                                                                                                               def_avagsz);
3517                             iter_svctm  = config_get_boolean_ondemand(var_name, "average service time",       def_svctm);
3518
3519                             struct disks_metadata dmp = {
3520                                     .do_io     = iter_io,
3521                                     .do_ops    = iter_ops,
3522                                     .do_qops   = iter_qops,
3523                                     .do_util   = iter_util,
3524                                     .do_iotime = iter_iotime,
3525                                     .do_await  = iter_await,
3526                                     .do_avagsz = iter_avagsz,
3527                                     .do_svctm  = iter_svctm,
3528
3529                                     // initialise data for differential charts
3530
3531                                     .prev_dstat.bytes_read        = dstat[i].bytes[DEVSTAT_READ],
3532                                     .prev_dstat.bytes_write       = dstat[i].bytes[DEVSTAT_WRITE],
3533                                     .prev_dstat.operations_read   = dstat[i].operations[DEVSTAT_READ],
3534                                     .prev_dstat.operations_write  = dstat[i].operations[DEVSTAT_WRITE],
3535                                     .prev_dstat.duration_read_ms  = dstat[i].duration[DEVSTAT_READ].sec * 1000
3536                                                                     + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE,
3537                                     .prev_dstat.duration_write_ms = dstat[i].duration[DEVSTAT_WRITE].sec * 1000
3538                                                                     + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE,
3539                                     .prev_dstat.busy_time_ms      = dstat[i].busy_time.sec * 1000
3540                                                                     + dstat[i].busy_time.frac * BINTIME_SCALE,
3541
3542                                     .st_io = NULL,
3543                                     .rd_io_in = NULL,
3544                                     .rd_io_out = NULL,
3545
3546                                     .st_ops = NULL,
3547                                     .rd_ops_in = NULL,
3548                                     .rd_ops_out = NULL,
3549
3550                                     .st_qops = NULL,
3551                                     .rd_qops = NULL,
3552
3553                                     .st_util = NULL,
3554                                     .rd_util = NULL,
3555
3556                                     .st_iotime = NULL,
3557                                     .rd_iotime_in = NULL,
3558                                     .rd_iotime_out = NULL,
3559
3560                                     .st_await = NULL,
3561                                     .rd_await_in = NULL,
3562                                     .rd_await_out = NULL,
3563
3564                                     .st_avagsz = NULL,
3565                                     .rd_avagsz_in = NULL,
3566                                     .rd_avagsz_out = NULL,
3567
3568                                     .st_svctm = NULL,
3569                                     .rd_svctm = NULL,
3570                             };
3571
3572                             dm = dictionary_set(disks, disk, &dmp, sizeof(struct disks_metadata));
3573                         }
3574
3575                         cur_dstat.duration_read_ms  = dstat[i].duration[DEVSTAT_READ].sec * 1000
3576                                                       + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
3577                         cur_dstat.duration_write_ms = dstat[i].duration[DEVSTAT_WRITE].sec * 1000
3578                                                       + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
3579                         cur_dstat.busy_time_ms = dstat[i].busy_time.sec * 1000 + dstat[i].busy_time.frac * BINTIME_SCALE;
3580
3581                         // --------------------------------------------------------------------
3582
3583                         if(dm->do_io == CONFIG_BOOLEAN_YES || (dm->do_io == CONFIG_BOOLEAN_AUTO &&
3584                                 (dstat[i].bytes[DEVSTAT_READ] || dstat[i].bytes[DEVSTAT_WRITE]))) {
3585                             if (unlikely(!dm->st_io)) {
3586                                 dm->st_io = rrdset_create_localhost("disk",
3587                                                                     disk,
3588                                                                     NULL,
3589                                                                     disk,
3590                                                                     "disk.io",
3591                                                                     "Disk I/O Bandwidth",
3592                                                                     "kilobytes/s",
3593                                                                     2000,
3594                                                                     update_every,
3595                                                                     RRDSET_TYPE_AREA
3596                                 );
3597
3598                                 dm->rd_io_in  = rrddim_add(dm->st_io, "reads",  NULL,  1, KILO_FACTOR,
3599                                                           RRD_ALGORITHM_INCREMENTAL);
3600                                 dm->rd_io_out = rrddim_add(dm->st_io, "writes", NULL, -1, KILO_FACTOR,
3601                                                            RRD_ALGORITHM_INCREMENTAL);
3602                             } else
3603                                 rrdset_next(dm->st_io);
3604
3605                             rrddim_set_by_pointer(dm->st_io, dm->rd_io_in,  dstat[i].bytes[DEVSTAT_READ]);
3606                             rrddim_set_by_pointer(dm->st_io, dm->rd_io_out, dstat[i].bytes[DEVSTAT_WRITE]);
3607                             rrdset_done(dm->st_io);
3608                         }
3609
3610                         // --------------------------------------------------------------------
3611
3612                         if(dm->do_ops == CONFIG_BOOLEAN_YES || (dm->do_ops == CONFIG_BOOLEAN_AUTO &&
3613                                 (dstat[i].operations[DEVSTAT_READ] || dstat[i].operations[DEVSTAT_WRITE]))) {
3614                             if (unlikely(!dm->st_ops)) {
3615                                 dm->st_ops = rrdset_create_localhost("disk_ops",
3616                                                                      disk,
3617                                                                      NULL,
3618                                                                      disk,
3619                                                                      "disk.ops",
3620                                                                      "Disk Completed I/O Operations",
3621                                                                      "operations/s",
3622                                                                      2001,
3623                                                                      update_every,
3624                                                                      RRDSET_TYPE_LINE
3625                                 );
3626
3627                                 rrdset_flag_set(dm->st_ops, RRDSET_FLAG_DETAIL);
3628
3629                                 dm->rd_ops_in = rrddim_add(dm->st_ops, "reads", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
3630                                 dm->rd_ops_out = rrddim_add(dm->st_ops, "writes", NULL, -1, 1,
3631                                                             RRD_ALGORITHM_INCREMENTAL);
3632                             } else
3633                                 rrdset_next(dm->st_ops);
3634
3635                             rrddim_set_by_pointer(dm->st_ops, dm->rd_ops_in, dstat[i].operations[DEVSTAT_READ]);
3636                             rrddim_set_by_pointer(dm->st_ops, dm->rd_ops_out, dstat[i].operations[DEVSTAT_WRITE]);
3637                             rrdset_done(dm->st_ops);
3638                         }
3639
3640                         // --------------------------------------------------------------------
3641
3642                         if(dm->do_qops == CONFIG_BOOLEAN_YES || (dm->do_qops == CONFIG_BOOLEAN_AUTO &&
3643                                 (dstat[i].start_count || dstat[i].end_count))) {
3644                             if (unlikely(!dm->st_qops)) {
3645                                 dm->st_qops = rrdset_create_localhost("disk_qops",
3646                                                                       disk,
3647                                                                       NULL,
3648                                                                       disk,
3649                                                                       "disk.qops",
3650                                                                       "Disk Current I/O Operations",
3651                                                                       "operations",
3652                                                                       2002,
3653                                                                       update_every,
3654                                                                       RRDSET_TYPE_LINE
3655                                 );
3656
3657                                 rrdset_flag_set(dm->st_qops, RRDSET_FLAG_DETAIL);
3658
3659                                 dm->rd_qops = rrddim_add(dm->st_qops, "operations", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
3660                             } else
3661                                 rrdset_next(dm->st_qops);
3662
3663                             rrddim_set_by_pointer(dm->st_qops, dm->rd_qops, dstat[i].start_count - dstat[i].end_count);
3664                             rrdset_done(dm->st_qops);
3665                         }
3666
3667                         // --------------------------------------------------------------------
3668
3669                         if(dm->do_util == CONFIG_BOOLEAN_YES || (dm->do_util == CONFIG_BOOLEAN_AUTO &&
3670                                                                  cur_dstat.busy_time_ms)) {
3671                             if (unlikely(!dm->st_util)) {
3672                                 dm->st_util = rrdset_create_localhost("disk_util",
3673                                                                       disk,
3674                                                                       NULL,
3675                                                                       disk,
3676                                                                       "disk.util",
3677                                                                       "Disk Utilization Time",
3678                                                                       "% of time working",
3679                                                                       2004,
3680                                                                       update_every,
3681                                                                       RRDSET_TYPE_AREA
3682                                 );
3683
3684                                 rrdset_flag_set(dm->st_util, RRDSET_FLAG_DETAIL);
3685
3686                                 dm->rd_util = rrddim_add(dm->st_util, "utilization", NULL, 1, 10,
3687                                                          RRD_ALGORITHM_INCREMENTAL);
3688                             } else
3689                                 rrdset_next(dm->st_util);
3690
3691                             rrddim_set_by_pointer(dm->st_util, dm->rd_util, cur_dstat.busy_time_ms);
3692                             rrdset_done(dm->st_util);
3693                         }
3694
3695                         // --------------------------------------------------------------------
3696
3697                         if(dm->do_iotime == CONFIG_BOOLEAN_YES || (dm->do_iotime == CONFIG_BOOLEAN_AUTO &&
3698                                 (cur_dstat.duration_read_ms || cur_dstat.duration_write_ms))) {
3699                             if (unlikely(!dm->st_iotime)) {
3700                                 dm->st_iotime = rrdset_create_localhost("disk_iotime",
3701                                                                         disk,
3702                                                                         NULL,
3703                                                                         disk,
3704                                                                         "disk.iotime",
3705                                                                         "Disk Total I/O Time",
3706                                                                         "milliseconds/s",
3707                                                                         2022,
3708                                                                         update_every,
3709                                                                         RRDSET_TYPE_LINE
3710                                 );
3711
3712                                 rrdset_flag_set(dm->st_iotime, RRDSET_FLAG_DETAIL);
3713
3714                                 dm->rd_iotime_in  = rrddim_add(dm->st_iotime, "reads",  NULL,  1, 1,
3715                                                                RRD_ALGORITHM_INCREMENTAL);
3716                                 dm->rd_iotime_out = rrddim_add(dm->st_iotime, "writes", NULL, -1, 1,
3717                                                                RRD_ALGORITHM_INCREMENTAL);
3718                             } else
3719                                 rrdset_next(dm->st_iotime);
3720
3721                             rrddim_set_by_pointer(dm->st_iotime, dm->rd_iotime_in,  cur_dstat.duration_read_ms);
3722                             rrddim_set_by_pointer(dm->st_iotime, dm->rd_iotime_out, cur_dstat.duration_write_ms);
3723                             rrdset_done(dm->st_iotime);
3724                         }
3725
3726                         // --------------------------------------------------------------------
3727                         // calculate differential charts
3728                         // only if this is not the first time we run
3729
3730                         if (likely(dt)) {
3731
3732                             // --------------------------------------------------------------------
3733
3734                             if(dm->do_await == CONFIG_BOOLEAN_YES || (dm->do_await == CONFIG_BOOLEAN_AUTO &&
3735                                     (dstat[i].operations[DEVSTAT_READ] || dstat[i].operations[DEVSTAT_WRITE]))) {
3736                                 if (unlikely(!dm->st_await)) {
3737                                     dm->st_await = rrdset_create_localhost("disk_await",
3738                                                                            disk,
3739                                                                            NULL,
3740                                                                            disk,
3741                                                                            "disk.await",
3742                                                                            "Average Completed I/O Operation Time",
3743                                                                            "ms per operation",
3744                                                                            2005,
3745                                                                            update_every,
3746                                                                            RRDSET_TYPE_LINE
3747                                     );
3748
3749                                     rrdset_flag_set(dm->st_await, RRDSET_FLAG_DETAIL);
3750
3751                                     dm->rd_await_in  = rrddim_add(dm->st_await, "reads",  NULL,  1, 1,
3752                                                                   RRD_ALGORITHM_ABSOLUTE);
3753                                     dm->rd_await_out = rrddim_add(dm->st_await, "writes", NULL, -1, 1,
3754                                                                   RRD_ALGORITHM_ABSOLUTE);
3755                                 } else
3756                                     rrdset_next(dm->st_await);
3757
3758                                 rrddim_set_by_pointer(dm->st_await, dm->rd_await_in,
3759                                                       (dstat[i].operations[DEVSTAT_READ] -
3760                                                        dm->prev_dstat.operations_read) ?
3761                                                       (cur_dstat.duration_read_ms - dm->prev_dstat.duration_read_ms) /
3762                                                       (dstat[i].operations[DEVSTAT_READ] -
3763                                                        dm->prev_dstat.operations_read) :
3764                                                       0);
3765                                 rrddim_set_by_pointer(dm->st_await, dm->rd_await_out,
3766                                                       (dstat[i].operations[DEVSTAT_WRITE] -
3767                                                        dm->prev_dstat.operations_write) ?
3768                                                       (cur_dstat.duration_write_ms - dm->prev_dstat.duration_write_ms) /
3769                                                       (dstat[i].operations[DEVSTAT_WRITE] -
3770                                                        dm->prev_dstat.operations_write) :
3771                                                       0);
3772                                 rrdset_done(dm->st_await);
3773                             }
3774
3775                             // --------------------------------------------------------------------
3776
3777                             if(dm->do_avagsz == CONFIG_BOOLEAN_YES || (dm->do_avagsz == CONFIG_BOOLEAN_AUTO &&
3778                                     (dstat[i].operations[DEVSTAT_READ] || dstat[i].operations[DEVSTAT_WRITE]))) {
3779                                 if (unlikely(!dm->st_avagsz)) {
3780                                     dm->st_avagsz = rrdset_create_localhost("disk_avgsz",
3781                                                                             disk,
3782                                                                             NULL,
3783                                                                             disk,
3784                                                                             "disk.avgsz",
3785                                                                             "Average Completed I/O Operation Bandwidth",
3786                                                                             "kilobytes per operation",
3787                                                                             2006,
3788                                                                             update_every,
3789                                                                             RRDSET_TYPE_AREA
3790                                     );
3791
3792                                     rrdset_flag_set(dm->st_avagsz, RRDSET_FLAG_DETAIL);
3793
3794                                     dm->rd_avagsz_in  = rrddim_add(dm->st_avagsz, "reads",  NULL,  1, KILO_FACTOR,
3795                                                                   RRD_ALGORITHM_ABSOLUTE);
3796                                     dm->rd_avagsz_out = rrddim_add(dm->st_avagsz, "writes", NULL, -1, KILO_FACTOR,
3797                                                                    RRD_ALGORITHM_ABSOLUTE);
3798                                 } else
3799                                     rrdset_next(dm->st_avagsz);
3800
3801                                 rrddim_set_by_pointer(dm->st_avagsz, dm->rd_avagsz_in,
3802                                                       (dstat[i].operations[DEVSTAT_READ] -
3803                                                        dm->prev_dstat.operations_read) ?
3804                                                       (dstat[i].bytes[DEVSTAT_READ] - dm->prev_dstat.bytes_read) /
3805                                                       (dstat[i].operations[DEVSTAT_READ] -
3806                                                        dm->prev_dstat.operations_read) :
3807                                                       0);
3808                                 rrddim_set_by_pointer(dm->st_avagsz, dm->rd_avagsz_out,
3809                                                       (dstat[i].operations[DEVSTAT_WRITE] -
3810                                                        dm->prev_dstat.operations_write) ?
3811                                                       (dstat[i].bytes[DEVSTAT_WRITE] - dm->prev_dstat.bytes_write) /
3812                                                       (dstat[i].operations[DEVSTAT_WRITE] -
3813                                                        dm->prev_dstat.operations_write) :
3814                                                       0);
3815                                 rrdset_done(dm->st_avagsz);
3816                             }
3817
3818                             // --------------------------------------------------------------------
3819
3820                             if(dm->do_svctm == CONFIG_BOOLEAN_YES || (dm->do_svctm == CONFIG_BOOLEAN_AUTO &&
3821                                     (dstat[i].operations[DEVSTAT_READ] || dstat[i].operations[DEVSTAT_WRITE]))) {
3822                                 if (unlikely(!dm->st_svctm)) {
3823                                     dm->st_svctm = rrdset_create_localhost("disk_svctm",
3824                                                                            disk,
3825                                                                            NULL,
3826                                                                            disk,
3827                                                                            "disk.svctm",
3828                                                                            "Average Service Time",
3829                                                                            "ms per operation",
3830                                                                            2007,
3831                                                                            update_every,
3832                                                                            RRDSET_TYPE_LINE
3833                                     );
3834
3835                                     rrdset_flag_set(dm->st_svctm, RRDSET_FLAG_DETAIL);
3836
3837                                     dm->rd_svctm = rrddim_add(dm->st_svctm, "svctm", NULL, 1, 1,
3838                                                               RRD_ALGORITHM_ABSOLUTE);
3839                                 } else
3840                                     rrdset_next(dm->st_svctm);
3841
3842                                 rrddim_set_by_pointer(dm->st_svctm, dm->rd_svctm,
3843                                     ((dstat[i].operations[DEVSTAT_READ] - dm->prev_dstat.operations_read) +
3844                                      (dstat[i].operations[DEVSTAT_WRITE] - dm->prev_dstat.operations_write)) ?
3845                                     (cur_dstat.busy_time_ms - dm->prev_dstat.busy_time_ms) /
3846                                     ((dstat[i].operations[DEVSTAT_READ] - dm->prev_dstat.operations_read) +
3847                                      (dstat[i].operations[DEVSTAT_WRITE] - dm->prev_dstat.operations_write)) :
3848                                     0);
3849                                 rrdset_done(dm->st_svctm);
3850                             }
3851
3852                             // --------------------------------------------------------------------
3853
3854                             dm->prev_dstat.bytes_read        = dstat[i].bytes[DEVSTAT_READ];
3855                             dm->prev_dstat.bytes_write       = dstat[i].bytes[DEVSTAT_WRITE];
3856                             dm->prev_dstat.operations_read   = dstat[i].operations[DEVSTAT_READ];
3857                             dm->prev_dstat.operations_write  = dstat[i].operations[DEVSTAT_WRITE];
3858                             dm->prev_dstat.duration_read_ms  = cur_dstat.duration_read_ms;
3859                             dm->prev_dstat.duration_write_ms = cur_dstat.duration_write_ms;
3860                             dm->prev_dstat.busy_time_ms      = cur_dstat.busy_time_ms;
3861                         }
3862                     }
3863                 }
3864
3865                 // --------------------------------------------------------------------
3866
3867                 if (unlikely(!do_system_io)) {
3868                     static RRDSET *st = NULL;
3869                     static RRDDIM *rd_in = NULL, *rd_out = NULL;
3870
3871                     st = rrdset_find_bytype_localhost("system", "io");
3872                     if (unlikely(!st)) {
3873                         st = rrdset_create_localhost("system",
3874                                                      "io",
3875                                                      NULL,
3876                                                      "disk",
3877                                                      NULL,
3878                                                      "Disk I/O",
3879                                                      "kilobytes/s",
3880                                                      150,
3881                                                      update_every,
3882                                                      RRDSET_TYPE_AREA
3883                         );
3884
3885                         rd_in  = rrddim_add(st, "in",  NULL,  1, 1, RRD_ALGORITHM_INCREMENTAL);
3886                         rd_out = rrddim_add(st, "out", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
3887                     } else
3888                         rrdset_next(st);
3889
3890                     rrddim_set_by_pointer(st, rd_in,  total_disk_kbytes_read);
3891                     rrddim_set_by_pointer(st, rd_out, total_disk_kbytes_write);
3892                     rrdset_done(st);
3893                 }
3894             }
3895         }
3896         if (unlikely(common_error)) {
3897             do_system_io = 0;
3898             error("DISABLED: system.io chart");
3899             do_io = 0;
3900             error("DISABLED: disk.* charts");
3901             do_ops = 0;
3902             error("DISABLED: disk_ops.* charts");
3903             do_qops = 0;
3904             error("DISABLED: disk_qops.* charts");
3905             do_util = 0;
3906             error("DISABLED: disk_util.* charts");
3907             do_iotime = 0;
3908             error("DISABLED: disk_iotime.* charts");
3909             do_await = 0;
3910             error("DISABLED: disk_await.* charts");
3911             do_avagsz = 0;
3912             error("DISABLED: disk_avgsz.* charts");
3913             do_svctm = 0;
3914             error("DISABLED: disk_svctm.* charts");
3915             error("DISABLED: kern.devstat module");
3916             return 1;
3917         }
3918     } else {
3919         error("DISABLED: kern.devstat module");
3920         return 1;
3921     }
3922
3923     return 0;
3924 }