summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/vnet/ip/reass/ip4_full_reass.c33
-rw-r--r--src/vppinfra/pool.h21
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 <stddef.h>
#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