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