OpenVPN
shaper.h
Go to the documentation of this file.
1 /*
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
6  * packet compression.
7  *
8  * Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net>
9  *
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.
13  *
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.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 #ifndef SHAPER_H
25 #define SHAPER_H
26 
27 /*#define SHAPER_DEBUG*/
28 
29 #ifdef ENABLE_FEATURE_SHAPER
30 
31 #include "basic.h"
32 #include "integer.h"
33 #include "misc.h"
34 #include "error.h"
35 #include "interval.h"
36 
37 /*
38  * A simple traffic shaper for
39  * the output direction.
40  */
41 
42 #define SHAPER_MIN 100 /* bytes per second */
43 #define SHAPER_MAX 100000000
44 
45 #define SHAPER_MAX_TIMEOUT 10 /* seconds */
46 
47 #define SHAPER_USE_FP
48 
49 struct shaper
50 {
51  int bytes_per_second;
52  struct timeval wakeup;
53 
54 #ifdef SHAPER_USE_FP
55  double factor;
56 #else
57  int factor;
58 #endif
59 };
60 
61 void shaper_msg(struct shaper *s);
62 
63 void shaper_reset_wakeup(struct shaper *s);
64 
65 /*
66  * We want to wake up in delay microseconds. If timeval is larger
67  * than delay, set timeval to delay.
68  */
69 bool shaper_soonest_event(struct timeval *tv, int delay);
70 
71 /*
72  * inline functions
73  */
74 
75 static inline void
76 shaper_reset(struct shaper *s, int bytes_per_second)
77 {
78  s->bytes_per_second = constrain_int(bytes_per_second, SHAPER_MIN, SHAPER_MAX);
79 
80 #ifdef SHAPER_USE_FP
81  s->factor = 1000000.0 / (double)s->bytes_per_second;
82 #else
83  s->factor = 1000000 / s->bytes_per_second;
84 #endif
85 }
86 
87 static inline void
88 shaper_init(struct shaper *s, int bytes_per_second)
89 {
90  shaper_reset(s, bytes_per_second);
92 }
93 
94 static inline int
95 shaper_current_bandwidth(struct shaper *s)
96 {
97  return s->bytes_per_second;
98 }
99 
100 /*
101  * Returns traffic shaping delay in microseconds relative to current
102  * time, or 0 if no delay.
103  */
104 static inline int
105 shaper_delay(struct shaper *s)
106 {
107  struct timeval tv;
108  int delay = 0;
109 
110  if (tv_defined(&s->wakeup))
111  {
112  ASSERT(!openvpn_gettimeofday(&tv, NULL));
113  delay = tv_subtract(&s->wakeup, &tv, SHAPER_MAX_TIMEOUT);
114 #ifdef SHAPER_DEBUG
115  dmsg(D_SHAPER_DEBUG, "SHAPER shaper_delay delay=%d", delay);
116 #endif
117  }
118 
119  return delay > 0 ? delay : 0;
120 }
121 
122 
123 /*
124  * We are about to send a datagram of nbytes bytes.
125  *
126  * Compute when we can send another datagram,
127  * based on target throughput (s->bytes_per_second).
128  */
129 static inline void
130 shaper_wrote_bytes(struct shaper *s, int nbytes)
131 {
132  struct timeval tv;
133 
134  /* compute delay in microseconds */
135  tv.tv_sec = 0;
136 #ifdef SHAPER_USE_FP
137  tv.tv_usec = min_int((int)((double)max_int(nbytes, 100) * s->factor), (SHAPER_MAX_TIMEOUT*1000000));
138 #else
139  tv.tv_usec = s->bytes_per_second
140  ? min_int(max_int(nbytes, 100) * s->factor, (SHAPER_MAX_TIMEOUT*1000000))
141  : 0;
142 #endif
143 
144  if (tv.tv_usec)
145  {
146  ASSERT(!openvpn_gettimeofday(&s->wakeup, NULL));
147  tv_add(&s->wakeup, &tv);
148 
149 #ifdef SHAPER_DEBUG
150  dmsg(D_SHAPER_DEBUG, "SHAPER shaper_wrote_bytes bytes=%d delay=%ld sec=%" PRIi64 " usec=%ld",
151  nbytes,
152  (long)tv.tv_usec,
153  (int64_t)s->wakeup.tv_sec,
154  (long)s->wakeup.tv_usec);
155 #endif
156  }
157 }
158 
159 #if 0
160 /*
161  * Increase/Decrease bandwidth by a percentage.
162  *
163  * Return true if bandwidth changed.
164  */
165 static inline bool
166 shaper_change_pct(struct shaper *s, int pct)
167 {
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;
173 }
174 #endif
175 
176 #endif /* ENABLE_FEATURE_SHAPER */
177 
178 #endif /* ifndef SHAPER_H */
#define dmsg
Definition: error.h:174
static int tv_subtract(const struct timeval *tv1, const struct timeval *tv2, const unsigned int max_seconds)
Definition: otime.h:148
#define ASSERT(x)
Definition: error.h:221
#define D_SHAPER_DEBUG
Definition: errlevel.h:170
static bool tv_defined(const struct timeval *tv)
Definition: otime.h:141
static void tv_add(struct timeval *dest, const struct timeval *src)
Definition: otime.h:165
void shaper_reset_wakeup(struct shaper *s)
Definition: shaper.c:86
static int openvpn_gettimeofday(struct timeval *tv, void *tz)
Definition: otime.h:115
bool shaper_soonest_event(struct timeval *tv, int delay)
Definition: shaper.c:41
static int max_int(int x, int y)
Definition: integer.h:44
__int64 int64_t
Definition: config-msvc.h:124
static int constrain_int(int x, int min, int max)
Definition: integer.h:70
static int min_int(int x, int y)
Definition: integer.h:57
void shaper_msg(struct shaper *s)
Definition: shaper.c:92