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

Reply via email to