From 3c55d11aef9774a5a629d2879993065d21059304 Mon Sep 17 00:00:00 2001 From: Nick Hainke Date: Fri, 11 Dec 2020 21:53:02 +0100 Subject: [PATCH] collectd: add snmp6 interface Add collectd plugin allowing to collect IPv6 interface statistics. Signed-off-by: Nick Hainke --- utils/collectd/Makefile | 4 +- .../931-snmp6-add-ipv6-statistics.patch | 239 ++++++++++++++++++ 2 files changed, 242 insertions(+), 1 deletion(-) create mode 100644 utils/collectd/patches/931-snmp6-add-ipv6-statistics.patch diff --git a/utils/collectd/Makefile b/utils/collectd/Makefile index 01cc944e10..040e58f5c0 100644 --- a/utils/collectd/Makefile +++ b/utils/collectd/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=collectd PKG_VERSION:=5.12.0 -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:=https://collectd.org/files/ \ @@ -185,6 +185,7 @@ COLLECTD_PLUGINS_SELECTED:= \ rrdtool \ sensors \ snmp \ + snmp6 \ syslog \ table \ tail \ @@ -450,6 +451,7 @@ $(eval $(call BuildPlugin,routeros,MikroTik RouterOS input,routeros,+PACKAGE_col $(eval $(call BuildPlugin,rrdtool,RRDtool output,rrdtool,+PACKAGE_collectd-mod-rrdtool:librrd1)) $(eval $(call BuildPlugin,sensors,lm_sensors input,sensors,+PACKAGE_collectd-mod-sensors:libsensors)) $(eval $(call BuildPlugin,snmp,SNMP input,snmp,+PACKAGE_collectd-mod-snmp:libnetsnmp)) +$(eval $(call BuildPlugin,snmp6,snmp6 input,snmp6,)) $(eval $(call BuildPlugin,syslog,syslog output,syslog,)) $(eval $(call BuildPlugin,tail,tail input,tail,)) $(eval $(call BuildPlugin,tail-csv,tail CSV input,tail_csv,)) diff --git a/utils/collectd/patches/931-snmp6-add-ipv6-statistics.patch b/utils/collectd/patches/931-snmp6-add-ipv6-statistics.patch new file mode 100644 index 0000000000..ed27502f9c --- /dev/null +++ b/utils/collectd/patches/931-snmp6-add-ipv6-statistics.patch @@ -0,0 +1,239 @@ +From: Nick Hainke +Date: Mon, 7 Dec 2020 19:29:54 +0100 +Subject: [PATCH] snmp6: add ipv6 statistics + +ChangeLog: snmp6 plugin: Add plugin for parsing IPv6 statistics + +We would like to have pure ipv6 interface statistics. To get them, +we parse the snmp6 interface. + +Signed-off-by: Nick Hainke +--- + Makefile.am | 8 +++ + README | 4 ++ + configure.ac | 2 + + src/collectd.conf.in | 6 ++ + src/snmp6.c | 135 +++++++++++++++++++++++++++++++++++++++++++ + src/types.db | 2 + + 6 files changed, 157 insertions(+) + create mode 100644 src/snmp6.c + +--- a/Makefile.am ++++ b/Makefile.am +@@ -1964,6 +1964,14 @@ TESTS += test_plugin_snmp_agent + + endif + ++if BUILD_PLUGIN_SNMP6 ++pkglib_LTLIBRARIES += snmp6.la ++snmp6_la_SOURCES = src/snmp6.c ++snmp6_la_CFLAGS = $(AM_CFLAGS) ++snmp6_la_LDFLAGS = $(PLUGIN_LDFLAGS) ++snmp6_la_LIBADD = libignorelist.la ++endif # BUILD_PLUGIN_SNMP6 ++ + if BUILD_PLUGIN_STATSD + pkglib_LTLIBRARIES += statsd.la + statsd_la_SOURCES = src/statsd.c +--- a/README ++++ b/README +@@ -422,6 +422,10 @@ Features + network devices such as switches, routers, thermometers, rack monitoring + servers, etc. See collectd-snmp(5). + ++ - snmp6 ++ Read values from SNMP6 (Simple Network Management Protocol). Supports pure ++ IPv6 interface statistics. ++ + - statsd + Acts as a StatsD server, reading values sent over the network from StatsD + clients and calculating rates and other aggregates out of these values. +--- a/configure.ac ++++ b/configure.ac +@@ -7162,6 +7162,7 @@ AC_PLUGIN([slurm], [$with_ + AC_PLUGIN([smart], [$plugin_smart], [SMART statistics]) + AC_PLUGIN([snmp], [$with_libnetsnmp], [SNMP querying plugin]) + AC_PLUGIN([snmp_agent], [$with_libnetsnmpagent], [SNMP agent plugin]) ++AC_PLUGIN([snmp6], [yes], [IPv6 Interface traffic statistics via snmp6]) + AC_PLUGIN([statsd], [yes], [StatsD plugin]) + AC_PLUGIN([swap], [$plugin_swap], [Swap usage statistics]) + AC_PLUGIN([synproxy], [$plugin_synproxy], [Synproxy stats plugin]) +@@ -7611,6 +7612,7 @@ AC_MSG_RESULT([ slurm . . . . . . . . + AC_MSG_RESULT([ smart . . . . . . . . $enable_smart]) + AC_MSG_RESULT([ snmp . . . . . . . . $enable_snmp]) + AC_MSG_RESULT([ snmp_agent . . . . . $enable_snmp_agent]) ++AC_MSG_RESULT([ snmp6 . . . . . . . . $enable_snmp6]) + AC_MSG_RESULT([ statsd . . . . . . . $enable_statsd]) + AC_MSG_RESULT([ swap . . . . . . . . $enable_swap]) + AC_MSG_RESULT([ synproxy . . . . . . $enable_synproxy]) +--- a/src/collectd.conf.in ++++ b/src/collectd.conf.in +@@ -207,6 +207,7 @@ + #@BUILD_PLUGIN_SMART_TRUE@LoadPlugin smart + #@BUILD_PLUGIN_SNMP_TRUE@LoadPlugin snmp + #@BUILD_PLUGIN_SNMP_AGENT_TRUE@LoadPlugin snmp_agent ++#@BUILD_PLUGIN_SNMP6_TRUE@LoadPlugin snmp6 + #@BUILD_PLUGIN_STATSD_TRUE@LoadPlugin statsd + #@BUILD_PLUGIN_SWAP_TRUE@LoadPlugin swap + #@BUILD_PLUGIN_SYSEVENT_TRUE@LoadPlugin sysevent +@@ -1718,6 +1719,11 @@ + # + # + ++# ++# Interface "eth0" ++# IgnoreSelected false ++# ++ + # + # Host "::" + # Port "8125" +--- /dev/null ++++ b/src/snmp6.c +@@ -0,0 +1,135 @@ ++/* ++ This Plugin is based opn the interface.c Plugin. ++*/ ++ ++#if HAVE_LINUX_IF_H ++#include ++#elif HAVE_NET_IF_H ++#include ++#endif ++ ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "plugin.h" ++#include "utils/cmds/putval.h" ++#include "utils/common/common.h" ++#include "utils/ignorelist/ignorelist.h" ++ ++static const char *config_keys[] = { ++ "Interface", ++ "IgnoreSelected", ++}; ++static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); ++ ++static ignorelist_t *ignorelist; ++struct ifaddrs *if_list; ++ ++static int snmp6_config(const char *key, const char *value) { ++ if (ignorelist == NULL) ++ ignorelist = ignorelist_create(/* invert = */ 1); ++ ++ if (strcasecmp(key, "Interface") == 0) { ++ ignorelist_add(ignorelist, value); ++ } else if (strcasecmp(key, "IgnoreSelected") == 0) { ++ int invert = 1; ++ if (IS_TRUE(value)) ++ invert = 0; ++ ignorelist_set_invert(ignorelist, invert); ++ } ++ ++ return 0; ++} ++ ++/* Copied from interface.c */ ++static void snmp6_submit(const char *dev, const char *type, derive_t rx, ++ derive_t tx) { ++ value_list_t vl = VALUE_LIST_INIT; ++ value_t values[] = { ++ {.derive = rx}, ++ {.derive = tx}, ++ }; ++ ++ if (ignorelist_match(ignorelist, dev) != 0) ++ return; ++ ++ vl.values = values; ++ vl.values_len = STATIC_ARRAY_SIZE(values); ++ sstrncpy(vl.plugin, "snmp6", sizeof(vl.plugin)); ++ sstrncpy(vl.plugin_instance, dev, sizeof(vl.plugin_instance)); ++ sstrncpy(vl.type, type, sizeof(vl.type)); ++ ++ plugin_dispatch_values(&vl); ++} /* void if_submit */ ++ ++int snmp_read(char *ifname) { ++ FILE *fh; ++ char buffer[1024]; ++ char *fields[16]; ++ int numfields; ++ int currline = 0; ++ derive_t data[76]; ++ char procpath[1024]; ++ int offset = 0; ++ ++ if (strncmp("all", ifname, strlen("all")) == 0) { ++ snprintf(procpath, 1024, "/proc/net/snmp6"); ++ offset = 1; ++ } else { ++ snprintf(procpath, 1024, "/proc/net/dev_snmp6/%s", ifname); ++ } ++ ++ if ((fh = fopen(procpath, "r")) == NULL) { ++ WARNING("interface plugin: fopen: %s", STRERRNO); ++ return -1; ++ } ++ ++ while (fgets(buffer, 1024, fh) != NULL) { ++ numfields = strsplit(buffer, fields, 16); ++ ++ if (numfields < 2) ++ continue; ++ ++ data[currline++] = atoll(fields[1]); ++ } ++ ++ fclose(fh); ++ ++ if (currline < 25) { ++ return -1; ++ } ++ ++ snmp6_submit(ifname, "if_octets", data[23 - offset], data[24 - offset]); ++ snmp6_submit(ifname, "if_octets_mcast", data[25 - offset], data[26 - offset]); ++ snmp6_submit(ifname, "if_octets_bcast", data[27 - offset], data[28 - offset]); ++ return 0; ++} ++ ++int read_all_interfaces(void) { ++#ifndef HAVE_IFADDRS_H ++ return -1; ++#else ++ if (getifaddrs(&if_list) != 0) ++ return -1; ++ ++ for (struct ifaddrs *if_ptr = if_list; if_ptr != NULL; ++ if_ptr = if_ptr->ifa_next) { ++ snmp_read(if_ptr->ifa_name); ++ } ++ snmp_read("all"); ++ return 0; ++#endif ++} ++ ++void module_register(void) { ++ plugin_register_config("snmp6", snmp6_config, config_keys, config_keys_num); ++ plugin_register_read("snmp6", read_all_interfaces); ++} /* void module_register */ +--- a/src/types.db ++++ b/src/types.db +@@ -132,6 +132,8 @@ if_dropped rx:DERIVE:0:U, t + if_errors rx:DERIVE:0:U, tx:DERIVE:0:U + if_multicast value:DERIVE:0:U + if_octets rx:DERIVE:0:U, tx:DERIVE:0:U ++if_octets_mcast rx:DERIVE:0:U, tx:DERIVE:0:U ++if_octets_bcast rx:DERIVE:0:U, tx:DERIVE:0:U + if_packets rx:DERIVE:0:U, tx:DERIVE:0:U + if_rx_dropped value:DERIVE:0:U + if_rx_errors value:DERIVE:0:U -- 2.30.2