]> git.bitcoin.ninja Git - flowspec-xdp/commitdiff
Prefer existing src buckets even if others timed out
authorMatt Corallo <git@bluematt.me>
Sat, 15 Jun 2024 21:32:45 +0000 (21:32 +0000)
committerMatt Corallo <git@bluematt.me>
Sat, 15 Jun 2024 21:32:45 +0000 (21:32 +0000)
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.

xdp.c

diff --git a/xdp.c b/xdp.c
index 187c220b0261fdaad0acc5ec7d48c6d36a4b86e5..4eea3e41aaad632e75110bf5d5a9fc84f659c258 100644 (file)
--- 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; \