diff options
Diffstat (limited to 'collectors/nfacct.plugin/plugin_nfacct.c')
-rw-r--r-- | collectors/nfacct.plugin/plugin_nfacct.c | 879 |
1 files changed, 0 insertions, 879 deletions
diff --git a/collectors/nfacct.plugin/plugin_nfacct.c b/collectors/nfacct.plugin/plugin_nfacct.c deleted file mode 100644 index 2863cd7eb..000000000 --- a/collectors/nfacct.plugin/plugin_nfacct.c +++ /dev/null @@ -1,879 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "libnetdata/libnetdata.h" -#include "libnetdata/required_dummies.h" - -#include <linux/netfilter/nfnetlink_conntrack.h> -#include <libmnl/libmnl.h> -#include <libnetfilter_acct/libnetfilter_acct.h> - -#define PLUGIN_NFACCT_NAME "nfacct.plugin" - -#define NETDATA_CHART_PRIO_NETFILTER_NEW 8701 -#define NETDATA_CHART_PRIO_NETFILTER_CHANGES 8702 -#define NETDATA_CHART_PRIO_NETFILTER_EXPECT 8703 -#define NETDATA_CHART_PRIO_NETFILTER_ERRORS 8705 -#define NETDATA_CHART_PRIO_NETFILTER_SEARCH 8710 - -#define NETDATA_CHART_PRIO_NETFILTER_PACKETS 8906 -#define NETDATA_CHART_PRIO_NETFILTER_BYTES 8907 - -#define NFACCT_RESTART_EVERY_SECONDS 86400 // restart the plugin every this many seconds - -static inline size_t mnl_buffer_size() { - long s = MNL_SOCKET_BUFFER_SIZE; - if(s <= 0) return 8192; - return (size_t)s; -} - -// variables -static int debug = 0; -static int netdata_update_every = 1; - -#define RRD_TYPE_NET_STAT_NETFILTER "netfilter" -#define RRD_TYPE_NET_STAT_CONNTRACK "netlink" - -static struct { - int update_every; - char *buf; - size_t buf_size; - struct mnl_socket *mnl; - struct nlmsghdr *nlh; - struct nfgenmsg *nfh; - unsigned int seq; - uint32_t portid; - - struct nlattr *tb[CTA_STATS_MAX+1]; - const char *attr2name[CTA_STATS_MAX+1]; - kernel_uint_t metrics[CTA_STATS_MAX+1]; - - struct nlattr *tb_exp[CTA_STATS_EXP_MAX+1]; - const char *attr2name_exp[CTA_STATS_EXP_MAX+1]; - kernel_uint_t metrics_exp[CTA_STATS_EXP_MAX+1]; -} nfstat_root = { - .update_every = 1, - .buf = NULL, - .buf_size = 0, - .mnl = NULL, - .nlh = NULL, - .nfh = NULL, - .seq = 0, - .portid = 0, - .tb = {}, - .attr2name = { - [CTA_STATS_SEARCHED] = "searched", - [CTA_STATS_FOUND] = "found", - [CTA_STATS_NEW] = "new", - [CTA_STATS_INVALID] = "invalid", - [CTA_STATS_IGNORE] = "ignore", - [CTA_STATS_DELETE] = "delete", - [CTA_STATS_DELETE_LIST] = "delete_list", - [CTA_STATS_INSERT] = "insert", - [CTA_STATS_INSERT_FAILED] = "insert_failed", - [CTA_STATS_DROP] = "drop", - [CTA_STATS_EARLY_DROP] = "early_drop", - [CTA_STATS_ERROR] = "icmp_error", - [CTA_STATS_SEARCH_RESTART] = "search_restart", - }, - .metrics = {}, - .tb_exp = {}, - .attr2name_exp = { - [CTA_STATS_EXP_NEW] = "new", - [CTA_STATS_EXP_CREATE] = "created", - [CTA_STATS_EXP_DELETE] = "deleted", - }, - .metrics_exp = {} -}; - - -static int nfstat_init(int update_every) { - nfstat_root.update_every = update_every; - - nfstat_root.buf_size = mnl_buffer_size(); - nfstat_root.buf = mallocz(nfstat_root.buf_size); - - nfstat_root.mnl = mnl_socket_open(NETLINK_NETFILTER); - if(!nfstat_root.mnl) { - collector_error("NFSTAT: mnl_socket_open() failed"); - return 1; - } - - nfstat_root.seq = (unsigned int)now_realtime_sec() - 1; - - if(mnl_socket_bind(nfstat_root.mnl, 0, MNL_SOCKET_AUTOPID) < 0) { - collector_error("NFSTAT: mnl_socket_bind() failed"); - return 1; - } - nfstat_root.portid = mnl_socket_get_portid(nfstat_root.mnl); - - return 0; -} - -static struct nlmsghdr * nfct_mnl_nlmsghdr_put(char *buf, uint16_t subsys, uint16_t type, uint8_t family, uint32_t seq) { - struct nlmsghdr *nlh; - struct nfgenmsg *nfh; - - nlh = mnl_nlmsg_put_header(buf); - nlh->nlmsg_type = (subsys << 8) | type; - nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP; - nlh->nlmsg_seq = seq; - - nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg)); - nfh->nfgen_family = family; - nfh->version = NFNETLINK_V0; - nfh->res_id = 0; - - return nlh; -} - -static int nfct_stats_attr_cb(const struct nlattr *attr, void *data) { - const struct nlattr **tb = data; - int type = mnl_attr_get_type(attr); - - if (mnl_attr_type_valid(attr, CTA_STATS_MAX) < 0) - return MNL_CB_OK; - - if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { - collector_error("NFSTAT: mnl_attr_validate() failed"); - return MNL_CB_ERROR; - } - - tb[type] = attr; - return MNL_CB_OK; -} - -static int nfstat_callback(const struct nlmsghdr *nlh, void *data) { - (void)data; - - struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh); - - mnl_attr_parse(nlh, sizeof(*nfg), nfct_stats_attr_cb, nfstat_root.tb); - - // printf("cpu=%-4u\t", ntohs(nfg->res_id)); - - int i; - // add the metrics of this CPU into the metrics - for (i = 0; i < CTA_STATS_MAX+1; i++) { - if (nfstat_root.tb[i]) { - // printf("%s=%u ", nfstat_root.attr2name[i], ntohl(mnl_attr_get_u32(nfstat_root.tb[i]))); - nfstat_root.metrics[i] += ntohl(mnl_attr_get_u32(nfstat_root.tb[i])); - } - } - // printf("\n"); - - return MNL_CB_OK; -} - -static int nfstat_collect_conntrack() { - // zero all metrics - we will sum the metrics of all CPUs later - int i; - for (i = 0; i < CTA_STATS_MAX+1; i++) - nfstat_root.metrics[i] = 0; - - // prepare the request - nfstat_root.nlh = nfct_mnl_nlmsghdr_put(nfstat_root.buf, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET_STATS_CPU, AF_UNSPEC, nfstat_root.seq); - - // send the request - if(mnl_socket_sendto(nfstat_root.mnl, nfstat_root.nlh, nfstat_root.nlh->nlmsg_len) < 0) { - collector_error("NFSTAT: mnl_socket_sendto() failed"); - return 1; - } - - // get the reply - ssize_t ret; - while ((ret = mnl_socket_recvfrom(nfstat_root.mnl, nfstat_root.buf, nfstat_root.buf_size)) > 0) { - if(mnl_cb_run( - nfstat_root.buf - , (size_t)ret - , nfstat_root.nlh->nlmsg_seq - , nfstat_root.portid - , nfstat_callback - , NULL - ) <= MNL_CB_STOP) - break; - } - - // verify we run without issues - if (ret == -1) { - collector_error("NFSTAT: error communicating with kernel. This plugin can only work when netdata runs as root."); - return 1; - } - - return 0; -} - -static int nfexp_stats_attr_cb(const struct nlattr *attr, void *data) -{ - const struct nlattr **tb = data; - int type = mnl_attr_get_type(attr); - - if (mnl_attr_type_valid(attr, CTA_STATS_EXP_MAX) < 0) - return MNL_CB_OK; - - if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { - collector_error("NFSTAT EXP: mnl_attr_validate() failed"); - return MNL_CB_ERROR; - } - - tb[type] = attr; - return MNL_CB_OK; -} - -static int nfstat_callback_exp(const struct nlmsghdr *nlh, void *data) { - (void)data; - - struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh); - - mnl_attr_parse(nlh, sizeof(*nfg), nfexp_stats_attr_cb, nfstat_root.tb_exp); - - int i; - for (i = 0; i < CTA_STATS_EXP_MAX+1; i++) { - if (nfstat_root.tb_exp[i]) { - nfstat_root.metrics_exp[i] += ntohl(mnl_attr_get_u32(nfstat_root.tb_exp[i])); - } - } - - return MNL_CB_OK; -} - -static int nfstat_collect_conntrack_expectations() { - // zero all metrics - we will sum the metrics of all CPUs later - int i; - for (i = 0; i < CTA_STATS_EXP_MAX+1; i++) - nfstat_root.metrics_exp[i] = 0; - - // prepare the request - nfstat_root.nlh = nfct_mnl_nlmsghdr_put(nfstat_root.buf, NFNL_SUBSYS_CTNETLINK_EXP, IPCTNL_MSG_EXP_GET_STATS_CPU, AF_UNSPEC, nfstat_root.seq); - - // send the request - if(mnl_socket_sendto(nfstat_root.mnl, nfstat_root.nlh, nfstat_root.nlh->nlmsg_len) < 0) { - collector_error("NFSTAT: mnl_socket_sendto() failed"); - return 1; - } - - // get the reply - ssize_t ret; - while ((ret = mnl_socket_recvfrom(nfstat_root.mnl, nfstat_root.buf, nfstat_root.buf_size)) > 0) { - if(mnl_cb_run( - nfstat_root.buf - , (size_t)ret - , nfstat_root.nlh->nlmsg_seq - , nfstat_root.portid - , nfstat_callback_exp - , NULL - ) <= MNL_CB_STOP) - break; - } - - // verify we run without issues - if (ret == -1) { - collector_error("NFSTAT: error communicating with kernel. This plugin can only work when netdata runs as root."); - return 1; - } - - return 0; -} - -static int nfstat_collect() { - nfstat_root.seq++; - - if(nfstat_collect_conntrack()) - return 1; - - if(nfstat_collect_conntrack_expectations()) - return 1; - - return 0; -} - -static void nfstat_send_metrics() { - static int new_chart_generated = 0, changes_chart_generated = 0, search_chart_generated = 0, errors_chart_generated = 0, expect_chart_generated = 0; - - if(!new_chart_generated) { - new_chart_generated = 1; - - printf("CHART %s.%s '' 'Connection Tracker New Connections' 'connections/s' %s '' line %d %d %s\n" - , RRD_TYPE_NET_STAT_NETFILTER - , RRD_TYPE_NET_STAT_CONNTRACK "_new" - , RRD_TYPE_NET_STAT_CONNTRACK - , NETDATA_CHART_PRIO_NETFILTER_NEW - , nfstat_root.update_every - , PLUGIN_NFACCT_NAME - ); - printf("DIMENSION %s '' incremental 1 1\n", nfstat_root.attr2name[CTA_STATS_NEW]); - printf("DIMENSION %s '' incremental -1 1\n", nfstat_root.attr2name[CTA_STATS_IGNORE]); - printf("DIMENSION %s '' incremental -1 1\n", nfstat_root.attr2name[CTA_STATS_INVALID]); - } - - printf( - "BEGIN %s.%s\n" - , RRD_TYPE_NET_STAT_NETFILTER - , RRD_TYPE_NET_STAT_CONNTRACK "_new" - ); - printf( - "SET %s = %lld\n" - , nfstat_root.attr2name[CTA_STATS_NEW] - , (collected_number) nfstat_root.metrics[CTA_STATS_NEW] - ); - printf( - "SET %s = %lld\n" - , nfstat_root.attr2name[CTA_STATS_IGNORE] - , (collected_number) nfstat_root.metrics[CTA_STATS_IGNORE] - ); - printf( - "SET %s = %lld\n" - , nfstat_root.attr2name[CTA_STATS_INVALID] - , (collected_number) nfstat_root.metrics[CTA_STATS_INVALID] - ); - printf("END\n"); - - // ---------------------------------------------------------------- - - if(!changes_chart_generated) { - changes_chart_generated = 1; - - printf("CHART %s.%s '' 'Connection Tracker Changes' 'changes/s' %s '' line %d %d detail %s\n" - , RRD_TYPE_NET_STAT_NETFILTER - , RRD_TYPE_NET_STAT_CONNTRACK "_changes" - , RRD_TYPE_NET_STAT_CONNTRACK - , NETDATA_CHART_PRIO_NETFILTER_CHANGES - , nfstat_root.update_every - , PLUGIN_NFACCT_NAME - ); - printf("DIMENSION %s '' incremental 1 1\n", nfstat_root.attr2name[CTA_STATS_INSERT]); - printf("DIMENSION %s '' incremental -1 1\n", nfstat_root.attr2name[CTA_STATS_DELETE]); - printf("DIMENSION %s '' incremental -1 1\n", nfstat_root.attr2name[CTA_STATS_DELETE_LIST]); - } - - printf( - "BEGIN %s.%s\n" - , RRD_TYPE_NET_STAT_NETFILTER - , RRD_TYPE_NET_STAT_CONNTRACK "_changes" - ); - printf( - "SET %s = %lld\n" - , nfstat_root.attr2name[CTA_STATS_INSERT] - , (collected_number) nfstat_root.metrics[CTA_STATS_INSERT] - ); - printf( - "SET %s = %lld\n" - , nfstat_root.attr2name[CTA_STATS_DELETE] - , (collected_number) nfstat_root.metrics[CTA_STATS_DELETE] - ); - printf( - "SET %s = %lld\n" - , nfstat_root.attr2name[CTA_STATS_DELETE_LIST] - , (collected_number) nfstat_root.metrics[CTA_STATS_DELETE_LIST] - ); - printf("END\n"); - - // ---------------------------------------------------------------- - - if(!search_chart_generated) { - search_chart_generated = 1; - - printf("CHART %s.%s '' 'Connection Tracker Searches' 'searches/s' %s '' line %d %d detail %s\n" - , RRD_TYPE_NET_STAT_NETFILTER - , RRD_TYPE_NET_STAT_CONNTRACK "_search" - , RRD_TYPE_NET_STAT_CONNTRACK - , NETDATA_CHART_PRIO_NETFILTER_SEARCH - , nfstat_root.update_every - , PLUGIN_NFACCT_NAME - ); - printf("DIMENSION %s '' incremental 1 1\n", nfstat_root.attr2name[CTA_STATS_SEARCHED]); - printf("DIMENSION %s '' incremental -1 1\n", nfstat_root.attr2name[CTA_STATS_SEARCH_RESTART]); - printf("DIMENSION %s '' incremental 1 1\n", nfstat_root.attr2name[CTA_STATS_FOUND]); - } - - printf( - "BEGIN %s.%s\n" - , RRD_TYPE_NET_STAT_NETFILTER - , RRD_TYPE_NET_STAT_CONNTRACK "_search" - ); - printf( - "SET %s = %lld\n" - , nfstat_root.attr2name[CTA_STATS_SEARCHED] - , (collected_number) nfstat_root.metrics[CTA_STATS_SEARCHED] - ); - printf( - "SET %s = %lld\n" - , nfstat_root.attr2name[CTA_STATS_SEARCH_RESTART] - , (collected_number) nfstat_root.metrics[CTA_STATS_SEARCH_RESTART] - ); - printf( - "SET %s = %lld\n" - , nfstat_root.attr2name[CTA_STATS_FOUND] - , (collected_number) nfstat_root.metrics[CTA_STATS_FOUND] - ); - printf("END\n"); - - // ---------------------------------------------------------------- - - if(!errors_chart_generated) { - errors_chart_generated = 1; - - printf("CHART %s.%s '' 'Connection Tracker Errors' 'events/s' %s '' line %d %d detail %s\n" - , RRD_TYPE_NET_STAT_NETFILTER - , RRD_TYPE_NET_STAT_CONNTRACK "_errors" - , RRD_TYPE_NET_STAT_CONNTRACK - , NETDATA_CHART_PRIO_NETFILTER_ERRORS - , nfstat_root.update_every - , PLUGIN_NFACCT_NAME - ); - printf("DIMENSION %s '' incremental 1 1\n", nfstat_root.attr2name[CTA_STATS_ERROR]); - printf("DIMENSION %s '' incremental -1 1\n", nfstat_root.attr2name[CTA_STATS_INSERT_FAILED]); - printf("DIMENSION %s '' incremental -1 1\n", nfstat_root.attr2name[CTA_STATS_DROP]); - printf("DIMENSION %s '' incremental -1 1\n", nfstat_root.attr2name[CTA_STATS_EARLY_DROP]); - } - - printf( - "BEGIN %s.%s\n" - , RRD_TYPE_NET_STAT_NETFILTER - , RRD_TYPE_NET_STAT_CONNTRACK "_errors" - ); - printf( - "SET %s = %lld\n" - , nfstat_root.attr2name[CTA_STATS_ERROR] - , (collected_number) nfstat_root.metrics[CTA_STATS_ERROR] - ); - printf( - "SET %s = %lld\n" - , nfstat_root.attr2name[CTA_STATS_INSERT_FAILED] - , (collected_number) nfstat_root.metrics[CTA_STATS_INSERT_FAILED] - ); - printf( - "SET %s = %lld\n" - , nfstat_root.attr2name[CTA_STATS_DROP] - , (collected_number) nfstat_root.metrics[CTA_STATS_DROP] - ); - printf( - "SET %s = %lld\n" - , nfstat_root.attr2name[CTA_STATS_EARLY_DROP] - , (collected_number) nfstat_root.metrics[CTA_STATS_EARLY_DROP] - ); - printf("END\n"); - - // ---------------------------------------------------------------- - - if(!expect_chart_generated) { - expect_chart_generated = 1; - - printf("CHART %s.%s '' 'Connection Tracker Expectations' 'expectations/s' %s '' line %d %d detail %s\n" - , RRD_TYPE_NET_STAT_NETFILTER - , RRD_TYPE_NET_STAT_CONNTRACK "_expect" - , RRD_TYPE_NET_STAT_CONNTRACK - , NETDATA_CHART_PRIO_NETFILTER_EXPECT - , nfstat_root.update_every - , PLUGIN_NFACCT_NAME - ); - printf("DIMENSION %s '' incremental 1 1\n", nfstat_root.attr2name[CTA_STATS_EXP_CREATE]); - printf("DIMENSION %s '' incremental -1 1\n", nfstat_root.attr2name[CTA_STATS_EXP_DELETE]); - printf("DIMENSION %s '' incremental 1 1\n", nfstat_root.attr2name[CTA_STATS_EXP_NEW]); - } - - printf( - "BEGIN %s.%s\n" - , RRD_TYPE_NET_STAT_NETFILTER - , RRD_TYPE_NET_STAT_CONNTRACK "_expect" - ); - printf( - "SET %s = %lld\n" - , nfstat_root.attr2name[CTA_STATS_EXP_CREATE] - , (collected_number) nfstat_root.metrics[CTA_STATS_EXP_CREATE] - ); - printf( - "SET %s = %lld\n" - , nfstat_root.attr2name[CTA_STATS_EXP_DELETE] - , (collected_number) nfstat_root.metrics[CTA_STATS_EXP_DELETE] - ); - printf( - "SET %s = %lld\n" - , nfstat_root.attr2name[CTA_STATS_EXP_NEW] - , (collected_number) nfstat_root.metrics[CTA_STATS_EXP_NEW] - ); - printf("END\n"); -} - - -struct nfacct_data { - char *name; - uint32_t hash; - - uint64_t pkts; - uint64_t bytes; - - int packets_dimension_added; - int bytes_dimension_added; - - int updated; - - struct nfacct_data *next; -}; - -static struct { - int update_every; - char *buf; - size_t buf_size; - struct mnl_socket *mnl; - struct nlmsghdr *nlh; - unsigned int seq; - uint32_t portid; - struct nfacct *nfacct_buffer; - struct nfacct_data *nfacct_metrics; -} nfacct_root = { - .update_every = 1, - .buf = NULL, - .buf_size = 0, - .mnl = NULL, - .nlh = NULL, - .seq = 0, - .portid = 0, - .nfacct_buffer = NULL, - .nfacct_metrics = NULL -}; - -static inline struct nfacct_data *nfacct_data_get(const char *name, uint32_t hash) { - struct nfacct_data *d = NULL, *last = NULL; - for(d = nfacct_root.nfacct_metrics; d ; last = d, d = d->next) { - if(unlikely(d->hash == hash && !strcmp(d->name, name))) - return d; - } - - d = callocz(1, sizeof(struct nfacct_data)); - d->name = strdupz(name); - d->hash = hash; - - if(!last) { - d->next = nfacct_root.nfacct_metrics; - nfacct_root.nfacct_metrics = d; - } - else { - d->next = last->next; - last->next = d; - } - - return d; -} - -static int nfacct_init(int update_every) { - nfacct_root.update_every = update_every; - - nfacct_root.buf_size = mnl_buffer_size(); - nfacct_root.buf = mallocz(nfacct_root.buf_size); - - nfacct_root.nfacct_buffer = nfacct_alloc(); - if(!nfacct_root.nfacct_buffer) { - collector_error("nfacct.plugin: nfacct_alloc() failed."); - return 0; - } - - nfacct_root.seq = (unsigned int)now_realtime_sec() - 1; - - nfacct_root.mnl = mnl_socket_open(NETLINK_NETFILTER); - if(!nfacct_root.mnl) { - collector_error("nfacct.plugin: mnl_socket_open() failed"); - return 1; - } - - if(mnl_socket_bind(nfacct_root.mnl, 0, MNL_SOCKET_AUTOPID) < 0) { - collector_error("nfacct.plugin: mnl_socket_bind() failed"); - return 1; - } - nfacct_root.portid = mnl_socket_get_portid(nfacct_root.mnl); - - return 0; -} - -static int nfacct_callback(const struct nlmsghdr *nlh, void *data) { - (void)data; - - if(nfacct_nlmsg_parse_payload(nlh, nfacct_root.nfacct_buffer) < 0) { - collector_error("NFACCT: nfacct_nlmsg_parse_payload() failed."); - return MNL_CB_OK; - } - - const char *name = nfacct_attr_get_str(nfacct_root.nfacct_buffer, NFACCT_ATTR_NAME); - uint32_t hash = simple_hash(name); - - struct nfacct_data *d = nfacct_data_get(name, hash); - - d->pkts = nfacct_attr_get_u64(nfacct_root.nfacct_buffer, NFACCT_ATTR_PKTS); - d->bytes = nfacct_attr_get_u64(nfacct_root.nfacct_buffer, NFACCT_ATTR_BYTES); - d->updated = 1; - - return MNL_CB_OK; -} - -static int nfacct_collect() { - // mark all old metrics as not-updated - struct nfacct_data *d; - for(d = nfacct_root.nfacct_metrics; d ; d = d->next) - d->updated = 0; - - // prepare the request - nfacct_root.seq++; - nfacct_root.nlh = nfacct_nlmsg_build_hdr(nfacct_root.buf, NFNL_MSG_ACCT_GET, NLM_F_DUMP, (uint32_t)nfacct_root.seq); - if(!nfacct_root.nlh) { - collector_error("NFACCT: nfacct_nlmsg_build_hdr() failed"); - return 1; - } - - // send the request - if(mnl_socket_sendto(nfacct_root.mnl, nfacct_root.nlh, nfacct_root.nlh->nlmsg_len) < 0) { - collector_error("NFACCT: mnl_socket_sendto() failed"); - return 1; - } - - // get the reply - ssize_t ret; - while((ret = mnl_socket_recvfrom(nfacct_root.mnl, nfacct_root.buf, nfacct_root.buf_size)) > 0) { - if(mnl_cb_run( - nfacct_root.buf - , (size_t)ret - , nfacct_root.seq - , nfacct_root.portid - , nfacct_callback - , NULL - ) <= 0) - break; - } - - // verify we run without issues - if (ret == -1) { - collector_error("NFACCT: error communicating with kernel. This plugin can only work when netdata runs as root."); - return 1; - } - - return 0; -} - -static void nfacct_send_metrics() { - static int bytes_chart_generated = 0, packets_chart_generated = 0; - - if(!nfacct_root.nfacct_metrics) return; - struct nfacct_data *d; - - if(!packets_chart_generated) { - packets_chart_generated = 1; - printf("CHART netfilter.nfacct_packets '' 'Netfilter Accounting Packets' 'packets/s' 'nfacct' '' stacked %d %d %s\n" - , NETDATA_CHART_PRIO_NETFILTER_PACKETS - , nfacct_root.update_every - , PLUGIN_NFACCT_NAME - ); - } - - for(d = nfacct_root.nfacct_metrics; d ; d = d->next) { - if(likely(d->updated)) { - if(unlikely(!d->packets_dimension_added)) { - d->packets_dimension_added = 1; - printf( - "CHART netfilter.nfacct_packets '' 'Netfilter Accounting Packets' 'packets/s' 'nfacct' '' stacked %d %d %s\n", - NETDATA_CHART_PRIO_NETFILTER_PACKETS, - nfacct_root.update_every, - PLUGIN_NFACCT_NAME); - printf("DIMENSION %s '' incremental 1 %d\n", d->name, nfacct_root.update_every); - } - } - } - printf("BEGIN netfilter.nfacct_packets\n"); - for(d = nfacct_root.nfacct_metrics; d ; d = d->next) { - if(likely(d->updated)) { - printf("SET %s = %lld\n" - , d->name - , (collected_number)d->pkts - ); - } - } - printf("END\n"); - - // ---------------------------------------------------------------- - - if(!bytes_chart_generated) { - bytes_chart_generated = 1; - printf("CHART netfilter.nfacct_bytes '' 'Netfilter Accounting Bandwidth' 'kilobytes/s' 'nfacct' '' stacked %d %d %s\n" - , NETDATA_CHART_PRIO_NETFILTER_BYTES - , nfacct_root.update_every - , PLUGIN_NFACCT_NAME - ); - } - - for(d = nfacct_root.nfacct_metrics; d ; d = d->next) { - if(likely(d->updated)) { - if(unlikely(!d->bytes_dimension_added)) { - d->bytes_dimension_added = 1; - printf( - "CHART netfilter.nfacct_bytes '' 'Netfilter Accounting Bandwidth' 'kilobytes/s' 'nfacct' '' stacked %d %d %s\n", - NETDATA_CHART_PRIO_NETFILTER_BYTES, - nfacct_root.update_every, - PLUGIN_NFACCT_NAME); - printf("DIMENSION %s '' incremental 1 %d\n", d->name, 1000 * nfacct_root.update_every); - } - } - } - printf("BEGIN netfilter.nfacct_bytes\n"); - for(d = nfacct_root.nfacct_metrics; d ; d = d->next) { - if(likely(d->updated)) { - printf("SET %s = %lld\n" - , d->name - , (collected_number)d->bytes - ); - } - } - printf("END\n"); -} - -static void nfacct_signal_handler(int signo) -{ - exit((signo == SIGPIPE)?1:0); -} - -// When Netdata crashes this plugin was becoming zombie, -// this function was added to remove it when sigpipe and other signals are received. -void nfacct_signals() -{ - int signals[] = { SIGPIPE, SIGINT, SIGTERM, 0}; - int i; - struct sigaction sa; - sa.sa_flags = 0; - sa.sa_handler = nfacct_signal_handler; - - // ignore all signals while we run in a signal handler - sigfillset(&sa.sa_mask); - - for (i = 0; signals[i]; i++) { - if(sigaction(signals[i], &sa, NULL) == -1) - collector_error("Cannot add the handler to signal %d", signals[i]); - } -} - -int main(int argc, char **argv) { - clocks_init(); - nd_log_initialize_for_external_plugins("nfacct.plugin"); - - // ------------------------------------------------------------------------ - // parse command line parameters - - int i, freq = 0; - for(i = 1; i < argc ; i++) { - if(isdigit(*argv[i]) && !freq) { - int n = str2i(argv[i]); - if(n > 0 && n < 86400) { - freq = n; - continue; - } - } - else if(strcmp("version", argv[i]) == 0 || strcmp("-version", argv[i]) == 0 || strcmp("--version", argv[i]) == 0 || strcmp("-v", argv[i]) == 0 || strcmp("-V", argv[i]) == 0) { - printf("nfacct.plugin %s\n", VERSION); - exit(0); - } - else if(strcmp("debug", argv[i]) == 0) { - debug = 1; - continue; - } - else if(strcmp("-h", argv[i]) == 0 || strcmp("--help", argv[i]) == 0) { - fprintf(stderr, - "\n" - " netdata nfacct.plugin %s\n" - " Copyright (C) 2015-2017 Costa Tsaousis <costa@tsaousis.gr>\n" - " Released under GNU General Public License v3 or later.\n" - " All rights reserved.\n" - "\n" - " This program is a data collector plugin for netdata.\n" - "\n" - " Available command line options:\n" - "\n" - " COLLECTION_FREQUENCY data collection frequency in seconds\n" - " minimum: %d\n" - "\n" - " debug enable verbose output\n" - " default: disabled\n" - "\n" - " -v\n" - " -V\n" - " --version print version and exit\n" - "\n" - " -h\n" - " --help print this message and exit\n" - "\n" - " For more information:\n" - " https://github.com/netdata/netdata/tree/master/collectors/nfacct.plugin\n" - "\n" - , VERSION - , netdata_update_every - ); - exit(1); - } - - collector_error("nfacct.plugin: ignoring parameter '%s'", argv[i]); - } - - nfacct_signals(); - - errno = 0; - - if(freq >= netdata_update_every) - netdata_update_every = freq; - else if(freq) - collector_error("update frequency %d seconds is too small for NFACCT. Using %d.", freq, netdata_update_every); - - if (debug) - fprintf(stderr, "nfacct.plugin: calling nfacct_init()\n"); - int nfacct = !nfacct_init(netdata_update_every); - - if (debug) - fprintf(stderr, "nfacct.plugin: calling nfstat_init()\n"); - int nfstat = !nfstat_init(netdata_update_every); - - // ------------------------------------------------------------------------ - // the main loop - - if(debug) fprintf(stderr, "nfacct.plugin: starting data collection\n"); - - time_t started_t = now_monotonic_sec(); - - size_t iteration; - usec_t step = netdata_update_every * USEC_PER_SEC; - - heartbeat_t hb; - heartbeat_init(&hb); - for(iteration = 0; 1; iteration++) { - usec_t dt = heartbeat_next(&hb, step); - - if(unlikely(netdata_exit)) break; - - if(debug && iteration) - fprintf(stderr, "nfacct.plugin: iteration %zu, dt %"PRIu64" usec\n" - , iteration - , dt - ); - - if(likely(nfacct)) { - if(debug) fprintf(stderr, "nfacct.plugin: calling nfacct_collect()\n"); - nfacct = !nfacct_collect(); - - if(likely(nfacct)) { - if(debug) fprintf(stderr, "nfacct.plugin: calling nfacct_send_metrics()\n"); - nfacct_send_metrics(); - } - } - - if(likely(nfstat)) { - if(debug) fprintf(stderr, "nfacct.plugin: calling nfstat_collect()\n"); - nfstat = !nfstat_collect(); - - if(likely(nfstat)) { - if(debug) fprintf(stderr, "nfacct.plugin: calling nfstat_send_metrics()\n"); - nfstat_send_metrics(); - } - } - - fflush(stdout); - - if (now_monotonic_sec() - started_t > NFACCT_RESTART_EVERY_SECONDS) { - collector_info("NFACCT reached my lifetime expectancy. Exiting to restart."); - fprintf(stdout, "EXIT\n"); - fflush(stdout); - exit(0); - } - } -} |