diff options
Diffstat (limited to 'shaper.h')
-rw-r--r-- | shaper.h | 178 |
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 |