summaryrefslogtreecommitdiffstats
path: root/src/plugins/wireguard/wireguard_api.c
diff options
context:
space:
mode:
authorAlexander Chernavin <achernavin@netgate.com>2023-03-16 09:48:45 +0000
committerFan Zhang <fanzhang.oss@gmail.com>2023-03-20 16:41:14 +0000
commitd76c029a85f0b5a4bb72c84fb4cd012cbd5465cd (patch)
tree6570d9a299f31487d179dc84406ca1c669c8bee7 /src/plugins/wireguard/wireguard_api.c
parent645a588ee3a136bd68b1e89414c6b0a192df3c31 (diff)
wireguard: fix sending peer events from worker threads
Type: fix API clients can register for peer events (e.g. to be notified when connection is established). In a multi-worker setup, peer events might be triggered from a worker thread. In order to send a peer event to the clients, an API message needs to be allocated and populated. API messages allocation is only allowed from the main thread. Currently, the code does not handle the case when a peer event is trying to be sent from a worker thread. In debug builds, when this happens, it causes SIGABRT in vl_msg_api_alloc_internal() because assertion "pool == 0 || vlib_get_thread_index () == 0" fails. In production builds, when this happens, it might cause unexplained behavior. There is a test that is supposed to catch this but all multi-worker Wireguard tests are currently disabled. This problem is likely to be one of the reasons they were disabled. With this fix, when a peer event is triggered from a worker thread, allocate and send corresponding API message from the main thread using RPC. Signed-off-by: Alexander Chernavin <achernavin@netgate.com> Change-Id: Ib3fe19f8070563b35732afd16c017411c089437e
Diffstat (limited to 'src/plugins/wireguard/wireguard_api.c')
-rw-r--r--src/plugins/wireguard/wireguard_api.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/src/plugins/wireguard/wireguard_api.c b/src/plugins/wireguard/wireguard_api.c
index c5334e0ecd4..e736efcd6c0 100644
--- a/src/plugins/wireguard/wireguard_api.c
+++ b/src/plugins/wireguard/wireguard_api.c
@@ -346,7 +346,7 @@ vl_api_want_wireguard_peer_events_t_handler (
REPLY_MACRO (VL_API_WANT_WIREGUARD_PEER_EVENTS_REPLY);
}
-void
+static void
wg_api_send_peer_event (vl_api_registration_t *rp, index_t peer_index,
wg_peer_flags flags)
{
@@ -360,10 +360,16 @@ wg_api_send_peer_event (vl_api_registration_t *rp, index_t peer_index,
vl_api_send_msg (rp, (u8 *) mp);
}
-void
-wg_api_peer_event (index_t peeri, wg_peer_flags flags)
+typedef struct
{
- wg_peer_t *peer = wg_peer_get (peeri);
+ index_t peeri;
+ wg_peer_flags flags;
+} wg_api_peer_event_args_t;
+
+static void
+wg_api_peer_event_cb (wg_api_peer_event_args_t *args)
+{
+ wg_peer_t *peer = wg_peer_get (args->peeri);
vpe_client_registration_t *api_client;
vl_api_registration_t *rp;
@@ -372,11 +378,23 @@ wg_api_peer_event (index_t peeri, wg_peer_flags flags)
rp = vl_api_client_index_to_registration (api_client->client_index);
if (rp)
{
- wg_api_send_peer_event (rp, peeri, flags);
+ wg_api_send_peer_event (rp, args->peeri, args->flags);
}
};
}
+void
+wg_api_peer_event (index_t peeri, wg_peer_flags flags)
+{
+ wg_api_peer_event_args_t args = {
+ .peeri = peeri,
+ .flags = flags,
+ };
+
+ vl_api_rpc_call_main_thread (wg_api_peer_event_cb, (u8 *) &args,
+ sizeof (args));
+}
+
static void
vl_api_wg_set_async_mode_t_handler (vl_api_wg_set_async_mode_t *mp)
{