]> git.ipfire.org Git - thirdparty/openvpn.git/blob - src/openvpn/shaper.h
Update Copyright statements to 2024
[thirdparty/openvpn.git] / src / openvpn / shaper.h
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 {
49 int bytes_per_second;
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);
89 shaper_reset_wakeup(s);
90 }
91
92 static inline int
93 shaper_current_bandwidth(struct shaper *s)
94 {
95 return s->bytes_per_second;
96 }
97
98 /*
99 * Returns traffic shaping delay in microseconds relative to current
100 * time, or 0 if no delay.
101 */
102 static inline int
103 shaper_delay(struct shaper *s)
104 {
105 struct timeval tv;
106 int delay = 0;
107
108 if (tv_defined(&s->wakeup))
109 {
110 ASSERT(!openvpn_gettimeofday(&tv, NULL));
111 delay = tv_subtract(&s->wakeup, &tv, SHAPER_MAX_TIMEOUT);
112 #ifdef SHAPER_DEBUG
113 dmsg(D_SHAPER_DEBUG, "SHAPER shaper_delay delay=%d", delay);
114 #endif
115 }
116
117 return delay > 0 ? delay : 0;
118 }
119
120
121 /*
122 * We are about to send a datagram of nbytes bytes.
123 *
124 * Compute when we can send another datagram,
125 * based on target throughput (s->bytes_per_second).
126 */
127 static inline void
128 shaper_wrote_bytes(struct shaper *s, int nbytes)
129 {
130 struct timeval tv;
131
132 /* compute delay in microseconds */
133 tv.tv_sec = 0;
134 #ifdef SHAPER_USE_FP
135 tv.tv_usec = min_int((int)((double)max_int(nbytes, 100) * s->factor), (SHAPER_MAX_TIMEOUT*1000000));
136 #else
137 tv.tv_usec = s->bytes_per_second
138 ? min_int(max_int(nbytes, 100) * s->factor, (SHAPER_MAX_TIMEOUT*1000000))
139 : 0;
140 #endif
141
142 if (tv.tv_usec)
143 {
144 ASSERT(!openvpn_gettimeofday(&s->wakeup, NULL));
145 tv_add(&s->wakeup, &tv);
146
147 #ifdef SHAPER_DEBUG
148 dmsg(D_SHAPER_DEBUG, "SHAPER shaper_wrote_bytes bytes=%d delay=%ld sec=%" PRIi64 " usec=%ld",
149 nbytes,
150 (long)tv.tv_usec,
151 (int64_t)s->wakeup.tv_sec,
152 (long)s->wakeup.tv_usec);
153 #endif
154 }
155 }
156
157 #if 0
158 /*
159 * Increase/Decrease bandwidth by a percentage.
160 *
161 * Return true if bandwidth changed.
162 */
163 static inline bool
164 shaper_change_pct(struct shaper *s, int pct)
165 {
166 const int orig_bandwidth = s->bytes_per_second;
167 const int new_bandwidth = orig_bandwidth + (orig_bandwidth * pct / 100);
168 ASSERT(s->bytes_per_second);
169 shaper_reset(s, new_bandwidth);
170 return s->bytes_per_second != orig_bandwidth;
171 }
172 #endif
173
174 #endif /* ifndef SHAPER_H */