ip: reassembly - pacing reassembly timeouts for v6 42/36242/1
authorVijayabhaskar Katamreddy <vkatamre@cisco.com>
Thu, 26 May 2022 15:03:47 +0000 (15:03 +0000)
committerVijayabhaskar Katamreddy <vkatamre@cisco.com>
Thu, 26 May 2022 15:03:47 +0000 (15:03 +0000)
Type: fix

Pace the main thread activity for reassembly timeouts, to avoid barrier syncs

Signed-off-by: Vijayabhaskar Katamreddy <vkatamre@cisco.com>
Change-Id: Iebe9a38d2a7a6471afa6621f12bb545668dc8384

src/vnet/ip/reass/ip6_full_reass.c

index 77d9b37..dbe52d3 100644 (file)
 #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)
           {