aboutsummaryrefslogtreecommitdiff
path: root/shaper.h
diff options
context:
space:
mode:
Diffstat (limited to 'shaper.h')
-rw-r--r--shaper.h178
1 files changed, 178 insertions, 0 deletions
diff --git a/shaper.h b/shaper.h
new file mode 100644
index 0000000..3aba241
--- /dev/null
+++ b/shaper.h
@@ -0,0 +1,178 @@
+/*
+ * OpenVPN -- An application to securely tunnel IP networks
+ * over a single UDP port, with support for SSL/TLS-based
+ * session authentication and key exchange,
+ * packet encryption, packet authentication, and
+ * packet compression.
+ *
+ * Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@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
+ */
+
+#ifndef SHAPER_H
+#define SHAPER_H
+
+/*#define SHAPER_DEBUG*/
+
+#ifdef HAVE_GETTIMEOFDAY
+
+#include "basic.h"
+#include "integer.h"
+#include "misc.h"
+#include "error.h"
+#include "interval.h"
+
+/*
+ * A simple traffic shaper for
+ * the output direction.
+ */
+
+#define SHAPER_MIN 100 /* bytes per second */
+#define SHAPER_MAX 100000000
+
+#define SHAPER_MAX_TIMEOUT 10 /* seconds */
+
+#define SHAPER_USE_FP
+
+struct shaper
+{
+ int bytes_per_second;
+ struct timeval wakeup;
+
+#ifdef SHAPER_USE_FP
+ double factor;
+#else
+ int factor;
+#endif
+};
+
+void shaper_msg (struct shaper *s);
+void shaper_reset_wakeup (struct shaper *s);
+
+/*
+ * We want to wake up in delay microseconds. If timeval is larger
+ * than delay, set timeval to delay.
+ */
+bool shaper_soonest_event (struct timeval *tv, int delay);
+
+/*
+ * inline functions
+ */
+
+static inline void
+shaper_reset (struct shaper *s, int bytes_per_second)
+{
+ s->bytes_per_second = bytes_per_second ? constrain_int (bytes_per_second, SHAPER_MIN, SHAPER_MAX) : 0;
+
+#ifdef SHAPER_USE_FP
+ s->factor = 1000000.0 / (double)s->bytes_per_second;
+#else
+ s->factor = 1000000 / s->bytes_per_second;
+#endif
+}
+
+static inline void
+shaper_init (struct shaper *s, int bytes_per_second)
+{
+ shaper_reset (s, bytes_per_second);
+ shaper_reset_wakeup (s);
+}
+
+static inline int
+shaper_current_bandwidth (struct shaper *s)
+{
+ return s->bytes_per_second;
+}
+
+/*
+ * Returns traffic shaping delay in microseconds relative to current
+ * time, or 0 if no delay.
+ */
+static inline int
+shaper_delay (struct shaper* s)
+{
+ struct timeval tv;
+ int delay = 0;
+
+ if (tv_defined (&s->wakeup))
+ {
+ ASSERT (!gettimeofday (&tv, NULL));
+ delay = tv_subtract (&s->wakeup, &tv, SHAPER_MAX_TIMEOUT);
+#ifdef SHAPER_DEBUG
+ dmsg (D_SHAPER_DEBUG, "SHAPER shaper_delay delay=%d", delay);
+#endif
+ }
+
+ return delay > 0 ? delay : 0;
+}
+
+
+/*
+ * We are about to send a datagram of nbytes bytes.
+ *
+ * Compute when we can send another datagram,
+ * based on target throughput (s->bytes_per_second).
+ */
+static inline void
+shaper_wrote_bytes (struct shaper* s, int nbytes)
+{
+ struct timeval tv;
+
+ /* compute delay in microseconds */
+ tv.tv_sec = 0;
+#ifdef SHAPER_USE_FP
+ tv.tv_usec = min_int ((int)((double)max_int (nbytes, 100) * s->factor), (SHAPER_MAX_TIMEOUT*1000000));
+#else
+ tv.tv_usec = s->bytes_per_second
+ ? min_int (max_int (nbytes, 100) * s->factor, (SHAPER_MAX_TIMEOUT*1000000))
+ : 0;
+#endif
+
+ if (tv.tv_usec)
+ {
+ ASSERT (!gettimeofday (&s->wakeup, NULL));
+ tv_add (&s->wakeup, &tv);
+
+#ifdef SHAPER_DEBUG
+ dmsg (D_SHAPER_DEBUG, "SHAPER shaper_wrote_bytes bytes=%d delay=%d sec=%d usec=%d",
+ nbytes,
+ (int)tv.tv_usec,
+ (int)s->wakeup.tv_sec,
+ (int)s->wakeup.tv_usec);
+#endif
+ }
+}
+
+#if 0
+/*
+ * Increase/Decrease bandwidth by a percentage.
+ *
+ * Return true if bandwidth changed.
+ */
+static inline bool
+shaper_change_pct (struct shaper *s, int pct)
+{
+ const int orig_bandwidth = s->bytes_per_second;
+ const int new_bandwidth = orig_bandwidth + (orig_bandwidth * pct / 100);
+ ASSERT (s->bytes_per_second);
+ shaper_reset (s, new_bandwidth);
+ return s->bytes_per_second != orig_bandwidth;
+}
+#endif
+
+#endif /* HAVE_GETTIMEOFDAY */
+
+#endif