2 #include <sys/sysctl.h>
3 // NEEDED BY: do_bandwidth
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>
15 #define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
17 // MacOS calculates load averages once every 5 seconds
18 #define MIN_LOADAVG_UPDATE_EVERY 5
20 int getsysctl(const char *name, void *ptr, size_t len);
22 int do_macos_sysctl(int update_every, usec_t dt) {
25 static int do_loadavg = -1, do_swap = -1, do_bandwidth = -1,
26 do_tcp_packets = -1, do_tcp_errors = -1, do_tcp_handshake = -1, do_ecn = -1,
27 do_tcpext_syscookies = -1, do_tcpext_ofo = -1, do_tcpext_connaborts = -1,
28 do_udp_packets = -1, do_udp_errors = -1;
31 if (unlikely(do_loadavg == -1)) {
32 do_loadavg = config_get_boolean("plugin:macos:sysctl", "enable load average", 1);
33 do_swap = config_get_boolean("plugin:macos:sysctl", "system swap", 1);
34 do_bandwidth = config_get_boolean("plugin:macos:sysctl", "bandwidth", 1);
35 do_tcp_packets = config_get_boolean("plugin:macos:sysctl", "ipv4 TCP packets", 1);
36 do_tcp_errors = config_get_boolean("plugin:macos:sysctl", "ipv4 TCP errors", 1);
37 do_tcp_handshake = config_get_boolean("plugin:macos:sysctl", "ipv4 TCP handshake issues", 1);
38 do_ecn = config_get_boolean_ondemand("plugin:macos:sysctl", "ECN packets", CONFIG_ONDEMAND_ONDEMAND);
39 do_tcpext_syscookies = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP SYN cookies", CONFIG_ONDEMAND_ONDEMAND);
40 do_tcpext_ofo = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP out-of-order queue", CONFIG_ONDEMAND_ONDEMAND);
41 do_tcpext_connaborts = config_get_boolean_ondemand("plugin:macos:sysctl", "TCP connection aborts", CONFIG_ONDEMAND_ONDEMAND);
42 do_udp_packets = config_get_boolean("plugin:macos:sysctl", "ipv4 UDP packets", 1);
43 do_udp_errors = config_get_boolean("plugin:macos:sysctl", "ipv4 UDP errors", 1);
48 int system_pagesize = getpagesize(); // wouldn't it be better to get value directly from hw.pagesize?
53 // NEEDED BY: do_loadavg
54 static usec_t last_loadavg_usec = 0;
55 struct loadavg sysload;
58 struct xsw_usage swap_usage;
60 // NEEDED BY: do_bandwidth
62 static char *ifstatdata = NULL;
64 struct if_msghdr *ifm;
70 // NEEDED BY: do_tcp...
71 struct tcpstat tcpstat;
72 uint64_t tcps_states[TCP_NSTATES];
74 // NEEDED BY: do_udp...
75 struct udpstat udpstat;
77 if (last_loadavg_usec <= dt) {
78 if (likely(do_loadavg)) {
79 if (unlikely(GETSYSCTL("vm.loadavg", sysload))) {
81 error("DISABLED: system.load");
84 st = rrdset_find_bytype("system", "load");
86 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);
87 rrddim_add(st, "load1", NULL, 1, 1000, RRDDIM_ABSOLUTE);
88 rrddim_add(st, "load5", NULL, 1, 1000, RRDDIM_ABSOLUTE);
89 rrddim_add(st, "load15", NULL, 1, 1000, RRDDIM_ABSOLUTE);
93 rrddim_set(st, "load1", (collected_number) ((double)sysload.ldavg[0] / sysload.fscale * 1000));
94 rrddim_set(st, "load5", (collected_number) ((double)sysload.ldavg[1] / sysload.fscale * 1000));
95 rrddim_set(st, "load15", (collected_number) ((double)sysload.ldavg[2] / sysload.fscale * 1000));
100 last_loadavg_usec = st->update_every * USEC_PER_SEC;
102 else last_loadavg_usec -= dt;
104 if (likely(do_swap)) {
105 if (unlikely(GETSYSCTL("vm.swapusage", swap_usage))) {
107 error("DISABLED: system.swap");
109 st = rrdset_find("system.swap");
111 st = rrdset_create("system", "swap", NULL, "swap", NULL, "System Swap", "MB", 201, update_every, RRDSET_TYPE_STACKED);
114 rrddim_add(st, "free", NULL, 1, 1048576, RRDDIM_ABSOLUTE);
115 rrddim_add(st, "used", NULL, 1, 1048576, RRDDIM_ABSOLUTE);
117 else rrdset_next(st);
119 rrddim_set(st, "free", swap_usage.xsu_avail);
120 rrddim_set(st, "used", swap_usage.xsu_used);
125 // --------------------------------------------------------------------
127 if (likely(do_bandwidth)) {
132 mib[4] = NET_RT_IFLIST2;
134 if (unlikely(sysctl(mib, 6, NULL, &size, NULL, 0))) {
135 error("MACOS: sysctl(%s...) failed: %s", "net interfaces", strerror(errno));
137 error("DISABLED: system.ipv4");
139 ifstatdata = reallocz(ifstatdata, size);
140 if (unlikely(sysctl(mib, 6, ifstatdata, &size, NULL, 0) < 0)) {
141 error("MACOS: sysctl(%s...) failed: %s", "net interfaces", strerror(errno));
143 error("DISABLED: system.ipv4");
145 lim = ifstatdata + size;
146 iftot.ift_ibytes = iftot.ift_obytes = 0;
147 for (next = ifstatdata; next < lim; ) {
148 ifm = (struct if_msghdr *)next;
149 next += ifm->ifm_msglen;
151 if (ifm->ifm_type == RTM_IFINFO2) {
152 struct if_msghdr2 *if2m = (struct if_msghdr2 *)ifm;
154 iftot.ift_ibytes += if2m->ifm_data.ifi_ibytes;
155 iftot.ift_obytes += if2m->ifm_data.ifi_obytes;
158 st = rrdset_find("system.ipv4");
160 st = rrdset_create("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA);
162 rrddim_add(st, "InOctets", "received", 8, 1024, RRDDIM_INCREMENTAL);
163 rrddim_add(st, "OutOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL);
165 else rrdset_next(st);
167 rrddim_set(st, "InOctets", iftot.ift_ibytes);
168 rrddim_set(st, "OutOctets", iftot.ift_obytes);
174 // --------------------------------------------------------------------
176 // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html
177 if (likely(do_tcp_packets || do_tcp_errors || do_tcp_handshake || do_tcpext_connaborts || do_tcpext_ofo || do_tcpext_syscookies || do_ecn)) {
178 if (unlikely(GETSYSCTL("net.inet.tcp.stats", tcpstat))){
180 error("DISABLED: ipv4.tcppackets");
182 error("DISABLED: ipv4.tcperrors");
183 do_tcp_handshake = 0;
184 error("DISABLED: ipv4.tcphandshake");
185 do_tcpext_connaborts = 0;
186 error("DISABLED: ipv4.tcpconnaborts");
188 error("DISABLED: ipv4.tcpofo");
189 do_tcpext_syscookies = 0;
190 error("DISABLED: ipv4.tcpsyncookies");
192 error("DISABLED: ipv4.ecnpkts");
194 if (likely(do_tcp_packets)) {
195 st = rrdset_find("ipv4.tcppackets");
197 st = rrdset_create("ipv4", "tcppackets", NULL, "tcp", NULL, "IPv4 TCP Packets",
199 2600, update_every, RRDSET_TYPE_LINE);
201 rrddim_add(st, "InSegs", "received", 1, 1, RRDDIM_INCREMENTAL);
202 rrddim_add(st, "OutSegs", "sent", -1, 1, RRDDIM_INCREMENTAL);
206 rrddim_set(st, "InSegs", tcpstat.tcps_rcvtotal);
207 rrddim_set(st, "OutSegs", tcpstat.tcps_sndtotal);
211 // --------------------------------------------------------------------
213 if (likely(do_tcp_errors)) {
214 st = rrdset_find("ipv4.tcperrors");
216 st = rrdset_create("ipv4", "tcperrors", NULL, "tcp", NULL, "IPv4 TCP Errors",
218 2700, update_every, RRDSET_TYPE_LINE);
221 rrddim_add(st, "InErrs", NULL, 1, 1, RRDDIM_INCREMENTAL);
222 rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
223 rrddim_add(st, "RetransSegs", NULL, -1, 1, RRDDIM_INCREMENTAL);
227 rrddim_set(st, "InErrs", tcpstat.tcps_rcvbadoff + tcpstat.tcps_rcvshort);
228 rrddim_set(st, "InCsumErrors", tcpstat.tcps_rcvbadsum);
229 rrddim_set(st, "RetransSegs", tcpstat.tcps_sndrexmitpack);
233 // --------------------------------------------------------------------
235 if (likely(do_tcp_handshake)) {
236 st = rrdset_find("ipv4.tcphandshake");
238 st = rrdset_create("ipv4", "tcphandshake", NULL, "tcp", NULL,
239 "IPv4 TCP Handshake Issues",
240 "events/s", 2900, update_every, RRDSET_TYPE_LINE);
243 rrddim_add(st, "EstabResets", NULL, 1, 1, RRDDIM_INCREMENTAL);
244 rrddim_add(st, "ActiveOpens", NULL, 1, 1, RRDDIM_INCREMENTAL);
245 rrddim_add(st, "PassiveOpens", NULL, 1, 1, RRDDIM_INCREMENTAL);
246 rrddim_add(st, "AttemptFails", NULL, 1, 1, RRDDIM_INCREMENTAL);
250 rrddim_set(st, "EstabResets", tcpstat.tcps_drops);
251 rrddim_set(st, "ActiveOpens", tcpstat.tcps_connattempt);
252 rrddim_set(st, "PassiveOpens", tcpstat.tcps_accepts);
253 rrddim_set(st, "AttemptFails", tcpstat.tcps_conndrops);
257 // --------------------------------------------------------------------
259 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))) {
260 do_tcpext_connaborts = CONFIG_ONDEMAND_YES;
261 st = rrdset_find("ipv4.tcpconnaborts");
263 st = rrdset_create("ipv4", "tcpconnaborts", NULL, "tcp", NULL, "TCP Connection Aborts", "connections/s", 3010, update_every, RRDSET_TYPE_LINE);
265 rrddim_add(st, "TCPAbortOnData", "baddata", 1, 1, RRDDIM_INCREMENTAL);
266 rrddim_add(st, "TCPAbortOnClose", "userclosed", 1, 1, RRDDIM_INCREMENTAL);
267 rrddim_add(st, "TCPAbortOnMemory", "nomemory", 1, 1, RRDDIM_INCREMENTAL);
268 rrddim_add(st, "TCPAbortOnTimeout", "timeout", 1, 1, RRDDIM_INCREMENTAL);
270 else rrdset_next(st);
272 rrddim_set(st, "TCPAbortOnData", tcpstat.tcps_rcvpackafterwin);
273 rrddim_set(st, "TCPAbortOnClose", tcpstat.tcps_rcvafterclose);
274 rrddim_set(st, "TCPAbortOnMemory", tcpstat.tcps_rcvmemdrop);
275 rrddim_set(st, "TCPAbortOnTimeout", tcpstat.tcps_persistdrop);
279 // --------------------------------------------------------------------
281 if (do_tcpext_ofo == CONFIG_ONDEMAND_YES || (do_tcpext_ofo == CONFIG_ONDEMAND_ONDEMAND && tcpstat.tcps_rcvoopack)) {
282 do_tcpext_ofo = CONFIG_ONDEMAND_YES;
283 st = rrdset_find("ipv4.tcpofo");
285 st = rrdset_create("ipv4", "tcpofo", NULL, "tcp", NULL, "TCP Out-Of-Order Queue", "packets/s", 3050, update_every, RRDSET_TYPE_LINE);
287 rrddim_add(st, "TCPOFOQueue", "inqueue", 1, 1, RRDDIM_INCREMENTAL);
289 else rrdset_next(st);
291 rrddim_set(st, "TCPOFOQueue", tcpstat.tcps_rcvoopack);
295 // --------------------------------------------------------------------
297 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))) {
298 do_tcpext_syscookies = CONFIG_ONDEMAND_YES;
300 st = rrdset_find("ipv4.tcpsyncookies");
302 st = rrdset_create("ipv4", "tcpsyncookies", NULL, "tcp", NULL, "TCP SYN Cookies", "packets/s", 3100, update_every, RRDSET_TYPE_LINE);
304 rrddim_add(st, "SyncookiesRecv", "received", 1, 1, RRDDIM_INCREMENTAL);
305 rrddim_add(st, "SyncookiesSent", "sent", -1, 1, RRDDIM_INCREMENTAL);
306 rrddim_add(st, "SyncookiesFailed", "failed", -1, 1, RRDDIM_INCREMENTAL);
308 else rrdset_next(st);
310 rrddim_set(st, "SyncookiesRecv", tcpstat.tcps_sc_recvcookie);
311 rrddim_set(st, "SyncookiesSent", tcpstat.tcps_sc_sendcookie);
312 rrddim_set(st, "SyncookiesFailed", tcpstat.tcps_sc_zonefail);
316 // --------------------------------------------------------------------
318 if (do_ecn == CONFIG_ONDEMAND_YES || (do_ecn == CONFIG_ONDEMAND_ONDEMAND && (tcpstat.tcps_ecn_recv_ce || tcpstat.tcps_ecn_not_supported))) {
319 do_ecn = CONFIG_ONDEMAND_YES;
320 st = rrdset_find("ipv4.ecnpkts");
322 st = rrdset_create("ipv4", "ecnpkts", NULL, "ecn", NULL, "IPv4 ECN Statistics", "packets/s", 8700, update_every, RRDSET_TYPE_LINE);
325 rrddim_add(st, "InCEPkts", "CEP", 1, 1, RRDDIM_INCREMENTAL);
326 rrddim_add(st, "InNoECTPkts", "NoECTP", -1, 1, RRDDIM_INCREMENTAL);
328 else rrdset_next(st);
330 rrddim_set(st, "InCEPkts", tcpstat.tcps_ecn_recv_ce);
331 rrddim_set(st, "InNoECTPkts", tcpstat.tcps_ecn_not_supported);
338 // --------------------------------------------------------------------
340 // see http://net-snmp.sourceforge.net/docs/mibs/udp.html
341 if (likely(do_udp_packets || do_udp_errors)) {
342 if (unlikely(GETSYSCTL("net.inet.udp.stats", udpstat))) {
344 error("DISABLED: ipv4.udppackets");
346 error("DISABLED: ipv4.udperrors");
348 if (likely(do_udp_packets)) {
349 st = rrdset_find("ipv4.udppackets");
351 st = rrdset_create("ipv4", "udppackets", NULL, "udp", NULL, "IPv4 UDP Packets",
352 "packets/s", 2601, update_every, RRDSET_TYPE_LINE);
354 rrddim_add(st, "InDatagrams", "received", 1, 1, RRDDIM_INCREMENTAL);
355 rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRDDIM_INCREMENTAL);
359 rrddim_set(st, "InDatagrams", udpstat.udps_ipackets);
360 rrddim_set(st, "OutDatagrams", udpstat.udps_opackets);
364 // --------------------------------------------------------------------
366 if (likely(do_udp_errors)) {
367 st = rrdset_find("ipv4.udperrors");
369 st = rrdset_create("ipv4", "udperrors", NULL, "udp", NULL, "IPv4 UDP Errors", "events/s",
370 2701, update_every, RRDSET_TYPE_LINE);
373 rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
374 rrddim_add(st, "InErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
375 rrddim_add(st, "NoPorts", NULL, 1, 1, RRDDIM_INCREMENTAL);
376 rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRDDIM_INCREMENTAL);
377 rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRDDIM_INCREMENTAL);
381 rrddim_set(st, "InErrors", udpstat.udps_hdrops + udpstat.udps_badlen);
382 rrddim_set(st, "NoPorts", udpstat.udps_noport);
383 rrddim_set(st, "RcvbufErrors", udpstat.udps_fullsock);
384 rrddim_set(st, "InCsumErrors", udpstat.udps_badsum + udpstat.udps_nosum);
385 rrddim_set(st, "IgnoredMulti", udpstat.udps_filtermcast);
394 int getsysctl(const char *name, void *ptr, size_t len)
398 if (unlikely(sysctlbyname(name, ptr, &nlen, NULL, 0) == -1)) {
399 error("MACOS: sysctl(%s...) failed: %s", name, strerror(errno));
402 if (unlikely(nlen != len)) {
403 error("MACOS: sysctl(%s...) expected %lu, got %lu", name, (unsigned long)len, (unsigned long)nlen);