From 8ae25a973cdc30083959fcc1c422504c75d355b9 Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Sun, 11 Mar 2012 19:22:06 +0100 Subject: [PATCH] ethstat plugin: Use the system header files if available. And disable the plugin when they are not. --- configure.in | 35 +++++++++- src/ethstat.c | 207 ++++++++++++++++++++++++++++++++++++---------------------- src/ethstat.h | 78 ---------------------- 3 files changed, 162 insertions(+), 158 deletions(-) delete mode 100644 src/ethstat.h diff --git a/configure.in b/configure.in index 0d992e1d..5c52ca01 100644 --- a/configure.in +++ b/configure.in @@ -403,6 +403,33 @@ AC_CHECK_HEADERS(linux/netdevice.h, [], [], #endif ]) +# For ethstat module +AC_CHECK_HEADERS(linux/sockios.h, + [have_linux_sockios_h="yes"], + [have_linux_sockios_h="no"], + [ +#if HAVE_SYS_IOCTL_H +# include +#endif +#if HAVE_NET_IF_H +# include +#endif + ]) +AC_CHECK_HEADERS(linux/ethtool.h, + [have_linux_ethtool_h="yes"], + [have_linux_ethtool_h="no"], + [ +#if HAVE_SYS_IOCTL_H +# include +#endif +#if HAVE_NET_IF_H +# include +#endif +#if HAVE_LINUX_SOCKIOS_H +# include +#endif + ]) + # For ipvs module have_linux_ip_vs_h="no" have_net_ip_vs_h="no" @@ -4433,6 +4460,7 @@ plugin_curl_xml="no" plugin_df="no" plugin_disk="no" plugin_entropy="no" +plugin_ethstat="no" plugin_fscache="no" plugin_interface="no" plugin_ipmi="no" @@ -4637,6 +4665,11 @@ then fi fi +if test "x$have_linux_sockios_h$have_linux_ethtool_h" = "xyesyes" +then + plugin_ethstat="yes" +fi + if test "x$have_getifaddrs" = "xyes" then plugin_interface="yes" @@ -4745,7 +4778,7 @@ AC_PLUGIN([disk], [$plugin_disk], [Disk usage statistics]) 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([ethstat], [$plugin_ethstat], [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]) diff --git a/src/ethstat.c b/src/ethstat.c index 8bc47ad4..b280a585 100644 --- a/src/ethstat.c +++ b/src/ethstat.c @@ -24,146 +24,195 @@ #include "common.h" #include "plugin.h" #include "configfile.h" -#include "ethstat.h" -#include -#include -#include +#if HAVE_SYS_IOCTL_H +# include +#endif +#if HAVE_NET_IF_H +# include +#endif +#if HAVE_LINUX_SOCKIOS_H +# include +#endif +#if HAVE_LINUX_ETHTOOL_H +# include +#endif + +static const char *config_keys[] = +{ + "Interface" +}; +static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); + +static char **interfaces = NULL; +static size_t interfaces_num = 0; static int ethstat_config (const char *key, const char *value) { - if (strcasecmp ("Iface", key) == 0) + if (strcasecmp ("Interface", key) == 0) { char **tmp; - tmp = realloc (ifacelist, - sizeof (*ifacelist) * (ifacenumber + 1)); + tmp = realloc (interfaces, + sizeof (*interfaces) * (interfaces_num + 1)); if (tmp == NULL) return (-1); - ifacelist = tmp; + interfaces = tmp; - ifacelist[ifacenumber] = strdup (value); - if (ifacelist[ifacenumber] == NULL) + interfaces[interfaces_num] = strdup (value); + if (interfaces[interfaces_num] == NULL) { ERROR ("ethstat plugin: strdup() failed."); return (-1); } - ifacenumber++; + interfaces_num++; INFO("ethstat plugin: Registred interface %s", value); } return (0); } -static void ethstat_submit_value (char *devname, char *counter, unsigned long long value) +static void ethstat_submit_value (const char *device, + const char *type_instance, derive_t value) { value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].counter = value; - + values[0].derive = 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.plugin_instance, device, sizeof (vl.plugin_instance)); sstrncpy (vl.type, "derive", sizeof (vl.type)); - sstrncpy (vl.type_instance, counter, sizeof (vl.type_instance)); + sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance)); plugin_dispatch_values (&vl); } - -static int getstats(char *devname, struct ifreq *ifr) { +static int ethstat_read_interface (char *device) +{ int fd; + struct ifreq req; struct ethtool_drvinfo drvinfo; struct ethtool_gstrings *strings; struct ethtool_stats *stats; - unsigned int n_stats, sz_str, sz_stats, i; - int err; + size_t n_stats; + size_t strings_size; + size_t stats_size; + size_t i; + int status; + memset (&req, 0, sizeof (req)); + sstrncpy(req.ifr_name, device, sizeof (req.ifr_name)); - fd = socket(AF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - ERROR("ethstat - %s : Cannot get control socket", devname); - return 1; - } + fd = socket(AF_INET, SOCK_DGRAM, /* protocol = */ 0); + if (fd < 0) + { + char errbuf[1024]; + ERROR("ethstat plugin: Failed to open control socket: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); + return 1; + } + memset (&drvinfo, 0, sizeof (drvinfo)); 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; + req.ifr_data = (void *) &drvinfo; + status = ioctl (fd, SIOCETHTOOL, &req); + if (status < 0) + { + char errbuf[1024]; + close (fd); + ERROR ("ethstat plugin: Failed to get driver information " + "from %s: %s", device, + sstrerror (errno, errbuf, sizeof (errbuf))); + return (-1); } - - n_stats = drvinfo.n_stats; - if (n_stats < 1) { - ERROR("ethstat - %s : No stats available", devname); - return 1; + n_stats = (size_t) drvinfo.n_stats; + if (n_stats < 1) + { + close (fd); + ERROR("ethstat plugin: No stats available for %s", device); + return (-1); } - sz_str = n_stats * ETH_GSTRING_LEN; - sz_stats = n_stats * sizeof(u64); + strings_size = sizeof (struct ethtool_gstrings) + + (n_stats * ETH_GSTRING_LEN); + stats_size = sizeof (struct ethtool_stats) + + (n_stats * sizeof (uint64_t)); - 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 = malloc (strings_size); + stats = malloc (stats_size); + if ((strings == NULL) || (stats == NULL)) + { + close (fd); + sfree (strings); + sfree (stats); + ERROR("ethstat plugin: malloc(3) failed."); + 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; + req.ifr_data = (void *) strings; + status = ioctl (fd, SIOCETHTOOL, &req); + if (status < 0) + { + char errbuf[1024]; + close (fd); + free (strings); + free (stats); + ERROR ("ethstat plugin: Cannot get strings from %s: %s", + device, + sstrerror (errno, errbuf, sizeof (errbuf))); + return (-1); } 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; - } + req.ifr_data = (void *) stats; + status = ioctl (fd, SIOCETHTOOL, &req); + if (status < 0) + { + char errbuf[1024]; + close (fd); + free(strings); + free(stats); + ERROR("ethstat plugin: Reading statistics from %s failed: %s", + device, + sstrerror (errno, errbuf, sizeof (errbuf))); + return (-1); + } - 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]); + for (i = 0; i < n_stats; i++) + { + const char *stat_name; + + stat_name = (void *) &strings->data[i * ETH_GSTRING_LEN], + DEBUG("ethstat plugin: device = \"%s\": %s = %"PRIu64, + device, stat_name, + (uint64_t) stats->data[i]); + ethstat_submit_value (device, + stat_name, (derive_t) stats->data[i]); } - free(strings); - free(stats); - return 0; -} + close (fd); + sfree (strings); + sfree (stats); + + return (0); +} /* }}} ethstat_read_interface */ 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)); - sstrncpy(ifr.ifr_name, ifacelist[i], sizeof (ifr.ifr_name)); - getstats(ifacelist[i], &ifr); - } + size_t i; + + for (i = 0; i < interfaces_num; i++) + ethstat_read_interface (interfaces[i]); + return 0; } diff --git a/src/ethstat.h b/src/ethstat.h deleted file mode 100644 index 531e2be0..00000000 --- a/src/ethstat.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * 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 - **/ - -#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 = NULL; -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]; -}; - - - -- 2.11.0