]> arthur.barton.de Git - netdata.git/blob - src/freebsd_sysctl.c
Fix displayed data multiplication in mem.committed in FreeBSD plugin
[netdata.git] / src / freebsd_sysctl.c
1 #include "common.h"
2
3 // NEEDED BY: struct vmtotal, struct vmmeter
4 #include <sys/vmmeter.h>
5 // NEEDED BY: struct devstat
6 #include <sys/devicestat.h>
7 // NEEDED BY: struct xswdev
8 #include <vm/vm_param.h>
9 // NEEDED BY: struct semid_kernel, struct shmid_kernel, struct msqid_kernel
10 #define _KERNEL
11 #include <sys/sem.h>
12 #include <sys/shm.h>
13 #include <sys/msg.h>
14 #undef _KERNEL
15 // NEEDED BY: struct sysctl_netisr_workstream, struct sysctl_netisr_work
16 #include <net/netisr.h>
17 // NEEDED BY: struct ifaddrs, getifaddrs()
18 #define _IFI_OQDROPS // It is for FreeNAS only. Most probably in future releases of FreeNAS it will be removed
19 #include <net/if.h>
20 #include <ifaddrs.h>
21 // NEEDED BY do_tcp...
22 #include <netinet/tcp_var.h>
23 // NEEDED BY do_udp...
24 #include <netinet/ip_var.h>
25 #include <netinet/udp.h>
26 #include <netinet/udp_var.h>
27 // NEEDED BY do_icmp...
28 #include <netinet/ip.h>
29 #include <netinet/ip_icmp.h>
30 #include <netinet/icmp_var.h>
31
32 // NEEDED BY: do_disk_io
33 #define RRD_TYPE_DISK "disk"
34
35 // FreeBSD calculates load averages once every 5 seconds
36 #define MIN_LOADAVG_UPDATE_EVERY 5
37
38 // NEEDED BY: do_bandwidth
39 #define IFA_DATA(s) (((struct if_data *)ifa->ifa_data)->ifi_ ## s)
40
41 int do_freebsd_sysctl(int update_every, usec_t dt) {
42     (void)dt;
43
44     static int do_cpu = -1, do_cpu_cores = -1, do_interrupts = -1, do_context = -1, do_forks = -1, do_processes = -1,
45         do_loadavg = -1, do_all_processes = -1, do_disk_io = -1, do_swap = -1, do_ram = -1, do_swapio = -1,
46         do_pgfaults = -1, do_committed = -1, do_ipc_semaphores = -1, do_ipc_shared_mem = -1, do_ipc_msg_queues = -1,
47         do_dev_intr = -1, do_soft_intr = -1, do_netisr = -1, do_netisr_per_core = -1, do_bandwidth = -1,
48         do_tcp_sockets = -1, do_tcp_packets = -1, do_tcp_errors = -1, do_tcp_handshake = -1,
49         do_ecn = -1, do_tcpext_syscookies = -1, do_tcpext_ofo = -1, do_tcpext_connaborts = -1,
50         do_udp_packets = -1, do_udp_errors = -1, do_icmp_packets = -1, do_icmpmsg = -1;
51
52     if (unlikely(do_cpu == -1)) {
53         do_cpu                  = config_get_boolean("plugin:freebsd:sysctl", "cpu utilization", 1);
54         do_cpu_cores            = config_get_boolean("plugin:freebsd:sysctl", "per cpu core utilization", 1);
55         do_interrupts           = config_get_boolean("plugin:freebsd:sysctl", "cpu interrupts", 1);
56         do_dev_intr             = config_get_boolean("plugin:freebsd:sysctl", "device interrupts", 1);
57         do_soft_intr            = config_get_boolean("plugin:freebsd:sysctl", "software interrupts", 1);
58         do_context              = config_get_boolean("plugin:freebsd:sysctl", "context switches", 1);
59         do_forks                = config_get_boolean("plugin:freebsd:sysctl", "processes started", 1);
60         do_processes            = config_get_boolean("plugin:freebsd:sysctl", "processes running", 1);
61         do_loadavg              = config_get_boolean("plugin:freebsd:sysctl", "enable load average", 1);
62         do_all_processes        = config_get_boolean("plugin:freebsd:sysctl", "enable total processes", 1);
63         do_disk_io              = config_get_boolean("plugin:freebsd:sysctl", "stats for all disks", 1);
64         do_swap                 = config_get_boolean("plugin:freebsd:sysctl", "system swap", 1);
65         do_ram                  = config_get_boolean("plugin:freebsd:sysctl", "system ram", 1);
66         do_swapio               = config_get_boolean("plugin:freebsd:sysctl", "swap i/o", 1);
67         do_pgfaults             = config_get_boolean("plugin:freebsd:sysctl", "memory page faults", 1);
68         do_committed            = config_get_boolean("plugin:freebsd:sysctl", "committed memory", 1);
69         do_ipc_semaphores       = config_get_boolean("plugin:freebsd:sysctl", "ipc semaphores", 1);
70         do_ipc_shared_mem       = config_get_boolean("plugin:freebsd:sysctl", "ipc shared memory", 1);
71         do_ipc_msg_queues       = config_get_boolean("plugin:freebsd:sysctl", "ipc message queues", 1);
72         do_netisr               = config_get_boolean("plugin:freebsd:sysctl", "netisr", 1);
73         do_netisr_per_core      = config_get_boolean("plugin:freebsd:sysctl", "netisr per core", 1);
74         do_bandwidth            = config_get_boolean("plugin:freebsd:sysctl", "bandwidth", 1);
75         do_tcp_sockets          = config_get_boolean("plugin:freebsd:sysctl", "ipv4 TCP connections", 1);
76         do_tcp_packets          = config_get_boolean("plugin:freebsd:sysctl", "ipv4 TCP packets", 1);
77         do_tcp_errors           = config_get_boolean("plugin:freebsd:sysctl", "ipv4 TCP errors", 1);
78         do_tcp_handshake        = config_get_boolean("plugin:freebsd:sysctl", "ipv4 TCP handshake issues", 1);
79         do_ecn                  = config_get_boolean_ondemand("plugin:freebsd:sysctl", "ECN packets", CONFIG_ONDEMAND_ONDEMAND);
80         do_tcpext_syscookies    = config_get_boolean_ondemand("plugin:freebsd:sysctl", "TCP SYN cookies", CONFIG_ONDEMAND_ONDEMAND);
81         do_tcpext_ofo           = config_get_boolean_ondemand("plugin:freebsd:sysctl", "TCP out-of-order queue", CONFIG_ONDEMAND_ONDEMAND);
82         do_tcpext_connaborts    = config_get_boolean_ondemand("plugin:freebsd:sysctl", "TCP connection aborts", CONFIG_ONDEMAND_ONDEMAND);
83         do_udp_packets          = config_get_boolean("plugin:freebsd:sysctl", "ipv4 UDP packets", 1);
84         do_udp_errors           = config_get_boolean("plugin:freebsd:sysctl", "ipv4 UDP errors", 1);
85     }
86
87     RRDSET *st;
88     RRDDIM *rd;
89
90     int system_pagesize = getpagesize(); // wouldn't it be better to get value directly from hw.pagesize?
91     int i, n;
92     void *p;
93     int common_error = 0;
94     size_t size;
95
96     // NEEDED BY: do_loadavg
97     static usec_t last_loadavg_usec = 0;
98     struct loadavg sysload;
99
100     // NEEDED BY: do_cpu, do_cpu_cores
101     long cp_time[CPUSTATES];
102
103     // NEEDED BY: du_cpu_cores, do_netisr, do_netisr_per_core
104     int ncpus;
105
106     // NEEDED BY: do_cpu_cores
107     static long *pcpu_cp_time = NULL;
108     char cpuid[8]; // no more than 4 digits expected
109
110     // NEEDED BY: do_all_processes, do_processes
111     struct vmtotal vmtotal_data;
112
113     // NEEDED BY: do_context, do_forks
114     u_int u_int_data;
115
116     // NEEDED BY: do_interrupts
117     size_t intrcnt_size;
118     unsigned long nintr = 0;
119     static unsigned long *intrcnt = NULL;
120     static char *intrnames = NULL;
121     unsigned long long totalintr = 0;
122
123     // NEEDED BY: do_disk_io
124     #define BINTIME_SCALE 5.42101086242752217003726400434970855712890625e-17 // this is 1000/2^64
125     int numdevs;
126     static void *devstat_data = NULL;
127     struct devstat *dstat;
128     struct cur_dstat {
129         collected_number duration_read_ms;
130         collected_number duration_write_ms;
131         collected_number busy_time_ms;
132     } cur_dstat;
133     struct prev_dstat {
134         collected_number bytes_read;
135         collected_number bytes_write;
136         collected_number operations_read;
137         collected_number operations_write;
138         collected_number duration_read_ms;
139         collected_number duration_write_ms;
140         collected_number busy_time_ms;
141     } prev_dstat;
142
143     // NEEDED BY: do_swap
144     size_t mibsize;
145     int mib[3]; // CTL_MAXNAME = 24 maximum mib components (sysctl.h)
146     struct xswdev xsw;
147     struct total_xsw {
148         collected_number bytes_used;
149         collected_number bytes_total;
150     } total_xsw = {0, 0};
151
152     // NEEDED BY: do_swapio, do_ram
153     struct vmmeter vmmeter_data;
154
155     // NEEDED BY: do_ram
156     int vfs_bufspace_count;
157
158     // NEEDED BY: do_ipc_semaphores
159     struct ipc_sem {
160         int semmni;
161         collected_number sets;
162         collected_number semaphores;
163     } ipc_sem = {0, 0, 0};
164     static struct semid_kernel *ipc_sem_data = NULL;
165
166     // NEEDED BY: do_ipc_shared_mem
167     struct ipc_shm {
168         u_long shmmni;
169         collected_number segs;
170         collected_number segsize;
171     } ipc_shm = {0, 0, 0};
172     static struct shmid_kernel *ipc_shm_data = NULL;
173
174     // NEEDED BY: do_ipc_msg_queues
175     struct ipc_msq {
176         int msgmni;
177         collected_number queues;
178         collected_number messages;
179         collected_number usedsize;
180         collected_number allocsize;
181     } ipc_msq = {0, 0, 0, 0, 0};
182     static struct msqid_kernel *ipc_msq_data = NULL;
183
184     // NEEDED BY: do_netisr, do_netisr_per_core
185     size_t netisr_workstream_size;
186     size_t netisr_work_size;
187     unsigned long num_netisr_workstreams = 0, num_netisr_works = 0;
188     static struct sysctl_netisr_workstream *netisr_workstream = NULL;
189     static struct sysctl_netisr_work *netisr_work = NULL;
190     static struct netisr_stats {
191         collected_number dispatched;
192         collected_number hybrid_dispatched;
193         collected_number qdrops;
194         collected_number queued;
195     } *netisr_stats = NULL;
196     char netstat_cpuid[21]; // no more than 4 digits expected
197
198     // NEEDED BY: do_bandwidth
199     struct ifaddrs *ifa, *ifap;
200     struct iftot {
201         u_long  ift_ibytes;
202         u_long  ift_obytes;
203     } iftot = {0, 0};
204
205     // NEEDED BY: do_tcp...
206     struct tcpstat tcpstat;
207     uint64_t tcps_states[TCP_NSTATES];
208
209     // NEEDED BY: do_udp...
210     struct udpstat udpstat;
211
212     // NEEDED BY: do_icmp...
213     struct icmpstat icmpstat;
214     struct icmp_total {
215         u_long  msgs_in;
216         u_long  msgs_out;
217     } icmp_total = {0, 0};
218
219     // --------------------------------------------------------------------
220
221     if (last_loadavg_usec <= dt) {
222         if (likely(do_loadavg)) {
223             if (unlikely(GETSYSCTL("vm.loadavg", sysload))) {
224                 do_loadavg = 0;
225                 error("DISABLED: system.load");
226             } else {
227
228                 st = rrdset_find_bytype("system", "load");
229                 if (unlikely(!st)) {
230                     st = rrdset_create("system", "load", NULL, "load", NULL, "System Load Average", "load", 100, (update_every < MIN_LOADAVG_UPDATE_EVERY) ? MIN_LOADAVG_UPDATE_EVERY : update_every, RRDSET_TYPE_LINE);
231                     rrddim_add(st, "load1", NULL, 1, 1000, RRDDIM_ABSOLUTE);
232                     rrddim_add(st, "load5", NULL, 1, 1000, RRDDIM_ABSOLUTE);
233                     rrddim_add(st, "load15", NULL, 1, 1000, RRDDIM_ABSOLUTE);
234                 }
235                 else rrdset_next(st);
236
237                 rrddim_set(st, "load1", (collected_number) ((double)sysload.ldavg[0] / sysload.fscale * 1000));
238                 rrddim_set(st, "load5", (collected_number) ((double)sysload.ldavg[1] / sysload.fscale * 1000));
239                 rrddim_set(st, "load15", (collected_number) ((double)sysload.ldavg[2] / sysload.fscale * 1000));
240                 rrdset_done(st);
241             }
242         }
243
244         last_loadavg_usec = st->update_every * USEC_PER_SEC;
245     }
246     else last_loadavg_usec -= dt;
247
248     // --------------------------------------------------------------------
249
250     if (likely(do_all_processes | do_processes | do_committed)) {
251         if (unlikely(GETSYSCTL("vm.vmtotal", vmtotal_data))) {
252             do_all_processes = 0;
253             error("DISABLED: system.active_processes");
254             do_processes = 0;
255             error("DISABLED: system.processes");
256             do_committed = 0;
257             error("DISABLED: mem.committed");
258         } else {
259             if (likely(do_all_processes)) {
260
261                 st = rrdset_find_bytype("system", "active_processes");
262                 if (unlikely(!st)) {
263                     st = rrdset_create("system", "active_processes", NULL, "processes", NULL, "System Active Processes", "processes", 750, update_every, RRDSET_TYPE_LINE);
264                     rrddim_add(st, "active", NULL, 1, 1, RRDDIM_ABSOLUTE);
265                 }
266                 else rrdset_next(st);
267
268                 rrddim_set(st, "active", (vmtotal_data.t_rq + vmtotal_data.t_dw + vmtotal_data.t_pw + vmtotal_data.t_sl + vmtotal_data.t_sw));
269                 rrdset_done(st);
270             }
271
272             // --------------------------------------------------------------------
273
274             if (likely(do_processes)) {
275
276                 st = rrdset_find_bytype("system", "processes");
277                 if (unlikely(!st)) {
278                     st = rrdset_create("system", "processes", NULL, "processes", NULL, "System Processes", "processes", 600, update_every, RRDSET_TYPE_LINE);
279
280                     rrddim_add(st, "running", NULL, 1, 1, RRDDIM_ABSOLUTE);
281                     rrddim_add(st, "blocked", NULL, -1, 1, RRDDIM_ABSOLUTE);
282                 }
283                 else rrdset_next(st);
284
285                 rrddim_set(st, "running", vmtotal_data.t_rq);
286                 rrddim_set(st, "blocked", (vmtotal_data.t_dw + vmtotal_data.t_pw));
287                 rrdset_done(st);
288             }
289
290             // --------------------------------------------------------------------
291
292             if (likely(do_committed)) {
293                 st = rrdset_find("mem.committed");
294                 if (unlikely(!st)) {
295                     st = rrdset_create("mem", "committed", NULL, "system", NULL, "Committed (Allocated) Memory", "MB", 5000, update_every, RRDSET_TYPE_AREA);
296                     st->isdetail = 1;
297
298                     rrddim_add(st, "Committed_AS", NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE);
299                 }
300                 else rrdset_next(st);
301
302                 rrddim_set(st, "Committed_AS", vmtotal_data.t_rm);
303                 rrdset_done(st);
304             }
305         }
306     }
307
308     // --------------------------------------------------------------------
309
310     if (likely(do_cpu)) {
311         if (unlikely(CPUSTATES != 5)) {
312             error("FREEBSD: There are %d CPU states (5 was expected)", CPUSTATES);
313             do_cpu = 0;
314             error("DISABLED: system.cpu");
315         } else {
316             if (unlikely(GETSYSCTL("kern.cp_time", cp_time))) {
317                 do_cpu = 0;
318                 error("DISABLED: system.cpu");
319             } else {
320
321                 st = rrdset_find_bytype("system", "cpu");
322                 if (unlikely(!st)) {
323                     st = rrdset_create("system", "cpu", NULL, "cpu", "system.cpu", "Total CPU utilization", "percentage", 100, update_every, RRDSET_TYPE_STACKED);
324
325                     rrddim_add(st, "user", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
326                     rrddim_add(st, "nice", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
327                     rrddim_add(st, "system", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
328                     rrddim_add(st, "interrupt", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
329                     rrddim_add(st, "idle", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
330                     rrddim_hide(st, "idle");
331                 }
332                 else rrdset_next(st);
333
334                 rrddim_set(st, "user", cp_time[0]);
335                 rrddim_set(st, "nice", cp_time[1]);
336                 rrddim_set(st, "system", cp_time[2]);
337                 rrddim_set(st, "interrupt", cp_time[3]);
338                 rrddim_set(st, "idle", cp_time[4]);
339                 rrdset_done(st);
340             }
341         }
342     }
343
344     // --------------------------------------------------------------------
345
346     if (likely(do_cpu_cores)) {
347         if (unlikely(CPUSTATES != 5)) {
348             error("FREEBSD: There are %d CPU states (5 was expected)", CPUSTATES);
349             do_cpu_cores = 0;
350             error("DISABLED: cpu.cpuXX");
351         } else {
352             if (unlikely(GETSYSCTL("kern.smp.cpus", ncpus))) {
353                 do_cpu_cores = 0;
354                 error("DISABLED: cpu.cpuXX");
355             } else {
356                 pcpu_cp_time = reallocz(pcpu_cp_time, sizeof(cp_time) * ncpus);
357
358                 for (i = 0; i < ncpus; i++) {
359                     if (unlikely(getsysctl("kern.cp_times", pcpu_cp_time, sizeof(cp_time) * ncpus))) {
360                         do_cpu_cores = 0;
361                         error("DISABLED: cpu.cpuXX");
362                         break;
363                     }
364                     if (unlikely(ncpus > 9999)) {
365                         error("FREEBSD: There are more than 4 digits in cpu cores number");
366                         do_cpu_cores = 0;
367                         error("DISABLED: cpu.cpuXX");
368                         break;
369                     }
370                     snprintfz(cpuid, 8, "cpu%d", i);
371
372                     st = rrdset_find_bytype("cpu", cpuid);
373                     if (unlikely(!st)) {
374                         st = rrdset_create("cpu", cpuid, NULL, "utilization", "cpu.cpu", "Core utilization", "percentage", 1000, update_every, RRDSET_TYPE_STACKED);
375
376                         rrddim_add(st, "user", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
377                         rrddim_add(st, "nice", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
378                         rrddim_add(st, "system", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
379                         rrddim_add(st, "interrupt", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
380                         rrddim_add(st, "idle", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL);
381                         rrddim_hide(st, "idle");
382                     }
383                     else rrdset_next(st);
384
385                     rrddim_set(st, "user", pcpu_cp_time[i * 5 + 0]);
386                     rrddim_set(st, "nice", pcpu_cp_time[i * 5 + 1]);
387                     rrddim_set(st, "system", pcpu_cp_time[i * 5 + 2]);
388                     rrddim_set(st, "interrupt", pcpu_cp_time[i * 5 + 3]);
389                     rrddim_set(st, "idle", pcpu_cp_time[i * 5 + 4]);
390                     rrdset_done(st);
391                 }
392             }
393         }
394     }
395
396     // --------------------------------------------------------------------
397
398     if (likely(do_interrupts)) {
399         if (unlikely(sysctlbyname("hw.intrcnt", NULL, &intrcnt_size, NULL, 0) == -1)) {
400             error("FREEBSD: sysctl(hw.intrcnt...) failed: %s", strerror(errno));
401             do_interrupts = 0;
402             error("DISABLED: system.intr");
403         } else {
404             nintr = intrcnt_size / sizeof(u_long);
405             intrcnt = reallocz(intrcnt, nintr * sizeof(u_long));
406             if (unlikely(getsysctl("hw.intrcnt", intrcnt, nintr * sizeof(u_long)))){
407                 do_interrupts = 0;
408                 error("DISABLED: system.intr");
409             } else {
410                 for (i = 0; i < nintr; i++)
411                     totalintr += intrcnt[i];
412
413                 st = rrdset_find_bytype("system", "intr");
414                 if (unlikely(!st)) {
415                     st = rrdset_create("system", "intr", NULL, "interrupts", NULL, "Total Hardware Interrupts", "interrupts/s", 900, update_every, RRDSET_TYPE_LINE);
416                     st->isdetail = 1;
417
418                     rrddim_add(st, "interrupts", NULL, 1, 1, RRDDIM_INCREMENTAL);
419                 }
420                 else rrdset_next(st);
421
422                 rrddim_set(st, "interrupts", totalintr);
423                 rrdset_done(st);
424
425                 // --------------------------------------------------------------------
426
427                 size = nintr * (MAXCOMLEN +1);
428                 intrnames = reallocz(intrnames, size);
429                 if (unlikely(getsysctl("hw.intrnames", intrnames, size))) {
430                     do_interrupts = 0;
431                     error("DISABLED: system.intr");
432                 } else {
433                     st = rrdset_find_bytype("system", "interrupts");
434                     if (unlikely(!st))
435                         st = rrdset_create("system", "interrupts", NULL, "interrupts", NULL, "System interrupts", "interrupts/s",
436                                            1000, update_every, RRDSET_TYPE_STACKED);
437                     else
438                         rrdset_next(st);
439
440                     for (i = 0; i < nintr; i++) {
441                         p = intrnames + i * (MAXCOMLEN + 1);
442                         if (unlikely((intrcnt[i] != 0) && (*(char*)p != 0))) {
443                             rd = rrddim_find(st, p);
444                             if (unlikely(!rd))
445                                 rd = rrddim_add(st, p, NULL, 1, 1, RRDDIM_INCREMENTAL);
446                             rrddim_set_by_pointer(st, rd, intrcnt[i]);
447                         }
448                     }
449                     rrdset_done(st);
450                 }
451             }
452         }
453     }
454
455     // --------------------------------------------------------------------
456
457     if (likely(do_dev_intr)) {
458         if (unlikely(GETSYSCTL("vm.stats.sys.v_intr", u_int_data))) {
459             do_dev_intr = 0;
460             error("DISABLED: system.dev_intr");
461         } else {
462
463             st = rrdset_find_bytype("system", "dev_intr");
464             if (unlikely(!st)) {
465                 st = rrdset_create("system", "dev_intr", NULL, "interrupts", NULL, "Device Interrupts", "interrupts/s", 1000, update_every, RRDSET_TYPE_LINE);
466
467                 rrddim_add(st, "interrupts", NULL, 1, 1, RRDDIM_INCREMENTAL);
468             }
469             else rrdset_next(st);
470
471             rrddim_set(st, "interrupts", u_int_data);
472             rrdset_done(st);
473         }
474     }
475
476     // --------------------------------------------------------------------
477
478     if (likely(do_soft_intr)) {
479         if (unlikely(GETSYSCTL("vm.stats.sys.v_soft", u_int_data))) {
480             do_soft_intr = 0;
481             error("DISABLED: system.dev_intr");
482         } else {
483
484             st = rrdset_find_bytype("system", "soft_intr");
485             if (unlikely(!st)) {
486                 st = rrdset_create("system", "soft_intr", NULL, "interrupts", NULL, "Software Interrupts", "interrupts/s", 1100, update_every, RRDSET_TYPE_LINE);
487
488                 rrddim_add(st, "interrupts", NULL, 1, 1, RRDDIM_INCREMENTAL);
489             }
490             else rrdset_next(st);
491
492             rrddim_set(st, "interrupts", u_int_data);
493             rrdset_done(st);
494         }
495     }
496
497     // --------------------------------------------------------------------
498
499     if (likely(do_context)) {
500         if (unlikely(GETSYSCTL("vm.stats.sys.v_swtch", u_int_data))) {
501             do_context = 0;
502             error("DISABLED: system.ctxt");
503         } else {
504
505             st = rrdset_find_bytype("system", "ctxt");
506             if (unlikely(!st)) {
507                 st = rrdset_create("system", "ctxt", NULL, "processes", NULL, "CPU Context Switches", "context switches/s", 800, update_every, RRDSET_TYPE_LINE);
508
509                 rrddim_add(st, "switches", NULL, 1, 1, RRDDIM_INCREMENTAL);
510             }
511             else rrdset_next(st);
512
513             rrddim_set(st, "switches", u_int_data);
514             rrdset_done(st);
515         }
516     }
517
518     // --------------------------------------------------------------------
519
520     if (likely(do_forks)) {
521         if (unlikely(GETSYSCTL("vm.stats.vm.v_forks", u_int_data))) {
522             do_forks = 0;
523             error("DISABLED: system.forks");
524         } else {
525
526             st = rrdset_find_bytype("system", "forks");
527             if (unlikely(!st)) {
528                 st = rrdset_create("system", "forks", NULL, "processes", NULL, "Started Processes", "processes/s", 700, update_every, RRDSET_TYPE_LINE);
529                 st->isdetail = 1;
530
531                 rrddim_add(st, "started", NULL, 1, 1, RRDDIM_INCREMENTAL);
532             }
533             else rrdset_next(st);
534
535             rrddim_set(st, "started", u_int_data);
536             rrdset_done(st);
537         }
538     }
539
540     // --------------------------------------------------------------------
541
542     if (likely(do_disk_io)) {
543         if (unlikely(GETSYSCTL("kern.devstat.numdevs", numdevs))) {
544             do_disk_io = 0;
545             error("DISABLED: disk.io");
546         } else {
547             devstat_data = reallocz(devstat_data, sizeof(long) + sizeof(struct devstat) * numdevs); // there is generation number before devstat structures
548             if (unlikely(getsysctl("kern.devstat.all", devstat_data, sizeof(long) + sizeof(struct devstat) * numdevs))) {
549                 do_disk_io = 0;
550                 error("DISABLED: disk.io");
551             } else {
552                 dstat = devstat_data + sizeof(long); // skip generation number
553                 collected_number total_disk_reads = 0;
554                 collected_number total_disk_writes = 0;
555
556                 for (i = 0; i < numdevs; i++) {
557                     if (((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_DIRECT) || ((dstat[i].device_type & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_STORARRAY)) {
558
559                         // --------------------------------------------------------------------
560
561                         st = rrdset_find_bytype(RRD_TYPE_DISK, dstat[i].device_name);
562                         if (unlikely(!st)) {
563                             st = rrdset_create(RRD_TYPE_DISK, dstat[i].device_name, NULL, dstat[i].device_name, "disk.io", "Disk I/O Bandwidth", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA);
564
565                             rrddim_add(st, "reads", NULL, 1, 1024, RRDDIM_INCREMENTAL);
566                             rrddim_add(st, "writes", NULL, -1, 1024, RRDDIM_INCREMENTAL);
567                         }
568                         else rrdset_next(st);
569
570                         total_disk_reads += dstat[i].bytes[DEVSTAT_READ];
571                         total_disk_writes += dstat[i].bytes[DEVSTAT_WRITE];
572                         prev_dstat.bytes_read = rrddim_set(st, "reads", dstat[i].bytes[DEVSTAT_READ]);
573                         prev_dstat.bytes_write = rrddim_set(st, "writes", dstat[i].bytes[DEVSTAT_WRITE]);
574                         rrdset_done(st);
575
576                         // --------------------------------------------------------------------
577
578                         st = rrdset_find_bytype("disk_ops", dstat[i].device_name);
579                         if (unlikely(!st)) {
580                             st = rrdset_create("disk_ops", dstat[i].device_name, NULL, dstat[i].device_name, "disk.ops", "Disk Completed I/O Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE);
581                             st->isdetail = 1;
582
583                             rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
584                             rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL);
585                         }
586                         else rrdset_next(st);
587
588                         prev_dstat.operations_read = rrddim_set(st, "reads", dstat[i].operations[DEVSTAT_READ]);
589                         prev_dstat.operations_write = rrddim_set(st, "writes", dstat[i].operations[DEVSTAT_WRITE]);
590                         rrdset_done(st);
591
592                         // --------------------------------------------------------------------
593
594                         st = rrdset_find_bytype("disk_qops", dstat[i].device_name);
595                         if (unlikely(!st)) {
596                             st = rrdset_create("disk_qops", dstat[i].device_name, NULL, dstat[i].device_name, "disk.qops", "Disk Current I/O Operations", "operations", 2002, update_every, RRDSET_TYPE_LINE);
597                             st->isdetail = 1;
598
599                             rrddim_add(st, "operations", NULL, 1, 1, RRDDIM_ABSOLUTE);
600                         }
601                         else rrdset_next(st);
602
603                         rrddim_set(st, "operations", dstat[i].start_count - dstat[i].end_count);
604                         rrdset_done(st);
605
606                         // --------------------------------------------------------------------
607
608                         st = rrdset_find_bytype("disk_util", dstat[i].device_name);
609                         if (unlikely(!st)) {
610                             st = rrdset_create("disk_util", dstat[i].device_name, NULL, dstat[i].device_name, "disk.util", "Disk Utilization Time", "% of time working", 2004, update_every, RRDSET_TYPE_AREA);
611                             st->isdetail = 1;
612
613                             rrddim_add(st, "utilization", NULL, 1, 10, RRDDIM_INCREMENTAL);
614                         }
615                         else rrdset_next(st);
616
617                         cur_dstat.busy_time_ms = dstat[i].busy_time.sec * 1000 + dstat[i].busy_time.frac * BINTIME_SCALE;
618                         prev_dstat.busy_time_ms = rrddim_set(st, "utilization", cur_dstat.busy_time_ms);
619                         rrdset_done(st);
620
621                         // --------------------------------------------------------------------
622
623                         st = rrdset_find_bytype("disk_iotime", dstat[i].device_name);
624                         if (unlikely(!st)) {
625                             st = rrdset_create("disk_iotime", dstat[i].device_name, NULL, dstat[i].device_name, "disk.iotime", "Disk Total I/O Time", "milliseconds/s", 2022, update_every, RRDSET_TYPE_LINE);
626                             st->isdetail = 1;
627
628                             rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
629                             rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL);
630                         }
631                         else rrdset_next(st);
632
633                         cur_dstat.duration_read_ms = dstat[i].duration[DEVSTAT_READ].sec * 1000 + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
634                         cur_dstat.duration_write_ms = dstat[i].duration[DEVSTAT_WRITE].sec * 1000 + dstat[i].duration[DEVSTAT_READ].frac * BINTIME_SCALE;
635                         prev_dstat.duration_read_ms = rrddim_set(st, "reads", cur_dstat.duration_read_ms);
636                         prev_dstat.duration_write_ms = rrddim_set(st, "writes", cur_dstat.duration_write_ms);
637                         rrdset_done(st);
638
639                         // --------------------------------------------------------------------
640                         // calculate differential charts
641                         // only if this is not the first time we run
642
643                         if (likely(dt)) {
644
645                             // --------------------------------------------------------------------
646
647                             st = rrdset_find_bytype("disk_await", dstat[i].device_name);
648                             if (unlikely(!st)) {
649                                 st = rrdset_create("disk_await", dstat[i].device_name, NULL, dstat[i].device_name, "disk.await", "Average Completed I/O Operation Time", "ms per operation", 2005, update_every, RRDSET_TYPE_LINE);
650                                 st->isdetail = 1;
651
652                                 rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_ABSOLUTE);
653                                 rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_ABSOLUTE);
654                             }
655                             else rrdset_next(st);
656
657                             rrddim_set(st, "reads", (dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) ?
658                                 (cur_dstat.duration_read_ms - prev_dstat.duration_read_ms) / (dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) : 0);
659                             rrddim_set(st, "writes", (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write) ?
660                                 (cur_dstat.duration_write_ms - prev_dstat.duration_write_ms) / (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write) : 0);
661                             rrdset_done(st);
662
663                             // --------------------------------------------------------------------
664
665                             st = rrdset_find_bytype("disk_avgsz", dstat[i].device_name);
666                             if (unlikely(!st)) {
667                                 st = rrdset_create("disk_avgsz", dstat[i].device_name, NULL, dstat[i].device_name, "disk.avgsz", "Average Completed I/O Operation Bandwidth", "kilobytes per operation", 2006, update_every, RRDSET_TYPE_AREA);
668                                 st->isdetail = 1;
669
670                                 rrddim_add(st, "reads", NULL, 1, 1024, RRDDIM_ABSOLUTE);
671                                 rrddim_add(st, "writes", NULL, -1, 1024, RRDDIM_ABSOLUTE);
672                             }
673                             else rrdset_next(st);
674
675                             rrddim_set(st, "reads", (dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) ?
676                                 (dstat[i].bytes[DEVSTAT_READ] - prev_dstat.bytes_read) / (dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) : 0);
677                             rrddim_set(st, "writes", (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write) ?
678                                 (dstat[i].bytes[DEVSTAT_WRITE] - prev_dstat.bytes_write) / (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write) : 0);
679                             rrdset_done(st);
680
681                             // --------------------------------------------------------------------
682
683                             st = rrdset_find_bytype("disk_svctm", dstat[i].device_name);
684                             if (unlikely(!st)) {
685                                 st = rrdset_create("disk_svctm", dstat[i].device_name, NULL, dstat[i].device_name, "disk.svctm", "Average Service Time", "ms per operation", 2007, update_every, RRDSET_TYPE_LINE);
686                                 st->isdetail = 1;
687
688                                 rrddim_add(st, "svctm", NULL, 1, 1, RRDDIM_ABSOLUTE);
689                             }
690                             else rrdset_next(st);
691
692                             rrddim_set(st, "svctm", ((dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) + (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write)) ?
693                                 (cur_dstat.busy_time_ms - prev_dstat.busy_time_ms) / ((dstat[i].operations[DEVSTAT_READ] - prev_dstat.operations_read) + (dstat[i].operations[DEVSTAT_WRITE] - prev_dstat.operations_write)) : 0);
694                             rrdset_done(st);
695                         }
696                     }
697
698                     // --------------------------------------------------------------------
699
700                     st = rrdset_find_bytype("system", "io");
701                     if (unlikely(!st)) {
702                         st = rrdset_create("system", "io", NULL, "disk", NULL, "Disk I/O", "kilobytes/s", 150, update_every, RRDSET_TYPE_AREA);
703                         rrddim_add(st, "in",  NULL,  1, 1024, RRDDIM_INCREMENTAL);
704                         rrddim_add(st, "out", NULL, -1, 1024, RRDDIM_INCREMENTAL);
705                     }
706                     else rrdset_next(st);
707
708                     rrddim_set(st, "in", total_disk_reads);
709                     rrddim_set(st, "out", total_disk_writes);
710                     rrdset_done(st);
711                 }
712             }
713         }
714     }
715
716     // --------------------------------------------------------------------
717
718
719     if (likely(do_swap)) {
720         mibsize = sizeof mib / sizeof mib[0];
721         if (unlikely(sysctlnametomib("vm.swap_info", mib, &mibsize) == -1)) {
722             error("FREEBSD: sysctl(%s...) failed: %s", "vm.swap_info", strerror(errno));
723             do_swap = 0;
724             error("DISABLED: system.swap");
725         } else {
726             for (i = 0; ; i++) {
727                 mib[mibsize] = i;
728                 size = sizeof(xsw);
729                 if (unlikely(sysctl(mib, mibsize + 1, &xsw, &size, NULL, 0) == -1 )) {
730                     if (unlikely(errno != ENOENT)) {
731                         error("FREEBSD: sysctl(%s...) failed: %s", "vm.swap_info", strerror(errno));
732                         do_swap = 0;
733                         error("DISABLED: system.swap");
734                     } else {
735                         if (unlikely(size != sizeof(xsw))) {
736                             error("FREEBSD: sysctl(%s...) expected %lu, got %lu", "vm.swap_info", (unsigned long)sizeof(xsw), (unsigned long)size);
737                             do_swap = 0;
738                             error("DISABLED: system.swap");
739                         } else break;
740                     }
741                 }
742                 total_xsw.bytes_used += xsw.xsw_used;
743                 total_xsw.bytes_total += xsw.xsw_nblks;
744             }
745
746             if (likely(do_swap)) {
747                 st = rrdset_find("system.swap");
748                 if (unlikely(!st)) {
749                     st = rrdset_create("system", "swap", NULL, "swap", NULL, "System Swap", "MB", 201, update_every, RRDSET_TYPE_STACKED);
750                     st->isdetail = 1;
751
752                     rrddim_add(st, "free",    NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE);
753                     rrddim_add(st, "used",    NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE);
754                 }
755                 else rrdset_next(st);
756
757                 rrddim_set(st, "used", total_xsw.bytes_used);
758                 rrddim_set(st, "free", total_xsw.bytes_total - total_xsw.bytes_used);
759                 rrdset_done(st);
760             }
761         }
762     }
763
764     // --------------------------------------------------------------------
765
766     if (likely(do_ram)) {
767         if (unlikely(GETSYSCTL("vm.stats.vm.v_active_count",    vmmeter_data.v_active_count) ||
768                      GETSYSCTL("vm.stats.vm.v_inactive_count",  vmmeter_data.v_inactive_count) ||
769                      GETSYSCTL("vm.stats.vm.v_wire_count",      vmmeter_data.v_wire_count) ||
770                      GETSYSCTL("vm.stats.vm.v_cache_count",     vmmeter_data.v_cache_count) ||
771                      GETSYSCTL("vfs.bufspace",                  vfs_bufspace_count) ||
772                      GETSYSCTL("vm.stats.vm.v_free_count",      vmmeter_data.v_free_count))) {
773             do_ram = 0;
774             error("DISABLED: system.ram");
775         } else {
776             st = rrdset_find("system.ram");
777             if (unlikely(!st)) {
778                 st = rrdset_create("system", "ram", NULL, "ram", NULL, "System RAM", "MB", 200, update_every, RRDSET_TYPE_STACKED);
779
780                 rrddim_add(st, "active",    NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE);
781                 rrddim_add(st, "inactive",  NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE);
782                 rrddim_add(st, "wired",     NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE);
783                 rrddim_add(st, "cache",     NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE);
784                 rrddim_add(st, "buffers",   NULL, 1, 1048576, RRDDIM_ABSOLUTE);
785                 rrddim_add(st, "free",      NULL, system_pagesize, 1048576, RRDDIM_ABSOLUTE);
786             }
787             else rrdset_next(st);
788
789             rrddim_set(st, "active",    vmmeter_data.v_active_count);
790             rrddim_set(st, "inactive",  vmmeter_data.v_inactive_count);
791             rrddim_set(st, "wired",     vmmeter_data.v_wire_count);
792             rrddim_set(st, "cache",     vmmeter_data.v_cache_count);
793             rrddim_set(st, "buffers",   vfs_bufspace_count);
794             rrddim_set(st, "free",      vmmeter_data.v_free_count);
795             rrdset_done(st);
796         }
797     }
798
799     // --------------------------------------------------------------------
800
801     if (likely(do_swapio)) {
802         if (unlikely(GETSYSCTL("vm.stats.vm.v_swappgsin", vmmeter_data.v_swappgsin) || GETSYSCTL("vm.stats.vm.v_swappgsout", vmmeter_data.v_swappgsout))) {
803             do_swapio = 0;
804             error("DISABLED: system.swapio");
805         } else {
806             st = rrdset_find("system.swapio");
807             if (unlikely(!st)) {
808                 st = rrdset_create("system", "swapio", NULL, "swap", NULL, "Swap I/O", "kilobytes/s", 250, update_every, RRDSET_TYPE_AREA);
809
810                 rrddim_add(st, "in",  NULL, system_pagesize, 1024, RRDDIM_INCREMENTAL);
811                 rrddim_add(st, "out", NULL, -system_pagesize, 1024, RRDDIM_INCREMENTAL);
812             }
813             else rrdset_next(st);
814
815             rrddim_set(st, "in", vmmeter_data.v_swappgsin);
816             rrddim_set(st, "out", vmmeter_data.v_swappgsout);
817             rrdset_done(st);
818         }
819     }
820
821     // --------------------------------------------------------------------
822
823     if (likely(do_pgfaults)) {
824         if (unlikely(GETSYSCTL("vm.stats.vm.v_vm_faults",   vmmeter_data.v_vm_faults) ||
825                      GETSYSCTL("vm.stats.vm.v_io_faults",   vmmeter_data.v_io_faults) ||
826                      GETSYSCTL("vm.stats.vm.v_cow_faults",  vmmeter_data.v_cow_faults) ||
827                      GETSYSCTL("vm.stats.vm.v_cow_optim",   vmmeter_data.v_cow_optim) ||
828                      GETSYSCTL("vm.stats.vm.v_intrans",     vmmeter_data.v_intrans))) {
829             do_pgfaults = 0;
830             error("DISABLED: mem.pgfaults");
831         } else {
832             st = rrdset_find("mem.pgfaults");
833             if (unlikely(!st)) {
834                 st = rrdset_create("mem", "pgfaults", NULL, "system", NULL, "Memory Page Faults", "page faults/s", 500, update_every, RRDSET_TYPE_LINE);
835                 st->isdetail = 1;
836
837                 rrddim_add(st, "memory", NULL, 1, 1, RRDDIM_INCREMENTAL);
838                 rrddim_add(st, "io_requiring", NULL, 1, 1, RRDDIM_INCREMENTAL);
839                 rrddim_add(st, "cow", NULL, 1, 1, RRDDIM_INCREMENTAL);
840                 rrddim_add(st, "cow_optimized", NULL, 1, 1, RRDDIM_INCREMENTAL);
841                 rrddim_add(st, "in_transit", NULL, 1, 1, RRDDIM_INCREMENTAL);
842             }
843             else rrdset_next(st);
844
845             rrddim_set(st, "memory", vmmeter_data.v_vm_faults);
846             rrddim_set(st, "io_requiring", vmmeter_data.v_io_faults);
847             rrddim_set(st, "cow", vmmeter_data.v_cow_faults);
848             rrddim_set(st, "cow_optimized", vmmeter_data.v_cow_optim);
849             rrddim_set(st, "in_transit", vmmeter_data.v_intrans);
850             rrdset_done(st);
851         }
852     }
853
854     // --------------------------------------------------------------------
855
856     if (likely(do_ipc_semaphores)) {
857         if (unlikely(GETSYSCTL("kern.ipc.semmni", ipc_sem.semmni))) {
858             do_ipc_semaphores = 0;
859             error("DISABLED: system.ipc_semaphores");
860             error("DISABLED: system.ipc_semaphore_arrays");
861         } else {
862             ipc_sem_data = reallocz(ipc_sem_data, sizeof(struct semid_kernel) * ipc_sem.semmni);
863             if (unlikely(getsysctl("kern.ipc.sema", ipc_sem_data, sizeof(struct semid_kernel) * ipc_sem.semmni))) {
864                 do_ipc_semaphores = 0;
865                 error("DISABLED: system.ipc_semaphores");
866                 error("DISABLED: system.ipc_semaphore_arrays");
867             } else {
868                 for (i = 0; i < ipc_sem.semmni; i++) {
869                     if (unlikely(ipc_sem_data[i].u.sem_perm.mode & SEM_ALLOC)) {
870                         ipc_sem.sets += 1;
871                         ipc_sem.semaphores += ipc_sem_data[i].u.sem_nsems;
872                     }
873                 }
874
875                 // --------------------------------------------------------------------
876
877                 st = rrdset_find("system.ipc_semaphores");
878                 if (unlikely(!st)) {
879                     st = rrdset_create("system", "ipc_semaphores", NULL, "ipc semaphores", NULL, "IPC Semaphores", "semaphores", 1000, rrd_update_every, RRDSET_TYPE_AREA);
880                     rrddim_add(st, "semaphores", NULL, 1, 1, RRDDIM_ABSOLUTE);
881                 }
882                 else rrdset_next(st);
883
884                 rrddim_set(st, "semaphores", ipc_sem.semaphores);
885                 rrdset_done(st);
886
887                 // --------------------------------------------------------------------
888
889                 st = rrdset_find("system.ipc_semaphore_arrays");
890                 if (unlikely(!st)) {
891                     st = rrdset_create("system", "ipc_semaphore_arrays", NULL, "ipc semaphores", NULL, "IPC Semaphore Arrays", "arrays", 1000, rrd_update_every, RRDSET_TYPE_AREA);
892                     rrddim_add(st, "arrays", NULL, 1, 1, RRDDIM_ABSOLUTE);
893                 }
894                 else rrdset_next(st);
895
896                 rrddim_set(st, "arrays", ipc_sem.sets);
897                 rrdset_done(st);
898             }
899         }
900     }
901
902     // --------------------------------------------------------------------
903
904     if (likely(do_ipc_shared_mem)) {
905         if (unlikely(GETSYSCTL("kern.ipc.shmmni", ipc_shm.shmmni))) {
906             do_ipc_shared_mem = 0;
907             error("DISABLED: system.ipc_shared_mem_segs");
908             error("DISABLED: system.ipc_shared_mem_size");
909         } else {
910             ipc_shm_data = reallocz(ipc_shm_data, sizeof(struct shmid_kernel) * ipc_shm.shmmni);
911             if (unlikely(getsysctl("kern.ipc.shmsegs", ipc_shm_data, sizeof(struct shmid_kernel) * ipc_shm.shmmni))) {
912                 do_ipc_shared_mem = 0;
913                 error("DISABLED: system.ipc_shared_mem_segs");
914                 error("DISABLED: system.ipc_shared_mem_size");
915             } else {
916                 for (i = 0; i < ipc_shm.shmmni; i++) {
917                     if (unlikely(ipc_shm_data[i].u.shm_perm.mode & 0x0800)) {
918                         ipc_shm.segs += 1;
919                         ipc_shm.segsize += ipc_shm_data[i].u.shm_segsz;
920                     }
921                 }
922
923                 // --------------------------------------------------------------------
924
925                 st = rrdset_find("system.ipc_shared_mem_segs");
926                 if (unlikely(!st)) {
927                     st = rrdset_create("system", "ipc_shared_mem_segs", NULL, "ipc shared memory", NULL, "IPC Shared Memory Segments", "segments", 1000, rrd_update_every, RRDSET_TYPE_AREA);
928                     rrddim_add(st, "segments", NULL, 1, 1, RRDDIM_ABSOLUTE);
929                 }
930                 else rrdset_next(st);
931
932                 rrddim_set(st, "segments", ipc_shm.segs);
933                 rrdset_done(st);
934
935                 // --------------------------------------------------------------------
936
937                 st = rrdset_find("system.ipc_shared_mem_size");
938                 if (unlikely(!st)) {
939                     st = rrdset_create("system", "ipc_shared_mem_size", NULL, "ipc shared memory", NULL, "IPC Shared Memory Segments Size", "kilobytes", 1000, rrd_update_every, RRDSET_TYPE_AREA);
940                     rrddim_add(st, "allocated", NULL, 1, 1024, RRDDIM_ABSOLUTE);
941                 }
942                 else rrdset_next(st);
943
944                 rrddim_set(st, "allocated", ipc_shm.segsize);
945                 rrdset_done(st);
946             }
947         }
948     }
949
950     // --------------------------------------------------------------------
951
952     if (likely(do_ipc_msg_queues)) {
953         if (unlikely(GETSYSCTL("kern.ipc.msgmni", ipc_msq.msgmni))) {
954             do_ipc_msg_queues = 0;
955             error("DISABLED: system.ipc_msq_queues");
956             error("DISABLED: system.ipc_msq_messages");
957             error("DISABLED: system.ipc_msq_size");
958         } else {
959             ipc_msq_data = reallocz(ipc_msq_data, sizeof(struct msqid_kernel) * ipc_msq.msgmni);
960             if (unlikely(getsysctl("kern.ipc.msqids", ipc_msq_data, sizeof(struct msqid_kernel) * ipc_msq.msgmni))) {
961                 do_ipc_msg_queues = 0;
962                 error("DISABLED: system.ipc_msq_queues");
963                 error("DISABLED: system.ipc_msq_messages");
964                 error("DISABLED: system.ipc_msq_size");
965             } else {
966                 for (i = 0; i < ipc_msq.msgmni; i++) {
967                     if (unlikely(ipc_msq_data[i].u.msg_qbytes != 0)) {
968                         ipc_msq.queues += 1;
969                         ipc_msq.messages += ipc_msq_data[i].u.msg_qnum;
970                         ipc_msq.usedsize += ipc_msq_data[i].u.msg_cbytes;
971                         ipc_msq.allocsize += ipc_msq_data[i].u.msg_qbytes;
972                     }
973                 }
974
975                 // --------------------------------------------------------------------
976
977                 st = rrdset_find("system.ipc_msq_queues");
978                 if (unlikely(!st)) {
979                     st = rrdset_create("system", "ipc_msq_queues", NULL, "ipc message queues", NULL, "Number of IPC Message Queues", "queues", 990, rrd_update_every, RRDSET_TYPE_AREA);
980                     rrddim_add(st, "queues", NULL, 1, 1, RRDDIM_ABSOLUTE);
981                 }
982                 else rrdset_next(st);
983
984                 rrddim_set(st, "queues", ipc_msq.queues);
985                 rrdset_done(st);
986
987                 // --------------------------------------------------------------------
988
989                 st = rrdset_find("system.ipc_msq_messages");
990                 if (unlikely(!st)) {
991                     st = rrdset_create("system", "ipc_msq_messages", NULL, "ipc message queues", NULL, "Number of Messages in IPC Message Queues", "messages", 1000, rrd_update_every, RRDSET_TYPE_AREA);
992                     rrddim_add(st, "messages", NULL, 1, 1, RRDDIM_ABSOLUTE);
993                 }
994                 else rrdset_next(st);
995
996                 rrddim_set(st, "messages", ipc_msq.messages);
997                 rrdset_done(st);
998
999                 // --------------------------------------------------------------------
1000
1001                 st = rrdset_find("system.ipc_msq_size");
1002                 if (unlikely(!st)) {
1003                     st = rrdset_create("system", "ipc_msq_size", NULL, "ipc message queues", NULL, "Size of IPC Message Queues", "bytes", 1100, rrd_update_every, RRDSET_TYPE_LINE);
1004                     rrddim_add(st, "allocated", NULL, 1, 1, RRDDIM_ABSOLUTE);
1005                     rrddim_add(st, "used", NULL, 1, 1, RRDDIM_ABSOLUTE);
1006                 }
1007                 else rrdset_next(st);
1008
1009                 rrddim_set(st, "allocated", ipc_msq.allocsize);
1010                 rrddim_set(st, "used", ipc_msq.usedsize);
1011                 rrdset_done(st);
1012
1013             }
1014         }
1015     }
1016
1017     // --------------------------------------------------------------------
1018
1019     if (likely(do_netisr || do_netisr_per_core)) {
1020         if (unlikely(GETSYSCTL("kern.smp.cpus", ncpus))) {
1021             common_error = 1;
1022         } else if (unlikely(ncpus > 9999)) {
1023             error("FREEBSD: There are more than 4 digits in cpu cores number");
1024             common_error = 1;
1025         } else if (unlikely(sysctlbyname("net.isr.workstream", NULL, &netisr_workstream_size, NULL, 0) == -1)) {
1026             error("FREEBSD: sysctl(net.isr.workstream...) failed: %s", strerror(errno));
1027             common_error = 1;
1028         } else if (unlikely(sysctlbyname("net.isr.work", NULL, &netisr_work_size, NULL, 0) == -1)) {
1029             error("FREEBSD: sysctl(net.isr.work...) failed: %s", strerror(errno));
1030             common_error = 1;
1031         } else {
1032             num_netisr_workstreams = netisr_workstream_size / sizeof(struct sysctl_netisr_workstream);
1033             netisr_workstream = reallocz(netisr_workstream, num_netisr_workstreams * sizeof(struct sysctl_netisr_workstream));
1034             if (unlikely(getsysctl("net.isr.workstream", netisr_workstream, num_netisr_workstreams * sizeof(struct sysctl_netisr_workstream)))){
1035                 common_error = 1;
1036             } else {
1037                 num_netisr_works = netisr_work_size / sizeof(struct sysctl_netisr_work);
1038                 netisr_work = reallocz(netisr_work, num_netisr_works * sizeof(struct sysctl_netisr_work));
1039                 if (unlikely(getsysctl("net.isr.work", netisr_work, num_netisr_works * sizeof(struct sysctl_netisr_work)))){
1040                     common_error = 1;
1041                 }
1042             }
1043         }
1044         if (unlikely(common_error)) {
1045             do_netisr = 0;
1046             error("DISABLED: system.softnet_stat");
1047             do_netisr_per_core = 0;
1048             error("DISABLED: system.cpuX_softnet_stat");
1049             common_error = 0;
1050         } else {
1051             netisr_stats = reallocz(netisr_stats, (ncpus + 1) * sizeof(struct netisr_stats));
1052             bzero(netisr_stats, (ncpus + 1) * sizeof(struct netisr_stats));
1053             for (i = 0; i < num_netisr_workstreams; i++) {
1054                 for (n = 0; n < num_netisr_works; n++) {
1055                     if (netisr_workstream[i].snws_wsid == netisr_work[n].snw_wsid) {
1056                         netisr_stats[netisr_workstream[i].snws_cpu].dispatched += netisr_work[n].snw_dispatched;
1057                         netisr_stats[netisr_workstream[i].snws_cpu].hybrid_dispatched += netisr_work[n].snw_hybrid_dispatched;
1058                         netisr_stats[netisr_workstream[i].snws_cpu].qdrops += netisr_work[n].snw_qdrops;
1059                         netisr_stats[netisr_workstream[i].snws_cpu].queued += netisr_work[n].snw_queued;
1060                     }
1061                 }
1062             }
1063             for (i = 0; i < ncpus; i++) {
1064                 netisr_stats[ncpus].dispatched += netisr_stats[i].dispatched;
1065                 netisr_stats[ncpus].hybrid_dispatched += netisr_stats[i].hybrid_dispatched;
1066                 netisr_stats[ncpus].qdrops += netisr_stats[i].qdrops;
1067                 netisr_stats[ncpus].queued += netisr_stats[i].queued;
1068             }
1069         }
1070     }
1071
1072     // --------------------------------------------------------------------
1073
1074     if (likely(do_netisr)) {
1075         st = rrdset_find_bytype("system", "softnet_stat");
1076         if (unlikely(!st)) {
1077             st = rrdset_create("system", "softnet_stat", NULL, "softnet_stat", NULL, "System softnet_stat", "events/s", 955, update_every, RRDSET_TYPE_LINE);
1078             rrddim_add(st, "dispatched", NULL, 1, 1, RRDDIM_INCREMENTAL);
1079             rrddim_add(st, "hybrid_dispatched", NULL, 1, 1, RRDDIM_INCREMENTAL);
1080             rrddim_add(st, "qdrops", NULL, 1, 1, RRDDIM_INCREMENTAL);
1081             rrddim_add(st, "queued", NULL, 1, 1, RRDDIM_INCREMENTAL);
1082         }
1083         else rrdset_next(st);
1084
1085         rrddim_set(st, "dispatched", netisr_stats[ncpus].dispatched);
1086         rrddim_set(st, "hybrid_dispatched", netisr_stats[ncpus].hybrid_dispatched);
1087         rrddim_set(st, "qdrops", netisr_stats[ncpus].qdrops);
1088         rrddim_set(st, "queued", netisr_stats[ncpus].queued);
1089         rrdset_done(st);
1090     }
1091
1092     // --------------------------------------------------------------------
1093
1094     if (likely(do_netisr_per_core)) {
1095         for (i = 0; i < ncpus ;i++) {
1096             snprintfz(netstat_cpuid, 21, "cpu%d_softnet_stat", i);
1097
1098             st = rrdset_find_bytype("cpu", netstat_cpuid);
1099             if (unlikely(!st)) {
1100                 st = rrdset_create("cpu", netstat_cpuid, NULL, "softnet_stat", NULL, "Per CPU netisr statistics", "events/s", 1101 + i, update_every, RRDSET_TYPE_LINE);
1101                 rrddim_add(st, "dispatched", NULL, 1, 1, RRDDIM_INCREMENTAL);
1102                 rrddim_add(st, "hybrid_dispatched", NULL, 1, 1, RRDDIM_INCREMENTAL);
1103                 rrddim_add(st, "qdrops", NULL, 1, 1, RRDDIM_INCREMENTAL);
1104                 rrddim_add(st, "queued", NULL, 1, 1, RRDDIM_INCREMENTAL);
1105             }
1106             else rrdset_next(st);
1107
1108             rrddim_set(st, "dispatched", netisr_stats[i].dispatched);
1109             rrddim_set(st, "hybrid_dispatched", netisr_stats[i].hybrid_dispatched);
1110             rrddim_set(st, "qdrops", netisr_stats[i].qdrops);
1111             rrddim_set(st, "queued", netisr_stats[i].queued);
1112             rrdset_done(st);
1113         }
1114     }
1115
1116     // --------------------------------------------------------------------
1117
1118     if (likely(do_bandwidth)) {
1119         if (unlikely(getifaddrs(&ifap))) {
1120             error("FREEBSD: getifaddrs()");
1121             do_bandwidth = 0;
1122             error("DISABLED: system.ipv4");
1123         } else {
1124             iftot.ift_ibytes = iftot.ift_obytes = 0;
1125             for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1126                 if (ifa->ifa_addr->sa_family != AF_INET)
1127                         continue;
1128                 iftot.ift_ibytes += IFA_DATA(ibytes);
1129                 iftot.ift_obytes += IFA_DATA(obytes);
1130             }
1131
1132             st = rrdset_find("system.ipv4");
1133             if (unlikely(!st)) {
1134                 st = rrdset_create("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA);
1135
1136                 rrddim_add(st, "InOctets", "received", 8, 1024, RRDDIM_INCREMENTAL);
1137                 rrddim_add(st, "OutOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL);
1138             }
1139             else rrdset_next(st);
1140
1141             rrddim_set(st, "InOctets", iftot.ift_ibytes);
1142             rrddim_set(st, "OutOctets", iftot.ift_obytes);
1143             rrdset_done(st);
1144
1145             // --------------------------------------------------------------------
1146
1147             iftot.ift_ibytes = iftot.ift_obytes = 0;
1148             for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1149                 if (ifa->ifa_addr->sa_family != AF_INET6)
1150                         continue;
1151                 iftot.ift_ibytes += IFA_DATA(ibytes);
1152                 iftot.ift_obytes += IFA_DATA(obytes);
1153             }
1154
1155             st = rrdset_find("system.ipv6");
1156             if (unlikely(!st)) {
1157                 st = rrdset_create("system", "ipv6", NULL, "network", NULL, "IPv6 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA);
1158
1159                 rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
1160                 rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
1161             }
1162             else rrdset_next(st);
1163
1164             rrddim_set(st, "sent", iftot.ift_obytes);
1165             rrddim_set(st, "received", iftot.ift_ibytes);
1166             rrdset_done(st);
1167
1168             for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1169                 if (ifa->ifa_addr->sa_family != AF_LINK)
1170                         continue;
1171
1172                 // --------------------------------------------------------------------
1173
1174                 st = rrdset_find_bytype("net", ifa->ifa_name);
1175                 if (unlikely(!st)) {
1176                     st = rrdset_create("net", ifa->ifa_name, NULL, ifa->ifa_name, "net.net", "Bandwidth", "kilobits/s", 7000, update_every, RRDSET_TYPE_AREA);
1177
1178                     rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL);
1179                     rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL);
1180                 }
1181                 else rrdset_next(st);
1182
1183                 rrddim_set(st, "received", IFA_DATA(ibytes));
1184                 rrddim_set(st, "sent", IFA_DATA(obytes));
1185                 rrdset_done(st);
1186
1187                 // --------------------------------------------------------------------
1188
1189                 st = rrdset_find_bytype("net_packets", ifa->ifa_name);
1190                 if (unlikely(!st)) {
1191                     st = rrdset_create("net_packets", ifa->ifa_name, NULL, ifa->ifa_name, "net.packets", "Packets", "packets/s", 7001, update_every, RRDSET_TYPE_LINE);
1192                     st->isdetail = 1;
1193
1194                     rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
1195                     rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
1196                     rrddim_add(st, "multicast_received", NULL, 1, 1, RRDDIM_INCREMENTAL);
1197                     rrddim_add(st, "multicast_sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
1198                 }
1199                 else rrdset_next(st);
1200
1201                 rrddim_set(st, "received", IFA_DATA(ipackets));
1202                 rrddim_set(st, "sent", IFA_DATA(opackets));
1203                 rrddim_set(st, "multicast_received", IFA_DATA(imcasts));
1204                 rrddim_set(st, "multicast_sent", IFA_DATA(omcasts));
1205                 rrdset_done(st);
1206
1207                 // --------------------------------------------------------------------
1208
1209                 st = rrdset_find_bytype("net_errors", ifa->ifa_name);
1210                 if (unlikely(!st)) {
1211                     st = rrdset_create("net_errors", ifa->ifa_name, NULL, ifa->ifa_name, "net.errors", "Interface Errors", "errors/s", 7002, update_every, RRDSET_TYPE_LINE);
1212                     st->isdetail = 1;
1213
1214                     rrddim_add(st, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL);
1215                     rrddim_add(st, "outbound", NULL, -1, 1, RRDDIM_INCREMENTAL);
1216                 }
1217                 else rrdset_next(st);
1218
1219                 rrddim_set(st, "inbound", IFA_DATA(ierrors));
1220                 rrddim_set(st, "outbound", IFA_DATA(oerrors));
1221                 rrdset_done(st);
1222
1223                 // --------------------------------------------------------------------
1224
1225                 st = rrdset_find_bytype("net_drops", ifa->ifa_name);
1226                 if (unlikely(!st)) {
1227                     st = rrdset_create("net_drops", ifa->ifa_name, NULL, ifa->ifa_name, "net.drops", "Interface Drops", "drops/s", 7003, update_every, RRDSET_TYPE_LINE);
1228                     st->isdetail = 1;
1229
1230                     rrddim_add(st, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL);
1231                     rrddim_add(st, "outbound", NULL, -1, 1, RRDDIM_INCREMENTAL);
1232                 }
1233                 else rrdset_next(st);
1234
1235                 rrddim_set(st, "inbound", IFA_DATA(iqdrops));
1236                 rrddim_set(st, "outbound", IFA_DATA(oqdrops));
1237                 rrdset_done(st);
1238
1239                 // --------------------------------------------------------------------
1240
1241                 st = rrdset_find_bytype("net_events", ifa->ifa_name);
1242                 if (unlikely(!st)) {
1243                     st = rrdset_create("net_events", ifa->ifa_name, NULL, ifa->ifa_name, "net.events", "Network Interface Events", "events/s", 7006, update_every, RRDSET_TYPE_LINE);
1244                     st->isdetail = 1;
1245
1246                     rrddim_add(st, "frames", NULL, 1, 1, RRDDIM_INCREMENTAL);
1247                     rrddim_add(st, "collisions", NULL, -1, 1, RRDDIM_INCREMENTAL);
1248                     rrddim_add(st, "carrier", NULL, -1, 1, RRDDIM_INCREMENTAL);
1249                 }
1250                 else rrdset_next(st);
1251
1252                 rrddim_set(st, "collisions", IFA_DATA(collisions));
1253                 rrdset_done(st);
1254             }
1255
1256             freeifaddrs(ifap);
1257         }
1258     }
1259
1260     // --------------------------------------------------------------------
1261
1262     // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html
1263     if (likely(do_tcp_sockets)) {
1264         if (unlikely(GETSYSCTL("net.inet.tcp.states", tcps_states))) {
1265             do_tcp_sockets = 0;
1266             error("DISABLED: ipv4.tcpsock");
1267         } else {
1268             if (likely(do_tcp_sockets)) {
1269                 st = rrdset_find("ipv4.tcpsock");
1270                 if (unlikely(!st)) {
1271                     st = rrdset_create("ipv4", "tcpsock", NULL, "tcp", NULL, "IPv4 TCP Connections",
1272                                        "active connections", 2500, update_every, RRDSET_TYPE_LINE);
1273
1274                     rrddim_add(st, "CurrEstab", "connections", 1, 1, RRDDIM_ABSOLUTE);
1275                 } else
1276                     rrdset_next(st);
1277
1278                 rrddim_set(st, "CurrEstab", tcps_states[TCPS_ESTABLISHED]);
1279                 rrdset_done(st);
1280             }
1281         }
1282     }
1283
1284     // --------------------------------------------------------------------
1285
1286     // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html
1287     if (likely(do_tcp_packets || do_tcp_errors || do_tcp_handshake || do_tcpext_connaborts || do_tcpext_ofo || do_tcpext_syscookies || do_ecn)) {
1288         if (unlikely(GETSYSCTL("net.inet.tcp.stats", tcpstat))){
1289             do_tcp_packets = 0;
1290             error("DISABLED: ipv4.tcppackets");
1291             do_tcp_errors = 0;
1292             error("DISABLED: ipv4.tcperrors");
1293             do_tcp_handshake = 0;
1294             error("DISABLED: ipv4.tcphandshake");
1295             do_tcpext_connaborts = 0;
1296             error("DISABLED: ipv4.tcpconnaborts");
1297             do_tcpext_ofo = 0;
1298             error("DISABLED: ipv4.tcpofo");
1299             do_tcpext_syscookies = 0;
1300             error("DISABLED: ipv4.tcpsyncookies");
1301             do_ecn = 0;
1302             error("DISABLED: ipv4.ecnpkts");
1303         } else {
1304             if (likely(do_tcp_packets)) {
1305                 st = rrdset_find("ipv4.tcppackets");
1306                 if (unlikely(!st)) {
1307                     st = rrdset_create("ipv4", "tcppackets", NULL, "tcp", NULL, "IPv4 TCP Packets",
1308                                        "packets/s",
1309                                        2600, update_every, RRDSET_TYPE_LINE);
1310
1311                     rrddim_add(st, "InSegs", "received", 1, 1, RRDDIM_INCREMENTAL);
1312                     rrddim_add(st, "OutSegs", "sent", -1, 1, RRDDIM_INCREMENTAL);
1313                 } else
1314                     rrdset_next(st);
1315
1316                 rrddim_set(st, "InSegs", tcpstat.tcps_rcvtotal);
1317                 rrddim_set(st, "OutSegs", tcpstat.tcps_sndtotal);
1318                 rrdset_done(st);
1319             }
1320
1321             // --------------------------------------------------------------------
1322
1323             if (likely(do_tcp_errors)) {
1324                 st = rrdset_find("ipv4.tcperrors");
1325                 if (unlikely(!st)) {
1326                     st = rrdset_create("ipv4", "tcperrors", NULL, "tcp", NULL, "IPv4 TCP Errors",
1327                                        "packets/s",
1328                                        2700, update_every, RRDSET_TYPE_LINE);
1329                     st->isdetail = 1;
1330
1331                     rrddim_add(st, "InErrs", NULL, 1, 1, RRDDIM_INCREMENTAL);
1332                     rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
1333                     rrddim_add(st, "RetransSegs", NULL, -1, 1, RRDDIM_INCREMENTAL);
1334                 } else
1335                     rrdset_next(st);
1336
1337                 rrddim_set(st, "InErrs", tcpstat.tcps_rcvbadoff + tcpstat.tcps_rcvreassfull + tcpstat.tcps_rcvshort);
1338                 rrddim_set(st, "InCsumErrors", tcpstat.tcps_rcvbadsum);
1339                 rrddim_set(st, "RetransSegs", tcpstat.tcps_sndrexmitpack);
1340                 rrdset_done(st);
1341             }
1342
1343             // --------------------------------------------------------------------
1344
1345             if (likely(do_tcp_handshake)) {
1346                 st = rrdset_find("ipv4.tcphandshake");
1347                 if (unlikely(!st)) {
1348                     st = rrdset_create("ipv4", "tcphandshake", NULL, "tcp", NULL,
1349                                        "IPv4 TCP Handshake Issues",
1350                                        "events/s", 2900, update_every, RRDSET_TYPE_LINE);
1351                     st->isdetail = 1;
1352
1353                     rrddim_add(st, "EstabResets", NULL, 1, 1, RRDDIM_INCREMENTAL);
1354                     rrddim_add(st, "ActiveOpens", NULL, 1, 1, RRDDIM_INCREMENTAL);
1355                     rrddim_add(st, "PassiveOpens", NULL, 1, 1, RRDDIM_INCREMENTAL);
1356                     rrddim_add(st, "AttemptFails", NULL, 1, 1, RRDDIM_INCREMENTAL);
1357                 } else
1358                     rrdset_next(st);
1359
1360                 rrddim_set(st, "EstabResets", tcpstat.tcps_drops);
1361                 rrddim_set(st, "ActiveOpens", tcpstat.tcps_connattempt);
1362                 rrddim_set(st, "PassiveOpens", tcpstat.tcps_accepts);
1363                 rrddim_set(st, "AttemptFails", tcpstat.tcps_conndrops);
1364                 rrdset_done(st);
1365             }
1366
1367             // --------------------------------------------------------------------
1368
1369             if (do_tcpext_connaborts == CONFIG_ONDEMAND_YES || (do_tcpext_connaborts == CONFIG_ONDEMAND_ONDEMAND && (tcpstat.tcps_rcvpackafterwin || tcpstat.tcps_rcvafterclose || tcpstat.tcps_rcvmemdrop || tcpstat.tcps_persistdrop || tcpstat.tcps_finwait2_drops))) {
1370                 do_tcpext_connaborts = CONFIG_ONDEMAND_YES;
1371                 st = rrdset_find("ipv4.tcpconnaborts");
1372                 if (unlikely(!st)) {
1373                     st = rrdset_create("ipv4", "tcpconnaborts", NULL, "tcp", NULL, "TCP Connection Aborts", "connections/s", 3010, update_every, RRDSET_TYPE_LINE);
1374
1375                     rrddim_add(st, "TCPAbortOnData",    "baddata",     1, 1, RRDDIM_INCREMENTAL);
1376                     rrddim_add(st, "TCPAbortOnClose",   "userclosed",  1, 1, RRDDIM_INCREMENTAL);
1377                     rrddim_add(st, "TCPAbortOnMemory",  "nomemory",    1, 1, RRDDIM_INCREMENTAL);
1378                     rrddim_add(st, "TCPAbortOnTimeout", "timeout",     1, 1, RRDDIM_INCREMENTAL);
1379                     rrddim_add(st, "TCPAbortOnLinger",  "linger",      1, 1, RRDDIM_INCREMENTAL);
1380                 }
1381                 else rrdset_next(st);
1382
1383                 rrddim_set(st, "TCPAbortOnData",    tcpstat.tcps_rcvpackafterwin);
1384                 rrddim_set(st, "TCPAbortOnClose",   tcpstat.tcps_rcvafterclose);
1385                 rrddim_set(st, "TCPAbortOnMemory",  tcpstat.tcps_rcvmemdrop);
1386                 rrddim_set(st, "TCPAbortOnTimeout", tcpstat.tcps_persistdrop);
1387                 rrddim_set(st, "TCPAbortOnLinger",  tcpstat.tcps_finwait2_drops);
1388                 rrdset_done(st);
1389             }
1390
1391             // --------------------------------------------------------------------
1392
1393             if (do_tcpext_ofo == CONFIG_ONDEMAND_YES || (do_tcpext_ofo == CONFIG_ONDEMAND_ONDEMAND && tcpstat.tcps_rcvoopack)) {
1394                 do_tcpext_ofo = CONFIG_ONDEMAND_YES;
1395                 st = rrdset_find("ipv4.tcpofo");
1396                 if (unlikely(!st)) {
1397                     st = rrdset_create("ipv4", "tcpofo", NULL, "tcp", NULL, "TCP Out-Of-Order Queue", "packets/s", 3050, update_every, RRDSET_TYPE_LINE);
1398
1399                     rrddim_add(st, "TCPOFOQueue", "inqueue",  1, 1, RRDDIM_INCREMENTAL);
1400                 }
1401                 else rrdset_next(st);
1402
1403                 rrddim_set(st, "TCPOFOQueue",   tcpstat.tcps_rcvoopack);
1404                 rrdset_done(st);
1405             }
1406
1407             // --------------------------------------------------------------------
1408
1409             if (do_tcpext_syscookies == CONFIG_ONDEMAND_YES || (do_tcpext_syscookies == CONFIG_ONDEMAND_ONDEMAND && (tcpstat.tcps_sc_sendcookie || tcpstat.tcps_sc_recvcookie || tcpstat.tcps_sc_zonefail))) {
1410                 do_tcpext_syscookies = CONFIG_ONDEMAND_YES;
1411
1412                 st = rrdset_find("ipv4.tcpsyncookies");
1413                 if (unlikely(!st)) {
1414                     st = rrdset_create("ipv4", "tcpsyncookies", NULL, "tcp", NULL, "TCP SYN Cookies", "packets/s", 3100, update_every, RRDSET_TYPE_LINE);
1415
1416                     rrddim_add(st, "SyncookiesRecv",   "received",  1, 1, RRDDIM_INCREMENTAL);
1417                     rrddim_add(st, "SyncookiesSent",   "sent",     -1, 1, RRDDIM_INCREMENTAL);
1418                     rrddim_add(st, "SyncookiesFailed", "failed",   -1, 1, RRDDIM_INCREMENTAL);
1419                 }
1420                 else rrdset_next(st);
1421
1422                 rrddim_set(st, "SyncookiesRecv",   tcpstat.tcps_sc_recvcookie);
1423                 rrddim_set(st, "SyncookiesSent",   tcpstat.tcps_sc_sendcookie);
1424                 rrddim_set(st, "SyncookiesFailed", tcpstat.tcps_sc_zonefail);
1425                 rrdset_done(st);
1426             }
1427
1428             // --------------------------------------------------------------------
1429
1430             if (do_ecn == CONFIG_ONDEMAND_YES || (do_ecn == CONFIG_ONDEMAND_ONDEMAND && (tcpstat.tcps_ecn_ce || tcpstat.tcps_ecn_ect0 || tcpstat.tcps_ecn_ect1))) {
1431                 do_ecn = CONFIG_ONDEMAND_YES;
1432                 st = rrdset_find("ipv4.ecnpkts");
1433                 if (unlikely(!st)) {
1434                     st = rrdset_create("ipv4", "ecnpkts", NULL, "ecn", NULL, "IPv4 ECN Statistics", "packets/s", 8700, update_every, RRDSET_TYPE_LINE);
1435                     st->isdetail = 1;
1436
1437                     rrddim_add(st, "InCEPkts", "CEP", 1, 1, RRDDIM_INCREMENTAL);
1438                     rrddim_add(st, "InNoECTPkts", "NoECTP", -1, 1, RRDDIM_INCREMENTAL);
1439                     rrddim_add(st, "InECT0Pkts", "ECTP0", 1, 1, RRDDIM_INCREMENTAL);
1440                     rrddim_add(st, "InECT1Pkts", "ECTP1", 1, 1, RRDDIM_INCREMENTAL);
1441                 }
1442                 else rrdset_next(st);
1443
1444                 rrddim_set(st, "InCEPkts", tcpstat.tcps_ecn_ce);
1445                 rrddim_set(st, "InNoECTPkts", tcpstat.tcps_ecn_ce - (tcpstat.tcps_ecn_ect0 + tcpstat.tcps_ecn_ect1));
1446                 rrddim_set(st, "InECT0Pkts", tcpstat.tcps_ecn_ect0);
1447                 rrddim_set(st, "InECT1Pkts", tcpstat.tcps_ecn_ect1);
1448                 rrdset_done(st);
1449             }
1450
1451         }
1452     }
1453
1454     // --------------------------------------------------------------------
1455
1456     // see http://net-snmp.sourceforge.net/docs/mibs/udp.html
1457     if (likely(do_udp_packets || do_udp_errors)) {
1458         if (unlikely(GETSYSCTL("net.inet.udp.stats", udpstat))) {
1459             do_udp_packets = 0;
1460             error("DISABLED: ipv4.udppackets");
1461             do_udp_errors = 0;
1462             error("DISABLED: ipv4.udperrors");
1463         } else {
1464             if (likely(do_udp_packets)) {
1465                 st = rrdset_find("ipv4.udppackets");
1466                 if (unlikely(!st)) {
1467                     st = rrdset_create("ipv4", "udppackets", NULL, "udp", NULL, "IPv4 UDP Packets",
1468                                        "packets/s", 2601, update_every, RRDSET_TYPE_LINE);
1469
1470                     rrddim_add(st, "InDatagrams", "received", 1, 1, RRDDIM_INCREMENTAL);
1471                     rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRDDIM_INCREMENTAL);
1472                 } else
1473                     rrdset_next(st);
1474
1475                 rrddim_set(st, "InDatagrams", udpstat.udps_ipackets);
1476                 rrddim_set(st, "OutDatagrams", udpstat.udps_opackets);
1477                 rrdset_done(st);
1478             }
1479
1480             // --------------------------------------------------------------------
1481
1482             if (likely(do_udp_errors)) {
1483                 st = rrdset_find("ipv4.udperrors");
1484                 if (unlikely(!st)) {
1485                     st = rrdset_create("ipv4", "udperrors", NULL, "udp", NULL, "IPv4 UDP Errors", "events/s",
1486                                        2701, update_every, RRDSET_TYPE_LINE);
1487                     st->isdetail = 1;
1488
1489                     rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
1490                     rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
1491                     rrddim_add(st, "NoPorts", NULL, 1, 1, RRDDIM_INCREMENTAL);
1492                     rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
1493                     rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRDDIM_INCREMENTAL);
1494                 } else
1495                     rrdset_next(st);
1496
1497                 rrddim_set(st, "InErrors", udpstat.udps_hdrops + udpstat.udps_badlen);
1498                 rrddim_set(st, "NoPorts", udpstat.udps_noport);
1499                 rrddim_set(st, "RcvbufErrors", udpstat.udps_fullsock);
1500                 rrddim_set(st, "InCsumErrors", udpstat.udps_badsum + udpstat.udps_nosum);
1501                 rrddim_set(st, "IgnoredMulti", udpstat.udps_filtermcast);
1502                 rrdset_done(st);
1503             }
1504         }
1505     }
1506
1507     // --------------------------------------------------------------------
1508
1509     if (likely(do_icmp_packets || do_icmpmsg)) {
1510         if (unlikely(GETSYSCTL("net.inet.icmp.stats", icmpstat))) {
1511             do_icmp_packets = 0;
1512             error("DISABLED: ipv4.icmp");
1513             error("DISABLED: ipv4.icmp_errors");
1514             do_icmpmsg = 0;
1515             error("DISABLED: ipv4.icmpmsg");
1516         } else {
1517             for (i = 0; i <= ICMP_MAXTYPE; i++) {
1518                 icmp_total.msgs_in += icmpstat.icps_inhist[i];
1519                 icmp_total.msgs_out += icmpstat.icps_outhist[i];
1520             }
1521             icmp_total.msgs_in += icmpstat.icps_badcode + icmpstat.icps_badlen + icmpstat.icps_checksum + icmpstat.icps_tooshort;
1522
1523             // --------------------------------------------------------------------
1524
1525             if (likely(do_icmp_packets)) {
1526                 st = rrdset_find("ipv4.icmp");
1527                 if (unlikely(!st)) {
1528                     st = rrdset_create("ipv4", "icmp", NULL, "icmp", NULL, "IPv4 ICMP Packets", "packets/s",
1529                                        2602,
1530                                        update_every, RRDSET_TYPE_LINE);
1531
1532                     rrddim_add(st, "InMsgs", "received", 1, 1, RRDDIM_INCREMENTAL);
1533                     rrddim_add(st, "OutMsgs", "sent", -1, 1, RRDDIM_INCREMENTAL);
1534                 } else
1535                     rrdset_next(st);
1536
1537                 rrddim_set(st, "InMsgs", icmp_total.msgs_in);
1538                 rrddim_set(st, "OutMsgs", icmp_total.msgs_out);
1539
1540                 rrdset_done(st);
1541
1542                 // --------------------------------------------------------------------
1543
1544                 st = rrdset_find("ipv4.icmp_errors");
1545                 if (unlikely(!st)) {
1546                     st = rrdset_create("ipv4", "icmp_errors", NULL, "icmp", NULL, "IPv4 ICMP Errors",
1547                                        "packets/s",
1548                                        2603, update_every, RRDSET_TYPE_LINE);
1549
1550                     rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
1551                     rrddim_add(st, "OutErrors", NULL, -1, 1, RRDDIM_INCREMENTAL);
1552                     rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
1553                 } else
1554                     rrdset_next(st);
1555
1556                 rrddim_set(st, "InErrors", icmpstat.icps_badcode + icmpstat.icps_badlen + icmpstat.icps_checksum + icmpstat.icps_tooshort);
1557                 rrddim_set(st, "OutErrors", icmpstat.icps_error);
1558                 rrddim_set(st, "InCsumErrors", icmpstat.icps_checksum);
1559
1560                 rrdset_done(st);
1561             }
1562
1563             // --------------------------------------------------------------------
1564
1565             if (likely(do_icmpmsg)) {
1566                 st = rrdset_find("ipv4.icmpmsg");
1567                 if (unlikely(!st)) {
1568                     st = rrdset_create("ipv4", "icmpmsg", NULL, "icmp", NULL, "IPv4 ICMP Messsages",
1569                                        "packets/s", 2604, update_every, RRDSET_TYPE_LINE);
1570
1571                     rrddim_add(st, "InEchoReps", NULL, 1, 1, RRDDIM_INCREMENTAL);
1572                     rrddim_add(st, "OutEchoReps", NULL, -1, 1, RRDDIM_INCREMENTAL);
1573                     rrddim_add(st, "InEchos", NULL, 1, 1, RRDDIM_INCREMENTAL);
1574                     rrddim_add(st, "OutEchos", NULL, -1, 1, RRDDIM_INCREMENTAL);
1575                 } else
1576                     rrdset_next(st);
1577
1578                     rrddim_set(st, "InEchoReps", icmpstat.icps_inhist[ICMP_ECHOREPLY]);
1579                     rrddim_set(st, "OutEchoReps", icmpstat.icps_outhist[ICMP_ECHOREPLY]);
1580                     rrddim_set(st, "InEchos", icmpstat.icps_inhist[ICMP_ECHO]);
1581                     rrddim_set(st, "OutEchos", icmpstat.icps_outhist[ICMP_ECHO]);
1582
1583                 rrdset_done(st);
1584             }
1585         }
1586     }
1587
1588     return 0;
1589 }