Browse code

management: add timer to output BYTECOUNT

BYTECOUNT on management interface is used to display client stats,
for example by openvpn-gui. At the moment BYTECOUNT is sent if
there is a traffic. With DCO, userspace process doesn't see data
channel traffic, BYTECOUNT is not sent and therefore stats
are not updated.

Fix displaying DCO client stats by adding a timer, which is triggerd
every n seconds, where n is set by existing management command
bytecount <n>. Output stats, taking into account stats from DCO,
when timer is triggered.

While on it, simplify bytecount routines call chains - inlining
functions which are used only once.

DCO stats fetching is not yet implemented.

Stats for the server mode (BYTECOUNT_CLI) are unaffected
by this change - to output those in timer callback we would need to
enumerate all peers, and I am not sure we want to output stats
for all peers every <n> seconds.

Signed-off-by: Lev Stipakov <lev@openvpn.net>
Acked-by: Arne Schwabe <arne@rfc2549.org>
Message-Id: <20221214224220.307-1-lstipakov@gmail.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg25707.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
(cherry picked from commit a9991b3eb6644785421398bff8cb3a728d131713)

Lev Stipakov authored on 2022/12/15 07:42:20
Showing 3 changed files
... ...
@@ -771,6 +771,13 @@ process_coarse_timers(struct context *c)
771 771
 
772 772
     /* Should we ping the remote? */
773 773
     check_ping_send(c);
774
+
775
+#ifdef ENABLE_MANAGEMENT
776
+    if (management)
777
+    {
778
+        management_check_bytecount(c, management, &c->c2.timeval);
779
+    }
780
+#endif /* ENABLE_MANAGEMENT */
774 781
 }
775 782
 
776 783
 static void
... ...
@@ -953,7 +960,7 @@ process_incoming_link_part1(struct context *c, struct link_socket_info *lsi, boo
953 953
 #ifdef ENABLE_MANAGEMENT
954 954
         if (management)
955 955
         {
956
-            management_bytes_in(management, c->c2.buf.len);
956
+            management_bytes_client(management, c->c2.buf.len, 0);
957 957
             management_bytes_server(management, &c->c2.link_read_bytes, &c->c2.link_write_bytes, &c->c2.mda_context);
958 958
         }
959 959
 #endif
... ...
@@ -1793,7 +1800,7 @@ process_outgoing_link(struct context *c)
1793 1793
 #ifdef ENABLE_MANAGEMENT
1794 1794
                 if (management)
1795 1795
                 {
1796
-                    management_bytes_out(management, size);
1796
+                    management_bytes_client(management, 0, size);
1797 1797
                     management_bytes_server(management, &c->c2.link_read_bytes, &c->c2.link_write_bytes, &c->c2.mda_context);
1798 1798
                 }
1799 1799
 #endif
... ...
@@ -42,6 +42,7 @@
42 42
 #include "ssl.h"
43 43
 #include "common.h"
44 44
 #include "manage.h"
45
+#include "openvpn.h"
45 46
 
46 47
 #include "memdbg.h"
47 48
 
... ...
@@ -460,32 +461,37 @@ man_status(struct management *man, const int version, struct status_output *so)
460 460
 static void
461 461
 man_bytecount(struct management *man, const int update_seconds)
462 462
 {
463
-    if (update_seconds >= 0)
463
+    if (update_seconds > 0)
464 464
     {
465 465
         man->connection.bytecount_update_seconds = update_seconds;
466
+        event_timeout_init(&man->connection.bytecount_update_interval,
467
+                           man->connection.bytecount_update_seconds,
468
+                           now);
466 469
     }
467 470
     else
468 471
     {
469 472
         man->connection.bytecount_update_seconds = 0;
473
+        event_timeout_clear(&man->connection.bytecount_update_interval);
470 474
     }
471 475
     msg(M_CLIENT, "SUCCESS: bytecount interval changed");
472 476
 }
473 477
 
474
-void
475
-man_bytecount_output_client(struct management *man)
478
+static void
479
+man_bytecount_output_client(struct management *man,
480
+                            counter_type dco_read_bytes,
481
+                            counter_type dco_write_bytes)
476 482
 {
477 483
     char in[32];
478 484
     char out[32];
485
+
479 486
     /* do in a roundabout way to work around possible mingw or mingw-glibc bug */
480
-    openvpn_snprintf(in, sizeof(in), counter_format, man->persist.bytes_in);
481
-    openvpn_snprintf(out, sizeof(out), counter_format, man->persist.bytes_out);
487
+    openvpn_snprintf(in, sizeof(in), counter_format, man->persist.bytes_in + dco_read_bytes);
488
+    openvpn_snprintf(out, sizeof(out), counter_format, man->persist.bytes_out + dco_write_bytes);
482 489
     msg(M_CLIENT, ">BYTECOUNT:%s,%s", in, out);
483
-    man->connection.bytecount_last_update = now;
484 490
 }
485 491
 
486 492
 void
487
-man_bytecount_output_server(struct management *man,
488
-                            const counter_type *bytes_in_total,
493
+man_bytecount_output_server(const counter_type *bytes_in_total,
489 494
                             const counter_type *bytes_out_total,
490 495
                             struct man_def_auth_context *mdac)
491 496
 {
... ...
@@ -2542,6 +2548,8 @@ man_connection_close(struct management *man)
2542 2542
     command_line_free(mc->in);
2543 2543
     buffer_list_free(mc->out);
2544 2544
 
2545
+    event_timeout_clear(&mc->bytecount_update_interval);
2546
+
2545 2547
     in_extra_reset(&man->connection, IER_RESET);
2546 2548
     buffer_list_free(mc->ext_key_input);
2547 2549
     man_connection_clear(mc);
... ...
@@ -4037,6 +4045,24 @@ management_sleep(const int n)
4037 4037
     }
4038 4038
 }
4039 4039
 
4040
+void
4041
+management_check_bytecount(struct context *c, struct management *man, struct timeval *timeval)
4042
+{
4043
+    if (event_timeout_trigger(&man->connection.bytecount_update_interval,
4044
+                              timeval, ETT_DEFAULT))
4045
+    {
4046
+        /* TODO: get stats from DCO */
4047
+
4048
+        counter_type dco_read_bytes = 0;
4049
+        counter_type dco_write_bytes = 0;
4050
+
4051
+        if (!(man->persist.callback.flags & MCF_SERVER))
4052
+        {
4053
+            man_bytecount_output_client(man, dco_read_bytes, dco_write_bytes);
4054
+        }
4055
+    }
4056
+}
4057
+
4040 4058
 #else  /* ifdef ENABLE_MANAGEMENT */
4041 4059
 
4042 4060
 void
... ...
@@ -295,7 +295,7 @@ struct man_connection {
295 295
     bool log_realtime;
296 296
     bool echo_realtime;
297 297
     int bytecount_update_seconds;
298
-    time_t bytecount_last_update;
298
+    struct event_timeout bytecount_update_interval;
299 299
 
300 300
     const char *up_query_type;
301 301
     int up_query_mode;
... ...
@@ -512,55 +512,27 @@ void management_auth_token(struct management *man, const char *token);
512 512
  * These functions drive the bytecount in/out counters.
513 513
  */
514 514
 
515
-void man_bytecount_output_client(struct management *man);
516
-
517
-static inline void
518
-man_bytecount_possible_output_client(struct management *man)
519
-{
520
-    if (man->connection.bytecount_update_seconds > 0
521
-        && now >= man->connection.bytecount_last_update
522
-        + man->connection.bytecount_update_seconds)
523
-    {
524
-        man_bytecount_output_client(man);
525
-    }
526
-}
527
-
528
-static inline void
529
-management_bytes_out_client(struct management *man, const int size)
530
-{
531
-    man->persist.bytes_out += size;
532
-    man_bytecount_possible_output_client(man);
533
-}
534
-
535
-static inline void
536
-management_bytes_in_client(struct management *man, const int size)
537
-{
538
-    man->persist.bytes_in += size;
539
-    man_bytecount_possible_output_client(man);
540
-}
541
-
542
-static inline void
543
-management_bytes_out(struct management *man, const int size)
544
-{
545
-    if (!(man->persist.callback.flags & MCF_SERVER))
546
-    {
547
-        management_bytes_out_client(man, size);
548
-    }
549
-}
515
+void
516
+management_check_bytecount(struct context *c,
517
+                           struct management *man,
518
+                           struct timeval *timeval);
550 519
 
551 520
 static inline void
552
-management_bytes_in(struct management *man, const int size)
521
+management_bytes_client(struct management *man,
522
+                        const int size_in,
523
+                        const int size_out)
553 524
 {
554 525
     if (!(man->persist.callback.flags & MCF_SERVER))
555 526
     {
556
-        management_bytes_in_client(man, size);
527
+        man->persist.bytes_in += size_in;
528
+        man->persist.bytes_out += size_out;
557 529
     }
558 530
 }
559 531
 
560
-void man_bytecount_output_server(struct management *man,
561
-                                 const counter_type *bytes_in_total,
562
-                                 const counter_type *bytes_out_total,
563
-                                 struct man_def_auth_context *mdac);
532
+void
533
+man_bytecount_output_server(const counter_type *bytes_in_total,
534
+                            const counter_type *bytes_out_total,
535
+                            struct man_def_auth_context *mdac);
564 536
 
565 537
 static inline void
566 538
 management_bytes_server(struct management *man,
... ...
@@ -570,9 +542,9 @@ management_bytes_server(struct management *man,
570 570
 {
571 571
     if (man->connection.bytecount_update_seconds > 0
572 572
         && now >= mdac->bytecount_last_update + man->connection.bytecount_update_seconds
573
-        && (mdac->flags & (DAF_CONNECTION_ESTABLISHED|DAF_CONNECTION_CLOSED)) == DAF_CONNECTION_ESTABLISHED)
573
+        && (mdac->flags & (DAF_CONNECTION_ESTABLISHED | DAF_CONNECTION_CLOSED)) == DAF_CONNECTION_ESTABLISHED)
574 574
     {
575
-        man_bytecount_output_server(man, bytes_in_total, bytes_out_total, mdac);
575
+        man_bytecount_output_server(bytes_in_total, bytes_out_total, mdac);
576 576
     }
577 577
 }
578 578