**/
#include "collectd.h"
+
#include "plugin.h"
#include "common.h"
#include <asm/types.h>
-#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <libmnl/libmnl.h>
+struct ir_link_stats_storage_s {
+
+ uint64_t rx_packets;
+ uint64_t tx_packets;
+ uint64_t rx_bytes;
+ uint64_t tx_bytes;
+ uint64_t rx_errors;
+ uint64_t tx_errors;
+
+ uint64_t rx_dropped;
+ uint64_t tx_dropped;
+ uint64_t multicast;
+ uint64_t collisions;
+
+ uint64_t rx_length_errors;
+ uint64_t rx_over_errors;
+ uint64_t rx_crc_errors;
+ uint64_t rx_frame_errors;
+ uint64_t rx_fifo_errors;
+ uint64_t rx_missed_errors;
+
+ uint64_t tx_aborted_errors;
+ uint64_t tx_carrier_errors;
+ uint64_t tx_fifo_errors;
+ uint64_t tx_heartbeat_errors;
+ uint64_t tx_window_errors;
+};
+
+union ir_link_stats_u {
+ struct rtnl_link_stats *stats32;
+#ifdef HAVE_RTNL_LINK_STATS64
+ struct rtnl_link_stats64 *stats64;
+#endif
+};
+
typedef struct ir_ignorelist_s
{
char *device;
{
ir_ignorelist_t *entry;
- entry = (ir_ignorelist_t *) malloc (sizeof (ir_ignorelist_t));
+ entry = calloc (1, sizeof (*entry));
if (entry == NULL)
return (-1);
- memset (entry, '\0', sizeof (ir_ignorelist_t));
-
if (strcasecmp (dev, "All") != 0)
{
entry->device = strdup (dev);
static int check_ignorelist (const char *dev,
const char *type, const char *type_instance)
{
- ir_ignorelist_t *i;
-
assert ((dev != NULL) && (type != NULL));
if (ir_ignorelist_head == NULL)
return (ir_ignorelist_invert ? 0 : 1);
- for (i = ir_ignorelist_head; i != NULL; i = i->next)
+ for (ir_ignorelist_t *i = ir_ignorelist_head; i != NULL; i = i->next)
{
/* i->device == NULL => match all devices */
if ((i->device != NULL)
{
char **temp;
- temp = (char **) realloc (iflist, (msg->ifi_index + 1) * sizeof (char *));
+ temp = realloc (iflist, (msg->ifi_index + 1) * sizeof (char *));
if (temp == NULL)
{
ERROR ("netlink plugin: update_iflist: realloc failed.");
} /* int update_iflist */
static void check_ignorelist_and_submit (const char *dev,
- struct rtnl_link_stats *stats)
+ struct ir_link_stats_storage_s *stats)
{
if (check_ignorelist (dev, "interface", NULL) == 0)
} /* void check_ignorelist_and_submit */
+#define COPY_RTNL_LINK_VALUE(dst_stats, src_stats, value_name) \
+ (dst_stats)->value_name = (src_stats)->value_name
+
+#define COPY_RTNL_LINK_STATS(dst_stats, src_stats) \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_packets); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_packets); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_bytes); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_bytes); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_dropped); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_dropped); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, multicast); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, collisions); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_length_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_over_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_crc_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_frame_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_fifo_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_missed_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_aborted_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_carrier_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_fifo_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_heartbeat_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_window_errors)
+
+#ifdef HAVE_RTNL_LINK_STATS64
+static void check_ignorelist_and_submit64 (const char *dev,
+ struct rtnl_link_stats64 *stats)
+{
+ struct ir_link_stats_storage_s s;
+
+ COPY_RTNL_LINK_STATS (&s, stats);
+
+ check_ignorelist_and_submit (dev, &s);
+}
+#endif
+
+static void check_ignorelist_and_submit32 (const char *dev,
+ struct rtnl_link_stats *stats)
+{
+ struct ir_link_stats_storage_s s;
+
+ COPY_RTNL_LINK_STATS(&s, stats);
+
+ check_ignorelist_and_submit (dev, &s);
+}
+
static int link_filter_cb (const struct nlmsghdr *nlh,
void *args __attribute__((unused)))
{
struct ifinfomsg *ifm = mnl_nlmsg_get_payload (nlh);
struct nlattr *attr;
- struct rtnl_link_stats *stats = NULL;
const char *dev = NULL;
+ union ir_link_stats_u stats;
if (nlh->nlmsg_type != RTM_NEWLINK)
{
ERROR ("netlink plugin: link_filter_cb: dev == NULL");
return MNL_CB_ERROR;
}
+#ifdef HAVE_RTNL_LINK_STATS64
+ mnl_attr_for_each (attr, nlh, sizeof (*ifm))
+ {
+ if (mnl_attr_get_type (attr) != IFLA_STATS64)
+ continue;
+
+ if (mnl_attr_validate2 (attr, MNL_TYPE_UNSPEC, sizeof (*stats.stats64)) < 0)
+ {
+ ERROR ("netlink plugin: link_filter_cb: IFLA_STATS64 mnl_attr_validate2 failed.");
+ return MNL_CB_ERROR;
+ }
+ stats.stats64 = mnl_attr_get_payload (attr);
+
+ check_ignorelist_and_submit64 (dev, stats.stats64);
+ return MNL_CB_OK;
+ }
+#endif
mnl_attr_for_each (attr, nlh, sizeof (*ifm))
{
if (mnl_attr_get_type (attr) != IFLA_STATS)
continue;
- if (mnl_attr_validate2 (attr, MNL_TYPE_UNSPEC, sizeof (*stats)) < 0)
+ if (mnl_attr_validate2 (attr, MNL_TYPE_UNSPEC, sizeof (*stats.stats32)) < 0)
{
ERROR ("netlink plugin: link_filter_cb: IFLA_STATS mnl_attr_validate2 failed.");
return MNL_CB_ERROR;
}
- stats = mnl_attr_get_payload (attr);
+ stats.stats32 = mnl_attr_get_payload (attr);
- check_ignorelist_and_submit (dev, stats);
- break;
- }
+ check_ignorelist_and_submit32 (dev, stats.stats32);
- if (stats == NULL)
- {
- DEBUG ("netlink plugin: link_filter: No statistics for interface %s.", dev);
return MNL_CB_OK;
}
+ DEBUG ("netlink plugin: link_filter: No statistics for interface %s.", dev);
return MNL_CB_OK;
+
} /* int link_filter_cb */
#if HAVE_TCA_STATS2
const char *kind = NULL;
/* char *type_instance; */
- char *tc_type;
+ const char *tc_type;
char tc_inst[DATA_MAX_NAME_LEN];
_Bool stats_submitted = 0;
int ret;
unsigned int seq, portid;
- size_t ifindex;
-
static const int type_id[] = { RTM_GETQDISC, RTM_GETTCLASS, RTM_GETTFILTER };
static const char *type_name[] = { "qdisc", "class", "filter" };
/* `link_filter_cb' will update `iflist' which is used here to iterate
* over all interfaces. */
- for (ifindex = 1; ifindex < iflist_len; ifindex++)
+ for (size_t ifindex = 1; ifindex < iflist_len; ifindex++)
{
struct tcmsg *tm;
- size_t type_index;
if (iflist[ifindex] == NULL)
continue;
- for (type_index = 0; type_index < STATIC_ARRAY_SIZE (type_id); type_index++)
+ for (size_t type_index = 0; type_index < STATIC_ARRAY_SIZE (type_id); type_index++)
{
if (check_ignorelist (iflist[ifindex], type_name[type_index], NULL))
{