The interface plugin on macosx uses getifaddrs to retrieve the network interface statistics from the kernel. This call returns 32-bit values and, with gigabit network interfaces, they can wrap in less than a minute. The following patch uses sysctl instead if it’s available which returns 64-bit counters.
Tested to work under MacOSX 10.10. *** collectd-master.orig/src/interface.c Thu Jun 11 05:36:12 2015 --- collectd-master/src/interface.c Thu Jun 11 07:55:54 2015 *************** *** 58,63 **** --- 58,70 ---- # include <libperfstat.h> #endif + #if HAVE_SYSCTL + #include <sys/sysctl.h> + #include <net/if_dl.h> + #include <net/route.h> + #undef HAVE_GETIFADDRS /* prefer sysctl over getifaddrs */ + #endif + /* * Various people have reported problems with `getifaddrs' and varying versions * of `glibc'. That's why it's disabled by default. Since more statistics are *************** *** 76,82 **** static int pnif; #endif /* HAVE_PERFSTAT */ ! #if !HAVE_GETIFADDRS && !KERNEL_LINUX && !HAVE_LIBKSTAT && !HAVE_LIBSTATGRAB && !HAVE_PERFSTAT # error "No applicable input method." #endif --- 83,89 ---- static int pnif; #endif /* HAVE_PERFSTAT */ ! #if !HAVE_GETIFADDRS && !KERNEL_LINUX && !HAVE_LIBKSTAT && !HAVE_LIBSTATGRAB && !HAVE_PERFSTAT && !HAVE_SYSCTL # error "No applicable input method." #endif *************** *** 372,378 **** if_submit (ifstat[i].name, "if_packets", ifstat[i].ipackets ,ifstat[i].opackets); if_submit (ifstat[i].name, "if_errors", ifstat[i].ierrors, ifstat[i].oerrors ); } ! #endif /* HAVE_PERFSTAT */ return (0); } /* int interface_read */ --- 379,437 ---- if_submit (ifstat[i].name, "if_packets", ifstat[i].ipackets ,ifstat[i].opackets); if_submit (ifstat[i].name, "if_errors", ifstat[i].ierrors, ifstat[i].oerrors ); } ! ! #elif defined(HAVE_SYSCTL) ! ! int mib[6], i; ! size_t len, nlen; ! char *buf, *cur, errbuf[1024], interface_name[64]; ! struct if_msghdr *ifm; ! ! mib[0] = CTL_NET; ! mib[1] = PF_ROUTE; ! mib[2] = 0; ! mib[3] = 0; ! mib[4] = NET_RT_IFLIST2; ! mib[5] = 0; ! ! if (sysctl (mib, 6, NULL, &len, NULL, 0) == -1) { ! WARNING ("interface plugin: sysctl (get-len): %s", sstrerror (errno, errbuf, sizeof (errbuf))); ! return (-1); ! } ! if ((buf = malloc (len)) == NULL) { ! WARNING ("interface plugin: malloc: %s", sstrerror (errno, errbuf, sizeof (errbuf))); ! return (-1); ! } ! if (sysctl (mib, 6, buf, &len, NULL, 0) == -1) { ! WARNING ("interface plugin: sysctl (fill-buf): %s", sstrerror (errno, errbuf, sizeof (errbuf))); ! return (-1); ! } ! cur = buf; ! while (cur < (buf + len)) { ! ifm = (struct if_msghdr *) cur; ! cur += ifm->ifm_msglen; ! if (ifm->ifm_type == RTM_IFINFO2) { ! struct if_msghdr2 *if2m = (struct if_msghdr2 *) ifm; ! struct sockaddr *s = (struct sockaddr *) (if2m + 1); ! if (s->sa_family == AF_LINK) { ! struct sockaddr_dl *sdl = (struct sockaddr_dl *) s; ! if (sdl->sdl_nlen > sizeof (interface_name) - 1) ! WARNING ("interface plugin: interface name too long, truncating"); ! nlen = sdl->sdl_nlen; ! if (nlen > sizeof (interface_name) - 1) ! nlen = sizeof (interface_name) - 1; ! for (i = 0; i < nlen; i++) ! interface_name[i] = sdl->sdl_data[i]; ! interface_name[i] = '\0'; ! if_submit (interface_name, "if_octets", if2m->ifm_data.ifi_ibytes, if2m->ifm_data.ifi_obytes); ! if_submit (interface_name, "if_packets", if2m->ifm_data.ifi_ipackets, if2m->ifm_data.ifi_opackets); ! if_submit (interface_name, "if_errors", if2m->ifm_data.ifi_ierrors, if2m->ifm_data.ifi_oerrors); ! } ! } ! } ! free (buf); ! ! #endif /* HAVE_SYSCTL */ return (0); } /* int interface_read */ _______________________________________________ collectd mailing list collectd@verplant.org http://mailman.verplant.org/listinfo/collectd