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-2009 OpenVPN Technologies, Inc. <sales@openvpn.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 version 2
12 * as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 /*#define SHAPER_DEBUG*/
30 #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 */
53 struct timeval wakeup
;
62 void shaper_msg (struct shaper
*s
);
63 void shaper_reset_wakeup (struct shaper
*s
);
66 * We want to wake up in delay microseconds. If timeval is larger
67 * than delay, set timeval to delay.
69 bool shaper_soonest_event (struct timeval
*tv
, int delay
);
76 shaper_reset (struct shaper
*s
, int bytes_per_second
)
78 s
->bytes_per_second
= bytes_per_second
? constrain_int (bytes_per_second
, SHAPER_MIN
, SHAPER_MAX
) : 0;
81 s
->factor
= 1000000.0 / (double)s
->bytes_per_second
;
83 s
->factor
= 1000000 / s
->bytes_per_second
;
88 shaper_init (struct shaper
*s
, int bytes_per_second
)
90 shaper_reset (s
, bytes_per_second
);
91 shaper_reset_wakeup (s
);
95 shaper_current_bandwidth (struct shaper
*s
)
97 return s
->bytes_per_second
;
101 * Returns traffic shaping delay in microseconds relative to current
102 * time, or 0 if no delay.
105 shaper_delay (struct shaper
* s
)
110 if (tv_defined (&s
->wakeup
))
112 ASSERT (!openvpn_gettimeofday (&tv
, NULL
));
113 delay
= tv_subtract (&s
->wakeup
, &tv
, SHAPER_MAX_TIMEOUT
);
115 dmsg (D_SHAPER_DEBUG
, "SHAPER shaper_delay delay=%d", delay
);
119 return delay
> 0 ? delay
: 0;
124 * We are about to send a datagram of nbytes bytes.
126 * Compute when we can send another datagram,
127 * based on target throughput (s->bytes_per_second).
130 shaper_wrote_bytes (struct shaper
* s
, int nbytes
)
134 /* compute delay in microseconds */
137 tv
.tv_usec
= min_int ((int)((double)max_int (nbytes
, 100) * s
->factor
), (SHAPER_MAX_TIMEOUT
*1000000));
139 tv
.tv_usec
= s
->bytes_per_second
140 ? min_int (max_int (nbytes
, 100) * s
->factor
, (SHAPER_MAX_TIMEOUT
*1000000))
146 ASSERT (!openvpn_gettimeofday (&s
->wakeup
, NULL
));
147 tv_add (&s
->wakeup
, &tv
);
150 dmsg (D_SHAPER_DEBUG
, "SHAPER shaper_wrote_bytes bytes=%d delay=%d sec=%d usec=%d",
153 (int)s
->wakeup
.tv_sec
,
154 (int)s
->wakeup
.tv_usec
);
161 * Increase/Decrease bandwidth by a percentage.
163 * Return true if bandwidth changed.
166 shaper_change_pct (struct shaper
*s
, int pct
)
168 const int orig_bandwidth
= s
->bytes_per_second
;
169 const int new_bandwidth
= orig_bandwidth
+ (orig_bandwidth
* pct
/ 100);
170 ASSERT (s
->bytes_per_second
);
171 shaper_reset (s
, new_bandwidth
);
172 return s
->bytes_per_second
!= orig_bandwidth
;
176 #endif /* HAVE_GETTIMEOFDAY */