From 8b874fc6a8ca58d420edee870e9ba8ef6fe439ae Mon Sep 17 00:00:00 2001 From: Vijayabhaskar Katamreddy Date: Fri, 13 May 2022 13:07:19 +0000 Subject: [PATCH] ip: reassembly - pacing reassembly timeouts Type: fix Pace the main thread activity for reassembly timeouts, to avoid barrier syncs Signed-off-by: Vijayabhaskar Katamreddy Change-Id: If8c62a05c7d28bfa6ac530c2cd5124834b4e8a70 --- src/vnet/ip/reass/ip4_full_reass.c | 33 +++++++++++++++++++++++++++++---- src/vppinfra/pool.h | 21 ++++++++++++++++----- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/vnet/ip/reass/ip4_full_reass.c b/src/vnet/ip/reass/ip4_full_reass.c index b5ea0276c88..1ac22615a60 100644 --- a/src/vnet/ip/reass/ip4_full_reass.c +++ b/src/vnet/ip/reass/ip4_full_reass.c @@ -29,8 +29,12 @@ #include #define MSEC_PER_SEC 1000 -#define IP4_REASS_TIMEOUT_DEFAULT_MS 100 -#define IP4_REASS_EXPIRE_WALK_INTERVAL_DEFAULT_MS 10000 // 10 seconds default +#define IP4_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 IP4_REASS_EXPIRE_WALK_INTERVAL_DEFAULT_MS 50 // 50 ms default #define IP4_REASS_MAX_REASSEMBLIES_DEFAULT 1024 #define IP4_REASS_MAX_REASSEMBLY_LENGTH_DEFAULT 3 #define IP4_REASS_HT_LOAD_FACTOR (0.75) @@ -155,6 +159,8 @@ typedef struct ip4_full_reass_t *pool; u32 reass_n; u32 id_counter; + // for pacing the main thread timeouts + u32 last_id; clib_spinlock_t lock; } ip4_full_reass_per_thread_t; @@ -1699,14 +1705,33 @@ ip4_full_reass_walk_expired (vlib_main_t *vm, vlib_node_runtime_t *node, vec_reset_length (pool_indexes_to_free); - pool_foreach_index (index, rt->pool) + /* 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 + (IP4_REASS_MAX_REASSEMBLIES_DEFAULT * + IP4_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); } - } + })); if (vec_len (pool_indexes_to_free)) vlib_node_increment_counter (vm, node->node_index, diff --git a/src/vppinfra/pool.h b/src/vppinfra/pool.h index 2a356291051..dd581efeeab 100644 --- a/src/vppinfra/pool.h +++ b/src/vppinfra/pool.h @@ -555,11 +555,22 @@ do { \ _pool_var(rv); \ }) -#define pool_foreach_index(i,v) \ - if (v) \ - for (i = pool_get_first_index (v); \ - i < vec_len (v); \ - i = pool_get_next_index (v, i)) \ +#define pool_foreach_index(i, v) \ + if (v) \ + for (i = pool_get_first_index (v); i < vec_len (v); \ + i = pool_get_next_index (v, i)) + +/* Iterate pool by index from s to e */ +#define pool_foreach_stepping_index(i, s, e, v, body) \ + for ((i) = (s); (i) < (e); (i) = pool_get_next_index (v, i)) \ + { \ + if (!pool_is_free_index ((v), (i))) \ + do \ + { \ + body; \ + } \ + while (0); \ + } /** * @brief Remove all elements from a pool in a safe way -- 2.16.6