2 * collectd - src/ethstat.c
3 * Copyright (C) 2011 Cyril Feraudet
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * Cyril Feraudet <cyril at feraudet.com>
26 #include "configfile.h"
29 # include <sys/ioctl.h>
34 #if HAVE_LINUX_SOCKIOS_H
35 # include <linux/sockios.h>
37 #if HAVE_LINUX_ETHTOOL_H
38 # include <linux/ethtool.h>
41 static const char *config_keys[] =
45 static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
47 static char **interfaces = NULL;
48 static size_t interfaces_num = 0;
50 static int ethstat_config (const char *key, const char *value)
52 if (strcasecmp ("Interface", key) == 0)
56 tmp = realloc (interfaces,
57 sizeof (*interfaces) * (interfaces_num + 1));
62 interfaces[interfaces_num] = strdup (value);
63 if (interfaces[interfaces_num] == NULL)
65 ERROR ("ethstat plugin: strdup() failed.");
70 INFO("ethstat plugin: Registred interface %s", value);
75 static void ethstat_submit_value (const char *device,
76 const char *type_instance, derive_t value)
79 value_list_t vl = VALUE_LIST_INIT;
81 values[0].derive = value;
85 sstrncpy (vl.host, hostname_g, sizeof (vl.host));
86 sstrncpy (vl.plugin, "ethstat", sizeof (vl.plugin));
87 sstrncpy (vl.plugin_instance, device, sizeof (vl.plugin_instance));
88 sstrncpy (vl.type, "derive", sizeof (vl.type));
89 sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
91 plugin_dispatch_values (&vl);
94 static int ethstat_read_interface (char *device)
98 struct ethtool_drvinfo drvinfo;
99 struct ethtool_gstrings *strings;
100 struct ethtool_stats *stats;
107 memset (&req, 0, sizeof (req));
108 sstrncpy(req.ifr_name, device, sizeof (req.ifr_name));
110 fd = socket(AF_INET, SOCK_DGRAM, /* protocol = */ 0);
114 ERROR("ethstat plugin: Failed to open control socket: %s",
115 sstrerror (errno, errbuf, sizeof (errbuf)));
119 memset (&drvinfo, 0, sizeof (drvinfo));
120 drvinfo.cmd = ETHTOOL_GDRVINFO;
121 req.ifr_data = (void *) &drvinfo;
122 status = ioctl (fd, SIOCETHTOOL, &req);
127 ERROR ("ethstat plugin: Failed to get driver information "
128 "from %s: %s", device,
129 sstrerror (errno, errbuf, sizeof (errbuf)));
133 n_stats = (size_t) drvinfo.n_stats;
137 ERROR("ethstat plugin: No stats available for %s", device);
141 strings_size = sizeof (struct ethtool_gstrings)
142 + (n_stats * ETH_GSTRING_LEN);
143 stats_size = sizeof (struct ethtool_stats)
144 + (n_stats * sizeof (uint64_t));
146 strings = malloc (strings_size);
147 stats = malloc (stats_size);
148 if ((strings == NULL) || (stats == NULL))
153 ERROR("ethstat plugin: malloc(3) failed.");
157 strings->cmd = ETHTOOL_GSTRINGS;
158 strings->string_set = ETH_SS_STATS;
159 strings->len = n_stats;
160 req.ifr_data = (void *) strings;
161 status = ioctl (fd, SIOCETHTOOL, &req);
168 ERROR ("ethstat plugin: Cannot get strings from %s: %s",
170 sstrerror (errno, errbuf, sizeof (errbuf)));
174 stats->cmd = ETHTOOL_GSTATS;
175 stats->n_stats = n_stats;
176 req.ifr_data = (void *) stats;
177 status = ioctl (fd, SIOCETHTOOL, &req);
184 ERROR("ethstat plugin: Reading statistics from %s failed: %s",
186 sstrerror (errno, errbuf, sizeof (errbuf)));
190 for (i = 0; i < n_stats; i++)
192 const char *stat_name;
194 stat_name = (void *) &strings->data[i * ETH_GSTRING_LEN],
195 DEBUG("ethstat plugin: device = \"%s\": %s = %"PRIu64,
197 (uint64_t) stats->data[i]);
198 ethstat_submit_value (device,
199 stat_name, (derive_t) stats->data[i]);
207 } /* }}} ethstat_read_interface */
209 static int ethstat_read(void)
213 for (i = 0; i < interfaces_num; i++)
214 ethstat_read_interface (interfaces[i]);
219 void module_register (void)
221 plugin_register_config ("ethstat", ethstat_config,
222 config_keys, config_keys_num);
223 plugin_register_read ("ethstat", ethstat_read);