X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=xdp.c;h=36a45e2a72783c2ee49a326c689edc16e69cd1a3;hb=f14e8156a096aaa3ba97498b90e028019aa3252a;hp=6a8c19e4f852bad1e108093332043d0033f8e55b;hpb=8bcbc3efa0d2c62d461d8f6f238a181376822d00;p=flowspec-xdp diff --git a/xdp.c b/xdp.c index 6a8c19e..36a45e2 100644 --- a/xdp.c +++ b/xdp.c @@ -151,7 +151,7 @@ struct xdp_md { static const int XDP_PASS = 0; static const int XDP_DROP = 1; -static long drop_cnt_map[RULECNT + STATIC_RULE_CNT]; +static long drop_cnt_map[STATS_RULECNT + STATIC_RULE_CNT]; #define INCREMENT_MATCH(reason) { drop_cnt_map[reason] += 1; drop_cnt_map[reason] += data_end - pktdata; } #else /* TEST */ @@ -164,7 +164,7 @@ struct match_counter { }; struct { __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); - __uint(max_entries, RULECNT + STATIC_RULE_CNT); + __uint(max_entries, STATS_RULECNT + STATIC_RULE_CNT); __u32 *key; struct match_counter *value; } drop_cnt_map SEC(".maps"); @@ -185,6 +185,11 @@ struct { #define RATE_BUCKET_BITS (RATE_BUCKET_DECIMAL_BITS + RATE_BUCKET_INTEGER_BITS) #define RATE_TIME_MASK ((1ULL << (64 - RATE_BUCKET_BITS)) - 1) +// Time going backwards 10ms+ or forward 32sec+ implies we should consider it +// an overflow, or at least stale enough that we should reset the entry. +#define RATE_MIN_TIME_OFFSET -10000000LL +#define RATE_MAX_TIME_OFFSET 32000000000LL + #ifdef RATE_CNT struct ratelimit { struct bpf_spin_lock lock; @@ -208,13 +213,19 @@ struct { // Then we build an array of MAX_ENTRIES/2**SRC_HASH_MAX_PARALLELISM_POW entries, // which are split into buckets of size SRC_HASH_BUCKET_COUNT. An entry can appear // in any of the SRC_HASH_BUCKET_COUNT buckets at it's hash value. -#define SRC_HASH_MAX_PARALLELISM_POW 9 +// +// Because we use buckets of size 16, see collision_prob.py, the number of +// elements we can hold with only a 1% probability of overflowing a bucket is: +// +// 128K-entry hash table (2MiB): ~33K sources +// 256K-entry hash table (4MiB): ~63K sources +// 512K-entry hash table (8MiB): ~119K sources +// 1M-entry hash table (16MiB): ~227K sources +#define SRC_HASH_MAX_PARALLELISM_POW 8 #define SRC_HASH_MAX_PARALLELISM (1 << SRC_HASH_MAX_PARALLELISM_POW) -#define SRC_HASH_BUCKET_COUNT_POW 3 +#define SRC_HASH_BUCKET_COUNT_POW 4 #define SRC_HASH_BUCKET_COUNT (1 << SRC_HASH_BUCKET_COUNT_POW) -#include "rand.h" - #define CREATE_PERSRC_LOOKUP(IPV, IP_TYPE) \ struct persrc_rate##IPV##_entry { \ uint64_t sent_time; \ @@ -232,9 +243,9 @@ struct persrc_rate##IPV##_ptr { \ }; \ \ __attribute__((always_inline)) \ -static inline struct persrc_rate##IPV##_ptr get_v##IPV##_persrc_ratelimit(IP_TYPE key, void *map, size_t map_limit) { \ +static inline struct persrc_rate##IPV##_ptr get_v##IPV##_persrc_ratelimit(IP_TYPE key, void *map, size_t map_limit, int64_t cur_time_masked) { \ struct persrc_rate##IPV##_ptr res = { .rate = NULL, .lock = NULL }; \ - uint64_t hash = siphash(&key, sizeof(key), COMPILE_TIME_RAND); \ + uint64_t hash = siphash_##IP_TYPE(key); \ \ const uint32_t map_key = hash % SRC_HASH_MAX_PARALLELISM; \ struct persrc_rate##IPV##_bucket *buckets = bpf_map_lookup_elem(map, &map_key); \ @@ -253,7 +264,13 @@ static inline struct persrc_rate##IPV##_ptr get_v##IPV##_persrc_ratelimit(IP_TYP res.rate = &first_bucket[i]; \ res.lock = &buckets->lock; \ return res; \ - } else if (min_sent_time > (first_bucket[i].sent_time & RATE_TIME_MASK)) { \ + } \ + 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_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; \ } \