]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Aggregator: Fixed hashing of adata
authorMaria Matejka <mq@ucw.cz>
Wed, 12 Jul 2023 13:11:00 +0000 (15:11 +0200)
committerMaria Matejka <mq@ucw.cz>
Wed, 12 Jul 2023 13:11:00 +0000 (15:11 +0200)
lib/hash.h
proto/aggregator/aggregator.c

index b30f7830744a84917548c2345d559b897360e7d0..3c173958ff8146b006c748ddc9715ea4a59d7ea4 100644 (file)
@@ -215,6 +215,14 @@ mem_hash_mix(u64 *h, const void *p, uint s)
     *h = *h * multiplier + pp[i];
 }
 
+static inline void
+mem_hash_mix_str(u64 *h, const char *s)
+{
+  const u64 multiplier = 0xb38bc09a61202731ULL;
+  while (s)
+    *h = *h * multiplier + *s++;
+}
+
 static inline void
 mem_hash_mix_num(u64 *h, u64 val)
 {
index 2215c66a933681a6fc5664ae4925d1bc2d4c04d7..66c60166f70b9d7e3511cda87045e4c744603168 100644 (file)
 #include "lib/flowspec.h"
 */
 
-/* Context of &f_val comparison. */
-struct cmp_ctx {
-  const struct aggregator_proto *p;
-  const struct network *net;
-  const int val_count;
-  u32 failed:1;
-};
-
 extern linpool *rte_update_pool;
 
 /*
@@ -257,7 +249,10 @@ aggregator_reload_buckets(void *data)
 
   HASH_WALK(p->buckets, next_hash, b)
     if (b->rte)
+    {
       aggregator_bucket_update(p, b, b->rte->net);
+      lp_flush(rte_update_pool);
+    }
   HASH_WALK_END;
 }
 
@@ -496,7 +491,65 @@ aggregator_rt_notify(struct proto *P, struct channel *src_ch, net *net, rte *new
     }
 
     /* Compute the hash */
-    tmp_bucket->hash = mem_hash(tmp_bucket->aggr_data, AGGR_DATA_MEMSIZE);
+    u64 haux;
+    mem_hash_init(&haux);
+    for (uint i = 0; i < p->aggr_on_count; i++)
+    {
+      mem_hash_mix_num(&haux, tmp_bucket->aggr_data[i].type);
+
+#define MX(k) mem_hash_mix(&haux, &IT(k), sizeof IT(k));
+#define IT(k) tmp_bucket->aggr_data[i].val.k
+
+      switch (tmp_bucket->aggr_data[i].type)
+      {
+       case T_VOID:
+         break;
+       case T_INT:
+       case T_BOOL:
+       case T_PAIR:
+       case T_QUAD:
+       case T_ENUM:
+         MX(i);
+         break;
+       case T_EC:
+       case T_RD:
+         MX(ec);
+         break;
+       case T_LC:
+         MX(lc);
+         break;
+       case T_IP:
+         MX(ip);
+         break;
+       case T_NET:
+         mem_hash_mix_num(&haux, net_hash(IT(net)));
+         break;
+       case T_STRING:
+         mem_hash_mix_str(&haux, IT(s));
+         break;
+       case T_PATH_MASK:
+         mem_hash_mix(&haux, IT(path_mask), sizeof(*IT(path_mask)) + IT(path_mask)->len * sizeof (IT(path_mask)->item));
+         break;
+       case T_PATH:
+       case T_CLIST:
+       case T_ECLIST:
+       case T_LCLIST:
+         mem_hash_mix(&haux, IT(ad)->data, IT(ad)->length);
+         break;
+       case T_PATH_MASK_ITEM:
+       case T_ROUTE:
+       case T_ROUTES_BLOCK:
+         bug("Invalid type %s in hashing", f_type_name(tmp_bucket->aggr_data[i].type));
+       case T_SET:
+         MX(t);
+         break;
+       case T_PREFIX_SET:
+         MX(ti);
+         break;
+      }
+    }
+
+    tmp_bucket->hash = mem_hash_value(&haux);
 
     /* Find the existing bucket */
     if (new_bucket = HASH_FIND(p->buckets, AGGR_BUCK, tmp_bucket))