wireguard: add dos mitigation support
[vpp.git] / src / plugins / wireguard / wireguard_if.h
index 9e6b619..2a6ab8e 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2020 Cisco and/or its affiliates.
  * Copyright (c) 2020 Doc.ai and/or its affiliates.
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,17 +26,20 @@ typedef struct wg_if_t_
   u32 sw_if_index;
 
   // Interface params
-  noise_local_t local;
+  /* noise_local_pool elt index */
+  u32 local_idx;
   cookie_checker_t cookie_checker;
   u16 port;
 
-  wg_index_table_t index_table;
-
   /* Source IP address for originated packets */
   ip_address_t src_ip;
 
   /* hash table of peers on this link */
   uword *peers;
+
+  /* Under load params */
+  f64 handshake_counting_end;
+  u32 handshake_num;
 } wg_if_t;
 
 
@@ -50,9 +54,8 @@ u8 *format_wg_if (u8 * s, va_list * va);
 typedef walk_rc_t (*wg_if_walk_cb_t) (index_t wgi, void *data);
 void wg_if_walk (wg_if_walk_cb_t fn, void *data);
 
-typedef walk_rc_t (*wg_if_peer_walk_cb_t) (wg_if_t * wgi, index_t peeri,
-                                          void *data);
-void wg_if_peer_walk (wg_if_t * wgi, wg_if_peer_walk_cb_t fn, void *data);
+typedef walk_rc_t (*wg_if_peer_walk_cb_t) (index_t peeri, void *data);
+index_t wg_if_peer_walk (wg_if_t * wgi, wg_if_peer_walk_cb_t fn, void *data);
 
 void wg_if_peer_add (wg_if_t * wgi, index_t peeri);
 void wg_if_peer_remove (wg_if_t * wgi, index_t peeri);
@@ -70,18 +73,56 @@ wg_if_get (index_t wgii)
   return (pool_elt_at_index (wg_if_pool, wgii));
 }
 
-extern index_t *wg_if_index_by_port;
+extern index_t **wg_if_indexes_by_port;
 
-static_always_inline wg_if_t *
-wg_if_get_by_port (u16 port)
+static_always_inline index_t *
+wg_if_indexes_get_by_port (u16 port)
 {
-  if (vec_len (wg_if_index_by_port) < port)
+  if (vec_len (wg_if_indexes_by_port) == 0)
     return (NULL);
-  if (INDEX_INVALID == wg_if_index_by_port[port])
+  if (vec_len (wg_if_indexes_by_port[port]) == 0)
     return (NULL);
-  return (wg_if_get (wg_if_index_by_port[port]));
+  return (wg_if_indexes_by_port[port]);
 }
 
+#define HANDSHAKE_COUNTING_INTERVAL            0.5
+#define UNDER_LOAD_INTERVAL                    1.0
+#define HANDSHAKE_NUM_PER_PEER_UNTIL_UNDER_LOAD 40
+
+static_always_inline bool
+wg_if_is_under_load (vlib_main_t *vm, wg_if_t *wgi)
+{
+  static f64 wg_under_load_end;
+  f64 now = vlib_time_now (vm);
+  u32 num_until_under_load =
+    hash_elts (wgi->peers) * HANDSHAKE_NUM_PER_PEER_UNTIL_UNDER_LOAD;
+
+  if (wgi->handshake_counting_end < now)
+    {
+      wgi->handshake_counting_end = now + HANDSHAKE_COUNTING_INTERVAL;
+      wgi->handshake_num = 0;
+    }
+  wgi->handshake_num++;
+
+  if (wgi->handshake_num >= num_until_under_load)
+    {
+      wg_under_load_end = now + UNDER_LOAD_INTERVAL;
+      return true;
+    }
+
+  if (wg_under_load_end > now)
+    {
+      return true;
+    }
+
+  return false;
+}
+
+static_always_inline void
+wg_if_dec_handshake_num (wg_if_t *wgi)
+{
+  wgi->handshake_num--;
+}
 
 #endif