]> arthur.barton.de Git - netdata.git/blob - src/macos_sysctl.c
Add IPv4 ICMP charts to macOS plugin
[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
19 #define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
20
21 // MacOS calculates load averages once every 5 seconds
22 #define MIN_LOADAVG_UPDATE_EVERY 5
23
24 int getsysctl(const char *name, void *ptr, size_t len);
25
26 int do_macos_sysctl(int update_every, usec_t dt) {
27     (void)dt;
28
29     static int do_loadavg = -1, do_swap = -1, do_bandwidth = -1,
30                do_tcp_packets = -1, do_tcp_errors = -1, do_tcp_handshake = -1, do_ecn = -1,
31                do_tcpext_syscookies = -1, do_tcpext_ofo = -1, do_tcpext_connaborts = -1,
32                do_udp_packets = -1, do_udp_errors = -1, do_icmp_packets = -1, do_icmpmsg = -1;
33
34
35     if (unlikely(do_loadavg == -1)) {
36         do_loadavg              = config_get_boolean("plugin:macos:sysctl", "enable load average", 1);
37         do_swap                 = config_get_boolean("plugin:macos:sysctl", "system swap", 1);
38         do_bandwidth            = config_get_boolean("plugin:macos:sysctl", "bandwidth", 1);
39         do_tcp_packets          = config_get_boolean("plugin:macos:sysctl", "ipv4 TCP packets", 1);
40         do_tcp_errors           = config_get_boolean("plugin:macos:sysctl", "ipv4 TCP errors", 1);
41         do_tcp_handshake        = config_get_boolean("plugin:macos:sysctl", "ipv4 TCP handshake issues", 1);
42         do_ecn                  = config_get_boolean_ondemand("plugin:macos:sysctl", "ECN packets", CONFIG_ONDEMAND_ONDEMAND);
43         do_tcpext_syscookies    = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP SYN cookies", CONFIG_ONDEMAND_ONDEMAND);
44         do_tcpext_ofo           = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP out-of-order queue", CONFIG_ONDEMAND_ONDEMAND);
45         do_tcpext_connaborts    = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP connection aborts", CONFIG_ONDEMAND_ONDEMAND);
46         do_udp_packets          = config_get_boolean("plugin:macos:sysctl", "ipv4 UDP packets", 1);
47         do_udp_errors           = config_get_boolean("plugin:macos:sysctl", "ipv4 UDP errors", 1);
48         do_icmp_packets         = config_get_boolean("plugin:macos:sysctl", "ipv4 ICMP packets", 1);
49         do_icmpmsg              = config_get_boolean("plugin:macos:sysctl", "ipv4 ICMP messages", 1);
50     }
51
52     RRDSET *st;
53
54     int system_pagesize = getpagesize(); // wouldn't it be better to get value directly from hw.pagesize?
55     int i, n;
56     int common_error = 0;
57     size_t size;
58
59     // NEEDED BY: do_loadavg
60     static usec_t last_loadavg_usec = 0;
61     struct loadavg sysload;
62
63     // NEEDED BY: do_swap
64     struct xsw_usage swap_usage;
65
66     // NEEDED BY: do_bandwidth
67     int mib[6];
68     static char *ifstatdata = NULL;
69     char *lim, *next;
70     struct if_msghdr *ifm;
71     struct iftot {
72         u_long  ift_ibytes;
73         u_long  ift_obytes;
74     } iftot = {0, 0};
75
76     // NEEDED BY: do_tcp...
77     struct tcpstat tcpstat;
78     uint64_t tcps_states[TCP_NSTATES];
79
80     // NEEDED BY: do_udp...
81     struct udpstat udpstat;
82
83     // NEEDED BY: do_icmp...
84     struct icmpstat icmpstat;
85     struct icmp_total {
86         u_long  msgs_in;
87         u_long  msgs_out;
88     } icmp_total = {0, 0};
89
90     // --------------------------------------------------------------------
91
92     if (last_loadavg_usec <= dt) {
93         if (likely(do_loadavg)) {
94             if (unlikely(GETSYSCTL("vm.loadavg", sysload))) {
95                 do_loadavg = 0;
96                 error("DISABLED: system.load");
97             } else {
98
99                 st = rrdset_find_bytype("system", "load");
100                 if (unlikely(!st)) {
101                     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);
102                     rrddim_add(st, "load1", NULL, 1, 1000, RRDDIM_ABSOLUTE);
103                     rrddim_add(st, "load5", NULL, 1, 1000, RRDDIM_ABSOLUTE);
104                     rrddim_add(st, "load15", NULL, 1, 1000, RRDDIM_ABSOLUTE);
105                 }
106                 else rrdset_next(st);
107
108                 rrddim_set(st, "load1", (collected_number) ((double)sysload.ldavg[0] / sysload.fscale * 1000));
109                 rrddim_set(st, "load5", (collected_number) ((double)sysload.ldavg[1] / sysload.fscale * 1000));
110                 rrddim_set(st, "load15", (collected_number) ((double)sysload.ldavg[2] / sysload.fscale * 1000));
111                 rrdset_done(st);
112             }
113         }
114
115         last_loadavg_usec = st->update_every * USEC_PER_SEC;
116     }
117     else last_loadavg_usec -= dt;
118
119     // --------------------------------------------------------------------
120
121     if (likely(do_swap)) {
122         if (unlikely(GETSYSCTL("vm.swapusage", swap_usage))) {
123             do_swap = 0;
124             error("DISABLED: system.swap");
125         } else {
126             st = rrdset_find("system.swap");
127             if (unlikely(!st)) {
128                 st = rrdset_create("system", "swap", NULL, "swap", NULL, "System Swap", "MB", 201, update_every, RRDSET_TYPE_STACKED);
129                 st->isdetail = 1;
130
131                 rrddim_add(st, "free",    NULL, 1, 1048576, RRDDIM_ABSOLUTE);
132                 rrddim_add(st, "used",    NULL, 1, 1048576, RRDDIM_ABSOLUTE);
133             }
134             else rrdset_next(st);
135
136             rrddim_set(st, "free", swap_usage.xsu_avail);
137             rrddim_set(st, "used", swap_usage.xsu_used);
138             rrdset_done(st);
139         }
140     }
141
142     // --------------------------------------------------------------------
143
144     if (likely(do_bandwidth)) {
145         mib[0] = CTL_NET;
146         mib[1] = PF_ROUTE;
147         mib[2] = 0;
148         mib[3] = AF_INET;
149         mib[4] = NET_RT_IFLIST2;
150         mib[5] = 0;
151         if (unlikely(sysctl(mib, 6, NULL, &size, NULL, 0))) {
152             error("MACOS: sysctl(%s...) failed: %s", "net interfaces", strerror(errno));
153             do_bandwidth = 0;
154             error("DISABLED: system.ipv4");
155         } else {
156             ifstatdata = reallocz(ifstatdata, size);
157             if (unlikely(sysctl(mib, 6, ifstatdata, &size, NULL, 0) < 0)) {
158                 error("MACOS: sysctl(%s...) failed: %s", "net interfaces", strerror(errno));
159                 do_bandwidth = 0;
160                 error("DISABLED: system.ipv4");
161             } else {
162                 lim = ifstatdata + size;
163                 iftot.ift_ibytes = iftot.ift_obytes = 0;
164                 for (next = ifstatdata; next < lim; ) {
165                     ifm = (struct if_msghdr *)next;
166                     next += ifm->ifm_msglen;
167
168                     if (ifm->ifm_type == RTM_IFINFO2) {
169                         struct if_msghdr2 *if2m = (struct if_msghdr2 *)ifm;
170
171                         iftot.ift_ibytes += if2m->ifm_data.ifi_ibytes;
172                         iftot.ift_obytes += if2m->ifm_data.ifi_obytes;
173                     }
174                 }
175                 st = rrdset_find("system.ipv4");
176                 if (unlikely(!st)) {
177                     st = rrdset_create("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA);
178
179                     rrddim_add(st, "InOctets", "received", 8, 1024, RRDDIM_INCREMENTAL);
180                     rrddim_add(st, "OutOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL);
181                 }
182                 else rrdset_next(st);
183
184                 rrddim_set(st, "InOctets", iftot.ift_ibytes);
185                 rrddim_set(st, "OutOctets", iftot.ift_obytes);
186                 rrdset_done(st);
187             }
188         }
189     }
190
191     // --------------------------------------------------------------------
192
193     // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html
194     if (likely(do_tcp_packets || do_tcp_errors || do_tcp_handshake || do_tcpext_connaborts || do_tcpext_ofo || do_tcpext_syscookies || do_ecn)) {
195         if (unlikely(GETSYSCTL("net.inet.tcp.stats", tcpstat))){
196             do_tcp_packets = 0;
197             error("DISABLED: ipv4.tcppackets");
198             do_tcp_errors = 0;
199             error("DISABLED: ipv4.tcperrors");
200             do_tcp_handshake = 0;
201             error("DISABLED: ipv4.tcphandshake");
202             do_tcpext_connaborts = 0;
203             error("DISABLED: ipv4.tcpconnaborts");
204             do_tcpext_ofo = 0;
205             error("DISABLED: ipv4.tcpofo");
206             do_tcpext_syscookies = 0;
207             error("DISABLED: ipv4.tcpsyncookies");
208             do_ecn = 0;
209             error("DISABLED: ipv4.ecnpkts");
210         } else {
211             if (likely(do_tcp_packets)) {
212                 st = rrdset_find("ipv4.tcppackets");
213                 if (unlikely(!st)) {
214                     st = rrdset_create("ipv4", "tcppackets", NULL, "tcp", NULL, "IPv4 TCP Packets",
215                                        "packets/s",
216                                        2600, update_every, RRDSET_TYPE_LINE);
217
218                     rrddim_add(st, "InSegs", "received", 1, 1, RRDDIM_INCREMENTAL);
219                     rrddim_add(st, "OutSegs", "sent", -1, 1, RRDDIM_INCREMENTAL);
220                 } else
221                     rrdset_next(st);
222
223                 rrddim_set(st, "InSegs", tcpstat.tcps_rcvtotal);
224                 rrddim_set(st, "OutSegs", tcpstat.tcps_sndtotal);
225                 rrdset_done(st);
226             }
227
228             // --------------------------------------------------------------------
229
230             if (likely(do_tcp_errors)) {
231                 st = rrdset_find("ipv4.tcperrors");
232                 if (unlikely(!st)) {
233                     st = rrdset_create("ipv4", "tcperrors", NULL, "tcp", NULL, "IPv4 TCP Errors",
234                                        "packets/s",
235                                        2700, update_every, RRDSET_TYPE_LINE);
236                     st->isdetail = 1;
237
238                     rrddim_add(st, "InErrs", NULL, 1, 1, RRDDIM_INCREMENTAL);
239                     rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
240                     rrddim_add(st, "RetransSegs", NULL, -1, 1, RRDDIM_INCREMENTAL);
241                 } else
242                     rrdset_next(st);
243
244                 rrddim_set(st, "InErrs", tcpstat.tcps_rcvbadoff + tcpstat.tcps_rcvshort);
245                 rrddim_set(st, "InCsumErrors", tcpstat.tcps_rcvbadsum);
246                 rrddim_set(st, "RetransSegs", tcpstat.tcps_sndrexmitpack);
247                 rrdset_done(st);
248             }
249
250             // --------------------------------------------------------------------
251
252             if (likely(do_tcp_handshake)) {
253                 st = rrdset_find("ipv4.tcphandshake");
254                 if (unlikely(!st)) {
255                     st = rrdset_create("ipv4", "tcphandshake", NULL, "tcp", NULL,
256                                        "IPv4 TCP Handshake Issues",
257                                        "events/s", 2900, update_every, RRDSET_TYPE_LINE);
258                     st->isdetail = 1;
259
260                     rrddim_add(st, "EstabResets", NULL, 1, 1, RRDDIM_INCREMENTAL);
261                     rrddim_add(st, "ActiveOpens", NULL, 1, 1, RRDDIM_INCREMENTAL);
262                     rrddim_add(st, "PassiveOpens", NULL, 1, 1, RRDDIM_INCREMENTAL);
263                     rrddim_add(st, "AttemptFails", NULL, 1, 1, RRDDIM_INCREMENTAL);
264                 } else
265                     rrdset_next(st);
266
267                 rrddim_set(st, "EstabResets", tcpstat.tcps_drops);
268                 rrddim_set(st, "ActiveOpens", tcpstat.tcps_connattempt);
269                 rrddim_set(st, "PassiveOpens", tcpstat.tcps_accepts);
270                 rrddim_set(st, "AttemptFails", tcpstat.tcps_conndrops);
271                 rrdset_done(st);
272             }
273
274             // --------------------------------------------------------------------
275
276             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))) {
277                 do_tcpext_connaborts = CONFIG_ONDEMAND_YES;
278                 st = rrdset_find("ipv4.tcpconnaborts");
279                 if (unlikely(!st)) {
280                     st = rrdset_create("ipv4", "tcpconnaborts", NULL, "tcp", NULL, "TCP Connection Aborts", "connections/s", 3010, update_every, RRDSET_TYPE_LINE);
281
282                     rrddim_add(st, "TCPAbortOnData",    "baddata",     1, 1, RRDDIM_INCREMENTAL);
283                     rrddim_add(st, "TCPAbortOnClose",   "userclosed",  1, 1, RRDDIM_INCREMENTAL);
284                     rrddim_add(st, "TCPAbortOnMemory",  "nomemory",    1, 1, RRDDIM_INCREMENTAL);
285                     rrddim_add(st, "TCPAbortOnTimeout", "timeout",     1, 1, RRDDIM_INCREMENTAL);
286                 }
287                 else rrdset_next(st);
288
289                 rrddim_set(st, "TCPAbortOnData",    tcpstat.tcps_rcvpackafterwin);
290                 rrddim_set(st, "TCPAbortOnClose",   tcpstat.tcps_rcvafterclose);
291                 rrddim_set(st, "TCPAbortOnMemory",  tcpstat.tcps_rcvmemdrop);
292                 rrddim_set(st, "TCPAbortOnTimeout", tcpstat.tcps_persistdrop);
293                 rrdset_done(st);
294             }
295
296             // --------------------------------------------------------------------
297
298             if (do_tcpext_ofo == CONFIG_ONDEMAND_YES || (do_tcpext_ofo == CONFIG_ONDEMAND_ONDEMAND && tcpstat.tcps_rcvoopack)) {
299                 do_tcpext_ofo = CONFIG_ONDEMAND_YES;
300                 st = rrdset_find("ipv4.tcpofo");
301                 if (unlikely(!st)) {
302                     st = rrdset_create("ipv4", "tcpofo", NULL, "tcp", NULL, "TCP Out-Of-Order Queue", "packets/s", 3050, update_every, RRDSET_TYPE_LINE);
303
304                     rrddim_add(st, "TCPOFOQueue", "inqueue",  1, 1, RRDDIM_INCREMENTAL);
305                 }
306                 else rrdset_next(st);
307
308                 rrddim_set(st, "TCPOFOQueue",   tcpstat.tcps_rcvoopack);
309                 rrdset_done(st);
310             }
311
312             // --------------------------------------------------------------------
313
314             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))) {
315                 do_tcpext_syscookies = CONFIG_ONDEMAND_YES;
316
317                 st = rrdset_find("ipv4.tcpsyncookies");
318                 if (unlikely(!st)) {
319                     st = rrdset_create("ipv4", "tcpsyncookies", NULL, "tcp", NULL, "TCP SYN Cookies", "packets/s", 3100, update_every, RRDSET_TYPE_LINE);
320
321                     rrddim_add(st, "SyncookiesRecv",   "received",  1, 1, RRDDIM_INCREMENTAL);
322                     rrddim_add(st, "SyncookiesSent",   "sent",     -1, 1, RRDDIM_INCREMENTAL);
323                     rrddim_add(st, "SyncookiesFailed", "failed",   -1, 1, RRDDIM_INCREMENTAL);
324                 }
325                 else rrdset_next(st);
326
327                 rrddim_set(st, "SyncookiesRecv",   tcpstat.tcps_sc_recvcookie);
328                 rrddim_set(st, "SyncookiesSent",   tcpstat.tcps_sc_sendcookie);
329                 rrddim_set(st, "SyncookiesFailed", tcpstat.tcps_sc_zonefail);
330                 rrdset_done(st);
331             }
332
333             // --------------------------------------------------------------------
334
335             if (do_ecn == CONFIG_ONDEMAND_YES || (do_ecn == CONFIG_ONDEMAND_ONDEMAND && (tcpstat.tcps_ecn_recv_ce || tcpstat.tcps_ecn_not_supported))) {
336                 do_ecn = CONFIG_ONDEMAND_YES;
337                 st = rrdset_find("ipv4.ecnpkts");
338                 if (unlikely(!st)) {
339                     st = rrdset_create("ipv4", "ecnpkts", NULL, "ecn", NULL, "IPv4 ECN Statistics", "packets/s", 8700, update_every, RRDSET_TYPE_LINE);
340                     st->isdetail = 1;
341
342                     rrddim_add(st, "InCEPkts", "CEP", 1, 1, RRDDIM_INCREMENTAL);
343                     rrddim_add(st, "InNoECTPkts", "NoECTP", -1, 1, RRDDIM_INCREMENTAL);
344                 }
345                 else rrdset_next(st);
346
347                 rrddim_set(st, "InCEPkts", tcpstat.tcps_ecn_recv_ce);
348                 rrddim_set(st, "InNoECTPkts", tcpstat.tcps_ecn_not_supported);
349                 rrdset_done(st);
350             }
351
352         }
353     }
354
355     // --------------------------------------------------------------------
356
357     // see http://net-snmp.sourceforge.net/docs/mibs/udp.html
358     if (likely(do_udp_packets || do_udp_errors)) {
359         if (unlikely(GETSYSCTL("net.inet.udp.stats", udpstat))) {
360             do_udp_packets = 0;
361             error("DISABLED: ipv4.udppackets");
362             do_udp_errors = 0;
363             error("DISABLED: ipv4.udperrors");
364         } else {
365             if (likely(do_udp_packets)) {
366                 st = rrdset_find("ipv4.udppackets");
367                 if (unlikely(!st)) {
368                     st = rrdset_create("ipv4", "udppackets", NULL, "udp", NULL, "IPv4 UDP Packets",
369                                        "packets/s", 2601, update_every, RRDSET_TYPE_LINE);
370
371                     rrddim_add(st, "InDatagrams", "received", 1, 1, RRDDIM_INCREMENTAL);
372                     rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRDDIM_INCREMENTAL);
373                 } else
374                     rrdset_next(st);
375
376                 rrddim_set(st, "InDatagrams", udpstat.udps_ipackets);
377                 rrddim_set(st, "OutDatagrams", udpstat.udps_opackets);
378                 rrdset_done(st);
379             }
380
381             // --------------------------------------------------------------------
382
383             if (likely(do_udp_errors)) {
384                 st = rrdset_find("ipv4.udperrors");
385                 if (unlikely(!st)) {
386                     st = rrdset_create("ipv4", "udperrors", NULL, "udp", NULL, "IPv4 UDP Errors", "events/s",
387                                        2701, update_every, RRDSET_TYPE_LINE);
388                     st->isdetail = 1;
389
390                     rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
391                     rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
392                     rrddim_add(st, "NoPorts", NULL, 1, 1, RRDDIM_INCREMENTAL);
393                     rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
394                     rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRDDIM_INCREMENTAL);
395                 } else
396                     rrdset_next(st);
397
398                 rrddim_set(st, "InErrors", udpstat.udps_hdrops + udpstat.udps_badlen);
399                 rrddim_set(st, "NoPorts", udpstat.udps_noport);
400                 rrddim_set(st, "RcvbufErrors", udpstat.udps_fullsock);
401                 rrddim_set(st, "InCsumErrors", udpstat.udps_badsum + udpstat.udps_nosum);
402                 rrddim_set(st, "IgnoredMulti", udpstat.udps_filtermcast);
403                 rrdset_done(st);
404             }
405         }
406     }
407
408     // --------------------------------------------------------------------
409
410     if (likely(do_icmp_packets || do_icmpmsg)) {
411         if (unlikely(GETSYSCTL("net.inet.icmp.stats", icmpstat))) {
412             do_icmp_packets = 0;
413             error("DISABLED: ipv4.icmp");
414             error("DISABLED: ipv4.icmp_errors");
415             do_icmpmsg = 0;
416             error("DISABLED: ipv4.icmpmsg");
417         } else {
418             for (i = 0; i <= ICMP_MAXTYPE; i++) {
419                 icmp_total.msgs_in += icmpstat.icps_inhist[i];
420                 icmp_total.msgs_out += icmpstat.icps_outhist[i];
421             }
422             icmp_total.msgs_in += icmpstat.icps_badcode + icmpstat.icps_badlen + icmpstat.icps_checksum + icmpstat.icps_tooshort;
423
424             // --------------------------------------------------------------------
425
426             if (likely(do_icmp_packets)) {
427                 st = rrdset_find("ipv4.icmp");
428                 if (unlikely(!st)) {
429                     st = rrdset_create("ipv4", "icmp", NULL, "icmp", NULL, "IPv4 ICMP Packets", "packets/s",
430                                        2602,
431                                        update_every, RRDSET_TYPE_LINE);
432
433                     rrddim_add(st, "InMsgs", "received", 1, 1, RRDDIM_INCREMENTAL);
434                     rrddim_add(st, "OutMsgs", "sent", -1, 1, RRDDIM_INCREMENTAL);
435                 } else
436                     rrdset_next(st);
437
438                 rrddim_set(st, "InMsgs", icmp_total.msgs_in);
439                 rrddim_set(st, "OutMsgs", icmp_total.msgs_out);
440
441                 rrdset_done(st);
442
443                 // --------------------------------------------------------------------
444
445                 st = rrdset_find("ipv4.icmp_errors");
446                 if (unlikely(!st)) {
447                     st = rrdset_create("ipv4", "icmp_errors", NULL, "icmp", NULL, "IPv4 ICMP Errors",
448                                        "packets/s",
449                                        2603, update_every, RRDSET_TYPE_LINE);
450
451                     rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
452                     rrddim_add(st, "OutErrors", NULL, -1, 1, RRDDIM_INCREMENTAL);
453                     rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
454                 } else
455                     rrdset_next(st);
456
457                 rrddim_set(st, "InErrors", icmpstat.icps_badcode + icmpstat.icps_badlen + icmpstat.icps_checksum + icmpstat.icps_tooshort);
458                 rrddim_set(st, "OutErrors", icmpstat.icps_error);
459                 rrddim_set(st, "InCsumErrors", icmpstat.icps_checksum);
460
461                 rrdset_done(st);
462             }
463
464             // --------------------------------------------------------------------
465
466             if (likely(do_icmpmsg)) {
467                 st = rrdset_find("ipv4.icmpmsg");
468                 if (unlikely(!st)) {
469                     st = rrdset_create("ipv4", "icmpmsg", NULL, "icmp", NULL, "IPv4 ICMP Messsages",
470                                        "packets/s", 2604, update_every, RRDSET_TYPE_LINE);
471
472                     rrddim_add(st, "InEchoReps", NULL, 1, 1, RRDDIM_INCREMENTAL);
473                     rrddim_add(st, "OutEchoReps", NULL, -1, 1, RRDDIM_INCREMENTAL);
474                     rrddim_add(st, "InEchos", NULL, 1, 1, RRDDIM_INCREMENTAL);
475                     rrddim_add(st, "OutEchos", NULL, -1, 1, RRDDIM_INCREMENTAL);
476                 } else
477                     rrdset_next(st);
478
479                     rrddim_set(st, "InEchoReps", icmpstat.icps_inhist[ICMP_ECHOREPLY]);
480                     rrddim_set(st, "OutEchoReps", icmpstat.icps_outhist[ICMP_ECHOREPLY]);
481                     rrddim_set(st, "InEchos", icmpstat.icps_inhist[ICMP_ECHO]);
482                     rrddim_set(st, "OutEchos", icmpstat.icps_outhist[ICMP_ECHO]);
483
484                 rrdset_done(st);
485             }
486         }
487     }
488
489     return 0;
490 }
491
492 int getsysctl(const char *name, void *ptr, size_t len)
493 {
494     size_t nlen = len;
495
496     if (unlikely(sysctlbyname(name, ptr, &nlen, NULL, 0) == -1)) {
497         error("MACOS: sysctl(%s...) failed: %s", name, strerror(errno));
498         return 1;
499     }
500     if (unlikely(nlen != len)) {
501         error("MACOS: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)len, (unsigned long)nlen);
502         return 1;
503     }
504     return 0;
505 }