wireguard: add atomic mutex 61/37361/5
authorGabriel Oginski <gabrielx.oginski@intel.com>
Thu, 6 Oct 2022 06:58:45 +0000 (06:58 +0000)
committerGabriel Oginski <gabrielx.oginski@intel.com>
Thu, 1 Dec 2022 06:47:07 +0000 (06:47 +0000)
The initiate handshake process can be called a numbers times for each
peers, then the main VPP thread called by Wireguard starting to
allocate memory. This behaviour can lead to out of memory when VPP has
a lot of Wireguard tunnels concurrently.

This fix add mutex to send only once handshake initiate at time for
each peers.

Type: fix
Signed-off-by: Gabriel Oginski <gabrielx.oginski@intel.com>
Change-Id: I13b4b2d47021753926d42a38ccadb36a411c5b79

src/plugins/wireguard/wireguard_peer.c
src/plugins/wireguard/wireguard_peer.h
src/plugins/wireguard/wireguard_send.c

index ef791c6..a8f1ab9 100644 (file)
@@ -83,6 +83,7 @@ wg_peer_clear (vlib_main_t * vm, wg_peer_t * peer)
   peer->new_handshake_interval_tick = 0;
   peer->rehandshake_interval_tick = 0;
   peer->timer_need_another_keepalive = false;
+  peer->handshake_is_sent = false;
   vec_free (peer->rewrite);
   vec_free (peer->allowed_ips);
   vec_free (peer->adj_indices);
index 85df072..613c264 100644 (file)
@@ -115,6 +115,9 @@ typedef struct wg_peer
   u32 rehandshake_interval_tick;
 
   bool timer_need_another_keepalive;
+
+  /* Handshake is sent to main thread? */
+  bool handshake_is_sent;
 } wg_peer_t;
 
 typedef struct wg_peer_table_bind_ctx_t_
index 72fa110..41b2e77 100644 (file)
@@ -214,8 +214,11 @@ wg_send_handshake_thread_fn (void *arg)
 
   wg_main_t *wmp = &wg_main;
   wg_peer_t *peer = wg_peer_get (a->peer_idx);
+  bool handshake;
 
   wg_send_handshake (wmp->vlib_main, peer, a->is_retry);
+  handshake = false;
+  __atomic_store_n (&peer->handshake_is_sent, handshake, __ATOMIC_RELEASE);
   return 0;
 }
 
@@ -227,8 +230,18 @@ wg_send_handshake_from_mt (u32 peer_idx, bool is_retry)
     .is_retry = is_retry,
   };
 
-  vl_api_rpc_call_main_thread (wg_send_handshake_thread_fn,
-                              (u8 *) & a, sizeof (a));
+  wg_peer_t *peer = wg_peer_get (peer_idx);
+
+  bool handshake =
+    __atomic_load_n (&peer->handshake_is_sent, __ATOMIC_ACQUIRE);
+
+  if (handshake == false)
+    {
+      handshake = true;
+      __atomic_store_n (&peer->handshake_is_sent, handshake, __ATOMIC_RELEASE);
+      vl_api_rpc_call_main_thread (wg_send_handshake_thread_fn, (u8 *) &a,
+                                  sizeof (a));
+    }
 }
 
 bool