--- 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) {