[collectd] interface plugin on macosx
Robert Viduya
robert at oit.gatech.edu
Thu Jun 11 14:02:22 CEST 2015
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 */
More information about the collectd
mailing list