| /* |
| * 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-2018 OpenVPN 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; if not, write to the Free Software Foundation, Inc., |
| * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| */ |
| |
| #ifndef SHAPER_H |
| #define SHAPER_H |
| |
| /*#define SHAPER_DEBUG*/ |
| |
| #ifdef ENABLE_FEATURE_SHAPER |
| |
| #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 = constrain_int(bytes_per_second, SHAPER_MIN, SHAPER_MAX); |
| |
| #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(!openvpn_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(!openvpn_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 /* ENABLE_FEATURE_SHAPER */ |
| |
| #endif /* ifndef SHAPER_H */ |