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-2024 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 #include "basic.h"
30 #include "integer.h"
31 #include "misc.h"
32 #include "error.h"
33 #include "interval.h"
34 
35 /*
36  * A simple traffic shaper for
37  * the output direction.
38  */
39 
40 #define SHAPER_MIN 100 /* bytes per second */
41 #define SHAPER_MAX 100000000
42 
43 #define SHAPER_MAX_TIMEOUT 10 /* seconds */
44 
45 #define SHAPER_USE_FP
46 
47 struct shaper
48 {
50  struct timeval wakeup;
51 
52 #ifdef SHAPER_USE_FP
53  double factor;
54 #else
55  int factor;
56 #endif
57 };
58 
59 void shaper_msg(struct shaper *s);
60 
61 void shaper_reset_wakeup(struct shaper *s);
62 
63 /*
64  * We want to wake up in delay microseconds. If timeval is larger
65  * than delay, set timeval to delay.
66  */
67 bool shaper_soonest_event(struct timeval *tv, int delay);
68 
69 /*
70  * inline functions
71  */
72 
73 static inline void
74 shaper_reset(struct shaper *s, int bytes_per_second)
75 {
76  s->bytes_per_second = constrain_int(bytes_per_second, SHAPER_MIN, SHAPER_MAX);
77 
78 #ifdef SHAPER_USE_FP
79  s->factor = 1000000.0 / (double)s->bytes_per_second;
80 #else
81  s->factor = 1000000 / s->bytes_per_second;
82 #endif
83 }
84 
85 static inline void
86 shaper_init(struct shaper *s, int bytes_per_second)
87 {
88  shaper_reset(s, bytes_per_second);
90 }
91 
92 /*
93  * Returns traffic shaping delay in microseconds relative to current
94  * time, or 0 if no delay.
95  */
96 static inline int
97 shaper_delay(struct shaper *s)
98 {
99  struct timeval tv;
100  int delay = 0;
101 
102  if (tv_defined(&s->wakeup))
103  {
104  ASSERT(!openvpn_gettimeofday(&tv, NULL));
105  delay = tv_subtract(&s->wakeup, &tv, SHAPER_MAX_TIMEOUT);
106 #ifdef SHAPER_DEBUG
107  dmsg(D_SHAPER_DEBUG, "SHAPER shaper_delay delay=%d", delay);
108 #endif
109  }
110 
111  return delay > 0 ? delay : 0;
112 }
113 
114 
115 /*
116  * We are about to send a datagram of nbytes bytes.
117  *
118  * Compute when we can send another datagram,
119  * based on target throughput (s->bytes_per_second).
120  */
121 static inline void
122 shaper_wrote_bytes(struct shaper *s, int nbytes)
123 {
124  struct timeval tv;
125 
126  /* compute delay in microseconds */
127  tv.tv_sec = 0;
128 #ifdef SHAPER_USE_FP
129  tv.tv_usec = min_int((int)((double)max_int(nbytes, 100) * s->factor), (SHAPER_MAX_TIMEOUT*1000000));
130 #else
131  tv.tv_usec = s->bytes_per_second
132  ? min_int(max_int(nbytes, 100) * s->factor, (SHAPER_MAX_TIMEOUT*1000000))
133  : 0;
134 #endif
135 
136  if (tv.tv_usec)
137  {
138  ASSERT(!openvpn_gettimeofday(&s->wakeup, NULL));
139  tv_add(&s->wakeup, &tv);
140 
141 #ifdef SHAPER_DEBUG
142  dmsg(D_SHAPER_DEBUG, "SHAPER shaper_wrote_bytes bytes=%d delay=%ld sec=%" PRIi64 " usec=%ld",
143  nbytes,
144  (long)tv.tv_usec,
145  (int64_t)s->wakeup.tv_sec,
146  (long)s->wakeup.tv_usec);
147 #endif
148  }
149 }
150 
151 #if 0
152 /*
153  * Increase/Decrease bandwidth by a percentage.
154  *
155  * Return true if bandwidth changed.
156  */
157 static inline bool
158 shaper_change_pct(struct shaper *s, int pct)
159 {
160  const int orig_bandwidth = s->bytes_per_second;
161  const int new_bandwidth = orig_bandwidth + (orig_bandwidth * pct / 100);
163  shaper_reset(s, new_bandwidth);
164  return s->bytes_per_second != orig_bandwidth;
165 }
166 #endif
167 
168 #endif /* ifndef SHAPER_H */
error.h
tv_subtract
static int tv_subtract(const struct timeval *tv1, const struct timeval *tv2, const unsigned int max_seconds)
Definition: otime.h:115
dmsg
#define dmsg(flags,...)
Definition: error.h:148
interval.h
ASSERT
#define ASSERT(x)
Definition: error.h:195
D_SHAPER_DEBUG
#define D_SHAPER_DEBUG
Definition: errlevel.h:176
shaper::wakeup
struct timeval wakeup
Definition: shaper.h:50
shaper_wrote_bytes
static void shaper_wrote_bytes(struct shaper *s, int nbytes)
Definition: shaper.h:122
shaper::factor
double factor
Definition: shaper.h:53
misc.h
shaper_soonest_event
bool shaper_soonest_event(struct timeval *tv, int delay)
Definition: shaper.c:37
shaper_reset_wakeup
void shaper_reset_wakeup(struct shaper *s)
Definition: shaper.c:82
shaper::bytes_per_second
int bytes_per_second
Definition: shaper.h:49
SHAPER_MIN
#define SHAPER_MIN
Definition: shaper.h:40
shaper
Definition: shaper.h:47
tv_add
static void tv_add(struct timeval *dest, const struct timeval *src)
Definition: otime.h:132
SHAPER_MAX_TIMEOUT
#define SHAPER_MAX_TIMEOUT
Definition: shaper.h:43
SHAPER_MAX
#define SHAPER_MAX
Definition: shaper.h:41
basic.h
max_int
static int max_int(int x, int y)
Definition: integer.h:89
shaper_msg
void shaper_msg(struct shaper *s)
Definition: shaper.c:88
openvpn_gettimeofday
static int openvpn_gettimeofday(struct timeval *tv, void *tz)
Definition: otime.h:64
min_int
static int min_int(int x, int y)
Definition: integer.h:102
shaper_reset
static void shaper_reset(struct shaper *s, int bytes_per_second)
Definition: shaper.h:74
shaper_delay
static int shaper_delay(struct shaper *s)
Definition: shaper.h:97
constrain_int
static int constrain_int(int x, int min, int max)
Definition: integer.h:115
integer.h
shaper_init
static void shaper_init(struct shaper *s, int bytes_per_second)
Definition: shaper.h:86
tv_defined
static bool tv_defined(const struct timeval *tv)
Definition: otime.h:108