summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/hash.h8
-rw-r--r--proto/aggregator/aggregator.c73
2 files changed, 72 insertions, 9 deletions
diff --git a/lib/hash.h b/lib/hash.h
index b30f7830..3c173958 100644
--- a/lib/hash.h
+++ b/lib/hash.h
@@ -216,6 +216,14 @@ mem_hash_mix(u64 *h, const void *p, uint s)
}
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)
{
mem_hash_mix(h, &val, sizeof(val));
diff --git a/proto/aggregator/aggregator.c b/proto/aggregator/aggregator.c
index 9d95c7db..6f6d09d5 100644
--- a/proto/aggregator/aggregator.c
+++ b/proto/aggregator/aggregator.c
@@ -62,14 +62,6 @@
#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;
/*
@@ -258,7 +250,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;
}
@@ -497,7 +492,67 @@ 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:
+ case T_BYTESTRING:
+ mem_hash_mix(&haux, IT(ad)->data, IT(ad)->length);
+ break;
+ case T_NONE:
+ 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))