]> git.ipfire.org Git - thirdparty/openvpn.git/commitdiff
Added "memstats" option to maintain real-time operating stats
authorJames Yonan <james@openvpn.net>
Tue, 18 Oct 2011 08:12:51 +0000 (08:12 +0000)
committerDavid Sommerseth <davids@redhat.com>
Wed, 14 Dec 2011 16:03:24 +0000 (17:03 +0100)
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

Makefile.am
error.c
forward.c
init.c
mstats.c [new file with mode: 0644]
mstats.h [new file with mode: 0644]
multi.c
options.c
options.h
syshead.h

index 075270fc69367d4e3ffd05f982cae5a651a2acd6..a47c0c1f2e5f1839c9656e39d40ecd5114045d08 100644 (file)
@@ -110,6 +110,7 @@ openvpn_SOURCES = \
        misc.c misc.h \
        mroute.c mroute.h \
        mss.c mss.h \
+       mstats.c mstats.h \
        mtcp.c mtcp.h \
        mtu.c mtu.h \
        mudp.c mudp.h \
diff --git a/error.c b/error.c
index a0de53e804654bba4d24840a7582583505770962..06b383fed0622f0c8d15d3ba08a8346f53fd3d42 100644 (file)
--- a/error.c
+++ b/error.c
@@ -35,6 +35,7 @@
 #include "status.h"
 #include "integer.h"
 #include "ps.h"
+#include "mstats.h"
 
 #ifdef USE_CRYPTO
 #ifdef USE_OPENSSL
@@ -679,6 +680,10 @@ openvpn_exit (const int status)
        port_share_abort (port_share);
 #endif
 
+#ifdef ENABLE_MEMSTATS
+      mstats_close();
+#endif
+
 #ifdef ABORT_ON_ERROR
       if (status == OPENVPN_EXIT_STATUS_ERROR)
        abort ();
index 4592cfc43ca411c6e0a39127f8324ab5a49a8124..c66031f9e1139acedeb41a66c331bd0d04f47c93 100644 (file)
--- a/forward.c
+++ b/forward.c
@@ -39,6 +39,7 @@
 #include "forward-inline.h"
 #include "occ-inline.h"
 #include "ping-inline.h"
+#include "mstats.h"
 
 counter_type link_read_bytes_global;  /* GLOBAL */
 counter_type link_write_bytes_global; /* GLOBAL */
@@ -738,6 +739,10 @@ process_incoming_link (struct context *c)
     {
       c->c2.link_read_bytes += c->c2.buf.len;
       link_read_bytes_global += c->c2.buf.len;
+#ifdef ENABLE_MEMSTATS
+      if (mmap_stats)
+       mmap_stats->link_read_bytes = link_read_bytes_global;
+#endif
       c->c2.original_recv_size = c->c2.buf.len;
 #ifdef ENABLE_MANAGEMENT
       if (management)
@@ -1137,6 +1142,10 @@ process_outgoing_link (struct context *c)
              c->c2.max_send_size_local = max_int (size, c->c2.max_send_size_local);
              c->c2.link_write_bytes += size;
              link_write_bytes_global += size;
+#ifdef ENABLE_MEMSTATS
+             if (mmap_stats)
+               mmap_stats->link_write_bytes = link_write_bytes_global;
+#endif
 #ifdef ENABLE_MANAGEMENT
              if (management)
                {
diff --git a/init.c b/init.c
index 82c1000d5c1c0ba498811e1741c2d9449a308a19..a225c266d690a991f1441f78e751583c1c7f016d 100644 (file)
--- a/init.c
+++ b/init.c
@@ -36,6 +36,7 @@
 #include "ps.h"
 #include "lladdr.h"
 #include "ping.h"
+#include "mstats.h"
 
 #include "memdbg.h"
 
@@ -815,6 +816,22 @@ init_static (void)
   }
 #endif
 
+#ifdef MSTATS_TEST
+  {
+    int i;
+    mstats_open("/dev/shm/mstats.dat");
+    for (i = 0; i < 30; ++i)
+      {
+       mmap_stats->n_clients += 1;
+       mmap_stats->link_write_bytes += 8;
+       mmap_stats->link_read_bytes += 16;
+       sleep(1);
+      }
+    mstats_close();
+    return false;
+  }
+#endif
+
   return true;
 }
 
@@ -1014,6 +1031,11 @@ do_uid_gid_chroot (struct context *c, bool no_delay)
          msg (M_INFO, "NOTE: UID/GID downgrade %s", why_not);
        }
 
+#ifdef ENABLE_MEMSTATS
+      if (c->options.memstats_fn)
+       mstats_open(c->options.memstats_fn);
+#endif
+
 #ifdef HAVE_SETCON
       /* Apply a SELinux context in order to restrict what OpenVPN can do
        * to _only_ what it is supposed to do after initialization is complete
diff --git a/mstats.c b/mstats.c
new file mode 100644 (file)
index 0000000..2f29d94
--- /dev/null
+++ b/mstats.c
@@ -0,0 +1,116 @@
+/*
+ *  OpenVPN -- An application to securely tunnel IP networks
+ *             over a single TCP/UDP port, with support for SSL/TLS-based
+ *             session authentication and key exchange,
+ *             packet encryption, packet authentication, and
+ *             packet compression.
+ *
+ *  Copyright (C) 2002-2011 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program (see the file COPYING included with this
+ *  distribution); if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Maintain usage stats in a memory-mapped file
+ */
+
+#include "syshead.h"
+
+#if defined(ENABLE_MEMSTATS)
+
+#include <sys/mman.h>
+
+#include "error.h"
+#include "misc.h"
+#include "mstats.h"
+
+#include "memdbg.h"
+
+volatile struct mmap_stats *mmap_stats = NULL; /* GLOBAL */
+static char mmap_fn[128];
+
+void
+mstats_open(const char *fn)
+{
+  void *data;
+  ssize_t stat;
+  int fd;
+  struct mmap_stats ms;
+
+  if (mmap_stats) /* already called? */
+    return;
+
+  /* verify that filename is not too long */
+  if (strlen(fn) >= sizeof(mmap_fn))
+    msg (M_FATAL, "mstats_open: filename too long");
+
+  /* create file that will be memory mapped */
+  fd = open (fn, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+  if (fd < 0)
+    {
+      msg (M_ERR, "mstats_open: cannot open: %s", fn);
+      return;
+    }
+
+  /* set the file to the correct size to contain a
+     struct mmap_stats, and zero it */
+  CLEAR(ms);
+  ms.state = MSTATS_ACTIVE;
+  stat = write(fd, &ms, sizeof(ms));
+  if (stat != sizeof(ms))
+    {
+      msg (M_ERR, "mstats_open: write error: %s", fn);
+      close(fd);
+      return;
+    }
+
+  /* mmap the file */
+  data = mmap(NULL, sizeof(struct mmap_stats), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+  if (data == MAP_FAILED)
+    {
+      msg (M_ERR, "mstats_open: write error: %s", fn);
+      close(fd);
+      return;
+    }
+
+  /* close the fd (mmap now controls the file) */
+  if (close(fd))
+    {
+      msg (M_ERR, "mstats_open: close error: %s", fn);
+    }
+
+  /* save filename so we can delete it later */
+  strcpy(mmap_fn, fn);
+
+  /* save a global pointer to memory-mapped region */
+  mmap_stats = (struct mmap_stats *)data;
+
+  msg (M_INFO, "memstats data will be written to %s", fn);
+}
+
+void
+mstats_close(void)
+{
+  if (mmap_stats)
+    {
+      mmap_stats->state = MSTATS_EXPIRED;
+      if (munmap((void *)mmap_stats, sizeof(struct mmap_stats)))
+       msg (M_WARN | M_ERRNO, "mstats_close: munmap error");
+      delete_file(mmap_fn);
+      mmap_stats = NULL;
+    }
+}
+
+#endif
diff --git a/mstats.h b/mstats.h
new file mode 100644 (file)
index 0000000..dab05fe
--- /dev/null
+++ b/mstats.h
@@ -0,0 +1,51 @@
+/*
+ *  OpenVPN -- An application to securely tunnel IP networks
+ *             over a single TCP/UDP port, with support for SSL/TLS-based
+ *             session authentication and key exchange,
+ *             packet encryption, packet authentication, and
+ *             packet compression.
+ *
+ *  Copyright (C) 2002-2011 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program (see the file COPYING included with this
+ *  distribution); if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*
+ * Maintain usage stats in a memory-mapped file
+ */
+
+#if !defined(OPENVPN_MEMSTATS_H) && defined(ENABLE_MEMSTATS)
+#define OPENVPN_MEMSTATS_H
+
+#include "basic.h"
+
+/* this struct is mapped to the file */
+struct mmap_stats {
+  counter_type link_read_bytes;   /* counter_type can be assumed to be a uint64_t */
+  counter_type link_write_bytes;
+  int n_clients;
+
+# define MSTATS_UNDEF   0
+# define MSTATS_ACTIVE  1
+# define MSTATS_EXPIRED 2
+  int state;
+};
+
+extern volatile struct mmap_stats *mmap_stats; /* GLOBAL */
+
+void mstats_open(const char *fn);
+void mstats_close(void);
+
+#endif
diff --git a/multi.c b/multi.c
index 81931fa94923c8e3018fa5a25fc3bea92c032c5e..9535f43adea2d322a20899c81b4a8d0a680498f4 100644 (file)
--- a/multi.c
+++ b/multi.c
@@ -31,6 +31,7 @@
 #include "misc.h"
 #include "otime.h"
 #include "gremlin.h"
+#include "mstats.h"
 
 #include "memdbg.h"
 
@@ -60,6 +61,15 @@ set_cc_config (struct multi_instance *mi, struct buffer_list *cc_config)
 }
 #endif
 
+static inline void
+update_mstat_n_clients(const int n_clients)
+{
+#ifdef ENABLE_MEMSTATS
+  if (mmap_stats)
+    mmap_stats->n_clients = n_clients;
+#endif
+}
+
 static bool
 learn_address_script (const struct multi_context *m,
                      const struct multi_instance *mi,
@@ -510,6 +520,7 @@ multi_close_instance (struct multi_context *m,
 
   /* adjust current client connection count */
   m->n_clients += mi->n_clients_delta;
+  update_mstat_n_clients(m->n_clients);
   mi->n_clients_delta = 0;
 
   /* prevent dangling pointers */
@@ -1842,6 +1853,7 @@ multi_connection_established (struct multi_context *m, struct multi_instance *mi
 
       /* increment number of current authenticated clients */
       ++m->n_clients;
+      update_mstat_n_clients(m->n_clients);
       --mi->n_clients_delta;
 
 #ifdef MANAGEMENT_DEF_AUTH
index 3a819c972b967b54b486deffcc8cadf95fb62b99..27193ff672694e109421a0c80755e3c7354a5211 100644 (file)
--- a/options.c
+++ b/options.c
@@ -299,6 +299,9 @@ static const char usage_message[] =
   "                  can be matched in policy routing and packetfilter rules.\n"
 #endif
   "--txqueuelen n  : Set the tun/tap TX queue length to n (Linux only).\n"
+#ifdef ENABLE_MEMSTATS
+  "--memstats file : Write live usage stats to memory mapped binary file.\n"
+#endif
   "--mlock         : Disable Paging -- ensures key material and tunnel\n"
   "                  data will never be written to disk.\n"
   "--up cmd        : Shell cmd to execute after successful tun device open.\n"
@@ -4602,6 +4605,13 @@ add_option (struct options *options,
       options->log = true;
       redirect_stdout_stderr (p[1], true);
     }
+#ifdef ENABLE_MEMSTATS
+  else if (streq (p[0], "memstats") && p[1])
+    {
+      VERIFY_PERMISSION (OPT_P_GENERAL);
+      options->memstats_fn = p[1];
+    }
+#endif
   else if (streq (p[0], "mlock"))
     {
       VERIFY_PERMISSION (OPT_P_GENERAL);
index 0f80e7072182638f96029c817326f51e78813ce0..06c4dcbd41699112405dae222797d954b782088a 100644 (file)
--- a/options.h
+++ b/options.h
@@ -260,6 +260,10 @@ struct options
 
   int fragment;                 /* internal fragmentation size */
 
+#ifdef ENABLE_MEMSTATS
+  char *memstats_fn;
+#endif
+
   bool mlock;
 
   int keepalive_ping;           /* a proxy for ping/ping-restart */
index f3c0ac9bb0d92cc7c8aa2fb3b312988f513a28b9..38de87b4f870d9048852d30fe066fbfff682dc5e 100644 (file)
--- a/syshead.h
+++ b/syshead.h
@@ -737,4 +737,11 @@ socket_defined (const socket_descriptor_t sd)
 #define LZO_VERSION_NUM "STUB"
 #endif
 
+/*
+ * Enable --memstats option
+ */
+#ifdef TARGET_LINUX
+#define ENABLE_MEMSTATS
+#endif
+
 #endif