]> arthur.barton.de Git - netdata.git/blob - src/macos_sysctl.c
250faa7d10e1742fca3db96fd945568158554028
[netdata.git] / src / macos_sysctl.c
1 #include "common.h"
2 #include <sys/sysctl.h>
3 // NEEDED BY: do_bandwidth
4 #include <net/route.h>
5 // NEEDED BY do_tcp...
6 #include <sys/socketvar.h>
7 #include <netinet/tcp_var.h>
8 #include <netinet/tcp_fsm.h>
9 // NEEDED BY do_udp..., do_ip...
10 #include <netinet/ip_var.h>
11 // NEEDED BY do_udp...
12 #include <netinet/udp.h>
13 #include <netinet/udp_var.h>
14 // NEEDED BY do_icmp...
15 #include <netinet/ip.h>
16 #include <netinet/ip_icmp.h>
17 #include <netinet/icmp_var.h>
18 // NEEDED BY do_icmp6...
19 #include <netinet/icmp6.h>
20 // NEEDED BY do_uptime
21 #include <time.h>
22
23 // MacOS calculates load averages once every 5 seconds
24 #define MIN_LOADAVG_UPDATE_EVERY 5
25
26 int do_macos_sysctl(int update_every, usec_t dt) {
27     static int do_loadavg = -1, do_swap = -1, do_bandwidth = -1,
28                do_tcp_packets = -1, do_tcp_errors = -1, do_tcp_handshake = -1, do_ecn = -1,
29                do_tcpext_syscookies = -1, do_tcpext_ofo = -1, do_tcpext_connaborts = -1,
30                do_udp_packets = -1, do_udp_errors = -1, do_icmp_packets = -1, do_icmpmsg = -1,
31                do_ip_packets = -1, do_ip_fragsout = -1, do_ip_fragsin = -1, do_ip_errors = -1,
32                do_ip6_packets = -1, do_ip6_fragsout = -1, do_ip6_fragsin = -1, do_ip6_errors = -1,
33                do_icmp6 = -1, do_icmp6_redir = -1, do_icmp6_errors = -1, do_icmp6_echos = -1,
34                do_icmp6_router = -1, do_icmp6_neighbor = -1, do_icmp6_types = -1, do_uptime = -1;
35
36
37     if (unlikely(do_loadavg == -1)) {
38         do_loadavg              = config_get_boolean("plugin:macos:sysctl", "enable load average", 1);
39         do_swap                 = config_get_boolean("plugin:macos:sysctl", "system swap", 1);
40         do_bandwidth            = config_get_boolean("plugin:macos:sysctl", "bandwidth", 1);
41         do_tcp_packets          = config_get_boolean("plugin:macos:sysctl", "ipv4 TCP packets", 1);
42         do_tcp_errors           = config_get_boolean("plugin:macos:sysctl", "ipv4 TCP errors", 1);
43         do_tcp_handshake        = config_get_boolean("plugin:macos:sysctl", "ipv4 TCP handshake issues", 1);
44         do_ecn                  = config_get_boolean_ondemand("plugin:macos:sysctl", "ECN packets", CONFIG_ONDEMAND_ONDEMAND);
45         do_tcpext_syscookies    = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP SYN cookies", CONFIG_ONDEMAND_ONDEMAND);
46         do_tcpext_ofo           = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP out-of-order queue", CONFIG_ONDEMAND_ONDEMAND);
47         do_tcpext_connaborts    = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP connection aborts", CONFIG_ONDEMAND_ONDEMAND);
48         do_udp_packets          = config_get_boolean("plugin:macos:sysctl", "ipv4 UDP packets", 1);
49         do_udp_errors           = config_get_boolean("plugin:macos:sysctl", "ipv4 UDP errors", 1);
50         do_icmp_packets         = config_get_boolean("plugin:macos:sysctl", "ipv4 ICMP packets", 1);
51         do_icmpmsg              = config_get_boolean("plugin:macos:sysctl", "ipv4 ICMP messages", 1);
52         do_ip_packets           = config_get_boolean("plugin:macos:sysctl", "ipv4 packets", 1);
53         do_ip_fragsout          = config_get_boolean("plugin:macos:sysctl", "ipv4 fragments sent", 1);
54         do_ip_fragsin           = config_get_boolean("plugin:macos:sysctl", "ipv4 fragments assembly", 1);
55         do_ip_errors            = config_get_boolean("plugin:macos:sysctl", "ipv4 errors", 1);
56         do_ip6_packets          = config_get_boolean_ondemand("plugin:macos:sysctl", "ipv6 packets", CONFIG_ONDEMAND_ONDEMAND);
57         do_ip6_fragsout         = config_get_boolean_ondemand("plugin:macos:sysctl", "ipv6 fragments sent", CONFIG_ONDEMAND_ONDEMAND);
58         do_ip6_fragsin          = config_get_boolean_ondemand("plugin:macos:sysctl", "ipv6 fragments assembly", CONFIG_ONDEMAND_ONDEMAND);
59         do_ip6_errors           = config_get_boolean_ondemand("plugin:macos:sysctl", "ipv6 errors", CONFIG_ONDEMAND_ONDEMAND);
60         do_icmp6                = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp", CONFIG_ONDEMAND_ONDEMAND);
61         do_icmp6_redir          = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp redirects", CONFIG_ONDEMAND_ONDEMAND);
62         do_icmp6_errors         = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp errors", CONFIG_ONDEMAND_ONDEMAND);
63         do_icmp6_echos          = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp echos", CONFIG_ONDEMAND_ONDEMAND);
64         do_icmp6_router         = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp router", CONFIG_ONDEMAND_ONDEMAND);
65         do_icmp6_neighbor       = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp neighbor", CONFIG_ONDEMAND_ONDEMAND);
66         do_icmp6_types          = config_get_boolean_ondemand("plugin:macos:sysctl", "icmp types", CONFIG_ONDEMAND_ONDEMAND);
67         do_uptime               = config_get_boolean("plugin:macos:sysctl", "system uptime", 1);
68     }
69
70     RRDSET *st;
71
72     int system_pagesize = getpagesize(); // wouldn't it be better to get value directly from hw.pagesize?
73     int i, n;
74     int common_error = 0;
75     size_t size;
76
77     // NEEDED BY: do_loadavg
78     static usec_t next_loadavg_dt = 0;
79     struct loadavg sysload;
80
81     // NEEDED BY: do_swap
82     struct xsw_usage swap_usage;
83
84     // NEEDED BY: do_bandwidth
85     int mib[6];
86     static char *ifstatdata = NULL;
87     char *lim, *next;
88     struct if_msghdr *ifm;
89     struct iftot {
90         u_long  ift_ibytes;
91         u_long  ift_obytes;
92     } iftot = {0, 0};
93
94     // NEEDED BY: do_tcp...
95     struct tcpstat tcpstat;
96     uint64_t tcps_states[TCP_NSTATES];
97
98     // NEEDED BY: do_udp...
99     struct udpstat udpstat;
100
101     // NEEDED BY: do_icmp...
102     struct icmpstat icmpstat;
103     struct icmp_total {
104         u_long  msgs_in;
105         u_long  msgs_out;
106     } icmp_total = {0, 0};
107
108     // NEEDED BY: do_ip...
109     struct ipstat ipstat;
110
111     // NEEDED BY: do_ip6...
112     /*
113      * Dirty workaround for /usr/include/netinet6/ip6_var.h absence.
114      * Struct ip6stat was copied from bsd/netinet6/ip6_var.h from xnu sources.
115      */
116 #define IP6S_SRCRULE_COUNT 16
117 #include <netinet6/scope6_var.h>
118     struct      ip6stat {
119         u_quad_t ip6s_total;            /* total packets received */
120         u_quad_t ip6s_tooshort;         /* packet too short */
121         u_quad_t ip6s_toosmall;         /* not enough data */
122         u_quad_t ip6s_fragments;        /* fragments received */
123         u_quad_t ip6s_fragdropped;      /* frags dropped(dups, out of space) */
124         u_quad_t ip6s_fragtimeout;      /* fragments timed out */
125         u_quad_t ip6s_fragoverflow;     /* fragments that exceeded limit */
126         u_quad_t ip6s_forward;          /* packets forwarded */
127         u_quad_t ip6s_cantforward;      /* packets rcvd for unreachable dest */
128         u_quad_t ip6s_redirectsent;     /* packets forwarded on same net */
129         u_quad_t ip6s_delivered;        /* datagrams delivered to upper level */
130         u_quad_t ip6s_localout;         /* total ip packets generated here */
131         u_quad_t ip6s_odropped;         /* lost packets due to nobufs, etc. */
132         u_quad_t ip6s_reassembled;      /* total packets reassembled ok */
133         u_quad_t ip6s_atmfrag_rcvd;     /* atomic fragments received */
134         u_quad_t ip6s_fragmented;       /* datagrams successfully fragmented */
135         u_quad_t ip6s_ofragments;       /* output fragments created */
136         u_quad_t ip6s_cantfrag;         /* don't fragment flag was set, etc. */
137         u_quad_t ip6s_badoptions;       /* error in option processing */
138         u_quad_t ip6s_noroute;          /* packets discarded due to no route */
139         u_quad_t ip6s_badvers;          /* ip6 version != 6 */
140         u_quad_t ip6s_rawout;           /* total raw ip packets generated */
141         u_quad_t ip6s_badscope;         /* scope error */
142         u_quad_t ip6s_notmember;        /* don't join this multicast group */
143         u_quad_t ip6s_nxthist[256];     /* next header history */
144         u_quad_t ip6s_m1;               /* one mbuf */
145         u_quad_t ip6s_m2m[32];          /* two or more mbuf */
146         u_quad_t ip6s_mext1;            /* one ext mbuf */
147         u_quad_t ip6s_mext2m;           /* two or more ext mbuf */
148         u_quad_t ip6s_exthdrtoolong;    /* ext hdr are not continuous */
149         u_quad_t ip6s_nogif;            /* no match gif found */
150         u_quad_t ip6s_toomanyhdr;       /* discarded due to too many headers */
151
152         /*
153          * statistics for improvement of the source address selection
154          * algorithm:
155          */
156         /* number of times that address selection fails */
157         u_quad_t ip6s_sources_none;
158         /* number of times that an address on the outgoing I/F is chosen */
159         u_quad_t ip6s_sources_sameif[SCOPE6_ID_MAX];
160         /* number of times that an address on a non-outgoing I/F is chosen */
161         u_quad_t ip6s_sources_otherif[SCOPE6_ID_MAX];
162         /*
163          * number of times that an address that has the same scope
164          * from the destination is chosen.
165          */
166         u_quad_t ip6s_sources_samescope[SCOPE6_ID_MAX];
167         /*
168          * number of times that an address that has a different scope
169          * from the destination is chosen.
170          */
171         u_quad_t ip6s_sources_otherscope[SCOPE6_ID_MAX];
172         /* number of times that a deprecated address is chosen */
173         u_quad_t ip6s_sources_deprecated[SCOPE6_ID_MAX];
174
175         u_quad_t ip6s_forward_cachehit;
176         u_quad_t ip6s_forward_cachemiss;
177
178         /* number of times that each rule of source selection is applied. */
179         u_quad_t ip6s_sources_rule[IP6S_SRCRULE_COUNT];
180
181         /* number of times we ignored address on expensive secondary interfaces */
182         u_quad_t ip6s_sources_skip_expensive_secondary_if;
183
184         /* pkt dropped, no mbufs for control data */
185         u_quad_t ip6s_pktdropcntrl;
186
187         /* total packets trimmed/adjusted  */
188         u_quad_t ip6s_adj;
189         /* hwcksum info discarded during adjustment */
190         u_quad_t ip6s_adj_hwcsum_clr;
191
192         /* duplicate address detection collisions */
193         u_quad_t ip6s_dad_collide;
194
195         /* DAD NS looped back */
196         u_quad_t ip6s_dad_loopcount;
197     } ip6stat;
198
199     // NEEDED BY: do_icmp6...
200     struct icmp6stat icmp6stat;
201     struct icmp6_total {
202         u_long  msgs_in;
203         u_long  msgs_out;
204     } icmp6_total = {0, 0};
205
206     // NEEDED BY: do_uptime
207     struct timespec boot_time, cur_time;
208
209     // --------------------------------------------------------------------
210
211     if (next_loadavg_dt <= dt) {
212         if (likely(do_loadavg)) {
213             if (unlikely(GETSYSCTL("vm.loadavg", sysload))) {
214                 do_loadavg = 0;
215                 error("DISABLED: system.load");
216             } else {
217
218                 st = rrdset_find_bytype_localhost("system", "load");
219                 if (unlikely(!st)) {
220                     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);
221                     rrddim_add(st, "load1", NULL, 1, 1000, RRDDIM_ALGORITHM_ABSOLUTE);
222                     rrddim_add(st, "load5", NULL, 1, 1000, RRDDIM_ALGORITHM_ABSOLUTE);
223                     rrddim_add(st, "load15", NULL, 1, 1000, RRDDIM_ALGORITHM_ABSOLUTE);
224                 }
225                 else rrdset_next(st);
226
227                 rrddim_set(st, "load1", (collected_number) ((double)sysload.ldavg[0] / sysload.fscale * 1000));
228                 rrddim_set(st, "load5", (collected_number) ((double)sysload.ldavg[1] / sysload.fscale * 1000));
229                 rrddim_set(st, "load15", (collected_number) ((double)sysload.ldavg[2] / sysload.fscale * 1000));
230                 rrdset_done(st);
231             }
232         }
233
234         next_loadavg_dt = st->update_every * USEC_PER_SEC;
235     }
236     else next_loadavg_dt -= dt;
237
238     // --------------------------------------------------------------------
239
240     if (likely(do_swap)) {
241         if (unlikely(GETSYSCTL("vm.swapusage", swap_usage))) {
242             do_swap = 0;
243             error("DISABLED: system.swap");
244         } else {
245             st = rrdset_find_localhost("system.swap");
246             if (unlikely(!st)) {
247                 st = rrdset_create("system", "swap", NULL, "swap", NULL, "System Swap", "MB", 201, update_every, RRDSET_TYPE_STACKED);
248                 st->isdetail = 1;
249
250                 rrddim_add(st, "free",    NULL, 1, 1048576, RRDDIM_ALGORITHM_ABSOLUTE);
251                 rrddim_add(st, "used",    NULL, 1, 1048576, RRDDIM_ALGORITHM_ABSOLUTE);
252             }
253             else rrdset_next(st);
254
255             rrddim_set(st, "free", swap_usage.xsu_avail);
256             rrddim_set(st, "used", swap_usage.xsu_used);
257             rrdset_done(st);
258         }
259     }
260
261     // --------------------------------------------------------------------
262
263     if (likely(do_bandwidth)) {
264         mib[0] = CTL_NET;
265         mib[1] = PF_ROUTE;
266         mib[2] = 0;
267         mib[3] = AF_INET;
268         mib[4] = NET_RT_IFLIST2;
269         mib[5] = 0;
270         if (unlikely(sysctl(mib, 6, NULL, &size, NULL, 0))) {
271             error("MACOS: sysctl(%s...) failed: %s", "net interfaces", strerror(errno));
272             do_bandwidth = 0;
273             error("DISABLED: system.ipv4");
274         } else {
275             ifstatdata = reallocz(ifstatdata, size);
276             if (unlikely(sysctl(mib, 6, ifstatdata, &size, NULL, 0) < 0)) {
277                 error("MACOS: sysctl(%s...) failed: %s", "net interfaces", strerror(errno));
278                 do_bandwidth = 0;
279                 error("DISABLED: system.ipv4");
280             } else {
281                 lim = ifstatdata + size;
282                 iftot.ift_ibytes = iftot.ift_obytes = 0;
283                 for (next = ifstatdata; next < lim; ) {
284                     ifm = (struct if_msghdr *)next;
285                     next += ifm->ifm_msglen;
286
287                     if (ifm->ifm_type == RTM_IFINFO2) {
288                         struct if_msghdr2 *if2m = (struct if_msghdr2 *)ifm;
289
290                         iftot.ift_ibytes += if2m->ifm_data.ifi_ibytes;
291                         iftot.ift_obytes += if2m->ifm_data.ifi_obytes;
292                     }
293                 }
294                 st = rrdset_find_localhost("system.ipv4");
295                 if (unlikely(!st)) {
296                     st = rrdset_create("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA);
297
298                     rrddim_add(st, "InOctets", "received", 8, 1024, RRDDIM_ALGORITHM_INCREMENTAL);
299                     rrddim_add(st, "OutOctets", "sent", -8, 1024, RRDDIM_ALGORITHM_INCREMENTAL);
300                 }
301                 else rrdset_next(st);
302
303                 rrddim_set(st, "InOctets", iftot.ift_ibytes);
304                 rrddim_set(st, "OutOctets", iftot.ift_obytes);
305                 rrdset_done(st);
306             }
307         }
308     }
309
310     // --------------------------------------------------------------------
311
312     // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html
313     if (likely(do_tcp_packets || do_tcp_errors || do_tcp_handshake || do_tcpext_connaborts || do_tcpext_ofo || do_tcpext_syscookies || do_ecn)) {
314         if (unlikely(GETSYSCTL("net.inet.tcp.stats", tcpstat))){
315             do_tcp_packets = 0;
316             error("DISABLED: ipv4.tcppackets");
317             do_tcp_errors = 0;
318             error("DISABLED: ipv4.tcperrors");
319             do_tcp_handshake = 0;
320             error("DISABLED: ipv4.tcphandshake");
321             do_tcpext_connaborts = 0;
322             error("DISABLED: ipv4.tcpconnaborts");
323             do_tcpext_ofo = 0;
324             error("DISABLED: ipv4.tcpofo");
325             do_tcpext_syscookies = 0;
326             error("DISABLED: ipv4.tcpsyncookies");
327             do_ecn = 0;
328             error("DISABLED: ipv4.ecnpkts");
329         } else {
330             if (likely(do_tcp_packets)) {
331                 st = rrdset_find_localhost("ipv4.tcppackets");
332                 if (unlikely(!st)) {
333                     st = rrdset_create("ipv4", "tcppackets", NULL, "tcp", NULL, "IPv4 TCP Packets",
334                                        "packets/s",
335                                        2600, update_every, RRDSET_TYPE_LINE);
336
337                     rrddim_add(st, "InSegs", "received", 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
338                     rrddim_add(st, "OutSegs", "sent", -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
339                 } else
340                     rrdset_next(st);
341
342                 rrddim_set(st, "InSegs", tcpstat.tcps_rcvtotal);
343                 rrddim_set(st, "OutSegs", tcpstat.tcps_sndtotal);
344                 rrdset_done(st);
345             }
346
347             // --------------------------------------------------------------------
348
349             if (likely(do_tcp_errors)) {
350                 st = rrdset_find_localhost("ipv4.tcperrors");
351                 if (unlikely(!st)) {
352                     st = rrdset_create("ipv4", "tcperrors", NULL, "tcp", NULL, "IPv4 TCP Errors",
353                                        "packets/s",
354                                        2700, update_every, RRDSET_TYPE_LINE);
355                     st->isdetail = 1;
356
357                     rrddim_add(st, "InErrs", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
358                     rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
359                     rrddim_add(st, "RetransSegs", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
360                 } else
361                     rrdset_next(st);
362
363                 rrddim_set(st, "InErrs", tcpstat.tcps_rcvbadoff + tcpstat.tcps_rcvshort);
364                 rrddim_set(st, "InCsumErrors", tcpstat.tcps_rcvbadsum);
365                 rrddim_set(st, "RetransSegs", tcpstat.tcps_sndrexmitpack);
366                 rrdset_done(st);
367             }
368
369             // --------------------------------------------------------------------
370
371             if (likely(do_tcp_handshake)) {
372                 st = rrdset_find_localhost("ipv4.tcphandshake");
373                 if (unlikely(!st)) {
374                     st = rrdset_create("ipv4", "tcphandshake", NULL, "tcp", NULL,
375                                        "IPv4 TCP Handshake Issues",
376                                        "events/s", 2900, update_every, RRDSET_TYPE_LINE);
377                     st->isdetail = 1;
378
379                     rrddim_add(st, "EstabResets", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
380                     rrddim_add(st, "ActiveOpens", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
381                     rrddim_add(st, "PassiveOpens", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
382                     rrddim_add(st, "AttemptFails", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
383                 } else
384                     rrdset_next(st);
385
386                 rrddim_set(st, "EstabResets", tcpstat.tcps_drops);
387                 rrddim_set(st, "ActiveOpens", tcpstat.tcps_connattempt);
388                 rrddim_set(st, "PassiveOpens", tcpstat.tcps_accepts);
389                 rrddim_set(st, "AttemptFails", tcpstat.tcps_conndrops);
390                 rrdset_done(st);
391             }
392
393             // --------------------------------------------------------------------
394
395             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))) {
396                 do_tcpext_connaborts = CONFIG_ONDEMAND_YES;
397                 st = rrdset_find_localhost("ipv4.tcpconnaborts");
398                 if (unlikely(!st)) {
399                     st = rrdset_create("ipv4", "tcpconnaborts", NULL, "tcp", NULL, "TCP Connection Aborts", "connections/s", 3010, update_every, RRDSET_TYPE_LINE);
400
401                     rrddim_add(st, "TCPAbortOnData",    "baddata",     1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
402                     rrddim_add(st, "TCPAbortOnClose",   "userclosed",  1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
403                     rrddim_add(st, "TCPAbortOnMemory",  "nomemory",    1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
404                     rrddim_add(st, "TCPAbortOnTimeout", "timeout",     1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
405                 }
406                 else rrdset_next(st);
407
408                 rrddim_set(st, "TCPAbortOnData",    tcpstat.tcps_rcvpackafterwin);
409                 rrddim_set(st, "TCPAbortOnClose",   tcpstat.tcps_rcvafterclose);
410                 rrddim_set(st, "TCPAbortOnMemory",  tcpstat.tcps_rcvmemdrop);
411                 rrddim_set(st, "TCPAbortOnTimeout", tcpstat.tcps_persistdrop);
412                 rrdset_done(st);
413             }
414
415             // --------------------------------------------------------------------
416
417             if (do_tcpext_ofo == CONFIG_ONDEMAND_YES || (do_tcpext_ofo == CONFIG_ONDEMAND_ONDEMAND && tcpstat.tcps_rcvoopack)) {
418                 do_tcpext_ofo = CONFIG_ONDEMAND_YES;
419                 st = rrdset_find_localhost("ipv4.tcpofo");
420                 if (unlikely(!st)) {
421                     st = rrdset_create("ipv4", "tcpofo", NULL, "tcp", NULL, "TCP Out-Of-Order Queue", "packets/s", 3050, update_every, RRDSET_TYPE_LINE);
422
423                     rrddim_add(st, "TCPOFOQueue", "inqueue",  1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
424                 }
425                 else rrdset_next(st);
426
427                 rrddim_set(st, "TCPOFOQueue",   tcpstat.tcps_rcvoopack);
428                 rrdset_done(st);
429             }
430
431             // --------------------------------------------------------------------
432
433             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))) {
434                 do_tcpext_syscookies = CONFIG_ONDEMAND_YES;
435
436                 st = rrdset_find_localhost("ipv4.tcpsyncookies");
437                 if (unlikely(!st)) {
438                     st = rrdset_create("ipv4", "tcpsyncookies", NULL, "tcp", NULL, "TCP SYN Cookies", "packets/s", 3100, update_every, RRDSET_TYPE_LINE);
439
440                     rrddim_add(st, "SyncookiesRecv",   "received",  1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
441                     rrddim_add(st, "SyncookiesSent",   "sent",     -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
442                     rrddim_add(st, "SyncookiesFailed", "failed",   -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
443                 }
444                 else rrdset_next(st);
445
446                 rrddim_set(st, "SyncookiesRecv",   tcpstat.tcps_sc_recvcookie);
447                 rrddim_set(st, "SyncookiesSent",   tcpstat.tcps_sc_sendcookie);
448                 rrddim_set(st, "SyncookiesFailed", tcpstat.tcps_sc_zonefail);
449                 rrdset_done(st);
450             }
451
452             // --------------------------------------------------------------------
453
454             if (do_ecn == CONFIG_ONDEMAND_YES || (do_ecn == CONFIG_ONDEMAND_ONDEMAND && (tcpstat.tcps_ecn_recv_ce || tcpstat.tcps_ecn_not_supported))) {
455                 do_ecn = CONFIG_ONDEMAND_YES;
456                 st = rrdset_find_localhost("ipv4.ecnpkts");
457                 if (unlikely(!st)) {
458                     st = rrdset_create("ipv4", "ecnpkts", NULL, "ecn", NULL, "IPv4 ECN Statistics", "packets/s", 8700, update_every, RRDSET_TYPE_LINE);
459                     st->isdetail = 1;
460
461                     rrddim_add(st, "InCEPkts", "CEP", 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
462                     rrddim_add(st, "InNoECTPkts", "NoECTP", -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
463                 }
464                 else rrdset_next(st);
465
466                 rrddim_set(st, "InCEPkts", tcpstat.tcps_ecn_recv_ce);
467                 rrddim_set(st, "InNoECTPkts", tcpstat.tcps_ecn_not_supported);
468                 rrdset_done(st);
469             }
470
471         }
472     }
473
474     // --------------------------------------------------------------------
475
476     // see http://net-snmp.sourceforge.net/docs/mibs/udp.html
477     if (likely(do_udp_packets || do_udp_errors)) {
478         if (unlikely(GETSYSCTL("net.inet.udp.stats", udpstat))) {
479             do_udp_packets = 0;
480             error("DISABLED: ipv4.udppackets");
481             do_udp_errors = 0;
482             error("DISABLED: ipv4.udperrors");
483         } else {
484             if (likely(do_udp_packets)) {
485                 st = rrdset_find_localhost("ipv4.udppackets");
486                 if (unlikely(!st)) {
487                     st = rrdset_create("ipv4", "udppackets", NULL, "udp", NULL, "IPv4 UDP Packets",
488                                        "packets/s", 2601, update_every, RRDSET_TYPE_LINE);
489
490                     rrddim_add(st, "InDatagrams", "received", 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
491                     rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
492                 } else
493                     rrdset_next(st);
494
495                 rrddim_set(st, "InDatagrams", udpstat.udps_ipackets);
496                 rrddim_set(st, "OutDatagrams", udpstat.udps_opackets);
497                 rrdset_done(st);
498             }
499
500             // --------------------------------------------------------------------
501
502             if (likely(do_udp_errors)) {
503                 st = rrdset_find_localhost("ipv4.udperrors");
504                 if (unlikely(!st)) {
505                     st = rrdset_create("ipv4", "udperrors", NULL, "udp", NULL, "IPv4 UDP Errors", "events/s",
506                                        2701, update_every, RRDSET_TYPE_LINE);
507                     st->isdetail = 1;
508
509                     rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
510                     rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
511                     rrddim_add(st, "NoPorts", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
512                     rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
513                     rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
514                 } else
515                     rrdset_next(st);
516
517                 rrddim_set(st, "InErrors", udpstat.udps_hdrops + udpstat.udps_badlen);
518                 rrddim_set(st, "NoPorts", udpstat.udps_noport);
519                 rrddim_set(st, "RcvbufErrors", udpstat.udps_fullsock);
520                 rrddim_set(st, "InCsumErrors", udpstat.udps_badsum + udpstat.udps_nosum);
521                 rrddim_set(st, "IgnoredMulti", udpstat.udps_filtermcast);
522                 rrdset_done(st);
523             }
524         }
525     }
526
527     // --------------------------------------------------------------------
528
529     if (likely(do_icmp_packets || do_icmpmsg)) {
530         if (unlikely(GETSYSCTL("net.inet.icmp.stats", icmpstat))) {
531             do_icmp_packets = 0;
532             error("DISABLED: ipv4.icmp");
533             error("DISABLED: ipv4.icmp_errors");
534             do_icmpmsg = 0;
535             error("DISABLED: ipv4.icmpmsg");
536         } else {
537             for (i = 0; i <= ICMP_MAXTYPE; i++) {
538                 icmp_total.msgs_in += icmpstat.icps_inhist[i];
539                 icmp_total.msgs_out += icmpstat.icps_outhist[i];
540             }
541             icmp_total.msgs_in += icmpstat.icps_badcode + icmpstat.icps_badlen + icmpstat.icps_checksum + icmpstat.icps_tooshort;
542
543             // --------------------------------------------------------------------
544
545             if (likely(do_icmp_packets)) {
546                 st = rrdset_find_localhost("ipv4.icmp");
547                 if (unlikely(!st)) {
548                     st = rrdset_create("ipv4", "icmp", NULL, "icmp", NULL, "IPv4 ICMP Packets", "packets/s",
549                                        2602,
550                                        update_every, RRDSET_TYPE_LINE);
551
552                     rrddim_add(st, "InMsgs", "received", 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
553                     rrddim_add(st, "OutMsgs", "sent", -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
554                 } else
555                     rrdset_next(st);
556
557                 rrddim_set(st, "InMsgs", icmp_total.msgs_in);
558                 rrddim_set(st, "OutMsgs", icmp_total.msgs_out);
559
560                 rrdset_done(st);
561
562                 // --------------------------------------------------------------------
563
564                 st = rrdset_find_localhost("ipv4.icmp_errors");
565                 if (unlikely(!st)) {
566                     st = rrdset_create("ipv4", "icmp_errors", NULL, "icmp", NULL, "IPv4 ICMP Errors",
567                                        "packets/s",
568                                        2603, update_every, RRDSET_TYPE_LINE);
569
570                     rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
571                     rrddim_add(st, "OutErrors", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
572                     rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
573                 } else
574                     rrdset_next(st);
575
576                 rrddim_set(st, "InErrors", icmpstat.icps_badcode + icmpstat.icps_badlen + icmpstat.icps_checksum + icmpstat.icps_tooshort);
577                 rrddim_set(st, "OutErrors", icmpstat.icps_error);
578                 rrddim_set(st, "InCsumErrors", icmpstat.icps_checksum);
579
580                 rrdset_done(st);
581             }
582
583             // --------------------------------------------------------------------
584
585             if (likely(do_icmpmsg)) {
586                 st = rrdset_find_localhost("ipv4.icmpmsg");
587                 if (unlikely(!st)) {
588                     st = rrdset_create("ipv4", "icmpmsg", NULL, "icmp", NULL, "IPv4 ICMP Messsages",
589                                        "packets/s", 2604, update_every, RRDSET_TYPE_LINE);
590
591                     rrddim_add(st, "InEchoReps", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
592                     rrddim_add(st, "OutEchoReps", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
593                     rrddim_add(st, "InEchos", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
594                     rrddim_add(st, "OutEchos", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
595                 } else
596                     rrdset_next(st);
597
598                     rrddim_set(st, "InEchoReps", icmpstat.icps_inhist[ICMP_ECHOREPLY]);
599                     rrddim_set(st, "OutEchoReps", icmpstat.icps_outhist[ICMP_ECHOREPLY]);
600                     rrddim_set(st, "InEchos", icmpstat.icps_inhist[ICMP_ECHO]);
601                     rrddim_set(st, "OutEchos", icmpstat.icps_outhist[ICMP_ECHO]);
602
603                 rrdset_done(st);
604             }
605         }
606     }
607
608     // --------------------------------------------------------------------
609
610     // see also http://net-snmp.sourceforge.net/docs/mibs/ip.html
611     if (likely(do_ip_packets || do_ip_fragsout || do_ip_fragsin || do_ip_errors)) {
612         if (unlikely(GETSYSCTL("net.inet.ip.stats", ipstat))) {
613             do_ip_packets = 0;
614             error("DISABLED: ipv4.packets");
615             do_ip_fragsout = 0;
616             error("DISABLED: ipv4.fragsout");
617             do_ip_fragsin = 0;
618             error("DISABLED: ipv4.fragsin");
619             do_ip_errors = 0;
620             error("DISABLED: ipv4.errors");
621         } else {
622             if (likely(do_ip_packets)) {
623                 st = rrdset_find_localhost("ipv4.packets");
624                 if (unlikely(!st)) {
625                     st = rrdset_create("ipv4", "packets", NULL, "packets", NULL, "IPv4 Packets", "packets/s",
626                                        3000, update_every, RRDSET_TYPE_LINE);
627
628                     rrddim_add(st, "InReceives", "received", 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
629                     rrddim_add(st, "OutRequests", "sent", -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
630                     rrddim_add(st, "ForwDatagrams", "forwarded", 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
631                     rrddim_add(st, "InDelivers", "delivered", 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
632                 } else
633                     rrdset_next(st);
634
635                 rrddim_set(st, "OutRequests", ipstat.ips_localout);
636                 rrddim_set(st, "InReceives", ipstat.ips_total);
637                 rrddim_set(st, "ForwDatagrams", ipstat.ips_forward);
638                 rrddim_set(st, "InDelivers", ipstat.ips_delivered);
639                 rrdset_done(st);
640             }
641
642             // --------------------------------------------------------------------
643
644             if (likely(do_ip_fragsout)) {
645                 st = rrdset_find_localhost("ipv4.fragsout");
646                 if (unlikely(!st)) {
647                     st = rrdset_create("ipv4", "fragsout", NULL, "fragments", NULL, "IPv4 Fragments Sent",
648                                        "packets/s", 3010, update_every, RRDSET_TYPE_LINE);
649                     st->isdetail = 1;
650
651                     rrddim_add(st, "FragOKs", "ok", 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
652                     rrddim_add(st, "FragFails", "failed", -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
653                     rrddim_add(st, "FragCreates", "created", 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
654                 } else
655                     rrdset_next(st);
656
657                 rrddim_set(st, "FragOKs", ipstat.ips_fragmented);
658                 rrddim_set(st, "FragFails", ipstat.ips_cantfrag);
659                 rrddim_set(st, "FragCreates", ipstat.ips_ofragments);
660                 rrdset_done(st);
661             }
662
663             // --------------------------------------------------------------------
664
665             if (likely(do_ip_fragsin)) {
666                 st = rrdset_find_localhost("ipv4.fragsin");
667                 if (unlikely(!st)) {
668                     st = rrdset_create("ipv4", "fragsin", NULL, "fragments", NULL,
669                                        "IPv4 Fragments Reassembly",
670                                        "packets/s", 3011, update_every, RRDSET_TYPE_LINE);
671                     st->isdetail = 1;
672
673                     rrddim_add(st, "ReasmOKs", "ok", 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
674                     rrddim_add(st, "ReasmFails", "failed", -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
675                     rrddim_add(st, "ReasmReqds", "all", 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
676                 } else
677                     rrdset_next(st);
678
679                 rrddim_set(st, "ReasmOKs", ipstat.ips_fragments);
680                 rrddim_set(st, "ReasmFails", ipstat.ips_fragdropped);
681                 rrddim_set(st, "ReasmReqds", ipstat.ips_reassembled);
682                 rrdset_done(st);
683             }
684
685             // --------------------------------------------------------------------
686
687             if (likely(do_ip_errors)) {
688                 st = rrdset_find_localhost("ipv4.errors");
689                 if (unlikely(!st)) {
690                     st = rrdset_create("ipv4", "errors", NULL, "errors", NULL, "IPv4 Errors", "packets/s",
691                                        3002,
692                                        update_every, RRDSET_TYPE_LINE);
693                     st->isdetail = 1;
694
695                     rrddim_add(st, "InDiscards", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
696                     rrddim_add(st, "OutDiscards", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
697
698                     rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
699                     rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
700
701                     rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
702                     rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
703                 } else
704                     rrdset_next(st);
705
706                 rrddim_set(st, "InDiscards", ipstat.ips_badsum + ipstat.ips_tooshort + ipstat.ips_toosmall + ipstat.ips_toolong);
707                 rrddim_set(st, "OutDiscards", ipstat.ips_odropped);
708                 rrddim_set(st, "InHdrErrors", ipstat.ips_badhlen + ipstat.ips_badlen + ipstat.ips_badoptions + ipstat.ips_badvers);
709                 rrddim_set(st, "InAddrErrors", ipstat.ips_badaddr);
710                 rrddim_set(st, "InUnknownProtos", ipstat.ips_noproto);
711                 rrddim_set(st, "OutNoRoutes", ipstat.ips_noroute);
712                 rrdset_done(st);
713             }
714         }
715     }
716  
717     // --------------------------------------------------------------------
718
719     if (likely(do_ip6_packets || do_ip6_fragsout || do_ip6_fragsin || do_ip6_errors)) {
720         if (unlikely(GETSYSCTL("net.inet6.ip6.stats", ip6stat))) {
721             do_ip6_packets = 0;
722             error("DISABLED: ipv6.packets");
723             do_ip6_fragsout = 0;
724             error("DISABLED: ipv6.fragsout");
725             do_ip6_fragsin = 0;
726             error("DISABLED: ipv6.fragsin");
727             do_ip6_errors = 0;
728             error("DISABLED: ipv6.errors");
729         } else {
730             if (do_ip6_packets == CONFIG_ONDEMAND_YES || (do_ip6_packets == CONFIG_ONDEMAND_ONDEMAND &&
731                                                           (ip6stat.ip6s_localout || ip6stat.ip6s_total ||
732                                                            ip6stat.ip6s_forward || ip6stat.ip6s_delivered))) {
733                 do_ip6_packets = CONFIG_ONDEMAND_YES;
734                 st = rrdset_find_localhost("ipv6.packets");
735                 if (unlikely(!st)) {
736                     st = rrdset_create("ipv6", "packets", NULL, "packets", NULL, "IPv6 Packets", "packets/s", 3000,
737                                        update_every, RRDSET_TYPE_LINE);
738
739                     rrddim_add(st, "received", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
740                     rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
741                     rrddim_add(st, "forwarded", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
742                     rrddim_add(st, "delivers", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
743                 } else
744                     rrdset_next(st);
745
746                 rrddim_set(st, "sent", ip6stat.ip6s_localout);
747                 rrddim_set(st, "received", ip6stat.ip6s_total);
748                 rrddim_set(st, "forwarded", ip6stat.ip6s_forward);
749                 rrddim_set(st, "delivers", ip6stat.ip6s_delivered);
750                 rrdset_done(st);
751             }
752
753             // --------------------------------------------------------------------
754
755             if (do_ip6_fragsout == CONFIG_ONDEMAND_YES || (do_ip6_fragsout == CONFIG_ONDEMAND_ONDEMAND &&
756                                                            (ip6stat.ip6s_fragmented || ip6stat.ip6s_cantfrag ||
757                                                             ip6stat.ip6s_ofragments))) {
758                 do_ip6_fragsout = CONFIG_ONDEMAND_YES;
759                 st = rrdset_find_localhost("ipv6.fragsout");
760                 if (unlikely(!st)) {
761                     st = rrdset_create("ipv6", "fragsout", NULL, "fragments", NULL, "IPv6 Fragments Sent",
762                                        "packets/s", 3010, update_every, RRDSET_TYPE_LINE);
763                     st->isdetail = 1;
764
765                     rrddim_add(st, "ok", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
766                     rrddim_add(st, "failed", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
767                     rrddim_add(st, "all", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
768                 } else
769                     rrdset_next(st);
770
771                 rrddim_set(st, "ok", ip6stat.ip6s_fragmented);
772                 rrddim_set(st, "failed", ip6stat.ip6s_cantfrag);
773                 rrddim_set(st, "all", ip6stat.ip6s_ofragments);
774                 rrdset_done(st);
775             }
776
777             // --------------------------------------------------------------------
778
779             if (do_ip6_fragsin == CONFIG_ONDEMAND_YES || (do_ip6_fragsin == CONFIG_ONDEMAND_ONDEMAND &&
780                                                           (ip6stat.ip6s_reassembled || ip6stat.ip6s_fragdropped ||
781                                                            ip6stat.ip6s_fragtimeout || ip6stat.ip6s_fragments))) {
782                 do_ip6_fragsin = CONFIG_ONDEMAND_YES;
783                 st = rrdset_find_localhost("ipv6.fragsin");
784                 if (unlikely(!st)) {
785                     st = rrdset_create("ipv6", "fragsin", NULL, "fragments", NULL, "IPv6 Fragments Reassembly",
786                                        "packets/s", 3011, update_every, RRDSET_TYPE_LINE);
787                     st->isdetail = 1;
788
789                     rrddim_add(st, "ok", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
790                     rrddim_add(st, "failed", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
791                     rrddim_add(st, "timeout", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
792                     rrddim_add(st, "all", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
793                 } else
794                     rrdset_next(st);
795
796                 rrddim_set(st, "ok", ip6stat.ip6s_reassembled);
797                 rrddim_set(st, "failed", ip6stat.ip6s_fragdropped);
798                 rrddim_set(st, "timeout", ip6stat.ip6s_fragtimeout);
799                 rrddim_set(st, "all", ip6stat.ip6s_fragments);
800                 rrdset_done(st);
801             }
802
803             // --------------------------------------------------------------------
804
805             if (do_ip6_errors == CONFIG_ONDEMAND_YES || (do_ip6_errors == CONFIG_ONDEMAND_ONDEMAND && (
806                     ip6stat.ip6s_toosmall ||
807                     ip6stat.ip6s_odropped ||
808                     ip6stat.ip6s_badoptions ||
809                     ip6stat.ip6s_badvers ||
810                     ip6stat.ip6s_exthdrtoolong ||
811                     ip6stat.ip6s_sources_none ||
812                     ip6stat.ip6s_tooshort ||
813                     ip6stat.ip6s_cantforward ||
814                     ip6stat.ip6s_noroute))) {
815                 do_ip6_errors = CONFIG_ONDEMAND_YES;
816                 st = rrdset_find_localhost("ipv6.errors");
817                 if (unlikely(!st)) {
818                     st = rrdset_create("ipv6", "errors", NULL, "errors", NULL, "IPv6 Errors", "packets/s", 3002,
819                                        update_every, RRDSET_TYPE_LINE);
820                     st->isdetail = 1;
821
822                     rrddim_add(st, "InDiscards", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
823                     rrddim_add(st, "OutDiscards", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
824
825                     rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
826                     rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
827                     rrddim_add(st, "InTruncatedPkts", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
828                     rrddim_add(st, "InNoRoutes", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
829
830                     rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
831                 } else
832                     rrdset_next(st);
833
834                 rrddim_set(st, "InDiscards", ip6stat.ip6s_toosmall);
835                 rrddim_set(st, "OutDiscards", ip6stat.ip6s_odropped);
836
837                 rrddim_set(st, "InHdrErrors",
838                            ip6stat.ip6s_badoptions + ip6stat.ip6s_badvers + ip6stat.ip6s_exthdrtoolong);
839                 rrddim_set(st, "InAddrErrors", ip6stat.ip6s_sources_none);
840                 rrddim_set(st, "InTruncatedPkts", ip6stat.ip6s_tooshort);
841                 rrddim_set(st, "InNoRoutes", ip6stat.ip6s_cantforward);
842
843                 rrddim_set(st, "OutNoRoutes", ip6stat.ip6s_noroute);
844                 rrdset_done(st);
845             }
846         }
847     }
848
849     // --------------------------------------------------------------------
850
851     if (likely(do_icmp6 || do_icmp6_redir || do_icmp6_errors || do_icmp6_echos || do_icmp6_router || do_icmp6_neighbor || do_icmp6_types)) {
852         if (unlikely(GETSYSCTL("net.inet6.icmp6.stats", icmp6stat))) {
853             do_icmp6 = 0;
854             error("DISABLED: ipv6.icmp");
855         } else {
856             for (i = 0; i <= ICMP6_MAXTYPE; i++) {
857                 icmp6_total.msgs_in += icmp6stat.icp6s_inhist[i];
858                 icmp6_total.msgs_out += icmp6stat.icp6s_outhist[i];
859             }
860             icmp6_total.msgs_in += icmp6stat.icp6s_badcode + icmp6stat.icp6s_badlen + icmp6stat.icp6s_checksum + icmp6stat.icp6s_tooshort;
861             if (do_icmp6 == CONFIG_ONDEMAND_YES || (do_icmp6 == CONFIG_ONDEMAND_ONDEMAND && (icmp6_total.msgs_in || icmp6_total.msgs_out))) {
862                 do_icmp6 = CONFIG_ONDEMAND_YES;
863                 st = rrdset_find_localhost("ipv6.icmp");
864                 if (unlikely(!st)) {
865                     st = rrdset_create("ipv6", "icmp", NULL, "icmp", NULL, "IPv6 ICMP Messages",
866                                        "messages/s", 10000, update_every, RRDSET_TYPE_LINE);
867
868                     rrddim_add(st, "received", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
869                     rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
870                 } else
871                     rrdset_next(st);
872
873                 rrddim_set(st, "sent", icmp6_total.msgs_in);
874                 rrddim_set(st, "received", icmp6_total.msgs_out);
875                 rrdset_done(st);
876             }
877
878             // --------------------------------------------------------------------
879
880             if (do_icmp6_redir == CONFIG_ONDEMAND_YES || (do_icmp6_redir == CONFIG_ONDEMAND_ONDEMAND && (icmp6stat.icp6s_inhist[ND_REDIRECT] || icmp6stat.icp6s_outhist[ND_REDIRECT]))) {
881                 do_icmp6_redir = CONFIG_ONDEMAND_YES;
882                 st = rrdset_find_localhost("ipv6.icmpredir");
883                 if (unlikely(!st)) {
884                     st = rrdset_create("ipv6", "icmpredir", NULL, "icmp", NULL, "IPv6 ICMP Redirects",
885                                        "redirects/s", 10050, update_every, RRDSET_TYPE_LINE);
886
887                     rrddim_add(st, "received", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
888                     rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
889                 } else
890                     rrdset_next(st);
891
892                 rrddim_set(st, "sent", icmp6stat.icp6s_inhist[ND_REDIRECT]);
893                 rrddim_set(st, "received", icmp6stat.icp6s_outhist[ND_REDIRECT]);
894                 rrdset_done(st);
895             }
896
897             // --------------------------------------------------------------------
898
899             if (do_icmp6_errors == CONFIG_ONDEMAND_YES || (do_icmp6_errors == CONFIG_ONDEMAND_ONDEMAND && (
900                                                                             icmp6stat.icp6s_badcode ||
901                                                                             icmp6stat.icp6s_badlen ||
902                                                                             icmp6stat.icp6s_checksum ||
903                                                                             icmp6stat.icp6s_tooshort ||
904                                                                             icmp6stat.icp6s_error ||
905                                                                             icmp6stat.icp6s_inhist[ICMP6_DST_UNREACH] ||
906                                                                             icmp6stat.icp6s_inhist[ICMP6_TIME_EXCEEDED] ||
907                                                                             icmp6stat.icp6s_inhist[ICMP6_PARAM_PROB] ||
908                                                                             icmp6stat.icp6s_outhist[ICMP6_DST_UNREACH] ||
909                                                                             icmp6stat.icp6s_outhist[ICMP6_TIME_EXCEEDED] ||
910                                                                             icmp6stat.icp6s_outhist[ICMP6_PARAM_PROB]))) {
911                 do_icmp6_errors = CONFIG_ONDEMAND_YES;
912                 st = rrdset_find_localhost("ipv6.icmperrors");
913                 if (unlikely(!st)) {
914                     st = rrdset_create("ipv6", "icmperrors", NULL, "icmp", NULL, "IPv6 ICMP Errors", "errors/s", 10100, update_every, RRDSET_TYPE_LINE);
915
916                     rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
917                     rrddim_add(st, "OutErrors", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
918
919                     rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
920                     rrddim_add(st, "InDestUnreachs", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
921                     rrddim_add(st, "InPktTooBigs", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
922                     rrddim_add(st, "InTimeExcds", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
923                     rrddim_add(st, "InParmProblems", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
924                     rrddim_add(st, "OutDestUnreachs", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
925                     rrddim_add(st, "OutTimeExcds", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
926                     rrddim_add(st, "OutParmProblems", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
927                 } else
928                     rrdset_next(st);
929
930                 rrddim_set(st, "InErrors", icmp6stat.icp6s_badcode + icmp6stat.icp6s_badlen + icmp6stat.icp6s_checksum + icmp6stat.icp6s_tooshort);
931                 rrddim_set(st, "OutErrors", icmp6stat.icp6s_error);
932                 rrddim_set(st, "InCsumErrors", icmp6stat.icp6s_checksum);
933                 rrddim_set(st, "InDestUnreachs", icmp6stat.icp6s_inhist[ICMP6_DST_UNREACH]);
934                 rrddim_set(st, "InPktTooBigs", icmp6stat.icp6s_badlen);
935                 rrddim_set(st, "InTimeExcds", icmp6stat.icp6s_inhist[ICMP6_TIME_EXCEEDED]);
936                 rrddim_set(st, "InParmProblems", icmp6stat.icp6s_inhist[ICMP6_PARAM_PROB]);
937                 rrddim_set(st, "OutDestUnreachs", icmp6stat.icp6s_outhist[ICMP6_DST_UNREACH]);
938                 rrddim_set(st, "OutTimeExcds", icmp6stat.icp6s_outhist[ICMP6_TIME_EXCEEDED]);
939                 rrddim_set(st, "OutParmProblems", icmp6stat.icp6s_outhist[ICMP6_PARAM_PROB]);
940                 rrdset_done(st);
941             }
942
943             // --------------------------------------------------------------------
944
945             if (do_icmp6_echos == CONFIG_ONDEMAND_YES || (do_icmp6_echos == CONFIG_ONDEMAND_ONDEMAND && (
946                                                                  icmp6stat.icp6s_inhist[ICMP6_ECHO_REQUEST] ||
947                                                                  icmp6stat.icp6s_outhist[ICMP6_ECHO_REQUEST] ||
948                                                                  icmp6stat.icp6s_inhist[ICMP6_ECHO_REPLY] ||
949                                                                  icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]))) {
950                 do_icmp6_echos = CONFIG_ONDEMAND_YES;
951                 st = rrdset_find_localhost("ipv6.icmpechos");
952                 if (unlikely(!st)) {
953                     st = rrdset_create("ipv6", "icmpechos", NULL, "icmp", NULL, "IPv6 ICMP Echo", "messages/s", 10200, update_every, RRDSET_TYPE_LINE);
954
955                     rrddim_add(st, "InEchos", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
956                     rrddim_add(st, "OutEchos", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
957                     rrddim_add(st, "InEchoReplies", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
958                     rrddim_add(st, "OutEchoReplies", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
959                 } else
960                     rrdset_next(st);
961
962                 rrddim_set(st, "InEchos", icmp6stat.icp6s_inhist[ICMP6_ECHO_REQUEST]);
963                 rrddim_set(st, "OutEchos", icmp6stat.icp6s_outhist[ICMP6_ECHO_REQUEST]);
964                 rrddim_set(st, "InEchoReplies", icmp6stat.icp6s_inhist[ICMP6_ECHO_REPLY]);
965                 rrddim_set(st, "OutEchoReplies", icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]);
966                 rrdset_done(st);
967             }
968
969             // --------------------------------------------------------------------
970
971             if (do_icmp6_router == CONFIG_ONDEMAND_YES || (do_icmp6_router == CONFIG_ONDEMAND_ONDEMAND && (
972                                                                     icmp6stat.icp6s_inhist[ND_ROUTER_SOLICIT] ||
973                                                                     icmp6stat.icp6s_outhist[ND_ROUTER_SOLICIT] ||
974                                                                     icmp6stat.icp6s_inhist[ND_ROUTER_ADVERT] ||
975                                                                     icmp6stat.icp6s_outhist[ND_ROUTER_ADVERT]))) {
976                 do_icmp6_router = CONFIG_ONDEMAND_YES;
977                 st = rrdset_find_localhost("ipv6.icmprouter");
978                 if (unlikely(!st)) {
979                     st = rrdset_create("ipv6", "icmprouter", NULL, "icmp", NULL, "IPv6 Router Messages", "messages/s", 10400, update_every, RRDSET_TYPE_LINE);
980
981                     rrddim_add(st, "InSolicits", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
982                     rrddim_add(st, "OutSolicits", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
983                     rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
984                     rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
985                 } else
986                     rrdset_next(st);
987
988                 rrddim_set(st, "InSolicits", icmp6stat.icp6s_inhist[ND_ROUTER_SOLICIT]);
989                 rrddim_set(st, "OutSolicits", icmp6stat.icp6s_outhist[ND_ROUTER_SOLICIT]);
990                 rrddim_set(st, "InAdvertisements", icmp6stat.icp6s_inhist[ND_ROUTER_ADVERT]);
991                 rrddim_set(st, "OutAdvertisements", icmp6stat.icp6s_outhist[ND_ROUTER_ADVERT]);
992                 rrdset_done(st);
993             }
994
995             // --------------------------------------------------------------------
996
997             if (do_icmp6_neighbor == CONFIG_ONDEMAND_YES || (do_icmp6_neighbor == CONFIG_ONDEMAND_ONDEMAND && (
998                                                                     icmp6stat.icp6s_inhist[ND_NEIGHBOR_SOLICIT] ||
999                                                                     icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT] ||
1000                                                                     icmp6stat.icp6s_inhist[ND_NEIGHBOR_ADVERT] ||
1001                                                                     icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]))) {
1002                 do_icmp6_neighbor = CONFIG_ONDEMAND_YES;
1003                 st = rrdset_find_localhost("ipv6.icmpneighbor");
1004                 if (unlikely(!st)) {
1005                     st = rrdset_create("ipv6", "icmpneighbor", NULL, "icmp", NULL, "IPv6 Neighbor Messages", "messages/s", 10500, update_every, RRDSET_TYPE_LINE);
1006
1007                     rrddim_add(st, "InSolicits", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
1008                     rrddim_add(st, "OutSolicits", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
1009                     rrddim_add(st, "InAdvertisements", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
1010                     rrddim_add(st, "OutAdvertisements", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
1011                 } else
1012                     rrdset_next(st);
1013
1014                 rrddim_set(st, "InSolicits", icmp6stat.icp6s_inhist[ND_NEIGHBOR_SOLICIT]);
1015                 rrddim_set(st, "OutSolicits", icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT]);
1016                 rrddim_set(st, "InAdvertisements", icmp6stat.icp6s_inhist[ND_NEIGHBOR_ADVERT]);
1017                 rrddim_set(st, "OutAdvertisements", icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]);
1018                 rrdset_done(st);
1019             }
1020
1021             // --------------------------------------------------------------------
1022
1023             if (do_icmp6_types == CONFIG_ONDEMAND_YES || (do_icmp6_types == CONFIG_ONDEMAND_ONDEMAND && (
1024                                                                     icmp6stat.icp6s_inhist[1] ||
1025                                                                     icmp6stat.icp6s_inhist[128] ||
1026                                                                     icmp6stat.icp6s_inhist[129] ||
1027                                                                     icmp6stat.icp6s_inhist[136] ||
1028                                                                     icmp6stat.icp6s_outhist[1] ||
1029                                                                     icmp6stat.icp6s_outhist[128] ||
1030                                                                     icmp6stat.icp6s_outhist[129] ||
1031                                                                     icmp6stat.icp6s_outhist[133] ||
1032                                                                     icmp6stat.icp6s_outhist[135] ||
1033                                                                     icmp6stat.icp6s_outhist[136]))) {
1034                 do_icmp6_types = CONFIG_ONDEMAND_YES;
1035                 st = rrdset_find_localhost("ipv6.icmptypes");
1036                 if (unlikely(!st)) {
1037                     st = rrdset_create("ipv6", "icmptypes", NULL, "icmp", NULL, "IPv6 ICMP Types",
1038                                        "messages/s", 10700, update_every, RRDSET_TYPE_LINE);
1039
1040                     rrddim_add(st, "InType1", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
1041                     rrddim_add(st, "InType128", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
1042                     rrddim_add(st, "InType129", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
1043                     rrddim_add(st, "InType136", NULL, 1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
1044                     rrddim_add(st, "OutType1", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
1045                     rrddim_add(st, "OutType128", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
1046                     rrddim_add(st, "OutType129", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
1047                     rrddim_add(st, "OutType133", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
1048                     rrddim_add(st, "OutType135", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
1049                     rrddim_add(st, "OutType143", NULL, -1, 1, RRDDIM_ALGORITHM_INCREMENTAL);
1050                 } else
1051                     rrdset_next(st);
1052
1053                 rrddim_set(st, "InType1", icmp6stat.icp6s_inhist[1]);
1054                 rrddim_set(st, "InType128", icmp6stat.icp6s_inhist[128]);
1055                 rrddim_set(st, "InType129", icmp6stat.icp6s_inhist[129]);
1056                 rrddim_set(st, "InType136", icmp6stat.icp6s_inhist[136]);
1057                 rrddim_set(st, "OutType1", icmp6stat.icp6s_outhist[1]);
1058                 rrddim_set(st, "OutType128", icmp6stat.icp6s_outhist[128]);
1059                 rrddim_set(st, "OutType129", icmp6stat.icp6s_outhist[129]);
1060                 rrddim_set(st, "OutType133", icmp6stat.icp6s_outhist[133]);
1061                 rrddim_set(st, "OutType135", icmp6stat.icp6s_outhist[135]);
1062                 rrddim_set(st, "OutType143", icmp6stat.icp6s_outhist[143]);
1063                 rrdset_done(st);
1064             }
1065         }
1066     }
1067
1068     // --------------------------------------------------------------------
1069
1070     if (likely(do_uptime)) {
1071         if (unlikely(GETSYSCTL("kern.boottime", boot_time))) {
1072             do_uptime = 0;
1073             error("DISABLED: system.uptime");
1074         } else {
1075             clock_gettime(CLOCK_REALTIME, &cur_time);
1076             st = rrdset_find_localhost("system.uptime");
1077
1078             if(unlikely(!st)) {
1079                 st = rrdset_create("system", "uptime", NULL, "uptime", NULL, "System Uptime", "seconds", 1000, update_every, RRDSET_TYPE_LINE);
1080                 rrddim_add(st, "uptime", NULL, 1, 1, RRDDIM_ALGORITHM_ABSOLUTE);
1081             }
1082             else rrdset_next(st);
1083
1084             rrddim_set(st, "uptime", cur_time.tv_sec - boot_time.tv_sec);
1085             rrdset_done(st);
1086         }
1087     }
1088
1089     return 0;
1090 }
1091
1092 int getsysctl(const char *name, void *ptr, size_t len)
1093 {
1094     size_t nlen = len;
1095
1096     if (unlikely(sysctlbyname(name, ptr, &nlen, NULL, 0) == -1)) {
1097         error("MACOS: sysctl(%s...) failed: %s", name, strerror(errno));
1098         return 1;
1099     }
1100     if (unlikely(nlen != len)) {
1101         error("MACOS: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)len, (unsigned long)nlen);
1102         return 1;
1103     }
1104     return 0;
1105 }