Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/netinet/cc/cc_hd.c
39476 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2009-2010
5
* Swinburne University of Technology, Melbourne, Australia
6
* Copyright (c) 2010 Lawrence Stewart <[email protected]>
7
* Copyright (c) 2010-2011 The FreeBSD Foundation
8
* All rights reserved.
9
*
10
* This software was developed at the Centre for Advanced Internet
11
* Architectures, Swinburne University of Technology, by David Hayes and
12
* Lawrence Stewart, made possible in part by a grant from the Cisco University
13
* Research Program Fund at Community Foundation Silicon Valley.
14
*
15
* Portions of this software were developed at the Centre for Advanced Internet
16
* Architectures, Swinburne University of Technology, Melbourne, Australia by
17
* David Hayes under sponsorship from the FreeBSD Foundation.
18
*
19
* Redistribution and use in source and binary forms, with or without
20
* modification, are permitted provided that the following conditions
21
* are met:
22
* 1. Redistributions of source code must retain the above copyright
23
* notice, this list of conditions and the following disclaimer.
24
* 2. Redistributions in binary form must reproduce the above copyright
25
* notice, this list of conditions and the following disclaimer in the
26
* documentation and/or other materials provided with the distribution.
27
*
28
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
29
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
32
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38
* SUCH DAMAGE.
39
*/
40
41
/*
42
* An implementation of the Hamilton Institute's delay-based congestion control
43
* algorithm for FreeBSD, based on "A strategy for fair coexistence of loss and
44
* delay-based congestion control algorithms," by L. Budzisz, R. Stanojevic, R.
45
* Shorten, and F. Baker, IEEE Commun. Lett., vol. 13, no. 7, pp. 555--557, Jul.
46
* 2009.
47
*
48
* Originally released as part of the NewTCP research project at Swinburne
49
* University of Technology's Centre for Advanced Internet Architectures,
50
* Melbourne, Australia, which was made possible in part by a grant from the
51
* Cisco University Research Program Fund at Community Foundation Silicon
52
* Valley. More details are available at:
53
* http://caia.swin.edu.au/urp/newtcp/
54
*/
55
56
#include <sys/param.h>
57
#include <sys/kernel.h>
58
#include <sys/khelp.h>
59
#include <sys/limits.h>
60
#include <sys/malloc.h>
61
#include <sys/module.h>
62
#include <sys/prng.h>
63
#include <sys/queue.h>
64
#include <sys/socket.h>
65
#include <sys/socketvar.h>
66
#include <sys/sysctl.h>
67
#include <sys/systm.h>
68
69
#include <net/vnet.h>
70
71
#include <netinet/in.h>
72
#include <netinet/in_pcb.h>
73
#include <netinet/tcp_seq.h>
74
#include <netinet/tcp_timer.h>
75
#include <netinet/tcp_var.h>
76
#include <netinet/cc/cc.h>
77
#include <netinet/cc/cc_module.h>
78
79
#include <netinet/khelp/h_ertt.h>
80
81
/* Largest possible number returned by prng32(). */
82
#define RANDOM_MAX UINT32_MAX
83
84
static void hd_ack_received(struct cc_var *ccv, ccsignal_t ack_type);
85
static int hd_mod_init(void);
86
static size_t hd_data_sz(void);
87
88
static int ertt_id;
89
90
VNET_DEFINE_STATIC(uint32_t, hd_qthresh) = 20;
91
VNET_DEFINE_STATIC(uint32_t, hd_qmin) = 5;
92
VNET_DEFINE_STATIC(uint32_t, hd_pmax) = 5;
93
#define V_hd_qthresh VNET(hd_qthresh)
94
#define V_hd_qmin VNET(hd_qmin)
95
#define V_hd_pmax VNET(hd_pmax)
96
97
struct cc_algo hd_cc_algo = {
98
.name = "hd",
99
.ack_received = hd_ack_received,
100
.mod_init = hd_mod_init,
101
.cc_data_sz = hd_data_sz,
102
.after_idle = newreno_cc_after_idle,
103
.cong_signal = newreno_cc_cong_signal,
104
.post_recovery = newreno_cc_post_recovery,
105
};
106
107
static size_t
108
hd_data_sz(void)
109
{
110
return (0);
111
}
112
113
/*
114
* Hamilton backoff function. Returns 1 if we should backoff or 0 otherwise.
115
*/
116
static __inline int
117
should_backoff(int qdly, int maxqdly)
118
{
119
unsigned long p;
120
121
if (qdly < V_hd_qthresh) {
122
p = (((RANDOM_MAX / 100) * V_hd_pmax) /
123
(V_hd_qthresh - V_hd_qmin)) * (qdly - V_hd_qmin);
124
} else {
125
if (qdly > V_hd_qthresh)
126
p = (((RANDOM_MAX / 100) * V_hd_pmax) /
127
(maxqdly - V_hd_qthresh)) * (maxqdly - qdly);
128
else
129
p = (RANDOM_MAX / 100) * V_hd_pmax;
130
}
131
132
return (prng32() < p);
133
}
134
135
/*
136
* If the ack type is CC_ACK, and the inferred queueing delay is greater than
137
* the Qmin threshold, cwnd is reduced probabilistically. When backing off due
138
* to delay, HD behaves like NewReno when an ECN signal is received. HD behaves
139
* as NewReno in all other circumstances.
140
*/
141
static void
142
hd_ack_received(struct cc_var *ccv, ccsignal_t ack_type)
143
{
144
struct ertt *e_t;
145
int qdly;
146
147
if (ack_type == CC_ACK) {
148
e_t = khelp_get_osd(&CCV(ccv, t_osd), ertt_id);
149
150
if (e_t->rtt && e_t->minrtt && V_hd_qthresh > 0) {
151
qdly = e_t->rtt - e_t->minrtt;
152
153
if (qdly > V_hd_qmin &&
154
!IN_RECOVERY(CCV(ccv, t_flags))) {
155
/* Probabilistic backoff of cwnd. */
156
if (should_backoff(qdly,
157
e_t->maxrtt - e_t->minrtt)) {
158
/*
159
* Update cwnd and ssthresh update to
160
* half cwnd and behave like an ECN (ie
161
* not a packet loss).
162
*/
163
newreno_cc_cong_signal(ccv,
164
CC_ECN);
165
return;
166
}
167
}
168
}
169
}
170
newreno_cc_ack_received(ccv, ack_type);
171
}
172
173
static int
174
hd_mod_init(void)
175
{
176
177
ertt_id = khelp_get_id("ertt");
178
if (ertt_id <= 0) {
179
printf("%s: h_ertt module not found\n", __func__);
180
return (ENOENT);
181
}
182
return (0);
183
}
184
185
static int
186
hd_pmax_handler(SYSCTL_HANDLER_ARGS)
187
{
188
int error;
189
uint32_t new;
190
191
new = V_hd_pmax;
192
error = sysctl_handle_int(oidp, &new, 0, req);
193
if (error == 0 && req->newptr != NULL) {
194
if (new == 0 || new > 100)
195
error = EINVAL;
196
else
197
V_hd_pmax = new;
198
}
199
200
return (error);
201
}
202
203
static int
204
hd_qmin_handler(SYSCTL_HANDLER_ARGS)
205
{
206
int error;
207
uint32_t new;
208
209
new = V_hd_qmin;
210
error = sysctl_handle_int(oidp, &new, 0, req);
211
if (error == 0 && req->newptr != NULL) {
212
if (new > V_hd_qthresh)
213
error = EINVAL;
214
else
215
V_hd_qmin = new;
216
}
217
218
return (error);
219
}
220
221
static int
222
hd_qthresh_handler(SYSCTL_HANDLER_ARGS)
223
{
224
int error;
225
uint32_t new;
226
227
new = V_hd_qthresh;
228
error = sysctl_handle_int(oidp, &new, 0, req);
229
if (error == 0 && req->newptr != NULL) {
230
if (new == 0 || new < V_hd_qmin)
231
error = EINVAL;
232
else
233
V_hd_qthresh = new;
234
}
235
236
return (error);
237
}
238
239
SYSCTL_DECL(_net_inet_tcp_cc_hd);
240
SYSCTL_NODE(_net_inet_tcp_cc, OID_AUTO, hd, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
241
"Hamilton delay-based congestion control related settings");
242
243
SYSCTL_PROC(_net_inet_tcp_cc_hd, OID_AUTO, queue_threshold,
244
CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
245
&VNET_NAME(hd_qthresh), 20, &hd_qthresh_handler, "IU",
246
"queueing congestion threshold (qth) in ticks");
247
248
SYSCTL_PROC(_net_inet_tcp_cc_hd, OID_AUTO, pmax,
249
CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
250
&VNET_NAME(hd_pmax), 5, &hd_pmax_handler, "IU",
251
"per packet maximum backoff probability as a percentage");
252
253
SYSCTL_PROC(_net_inet_tcp_cc_hd, OID_AUTO, queue_min,
254
CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
255
&VNET_NAME(hd_qmin), 5, &hd_qmin_handler, "IU",
256
"minimum queueing delay threshold (qmin) in ticks");
257
258
DECLARE_CC_MODULE(hd, &hd_cc_algo);
259
MODULE_VERSION(hd, 2);
260
MODULE_DEPEND(hd, ertt, 1, 1, 1);
261
262