--- collectd-5.7.2_orig/src/iptables.c
+++ collectd-5.7.2/src/iptables.c
@@ -206,9 +206,67 @@ static int iptables_config(const char *k
return (0);
} /* int iptables_config */
+/* stack for storing value_list_t's that would otherwise be dispatched immediately */
+typedef struct value_list_list_s {
+ value_t value;
+ value_list_t vl;
+ struct value_list_list_s* next;
+} value_list_list_t;
+
+/* adds a value_list_t to an existing one that shares the same comment or push it as a new node */
+static void plugin_aggregate_values(value_list_list_t **vll, const value_list_t *vl) {
+ assert(vl->values_len == 1); // using only a single value
+ assert(vl->meta == NULL); // not used
+
+ // check whether there already is a node for this counter
+ value_list_list_t *it = *vll;
+ while (it != NULL) {
+ if (
+ (strcmp(it->vl.plugin_instance, vl->plugin_instance) == 0) &&
+ (strcmp(it->vl.type, vl->type) == 0) &&
+ (strcmp(it->vl.type_instance, vl->type_instance) == 0)
+ ) {
+ break; // found it
+ }
+ it = it->next;
+ }
+
+ if (it == NULL) {
+ // allocate new stack node
+ it = (value_list_list_t*)malloc(sizeof(value_list_list_t)); // XXX: could use plugin_value_list_clone() instead?
+ if (it == NULL) {
+ return; // oom
+ }
+
+ // deep copy
+ it->vl = *vl;
+ it->value = *vl->values;
+ it->vl.values = &it->value;
+
+ // update stack
+ it->next = *vll;
+ *vll = it;
+ } else {
+ // found: sum up
+ it->value.derive += vl->values->derive; // we know it's a derive
+ }
+}
+
+/* dispatch buffered value_list_t's and clear stack */
+static void plugin_dispatch_aggregate_values(value_list_list_t *vll) {
+ while (vll != NULL) {
+ plugin_dispatch_values (&vll->vl);
+ value_list_list_t* tmp = vll;
+ vll = vll->next;
+ free(tmp);
+ }
+}
+
static int submit6_match(const struct ip6t_entry_match *match,
const struct ip6t_entry *entry,
- const ip_chain_t *chain, int rule_num) {
+ const ip_chain_t *chain, int rule_num,
+ value_list_list_t **vll) {
+
int status;
value_list_t vl = VALUE_LIST_INIT;
@@ -244,11 +302,11 @@ static int submit6_match(const struct ip
sstrncpy(vl.type, "ipt_bytes", sizeof(vl.type));
vl.values = &(value_t){.derive = (derive_t)entry->counters.bcnt};
vl.values_len = 1;
- plugin_dispatch_values(&vl);
+ plugin_aggregate_values(vll, &vl);
sstrncpy(vl.type, "ipt_packets", sizeof(vl.type));
vl.values = &(value_t){.derive = (derive_t)entry->counters.pcnt};
- plugin_dispatch_values(&vl);
+ plugin_aggregate_values(vll, &vl);
return (0);
} /* int submit6_match */
@@ -256,7 +314,9 @@ static int submit6_match(const struct ip
/* This needs to return `int' for IPT_MATCH_ITERATE to work. */
static int submit_match(const struct ipt_entry_match *match,
const struct ipt_entry *entry, const ip_chain_t *chain,
- int rule_num) {
+ int rule_num,
+ value_list_list_t **vll) {
+
int status;
value_list_t vl = VALUE_LIST_INIT;
@@ -292,11 +352,11 @@ static int submit_match(const struct ipt
sstrncpy(vl.type, "ipt_bytes", sizeof(vl.type));
vl.values = &(value_t){.derive = (derive_t)entry->counters.bcnt};
vl.values_len = 1;
- plugin_dispatch_values(&vl);
+ plugin_aggregate_values(vll, &vl);
sstrncpy(vl.type, "ipt_packets", sizeof(vl.type));
vl.values = &(value_t){.derive = (derive_t)entry->counters.pcnt};
- plugin_dispatch_values(&vl);
+ plugin_aggregate_values(vll, &vl);
return (0);
} /* int submit_match */
@@ -314,16 +374,18 @@ static void submit6_chain(ip6tc_handle_t
}
rule_num = 1;
+ value_list_list_t *vll = NULL;
while (entry) {
if (chain->rule_type == RTYPE_NUM) {
- submit6_match(NULL, entry, chain, rule_num);
+ submit6_match(NULL, entry, chain, rule_num, &vll);
} else {
- IP6T_MATCH_ITERATE(entry, submit6_match, entry, chain, rule_num);
+ IP6T_MATCH_ITERATE(entry, submit6_match, entry, chain, rule_num, &vll);
}
entry = ip6tc_next_rule(entry, handle);
rule_num++;
} /* while (entry) */
+ plugin_dispatch_aggregate_values(vll);
}
/* ipv4 submit_chain */
@@ -339,16 +401,18 @@ static void submit_chain(iptc_handle_t *
}
rule_num = 1;
+ value_list_list_t *vll = NULL;
while (entry) {
if (chain->rule_type == RTYPE_NUM) {
- submit_match(NULL, entry, chain, rule_num);
+ submit_match(NULL, entry, chain, rule_num, &vll);
} else {
- IPT_MATCH_ITERATE(entry, submit_match, entry, chain, rule_num);
+ IPT_MATCH_ITERATE(entry, submit_match, entry, chain, rule_num, &vll);
}
entry = iptc_next_rule(entry, handle);
rule_num++;
} /* while (entry) */
+ plugin_dispatch_aggregate_values(vll);
}
static int iptables_read(void) {