Browse code

Added "memstats" option to maintain real-time operating stats in a memory-mapped file.

Version 2.1.16

git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@7653 e7ae566f-a301-0410-adde-c780ea21d3b5

James Yonan authored on 2011/10/18 17:12:51
Showing 10 changed files
... ...
@@ -110,6 +110,7 @@ openvpn_SOURCES = \
110 110
 	misc.c misc.h \
111 111
 	mroute.c mroute.h \
112 112
 	mss.c mss.h \
113
+	mstats.c mstats.h \
113 114
 	mtcp.c mtcp.h \
114 115
 	mtu.c mtu.h \
115 116
 	mudp.c mudp.h \
... ...
@@ -35,6 +35,7 @@
35 35
 #include "status.h"
36 36
 #include "integer.h"
37 37
 #include "ps.h"
38
+#include "mstats.h"
38 39
 
39 40
 #ifdef USE_CRYPTO
40 41
 #ifdef USE_OPENSSL
... ...
@@ -679,6 +680,10 @@ openvpn_exit (const int status)
679 679
 	port_share_abort (port_share);
680 680
 #endif
681 681
 
682
+#ifdef ENABLE_MEMSTATS
683
+      mstats_close();
684
+#endif
685
+
682 686
 #ifdef ABORT_ON_ERROR
683 687
       if (status == OPENVPN_EXIT_STATUS_ERROR)
684 688
 	abort ();
... ...
@@ -39,6 +39,7 @@
39 39
 #include "forward-inline.h"
40 40
 #include "occ-inline.h"
41 41
 #include "ping-inline.h"
42
+#include "mstats.h"
42 43
 
43 44
 counter_type link_read_bytes_global;  /* GLOBAL */
44 45
 counter_type link_write_bytes_global; /* GLOBAL */
... ...
@@ -738,6 +739,10 @@ process_incoming_link (struct context *c)
738 738
     {
739 739
       c->c2.link_read_bytes += c->c2.buf.len;
740 740
       link_read_bytes_global += c->c2.buf.len;
741
+#ifdef ENABLE_MEMSTATS
742
+      if (mmap_stats)
743
+	mmap_stats->link_read_bytes = link_read_bytes_global;
744
+#endif
741 745
       c->c2.original_recv_size = c->c2.buf.len;
742 746
 #ifdef ENABLE_MANAGEMENT
743 747
       if (management)
... ...
@@ -1137,6 +1142,10 @@ process_outgoing_link (struct context *c)
1137 1137
 	      c->c2.max_send_size_local = max_int (size, c->c2.max_send_size_local);
1138 1138
 	      c->c2.link_write_bytes += size;
1139 1139
 	      link_write_bytes_global += size;
1140
+#ifdef ENABLE_MEMSTATS
1141
+	      if (mmap_stats)
1142
+		mmap_stats->link_write_bytes = link_write_bytes_global;
1143
+#endif
1140 1144
 #ifdef ENABLE_MANAGEMENT
1141 1145
 	      if (management)
1142 1146
 		{
... ...
@@ -36,6 +36,7 @@
36 36
 #include "ps.h"
37 37
 #include "lladdr.h"
38 38
 #include "ping.h"
39
+#include "mstats.h"
39 40
 
40 41
 #include "memdbg.h"
41 42
 
... ...
@@ -815,6 +816,22 @@ init_static (void)
815 815
   }
816 816
 #endif
817 817
 
818
+#ifdef MSTATS_TEST
819
+  {
820
+    int i;
821
+    mstats_open("/dev/shm/mstats.dat");
822
+    for (i = 0; i < 30; ++i)
823
+      {
824
+	mmap_stats->n_clients += 1;
825
+	mmap_stats->link_write_bytes += 8;
826
+	mmap_stats->link_read_bytes += 16;
827
+	sleep(1);
828
+      }
829
+    mstats_close();
830
+    return false;
831
+  }
832
+#endif
833
+
818 834
   return true;
819 835
 }
820 836
 
... ...
@@ -1014,6 +1031,11 @@ do_uid_gid_chroot (struct context *c, bool no_delay)
1014 1014
 	  msg (M_INFO, "NOTE: UID/GID downgrade %s", why_not);
1015 1015
 	}
1016 1016
 
1017
+#ifdef ENABLE_MEMSTATS
1018
+      if (c->options.memstats_fn)
1019
+	mstats_open(c->options.memstats_fn);
1020
+#endif
1021
+
1017 1022
 #ifdef HAVE_SETCON
1018 1023
       /* Apply a SELinux context in order to restrict what OpenVPN can do
1019 1024
        * to _only_ what it is supposed to do after initialization is complete
1020 1025
new file mode 100644
... ...
@@ -0,0 +1,116 @@
0
+/*
1
+ *  OpenVPN -- An application to securely tunnel IP networks
2
+ *             over a single TCP/UDP port, with support for SSL/TLS-based
3
+ *             session authentication and key exchange,
4
+ *             packet encryption, packet authentication, and
5
+ *             packet compression.
6
+ *
7
+ *  Copyright (C) 2002-2011 OpenVPN Technologies, Inc. <sales@openvpn.net>
8
+ *
9
+ *  This program is free software; you can redistribute it and/or modify
10
+ *  it under the terms of the GNU General Public License version 2
11
+ *  as published by the Free Software Foundation.
12
+ *
13
+ *  This program is distributed in the hope that it will be useful,
14
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ *  GNU General Public License for more details.
17
+ *
18
+ *  You should have received a copy of the GNU General Public License
19
+ *  along with this program (see the file COPYING included with this
20
+ *  distribution); if not, write to the Free Software Foundation, Inc.,
21
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
+ */
23
+
24
+/*
25
+ * Maintain usage stats in a memory-mapped file
26
+ */
27
+
28
+#include "syshead.h"
29
+
30
+#if defined(ENABLE_MEMSTATS)
31
+
32
+#include <sys/mman.h>
33
+
34
+#include "error.h"
35
+#include "misc.h"
36
+#include "mstats.h"
37
+
38
+#include "memdbg.h"
39
+
40
+volatile struct mmap_stats *mmap_stats = NULL; /* GLOBAL */
41
+static char mmap_fn[128];
42
+
43
+void
44
+mstats_open(const char *fn)
45
+{
46
+  void *data;
47
+  ssize_t stat;
48
+  int fd;
49
+  struct mmap_stats ms;
50
+
51
+  if (mmap_stats) /* already called? */
52
+    return;
53
+
54
+  /* verify that filename is not too long */
55
+  if (strlen(fn) >= sizeof(mmap_fn))
56
+    msg (M_FATAL, "mstats_open: filename too long");
57
+
58
+  /* create file that will be memory mapped */
59
+  fd = open (fn, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
60
+  if (fd < 0)
61
+    {
62
+      msg (M_ERR, "mstats_open: cannot open: %s", fn);
63
+      return;
64
+    }
65
+
66
+  /* set the file to the correct size to contain a
67
+     struct mmap_stats, and zero it */
68
+  CLEAR(ms);
69
+  ms.state = MSTATS_ACTIVE;
70
+  stat = write(fd, &ms, sizeof(ms));
71
+  if (stat != sizeof(ms))
72
+    {
73
+      msg (M_ERR, "mstats_open: write error: %s", fn);
74
+      close(fd);
75
+      return;
76
+    }
77
+
78
+  /* mmap the file */
79
+  data = mmap(NULL, sizeof(struct mmap_stats), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
80
+  if (data == MAP_FAILED)
81
+    {
82
+      msg (M_ERR, "mstats_open: write error: %s", fn);
83
+      close(fd);
84
+      return;
85
+    }
86
+
87
+  /* close the fd (mmap now controls the file) */
88
+  if (close(fd))
89
+    {
90
+      msg (M_ERR, "mstats_open: close error: %s", fn);
91
+    }
92
+
93
+  /* save filename so we can delete it later */
94
+  strcpy(mmap_fn, fn);
95
+
96
+  /* save a global pointer to memory-mapped region */
97
+  mmap_stats = (struct mmap_stats *)data;
98
+
99
+  msg (M_INFO, "memstats data will be written to %s", fn);
100
+}
101
+
102
+void
103
+mstats_close(void)
104
+{
105
+  if (mmap_stats)
106
+    {
107
+      mmap_stats->state = MSTATS_EXPIRED;
108
+      if (munmap((void *)mmap_stats, sizeof(struct mmap_stats)))
109
+	msg (M_WARN | M_ERRNO, "mstats_close: munmap error");
110
+      delete_file(mmap_fn);
111
+      mmap_stats = NULL;
112
+    }
113
+}
114
+
115
+#endif
0 116
new file mode 100644
... ...
@@ -0,0 +1,51 @@
0
+/*
1
+ *  OpenVPN -- An application to securely tunnel IP networks
2
+ *             over a single TCP/UDP port, with support for SSL/TLS-based
3
+ *             session authentication and key exchange,
4
+ *             packet encryption, packet authentication, and
5
+ *             packet compression.
6
+ *
7
+ *  Copyright (C) 2002-2011 OpenVPN Technologies, Inc. <sales@openvpn.net>
8
+ *
9
+ *  This program is free software; you can redistribute it and/or modify
10
+ *  it under the terms of the GNU General Public License version 2
11
+ *  as published by the Free Software Foundation.
12
+ *
13
+ *  This program is distributed in the hope that it will be useful,
14
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ *  GNU General Public License for more details.
17
+ *
18
+ *  You should have received a copy of the GNU General Public License
19
+ *  along with this program (see the file COPYING included with this
20
+ *  distribution); if not, write to the Free Software Foundation, Inc.,
21
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
+ */
23
+
24
+/*
25
+ * Maintain usage stats in a memory-mapped file
26
+ */
27
+
28
+#if !defined(OPENVPN_MEMSTATS_H) && defined(ENABLE_MEMSTATS)
29
+#define OPENVPN_MEMSTATS_H
30
+
31
+#include "basic.h"
32
+
33
+/* this struct is mapped to the file */
34
+struct mmap_stats {
35
+  counter_type link_read_bytes;   /* counter_type can be assumed to be a uint64_t */
36
+  counter_type link_write_bytes;
37
+  int n_clients;
38
+
39
+# define MSTATS_UNDEF   0
40
+# define MSTATS_ACTIVE  1
41
+# define MSTATS_EXPIRED 2
42
+  int state;
43
+};
44
+
45
+extern volatile struct mmap_stats *mmap_stats; /* GLOBAL */
46
+
47
+void mstats_open(const char *fn);
48
+void mstats_close(void);
49
+
50
+#endif
... ...
@@ -31,6 +31,7 @@
31 31
 #include "misc.h"
32 32
 #include "otime.h"
33 33
 #include "gremlin.h"
34
+#include "mstats.h"
34 35
 
35 36
 #include "memdbg.h"
36 37
 
... ...
@@ -60,6 +61,15 @@ set_cc_config (struct multi_instance *mi, struct buffer_list *cc_config)
60 60
 }
61 61
 #endif
62 62
 
63
+static inline void
64
+update_mstat_n_clients(const int n_clients)
65
+{
66
+#ifdef ENABLE_MEMSTATS
67
+  if (mmap_stats)
68
+    mmap_stats->n_clients = n_clients;
69
+#endif
70
+}
71
+
63 72
 static bool
64 73
 learn_address_script (const struct multi_context *m,
65 74
 		      const struct multi_instance *mi,
... ...
@@ -510,6 +520,7 @@ multi_close_instance (struct multi_context *m,
510 510
 
511 511
   /* adjust current client connection count */
512 512
   m->n_clients += mi->n_clients_delta;
513
+  update_mstat_n_clients(m->n_clients);
513 514
   mi->n_clients_delta = 0;
514 515
 
515 516
   /* prevent dangling pointers */
... ...
@@ -1842,6 +1853,7 @@ multi_connection_established (struct multi_context *m, struct multi_instance *mi
1842 1842
 
1843 1843
       /* increment number of current authenticated clients */
1844 1844
       ++m->n_clients;
1845
+      update_mstat_n_clients(m->n_clients);
1845 1846
       --mi->n_clients_delta;
1846 1847
 
1847 1848
 #ifdef MANAGEMENT_DEF_AUTH
... ...
@@ -299,6 +299,9 @@ static const char usage_message[] =
299 299
   "                  can be matched in policy routing and packetfilter rules.\n"
300 300
 #endif
301 301
   "--txqueuelen n  : Set the tun/tap TX queue length to n (Linux only).\n"
302
+#ifdef ENABLE_MEMSTATS
303
+  "--memstats file : Write live usage stats to memory mapped binary file.\n"
304
+#endif
302 305
   "--mlock         : Disable Paging -- ensures key material and tunnel\n"
303 306
   "                  data will never be written to disk.\n"
304 307
   "--up cmd        : Shell cmd to execute after successful tun device open.\n"
... ...
@@ -4602,6 +4605,13 @@ add_option (struct options *options,
4602 4602
       options->log = true;
4603 4603
       redirect_stdout_stderr (p[1], true);
4604 4604
     }
4605
+#ifdef ENABLE_MEMSTATS
4606
+  else if (streq (p[0], "memstats") && p[1])
4607
+    {
4608
+      VERIFY_PERMISSION (OPT_P_GENERAL);
4609
+      options->memstats_fn = p[1];
4610
+    }
4611
+#endif
4605 4612
   else if (streq (p[0], "mlock"))
4606 4613
     {
4607 4614
       VERIFY_PERMISSION (OPT_P_GENERAL);
... ...
@@ -260,6 +260,10 @@ struct options
260 260
 
261 261
   int fragment;                 /* internal fragmentation size */
262 262
 
263
+#ifdef ENABLE_MEMSTATS
264
+  char *memstats_fn;
265
+#endif
266
+
263 267
   bool mlock;
264 268
 
265 269
   int keepalive_ping;           /* a proxy for ping/ping-restart */
... ...
@@ -737,4 +737,11 @@ socket_defined (const socket_descriptor_t sd)
737 737
 #define LZO_VERSION_NUM "STUB"
738 738
 #endif
739 739
 
740
+/*
741
+ * Enable --memstats option
742
+ */
743
+#ifdef TARGET_LINUX
744
+#define ENABLE_MEMSTATS
745
+#endif
746
+
740 747
 #endif