diff options
author | Maria Matejka <mq@ucw.cz> | 2023-07-12 15:11:00 +0200 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2023-09-26 15:46:24 +0200 |
commit | 8674d7ab4bf76cadc256ca24609ffe4b1e8fcbf4 (patch) | |
tree | 946b2b478f35042f6e2d61b1a9eeb6fd3125e088 | |
parent | 977b82fba49b22d9548546d88b105945921efaed (diff) |
Aggregator: Fixed hashing of adata
-rw-r--r-- | lib/hash.h | 8 | ||||
-rw-r--r-- | proto/aggregator/aggregator.c | 73 |
2 files changed, 72 insertions, 9 deletions
@@ -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)) |