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
47struct shaper
48{
50 struct timeval wakeup;
51
52#ifdef SHAPER_USE_FP
53 double factor;
54#else
55 int factor;
56#endif
57};
58
59void shaper_msg(struct shaper *s);
60
61void 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 */
67bool shaper_soonest_event(struct timeval *tv, int delay);
68
69/*
70 * inline functions
71 */
72
73static inline void
74shaper_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
85static inline void
86shaper_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 */
96static inline int
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 */
121static inline void
122shaper_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 {
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 */
157static inline bool
158shaper_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 */
#define D_SHAPER_DEBUG
Definition errlevel.h:176
static int min_int(int x, int y)
Definition integer.h:102
static int max_int(int x, int y)
Definition integer.h:89
static int constrain_int(int x, int min, int max)
Definition integer.h:115
#define dmsg(flags,...)
Definition error.h:148
#define ASSERT(x)
Definition error.h:195
static int tv_subtract(const struct timeval *tv1, const struct timeval *tv2, const unsigned int max_seconds)
Definition otime.h:115
static int openvpn_gettimeofday(struct timeval *tv, void *tz)
Definition otime.h:64
static bool tv_defined(const struct timeval *tv)
Definition otime.h:108
static void tv_add(struct timeval *dest, const struct timeval *src)
Definition otime.h:132
void shaper_msg(struct shaper *s)
Definition shaper.c:88
static void shaper_wrote_bytes(struct shaper *s, int nbytes)
Definition shaper.h:122
static void shaper_reset(struct shaper *s, int bytes_per_second)
Definition shaper.h:74
#define SHAPER_MAX_TIMEOUT
Definition shaper.h:43
void shaper_reset_wakeup(struct shaper *s)
Definition shaper.c:82
static void shaper_init(struct shaper *s, int bytes_per_second)
Definition shaper.h:86
#define SHAPER_MAX
Definition shaper.h:41
static int shaper_delay(struct shaper *s)
Definition shaper.h:97
#define SHAPER_MIN
Definition shaper.h:40
bool shaper_soonest_event(struct timeval *tv, int delay)
Definition shaper.c:37
double factor
Definition shaper.h:53
struct timeval wakeup
Definition shaper.h:50
int bytes_per_second
Definition shaper.h:49