From: Matt Corallo Date: Sat, 15 Jun 2024 21:32:45 +0000 (+0000) Subject: Prefer existing src buckets even if others timed out X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=3f743cd21690bb0452deff2e8eff52ed02df7cef;p=flowspec-xdp Prefer existing src buckets even if others timed out If we have some timed-out buckets in a source-based ratelimit, we'll use those even if a later bucket is already storing the counter for the source of the current packet. This is obviously busted, so don't do that. --- diff --git a/xdp.c b/xdp.c index 187c220..4eea3e4 100644 --- a/xdp.c +++ b/xdp.c @@ -273,24 +273,26 @@ static int check_v##IPV##_persrc_ratelimit(IP_TYPE key, void *map, size_t map_li struct persrc_rate##IPV##_entry *first_bucket = &buckets->entries[(hash % map_limit) & (~(SRC_HASH_BUCKET_COUNT - 1))]; \ bpf_spin_lock(&buckets->lock); \ \ - uint64_t min_sent_idx = 0; /* Must be uint64_t or BPF verifier gets lost and thinks it can be any value */ \ + uint64_t bucket_idx = SRC_HASH_BUCKET_COUNT; \ + uint64_t min_sent_idx = 0; \ uint64_t min_sent_time = UINT64_MAX; \ for (uint64_t i = 0; i < SRC_HASH_BUCKET_COUNT; i++) { \ if (first_bucket[i].srcip == key) { \ - min_sent_idx = i; \ + bucket_idx = i; \ break; \ } \ int64_t time_offset = ((int64_t)cur_time_masked) - (first_bucket[i].sent_time & RATE_TIME_MASK); \ if (time_offset < RATE_MIN_TIME_OFFSET || time_offset > RATE_MAX_TIME_OFFSET) { \ + min_sent_time = 0; \ min_sent_idx = i; \ - break; \ } \ if ((first_bucket[i].sent_time & RATE_TIME_MASK) < min_sent_time) { \ min_sent_time = first_bucket[i].sent_time & RATE_TIME_MASK; \ min_sent_idx = i; \ } \ } \ - struct persrc_rate##IPV##_entry *entry = &first_bucket[min_sent_idx]; \ + if (bucket_idx >= SRC_HASH_BUCKET_COUNT) bucket_idx = min_sent_idx; \ + struct persrc_rate##IPV##_entry *entry = &first_bucket[bucket_idx]; \ if (entry->srcip != key) { \ entry->srcip = key; \ entry->sent_time = 0; \