--- collectd-5.5.1_orig/src/iptables.c
+++ collectd-5.5.1/src/iptables.c
@@ -236,10 +236,79 @@ static int iptables_config (const char *
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; // deep copy of vl.values
+ 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)
+ {
+ 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)
+ {
+ // found: sum up
+ it->value.derive += vl->values->derive; // we know it's a derive
+ }
+ else
+ {
+ // 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;
+ }
+}
+
+
+/* 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)
+ int rule_num,
+ value_list_list_t **vll)
{
int status;
value_t values[1];
@@ -286,11 +355,11 @@ static int submit6_match (const struct i
sstrncpy (vl.type, "ipt_bytes", sizeof (vl.type));
values[0].derive = (derive_t) entry->counters.bcnt;
- plugin_dispatch_values (&vl);
+ plugin_aggregate_values (vll, &vl);
sstrncpy (vl.type, "ipt_packets", sizeof (vl.type));
values[0].derive = (derive_t) entry->counters.pcnt;
- plugin_dispatch_values (&vl);
+ plugin_aggregate_values (vll, &vl);
return (0);
} /* int submit_match */
@@ -300,7 +369,8 @@ static int submit6_match (const struct i
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_t values[1];
@@ -347,11 +417,11 @@ static int submit_match (const struct ip
sstrncpy (vl.type, "ipt_bytes", sizeof (vl.type));
values[0].derive = (derive_t) entry->counters.bcnt;
- plugin_dispatch_values (&vl);
+ plugin_aggregate_values (vll, &vl);
sstrncpy (vl.type, "ipt_packets", sizeof (vl.type));
values[0].derive = (derive_t) entry->counters.pcnt;
- plugin_dispatch_values (&vl);
+ plugin_aggregate_values (vll, &vl);
return (0);
} /* int submit_match */
@@ -362,6 +432,7 @@ static void submit6_chain( ip6tc_handle_
{
const struct ip6t_entry *entry;
int rule_num;
+ value_list_list_t* vll = NULL;
/* Find first rule for chain and use the iterate macro */
entry = ip6tc_first_rule( chain->chain, handle );
@@ -376,16 +447,18 @@ static void submit6_chain( ip6tc_handle_
{
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 );
}
@@ -394,6 +467,7 @@ static void submit_chain( iptc_handle_t
{
const struct ipt_entry *entry;
int rule_num;
+ value_list_list_t* vll = NULL;
/* Find first rule for chain and use the iterate macro */
entry = iptc_first_rule( chain->chain, handle );
@@ -408,16 +482,18 @@ static void submit_chain( iptc_handle_t
{
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 );
}