Browse code

Introduce dco_get_peer_stats API and Windows implementation

dco_get_peer_stats fetches stats for a single peer. This is mostly
useful in client mode. So far only Windows implements that.

Signed-off-by: Lev Stipakov <lev@openvpn.net>
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <20221214211426.227-1-lstipakov@gmail.com>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg25703.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
(cherry picked from commit 74d5ece4a035fbbd962ba5ea73c19118b82f8f45)

Lev Stipakov authored on 2022/12/15 06:14:26
Showing 5 changed files
... ...
@@ -236,6 +236,13 @@ void dco_delete_iroutes(struct multi_context *m, struct multi_instance *mi);
236 236
 int dco_get_peer_stats_multi(dco_context_t *dco, struct multi_context *m);
237 237
 
238 238
 /**
239
+ * Update traffic statistics for single peer
240
+ *
241
+ * @param c   instance context of the peer
242
+ **/
243
+int dco_get_peer_stats(struct context *c);
244
+
245
+/**
239 246
  * Retrieve the list of ciphers supported by the current platform
240 247
  *
241 248
  * @return                   list of colon-separated ciphers
... ...
@@ -362,6 +369,12 @@ dco_get_peer_stats_multi(dco_context_t *dco, struct multi_context *m)
362 362
     return 0;
363 363
 }
364 364
 
365
+static inline int
366
+dco_get_peer_stats(struct context *c)
367
+{
368
+    return 0;
369
+}
370
+
365 371
 static inline const char *
366 372
 dco_get_supported_ciphers()
367 373
 {
... ...
@@ -743,6 +743,13 @@ dco_get_peer_stats_multi(dco_context_t *dco, struct multi_context *m)
743 743
     return 0;
744 744
 }
745 745
 
746
+int
747
+dco_get_peer_stats(struct context *c)
748
+{
749
+    /* Not implemented. */
750
+    return 0;
751
+}
752
+
746 753
 const char *
747 754
 dco_get_supported_ciphers()
748 755
 {
... ...
@@ -924,6 +924,13 @@ dco_get_peer_stats_multi(dco_context_t *dco, struct multi_context *m)
924 924
     return 0;
925 925
 }
926 926
 
927
+int
928
+dco_get_peer_stats(struct context *c)
929
+{
930
+    /* Not implemented. */
931
+    return 0;
932
+}
933
+
927 934
 bool
928 935
 dco_available(int msglevel)
929 936
 {
... ...
@@ -33,6 +33,7 @@
33 33
 #include "tun.h"
34 34
 #include "crypto.h"
35 35
 #include "ssl_common.h"
36
+#include "openvpn.h"
36 37
 
37 38
 #include <bcrypt.h>
38 39
 #include <winsock2.h>
... ...
@@ -406,6 +407,33 @@ dco_get_peer_stats_multi(dco_context_t *dco, struct multi_context *m)
406 406
     return 0;
407 407
 }
408 408
 
409
+int
410
+dco_get_peer_stats(struct context *c)
411
+{
412
+    struct tuntap *tt = c->c1.tuntap;
413
+
414
+    if (!tuntap_defined(tt))
415
+    {
416
+        return -1;
417
+    }
418
+
419
+    OVPN_STATS stats;
420
+    ZeroMemory(&stats, sizeof(OVPN_STATS));
421
+
422
+    DWORD bytes_returned = 0;
423
+    if (!DeviceIoControl(tt->hand, OVPN_IOCTL_GET_STATS, NULL, 0,
424
+                         &stats, sizeof(stats), &bytes_returned, NULL))
425
+    {
426
+        msg(M_WARN | M_ERRNO, "DeviceIoControl(OVPN_IOCTL_GET_STATS) failed");
427
+        return -1;
428
+    }
429
+
430
+    c->c2.dco_read_bytes = stats.TransportBytesReceived;
431
+    c->c2.dco_write_bytes = stats.TransportBytesSent;
432
+
433
+    return 0;
434
+}
435
+
409 436
 void
410 437
 dco_event_set(dco_context_t *dco, struct event_set *es, void *arg)
411 438
 {
... ...
@@ -43,6 +43,7 @@
43 43
 #include "common.h"
44 44
 #include "manage.h"
45 45
 #include "openvpn.h"
46
+#include "dco.h"
46 47
 
47 48
 #include "memdbg.h"
48 49
 
... ...
@@ -4051,11 +4052,15 @@ management_check_bytecount(struct context *c, struct management *man, struct tim
4051 4051
     if (event_timeout_trigger(&man->connection.bytecount_update_interval,
4052 4052
                               timeval, ETT_DEFAULT))
4053 4053
     {
4054
-        /* TODO: get stats from DCO */
4055
-
4056 4054
         counter_type dco_read_bytes = 0;
4057 4055
         counter_type dco_write_bytes = 0;
4058 4056
 
4057
+        if (dco_enabled(&c->options) && (dco_get_peer_stats(c) == 0))
4058
+        {
4059
+            dco_read_bytes = c->c2.dco_read_bytes;
4060
+            dco_write_bytes = c->c2.dco_write_bytes;
4061
+        }
4062
+
4059 4063
         if (!(man->persist.callback.flags & MCF_SERVER))
4060 4064
         {
4061 4065
             man_bytecount_output_client(man, dco_read_bytes, dco_write_bytes);