Hi all, 

For my needs at work I wrote a plugin for collectd and I
wish to share it with you. 

This plugins, temporary called ethstat and
wrote in C, collect lot of performance counter about network interface
as "ethtool -S ethX" do by asking NIC driver module. 

At the moment
this plugin work only under Linux. Any help would be great for make it
working under Solaris, AIX and co ... 

If you think this plugin may be
included to collectd sources, what is the procedure to do it ?


Regards, 

Cyril Feraudet 

To be added to configuration file to make
it work : 

LoadPlugin ethstat 

 Iface "eth0"

# Iface "eth1"

# Iface
"eth2"

# Iface "eth3"

  
--- ../collectd-5.0.0/configure.in	2011-03-27 18:35:08.000000000 +0200
+++ ./configure.in	2011-09-27 14:30:33.000000000 +0200
@@ -4631,6 +4632,7 @@
 AC_PLUGIN([dns],         [$with_libpcap],      [DNS traffic analysis])
 AC_PLUGIN([email],       [yes],                [EMail statistics])
 AC_PLUGIN([entropy],     [$plugin_entropy],    [Entropy statistics])
+AC_PLUGIN([ethstat],     [yes],                [Stats from NIC driver])
 AC_PLUGIN([exec],        [yes],                [Execution of external programs])
 AC_PLUGIN([filecount],   [yes],                [Count files in directories])
 AC_PLUGIN([fscache],     [$plugin_fscache],    [fscache statistics])
@@ -4958,6 +4961,7 @@
     dns . . . . . . . . . $enable_dns
     email . . . . . . . . $enable_email
     entropy . . . . . . . $enable_entropy
+    ethstat . . . . . . . $enable_ethstat
     exec  . . . . . . . . $enable_exec
     filecount . . . . . . $enable_filecount
     fscache . . . . . . . $enable_fscache
--- ../collectd-5.0.0/src/Makefile.am	2011-03-27 18:35:08.000000000 +0200
+++ ./src/Makefile.am	2011-09-27 14:31:36.000000000 +0200
@@ -381,6 +389,14 @@
 collectd_DEPENDENCIES += exec.la
 endif
 
+if BUILD_PLUGIN_ETHSTAT
+pkglib_LTLIBRARIES += ethstat.la
+ethstat_la_SOURCES = ethstat.c
+ethstat_la_LDFLAGS = -module -avoid-version
+collectd_LDADD += "-dlopen" ethstat.la
+collectd_DEPENDENCIES += ethstat.la
+endif
+
 if BUILD_PLUGIN_FILECOUNT
 pkglib_LTLIBRARIES += filecount.la
 filecount_la_SOURCES = filecount.c

--- ../collectd-5.0.0/src/ethstat.h	1970-01-01 01:00:00.000000000 +0100
+++ ./src/ethstat.h	2011-09-29 19:16:41.000000000 +0200
@@ -0,0 +1,78 @@
+/**
+ * collectd - src/ethstat.h
+ * Copyright (C) 2011       Cyril Feraudet
+ *
+ * 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Cyril Feraudet <cyril at feraudet.com>
+ **/
+
+#define ETHTOOL_BUSINFO_LEN     32
+#define ETHTOOL_GDRVINFO	0x00000003 /* Get driver info. */
+#define ETH_GSTRING_LEN		32
+#define ETHTOOL_GSTRINGS	0x0000001b /* get specified string set */
+#define ETHTOOL_GSTATS          0x0000001d /* get NIC-specific statistics */
+
+enum ethtool_stringset {
+        ETH_SS_TEST             = 0,
+        ETH_SS_STATS,
+};
+
+typedef unsigned long long u64;
+typedef unsigned char __u8;
+typedef unsigned short __u16;
+typedef unsigned int __u32;
+typedef unsigned long long  __u64;
+
+
+static const char *config_keys[] =
+{
+	"Iface"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static char **ifacelist;
+static int ifacenumber = 0;
+struct ethtool_drvinfo {
+        __u32   cmd;
+        char    driver[32];     /* driver short name, "tulip", "eepro100" */
+        char    version[32];    /* driver version string */
+        char    fw_version[32]; /* firmware version string, if applicable */
+        char    bus_info[ETHTOOL_BUSINFO_LEN];  /* Bus info for this IF. */
+                                /* For PCI devices, use pci_name(pci_dev). */
+        char    reserved1[32];
+        char    reserved2[16];
+        __u32   n_stats;        /* number of u64's from ETHTOOL_GSTATS */
+        __u32   testinfo_len;
+        __u32   eedump_len;     /* Size of data from ETHTOOL_GEEPROM (bytes) */
+        __u32   regdump_len;    /* Size of data from ETHTOOL_GREGS (bytes) */
+};
+
+struct ethtool_gstrings {
+        __u32   cmd;            /* ETHTOOL_GSTRINGS */
+        __u32   string_set;     /* string set id e.c. ETH_SS_TEST, etc*/
+        __u32   len;            /* number of strings in the string set */
+        __u8    data[0];
+};
+
+struct ethtool_stats {
+        __u32   cmd;            /* ETHTOOL_GSTATS */
+        __u32   n_stats;        /* number of u64's being returned */
+        __u64   data[0];
+};
+
+
+
--- ../collectd-5.0.0/src/ethstat.c	1970-01-01 01:00:00.000000000 +0100
+++ ./src/ethstat.c	2011-09-30 13:58:38.000000000 +0200
@@ -0,0 +1,178 @@
+/**
+ * collectd - src/ethstat.c
+ * Copyright (C) 2011       Cyril Feraudet
+ *
+ * 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Cyril Feraudet <cyril at feraudet.com>
+ **/
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include <sys/types.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <net/if.h>
+#include <linux/sockios.h> 
+#include "ethstat.h"
+
+# if KERNEL_LINUX
+
+
+static int ethstat_config (const char *key, const char *value)
+{
+	if (strcasecmp (key, "Iface") == 0) {
+		ifacelist[ifacenumber] = malloc(strlen(value) + 1);
+		strcpy(ifacelist[ifacenumber++], value);
+		INFO("ethstat: Registred iface %s", value);
+	}
+	return (0);
+}
+
+
+static void ethstat_submit_value (char *devname, char *counter, unsigned long long value)
+{
+	value_t values[1];
+	value_list_t vl = VALUE_LIST_INIT;
+
+	values[0].counter = value;
+
+	vl.values = values;
+	vl.values_len = 1;
+	sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+	sstrncpy (vl.plugin, "ethstat", sizeof (vl.plugin));
+	sstrncpy (vl.plugin_instance, devname, sizeof (vl.plugin_instance));
+	sstrncpy (vl.type, "derive", sizeof (vl.type));
+	sstrncpy (vl.type_instance, counter, sizeof (vl.type_instance));
+
+	plugin_dispatch_values (&vl);
+}
+
+
+static int getstats(char *devname, struct ifreq *ifr) {
+        int fd;
+	struct ethtool_drvinfo drvinfo;
+	struct ethtool_gstrings *strings;
+	struct ethtool_stats *stats;
+	unsigned int n_stats, sz_str, sz_stats, i;
+	int err;
+
+
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+        if (fd < 0) {
+                ERROR("ethstat - %s : Cannot get control socket", devname);
+                return 1;
+        }
+
+        drvinfo.cmd = ETHTOOL_GDRVINFO;
+        ifr->ifr_data = (caddr_t)&drvinfo;
+        err = ioctl(fd, SIOCETHTOOL, ifr);
+        if (err < 0) {
+                ERROR("ethstat - %s : Cannot get driver information", devname);
+                return 1;
+        }
+
+
+        n_stats = drvinfo.n_stats;
+        if (n_stats < 1) {
+                ERROR("ethstat - %s : No stats available", devname);
+                return 1;
+        }
+
+        sz_str = n_stats * ETH_GSTRING_LEN;
+        sz_stats = n_stats * sizeof(u64);
+
+        strings = calloc(1, sz_str + sizeof(struct ethtool_gstrings));
+        stats = calloc(1, sz_stats + sizeof(struct ethtool_stats));
+        if (!strings || !stats) {
+                ERROR("ethstat - %s No memory available", devname);
+                return 1;
+        }
+
+        strings->cmd = ETHTOOL_GSTRINGS;
+        strings->string_set = ETH_SS_STATS;
+        strings->len = n_stats;
+        ifr->ifr_data = (caddr_t) strings;
+        err = ioctl(fd, SIOCETHTOOL, ifr);
+        if (err < 0) {
+                ERROR("ethstat - %s : Cannot get stats strings information", devname);
+                free(strings);
+                free(stats);
+                return 96;
+        }
+
+        stats->cmd = ETHTOOL_GSTATS;
+        stats->n_stats = n_stats;
+        ifr->ifr_data = (caddr_t) stats;
+        err = ioctl(fd, SIOCETHTOOL, ifr);
+        if (err < 0) {
+                ERROR("ethstat - %s : Cannot get stats information", devname);
+                free(strings);
+                free(stats);
+                return 97;
+        }
+
+        for (i = 0; i < n_stats; i++) {
+                DEBUG("ethstat - %s : %s: %llu",
+			devname,
+                        &strings->data[i * ETH_GSTRING_LEN],
+                        stats->data[i]);
+		ethstat_submit_value (
+			devname,
+			(char*)&strings->data[i * ETH_GSTRING_LEN],
+			stats->data[i]);
+        }
+        free(strings);
+        free(stats);
+
+
+	return 0;
+}
+
+
+static int ethstat_read(void)
+{
+	struct ifreq ifr;
+	int i;
+
+	for (i = 0 ; i < ifacenumber ; i++) {
+		DEBUG("ethstat - Processing : %s\n", ifacelist[i]);
+		memset(&ifr, 0, sizeof(ifr));
+        	strcpy(ifr.ifr_name, ifacelist[i]);
+		getstats(ifacelist[i], &ifr);
+	}
+	return 0;
+}
+
+void module_register (void)
+{
+	ifacelist = malloc(sizeof(char*));
+	plugin_register_config ("ethstat", ethstat_config,
+			config_keys, config_keys_num);
+	plugin_register_read ("ethstat", ethstat_read);
+}
+
+# endif
_______________________________________________
collectd mailing list
collectd@verplant.org
http://mailman.verplant.org/listinfo/collectd

Reply via email to