]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
management: ensure consistent BYTECOUNT timing on server
authorRalf Lici <ralf@mandelbit.com>
Tue, 21 Oct 2025 07:08:20 +0000 (09:08 +0200)
committerGert Doering <gert@greenie.muc.de>
Tue, 28 Oct 2025 18:45:30 +0000 (19:45 +0100)
The BYTECOUNT notification is expected to be emitted every N seconds
when a management client issues the 'bytecount N' command. However, the
server currently relies on timeouts from unrelated periodic operations,
resulting in irregular notification timing.

This issue is especially noticeable with low bytecount intervals and DCO
enabled, as openvpn handles less traffic in userspace, causing the main
loop to run less frequently.

To address this, refactor the timeout logic and pass the timeval
reference to management_check_bytecount_server so that the timeout is
correctly set and notifications adhere to the specified interval.

Change-Id: Ifb1c49fce75e671f699f5db5f6da7246f6e0b519
Signed-off-by: Ralf Lici <ralf@mandelbit.com>
Acked-by: Lev Stipakov <lstipakov@gmail.com>
Message-Id: <20251021070825.20773-1-gert@greenie.muc.de>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg33812.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
src/openvpn/manage.c
src/openvpn/manage.h
src/openvpn/multi.c
src/openvpn/multi.h

index 1cb5c6388aa91c4cdbc92d894583d0ce55e867e0..685b137cfba103b8facc56fbe90ff4d43a42696c 100644 (file)
@@ -4184,16 +4184,14 @@ management_check_bytecount_client(struct context *c, struct management *man, str
 }
 
 void
-management_check_bytecount_server(struct multi_context *multi)
+management_check_bytecount_server(struct multi_context *multi, struct timeval *timeval)
 {
     if (!(management->persist.callback.flags & MCF_SERVER))
     {
         return;
     }
 
-    struct timeval null;
-    CLEAR(null);
-    if (event_timeout_trigger(&management->connection.bytecount_update_interval, &null, ETT_DEFAULT))
+    if (event_timeout_trigger(&management->connection.bytecount_update_interval, timeval, ETT_DEFAULT))
     {
         /* fetch counters from dco */
         if (dco_enabled(&multi->top.options))
index a31eb068134d9a9caaede49febf7dd72fefabff6..fe460bfbb9060f936374fdb34cf244d63f1fe35d 100644 (file)
@@ -493,7 +493,7 @@ void management_auth_token(struct management *man, const char *token);
 
 void management_check_bytecount_client(struct context *c, struct management *man, struct timeval *timeval);
 
-void management_check_bytecount_server(struct multi_context *multi);
+void management_check_bytecount_server(struct multi_context *multi, struct timeval *timeval);
 
 void man_persist_client_stats(struct management *man, struct context *c);
 
index f60944d208c10216ca179e0e2fd087095439407d..11e4d8c707b32f77bb46fd80a1808fd953c0a26a 100644 (file)
@@ -3797,13 +3797,6 @@ multi_process_per_second_timers_dowork(struct multi_context *m)
     {
         check_stale_routes(m);
     }
-
-#ifdef ENABLE_MANAGEMENT
-    if (management)
-    {
-        management_check_bytecount_server(m);
-    }
-#endif /* ENABLE_MANAGEMENT */
 }
 
 static void
@@ -4154,6 +4147,29 @@ multi_assign_peer_id(struct multi_context *m, struct multi_instance *mi)
     ASSERT(mi->context.c2.tls_multi->peer_id < m->max_clients);
 }
 
+/**
+ * @brief Determines the earliest wakeup interval based on periodic operations.
+ *
+ * Updates the \c timeval to reflect the next scheduled wakeup time.
+ * Also sets \c multi->earliest_wakeup to the instance with the earliest wakeup.
+ *
+ * @param multi     Pointer to the multi context
+ * @param timeval   Pointer to the timeval structure to be updated with the
+ *                  next wakeup time
+ */
+static void
+multi_get_timeout(struct multi_context *multi, struct timeval *timeval)
+{
+    multi_get_timeout_instance(multi, timeval);
+
+#ifdef ENABLE_MANAGEMENT
+    if (management)
+    {
+        management_check_bytecount_server(multi, timeval);
+    }
+#endif /* ENABLE_MANAGEMENT */
+}
+
 /**************************************************************************/
 /**
  * Main event loop for OpenVPN in point-to-multipoint server mode.
index 594ea3aa2dff8e133875db7580ea7a90b7312296..50f8d1049030567f8da66769826d4665ab3b2f9a 100644 (file)
@@ -581,15 +581,16 @@ multi_process_per_second_timers(struct multi_context *m)
 }
 
 /*
- * Compute earliest timeout expiry from the set of
- * all instances.  Output:
+ * Updates \c dest with the earliest timeout as a delta relative to the current
+ * time and sets \c m->earliest_wakeup to the \c multi_instance with the
+ * soonest scheduled wakeup.
  *
- * m->earliest_wakeup : instance needing the earliest service.
- * dest               : earliest timeout as a delta in relation
- *                      to current time.
+ * @param m     Pointer to the multi context
+ * @param dest  Pointer to a timeval struct that will hold the earliest timeout
+ *              delta.
  */
 static inline void
-multi_get_timeout(struct multi_context *m, struct timeval *dest)
+multi_get_timeout_instance(struct multi_context *m, struct timeval *dest)
 {
     struct timeval tv, current;