diff options
-rw-r--r-- | src/vnet/ip/reass/ip6_full_reass.c | 44 |
1 files changed, 35 insertions, 9 deletions
diff --git a/src/vnet/ip/reass/ip6_full_reass.c b/src/vnet/ip/reass/ip6_full_reass.c index 77d9b377851..dbe52d3caf1 100644 --- a/src/vnet/ip/reass/ip6_full_reass.c +++ b/src/vnet/ip/reass/ip6_full_reass.c @@ -28,8 +28,11 @@ #include <vnet/ip/ip6_inlines.h> #define MSEC_PER_SEC 1000 -#define IP6_FULL_REASS_TIMEOUT_DEFAULT_MS 100 -#define IP6_FULL_REASS_EXPIRE_WALK_INTERVAL_DEFAULT_MS 10000 // 10 seconds default +#define IP6_FULL_REASS_TIMEOUT_DEFAULT_MS 200 +/* As there are only 1024 reass context per thread, either the DDOS attacks + * or fractions of real timeouts, would consume these contexts quickly and + * running out context space and unable to perform reassembly */ +#define IP6_FULL_REASS_EXPIRE_WALK_INTERVAL_DEFAULT_MS 50 // 50 ms default #define IP6_FULL_REASS_MAX_REASSEMBLIES_DEFAULT 1024 #define IP6_FULL_REASS_MAX_REASSEMBLY_LENGTH_DEFAULT 3 #define IP6_FULL_REASS_HT_LOAD_FACTOR (0.75) @@ -135,6 +138,8 @@ typedef struct ip6_full_reass_t *pool; u32 reass_n; u32 id_counter; + // for pacing the main thread timeouts + u32 last_id; clib_spinlock_t lock; } ip6_full_reass_per_thread_t; @@ -1638,13 +1643,34 @@ ip6_full_reass_walk_expired (vlib_main_t *vm, vlib_node_runtime_t *node, clib_spinlock_lock (&rt->lock); vec_reset_length (pool_indexes_to_free); - pool_foreach_index (index, rt->pool) { - reass = pool_elt_at_index (rt->pool, index); - if (now > reass->last_heard + rm->timeout) - { - vec_add1 (pool_indexes_to_free, index); - } - } + /* Pace the number of timeouts handled per thread,to avoid barrier + * sync issues in real world scenarios */ + + u32 beg = rt->last_id; + /* to ensure we walk at least once per sec per context */ + u32 end = beg + (IP6_FULL_REASS_MAX_REASSEMBLIES_DEFAULT * + IP6_FULL_REASS_EXPIRE_WALK_INTERVAL_DEFAULT_MS / + MSEC_PER_SEC + + 1); + if (end > vec_len (rt->pool)) + { + end = vec_len (rt->pool); + rt->last_id = 0; + } + else + { + rt->last_id = end; + } + + pool_foreach_stepping_index (index, beg, end, rt->pool) + { + reass = pool_elt_at_index (rt->pool, index); + if (now > reass->last_heard + rm->timeout) + { + vec_add1 (pool_indexes_to_free, index); + } + } + int *i; vec_foreach (i, pool_indexes_to_free) { |