2
* OpenVPN -- An application to securely tunnel IP networks
3
* over a single UDP port, with support for SSL/TLS-based
4
* session authentication and key exchange,
5
* packet encryption, packet authentication, and
8
* Copyright (C) 2002-2004 James Yonan <jim@yonan.net>
10
* This program is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; either version 2 of the License, or
13
* (at your option) any later version.
15
* This program is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
20
* You should have received a copy of the GNU General Public License
21
* along with this program (see the file COPYING included with this
22
* distribution); if not, write to the Free Software Foundation, Inc.,
23
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29
#define SHAPER_DEBUG 0
31
#ifdef HAVE_GETTIMEOFDAY
39
* A simple traffic shaper for
40
* the output direction.
43
#define SHAPER_MIN 100 /* bytes per second */
44
#define SHAPER_MAX 100000000
46
#define SHAPER_MAX_TIMEOUT 10 /* seconds */
51
struct timeval wakeup;
54
void shaper_msg (struct shaper *s);
61
shaper_reset (struct shaper *s, int bytes_per_second)
63
s->bytes_per_second = bytes_per_second ? constrain_int (bytes_per_second, SHAPER_MIN, SHAPER_MAX) : 0;
67
shaper_reset_wakeup (struct shaper *s)
73
shaper_init (struct shaper *s, int bytes_per_second)
75
shaper_reset (s, bytes_per_second);
76
shaper_reset_wakeup (s);
80
shaper_current_bandwidth (struct shaper *s)
82
return s->bytes_per_second;
86
* Returns traffic shaping delay in microseconds relative to current
87
* time, or 0 if no delay.
90
shaper_delay (struct shaper* s)
95
if (tv_defined (&s->wakeup))
97
ASSERT (!gettimeofday (&tv, NULL));
98
delay = tv_subtract (&s->wakeup, &tv, SHAPER_MAX_TIMEOUT);
100
msg (D_SHAPER_DEBUG, "SHAPER shaper_delay delay=%d", delay);
104
return delay > 0 ? delay : 0;
108
* We want to wake up in delay microseconds. If timeval is 0 (undefined) or larger
109
* than delay, set timeval to delay.
112
shaper_soonest_event (struct timeval *tv, int delay)
114
if (!tv->tv_usec && delay < 1000000)
121
const int sec = delay / 1000000;
122
const int usec = delay % 1000000;
124
if ((!tv->tv_sec && !tv->tv_usec) || (sec < tv->tv_sec))
129
else if (sec == tv->tv_sec)
131
if (usec < tv->tv_usec)
138
msg (D_SHAPER_DEBUG, "SHAPER shaper_soonest_event sec=%d usec=%d",
139
(int)tv->tv_sec, (int)tv->tv_usec);
144
* We are about to send a datagram of nbytes bytes.
146
* Compute when we can send another datagram,
147
* based on target throughput (s->bytes_per_second).
150
shaper_wrote_bytes (struct shaper* s, int nbytes)
152
/* delay in microseconds */
153
const int delay = s->bytes_per_second
154
? min_int (((1000000 / s->bytes_per_second) * max_int (nbytes, 200)), (SHAPER_MAX_TIMEOUT*1000000))
159
ASSERT (!gettimeofday (&s->wakeup, NULL));
160
s->wakeup.tv_usec += delay;
161
while (s->wakeup.tv_usec >= 1000000)
164
s->wakeup.tv_usec -= 1000000;
167
msg (D_SHAPER_DEBUG, "SHAPER shaper_wrote_bytes bytes=%d delay=%d sec=%d usec=%d",
168
nbytes, delay, (int)s->wakeup.tv_sec, (int)s->wakeup.tv_usec);
174
* Increase/Decrease bandwidth by a percentage.
176
* Return true if bandwidth changed.
179
shaper_change_pct (struct shaper *s, int pct)
181
const int orig_bandwidth = s->bytes_per_second;
182
const int new_bandwidth = orig_bandwidth + (orig_bandwidth * pct / 100);
183
ASSERT (s->bytes_per_second);
184
shaper_reset (s, new_bandwidth);
185
return s->bytes_per_second != orig_bandwidth;
188
#endif /* HAVE_GETTIMEOFDAY */