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