{GPL, other}: Relicense to MIT license.
[collectd.git] / src / interface.c
index fad37db..df8ffb4 100644 (file)
@@ -1,6 +1,7 @@
 /**
  * collectd - src/interface.c
- * Copyright (C) 2005-2008  Florian octo Forster
+ * Copyright (C) 2005-2010  Florian octo Forster
+ * Copyright (C) 2009       Manuel Sanmartin
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -16,8 +17,9 @@
  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  *
  * Authors:
- *   Florian octo Forster <octo at verplant.org>
+ *   Florian octo Forster <octo at collectd.org>
  *   Sune Marcher <sm at flork.dk>
+ *   Manuel Sanmartin
  **/
 
 #include "collectd.h"
 # include <statgrab.h>
 #endif
 
+#if HAVE_PERFSTAT
+# include <sys/protosw.h>
+# include <libperfstat.h>
+#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
 # endif /* !COLLECT_GETIFADDRS */
 #endif /* KERNEL_LINUX */
 
-#if !HAVE_GETIFADDRS && !KERNEL_LINUX && !HAVE_LIBKSTAT && !HAVE_LIBSTATGRAB
+#if HAVE_PERFSTAT
+static perfstat_netinterface_t *ifstat;
+static int nif;
+static int pnif;
+#endif /* HAVE_PERFSTAT */
+
+#if !HAVE_GETIFADDRS && !KERNEL_LINUX && !HAVE_LIBKSTAT && !HAVE_LIBSTATGRAB && !HAVE_PERFSTAT
 # error "No applicable input method."
 #endif
 
@@ -99,9 +112,7 @@ static int interface_config (const char *key, const char *value)
        else if (strcasecmp (key, "IgnoreSelected") == 0)
        {
                int invert = 1;
-               if ((strcasecmp (value, "True") == 0)
-                               || (strcasecmp (value, "Yes") == 0)
-                               || (strcasecmp (value, "On") == 0))
+               if (IS_TRUE (value))
                        invert = 0;
                ignorelist_set_invert (ignorelist, invert);
        }
@@ -117,7 +128,7 @@ static int interface_config (const char *key, const char *value)
 static int interface_init (void)
 {
        kstat_t *ksp_chain;
-       unsigned long long val;
+       derive_t val;
 
        numif = 0;
 
@@ -144,8 +155,8 @@ static int interface_init (void)
 #endif /* HAVE_LIBKSTAT */
 
 static void if_submit (const char *dev, const char *type,
-               unsigned long long rx,
-               unsigned long long tx)
+               derive_t rx,
+               derive_t tx)
 {
        value_t values[2];
        value_list_t vl = VALUE_LIST_INIT;
@@ -153,15 +164,15 @@ static void if_submit (const char *dev, const char *type,
        if (ignorelist_match (ignorelist, dev) != 0)
                return;
 
-       values[0].counter = rx;
-       values[1].counter = tx;
+       values[0].derive = rx;
+       values[1].derive = tx;
 
        vl.values = values;
        vl.values_len = 2;
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "interface", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
        sstrncpy (vl.type, type, sizeof (vl.type));
-       sstrncpy (vl.type_instance, dev, sizeof (vl.type_instance));
 
        plugin_dispatch_values (&vl);
 } /* void if_submit */
@@ -202,18 +213,19 @@ static int interface_read (void)
 
        for (if_ptr = if_list; if_ptr != NULL; if_ptr = if_ptr->ifa_next)
        {
-               if ((if_data = (struct IFA_DATA *) if_ptr->ifa_data) == NULL)
-                       continue;
+               if (if_ptr->ifa_addr != NULL && if_ptr->ifa_addr->sa_family == AF_LINK) {
+                       if_data = (struct IFA_DATA *) if_ptr->ifa_data;
 
-               if_submit (if_ptr->ifa_name, "if_octets",
+                       if_submit (if_ptr->ifa_name, "if_octets",
                                if_data->IFA_RX_BYTES,
                                if_data->IFA_TX_BYTES);
-               if_submit (if_ptr->ifa_name, "if_packets",
+                       if_submit (if_ptr->ifa_name, "if_packets",
                                if_data->IFA_RX_PACKT,
                                if_data->IFA_TX_PACKT);
-               if_submit (if_ptr->ifa_name, "if_errors",
+                       if_submit (if_ptr->ifa_name, "if_errors",
                                if_data->IFA_RX_ERROR,
                                if_data->IFA_TX_ERROR);
+               }
        }
 
        freeifaddrs (if_list);
@@ -222,9 +234,9 @@ static int interface_read (void)
 #elif KERNEL_LINUX
        FILE *fh;
        char buffer[1024];
-       unsigned long long incoming, outgoing;
+       derive_t incoming, outgoing;
        char *device;
-       
+
        char *dummy;
        char *fields[16];
        int numfields;
@@ -250,7 +262,7 @@ static int interface_read (void)
 
                if (device[0] == '\0')
                        continue;
-               
+
                numfields = strsplit (dummy, fields, 16);
 
                if (numfields < 11)
@@ -274,8 +286,8 @@ static int interface_read (void)
 
 #elif HAVE_LIBKSTAT
        int i;
-       unsigned long long rx;
-       unsigned long long tx;
+       derive_t rx;
+       derive_t tx;
 
        if (kc == NULL)
                return (-1);
@@ -285,16 +297,29 @@ static int interface_read (void)
                if (kstat_read (kc, ksp[i], NULL) == -1)
                        continue;
 
-               rx = get_kstat_value (ksp[i], "rbytes");
-               tx = get_kstat_value (ksp[i], "obytes");
+               /* try to get 64bit counters */
+               rx = get_kstat_value (ksp[i], "rbytes64");
+               tx = get_kstat_value (ksp[i], "obytes64");
+               /* or fallback to 32bit */
+               if (rx == -1LL)
+                       rx = get_kstat_value (ksp[i], "rbytes");
+               if (tx == -1LL)
+                       tx = get_kstat_value (ksp[i], "obytes");
                if ((rx != -1LL) || (tx != -1LL))
                        if_submit (ksp[i]->ks_name, "if_octets", rx, tx);
 
-               rx = get_kstat_value (ksp[i], "ipackets");
-               tx = get_kstat_value (ksp[i], "opackets");
+               /* try to get 64bit counters */
+               rx = get_kstat_value (ksp[i], "ipackets64");
+               tx = get_kstat_value (ksp[i], "opackets64");
+               /* or fallback to 32bit */
+               if (rx == -1LL)
+                       rx = get_kstat_value (ksp[i], "ipackets");
+               if (tx == -1LL)
+                       tx = get_kstat_value (ksp[i], "opackets");
                if ((rx != -1LL) || (tx != -1LL))
                        if_submit (ksp[i]->ks_name, "if_packets", rx, tx);
 
+               /* no 64bit error counters yet */
                rx = get_kstat_value (ksp[i], "ierrors");
                tx = get_kstat_value (ksp[i], "oerrors");
                if ((rx != -1LL) || (tx != -1LL))
@@ -310,7 +335,44 @@ static int interface_read (void)
 
        for (i = 0; i < num; i++)
                if_submit (ios[i].interface_name, "if_octets", ios[i].rx, ios[i].tx);
-#endif /* HAVE_LIBSTATGRAB */
+/* #endif HAVE_LIBSTATGRAB */
+
+#elif defined(HAVE_PERFSTAT)
+       perfstat_id_t id;
+       int i, ifs;
+
+       if ((nif =  perfstat_netinterface(NULL, NULL, sizeof(perfstat_netinterface_t), 0)) < 0)
+       {
+               char errbuf[1024];
+               WARNING ("interface plugin: perfstat_netinterface: %s",
+                       sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       if (pnif != nif || ifstat == NULL)
+       {
+               if (ifstat != NULL)
+                       free(ifstat);
+               ifstat = malloc(nif * sizeof(perfstat_netinterface_t));
+       }
+       pnif = nif;
+
+       id.name[0]='\0';
+       if ((ifs = perfstat_netinterface(&id, ifstat, sizeof(perfstat_netinterface_t), nif)) < 0)
+       {
+               char errbuf[1024];
+               WARNING ("interface plugin: perfstat_netinterface (interfaces=%d): %s",
+                       nif, sstrerror (errno, errbuf, sizeof (errbuf)));
+               return (-1);
+       }
+
+       for (i = 0; i < ifs; i++)
+       {
+               if_submit (ifstat[i].name, "if_octets", ifstat[i].ibytes, ifstat[i].obytes);
+               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 */