X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fnetlink.c;h=70c10c9dc88bbc69428b43faa962db6f5532cd43;hb=2ece265d5c296b56ab760d10c92054eef094e1bd;hp=3c4642c296f82ea32c32a80e81db426225188d32;hpb=c1219a1c9db2e8400e2ee94b87f86ccd441485d5;p=collectd.git diff --git a/src/netlink.c b/src/netlink.c index 3c4642c2..70c10c9d 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -26,11 +26,11 @@ **/ #include "collectd.h" + #include "plugin.h" #include "common.h" #include -#include #include #include @@ -43,6 +43,41 @@ #include +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; @@ -75,12 +110,10 @@ static int add_ignorelist (const char *dev, const char *type, { 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); @@ -124,14 +157,12 @@ static int add_ignorelist (const char *dev, const char *type, 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) @@ -163,14 +194,10 @@ static int check_ignorelist (const char *dev, static void submit_one (const char *dev, const char *type, const char *type_instance, derive_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].derive = value; - - vl.values = values; + vl.values = &(value_t) { .derive = value }; vl.values_len = 1; - sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "netlink", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance)); sstrncpy (vl.type, type, sizeof (vl.type)); @@ -185,15 +212,14 @@ static void submit_two (const char *dev, const char *type, const char *type_instance, derive_t rx, derive_t tx) { - value_t values[2]; value_list_t vl = VALUE_LIST_INIT; - - values[0].derive = rx; - values[1].derive = tx; + value_t values[] = { + { .derive = rx }, + { .derive = tx }, + }; vl.values = values; - vl.values_len = 2; - sstrncpy (vl.host, hostname_g, sizeof (vl.host)); + vl.values_len = STATIC_ARRAY_SIZE (values); sstrncpy (vl.plugin, "netlink", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance)); sstrncpy (vl.type, type, sizeof (vl.type)); @@ -212,7 +238,7 @@ static int update_iflist (struct ifinfomsg *msg, const char *dev) { 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."); @@ -235,7 +261,7 @@ static int update_iflist (struct ifinfomsg *msg, const char *dev) } /* 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) @@ -275,13 +301,61 @@ static void check_ignorelist_and_submit (const char *dev, } /* 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) { @@ -313,30 +387,44 @@ static int link_filter_cb (const struct nlmsghdr *nlh, 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 @@ -374,7 +462,7 @@ static int qos_filter_cb (const struct nlmsghdr *nlh, void *args) 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; @@ -630,8 +718,6 @@ static int ir_read (void) 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" }; @@ -666,15 +752,14 @@ static int ir_read (void) /* `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)) {