2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2007-2008
5 * Swinburne University of Technology, Melbourne, Australia.
6 * Copyright (c) 2009-2010 Lawrence Stewart <lstewart@freebsd.org>
7 * Copyright (c) 2010 The FreeBSD Foundation
10 * This software was developed at the Centre for Advanced Internet
11 * Architectures, Swinburne University of Technology, by Lawrence Stewart and
12 * James Healy, made possible in part by a grant from the Cisco University
13 * Research Program Fund at Community Foundation Silicon Valley.
15 * Portions of this software were developed at the Centre for Advanced
16 * Internet Architectures, Swinburne University of Technology, Melbourne,
17 * Australia by David Hayes under sponsorship from the FreeBSD Foundation.
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
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.
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
42 * This software was first released in 2007 by James Healy and Lawrence Stewart
43 * whilst working on the NewTCP research project at Swinburne University of
44 * Technology's Centre for Advanced Internet Architectures, Melbourne,
45 * Australia, which was made possible in part by a grant from the Cisco
46 * University Research Program Fund at Community Foundation Silicon Valley.
47 * More details are available at:
48 * http://caia.swin.edu.au/urp/newtcp/
51 #include <sys/cdefs.h>
52 __FBSDID("$FreeBSD$");
54 #include <sys/param.h>
55 #include <sys/kernel.h>
56 #include <sys/libkern.h>
58 #include <sys/malloc.h>
59 #include <sys/module.h>
60 #include <sys/mutex.h>
61 #include <sys/queue.h>
62 #include <sys/rwlock.h>
64 #include <sys/socket.h>
65 #include <sys/socketvar.h>
66 #include <sys/sysctl.h>
70 #include <netinet/in.h>
71 #include <netinet/in_pcb.h>
72 #include <netinet/tcp.h>
73 #include <netinet/tcp_var.h>
74 #include <netinet/cc/cc.h>
76 #include <netinet/cc/cc_module.h>
79 * List of available cc algorithms on the current system. First element
80 * is used as the system default CC algorithm.
82 struct cc_head cc_list = STAILQ_HEAD_INITIALIZER(cc_list);
84 /* Protects the cc_list TAILQ. */
85 struct rwlock cc_list_lock;
87 VNET_DEFINE(struct cc_algo *, default_cc_ptr) = &newreno_cc_algo;
90 * Sysctl handler to show and change the default CC algorithm.
93 cc_default_algo(SYSCTL_HANDLER_ARGS)
95 char default_cc[TCP_CA_NAME_MAX];
96 struct cc_algo *funcs;
99 /* Get the current default: */
101 strlcpy(default_cc, CC_DEFAULT()->name, sizeof(default_cc));
104 error = sysctl_handle_string(oidp, default_cc, sizeof(default_cc), req);
106 /* Check for error or no change */
107 if (error != 0 || req->newptr == NULL)
112 /* Find algo with specified name and set it to default. */
114 STAILQ_FOREACH(funcs, &cc_list, entries) {
115 if (strncmp(default_cc, funcs->name, sizeof(default_cc)))
117 V_default_cc_ptr = funcs;
127 * Sysctl handler to display the list of available CC algorithms.
130 cc_list_available(SYSCTL_HANDLER_ARGS)
132 struct cc_algo *algo;
134 int err, first, nalgos;
140 STAILQ_FOREACH(algo, &cc_list, entries) {
145 s = sbuf_new(NULL, NULL, nalgos * TCP_CA_NAME_MAX, SBUF_FIXEDLEN);
151 * It is theoretically possible for the CC list to have grown in size
152 * since the call to sbuf_new() and therefore for the sbuf to be too
153 * small. If this were to happen (incredibly unlikely), the sbuf will
154 * reach an overflow condition, sbuf_printf() will return an error and
155 * the sysctl will fail gracefully.
158 STAILQ_FOREACH(algo, &cc_list, entries) {
159 err = sbuf_printf(s, first ? "%s" : ", %s", algo->name);
161 /* Sbuf overflow condition. */
171 err = sysctl_handle_string(oidp, sbuf_data(s), 0, req);
179 * Reset the default CC algo to NewReno for any netstack which is using the algo
180 * that is about to go away as its default.
183 cc_checkreset_default(struct cc_algo *remove_cc)
185 VNET_ITERATOR_DECL(vnet_iter);
187 CC_LIST_LOCK_ASSERT();
189 VNET_LIST_RLOCK_NOSLEEP();
190 VNET_FOREACH(vnet_iter) {
191 CURVNET_SET(vnet_iter);
192 if (strncmp(CC_DEFAULT()->name, remove_cc->name,
193 TCP_CA_NAME_MAX) == 0)
194 V_default_cc_ptr = &newreno_cc_algo;
197 VNET_LIST_RUNLOCK_NOSLEEP();
201 * Initialise CC subsystem on system boot.
207 STAILQ_INIT(&cc_list);
211 * Returns non-zero on success, 0 on failure.
214 cc_deregister_algo(struct cc_algo *remove_cc)
216 struct cc_algo *funcs, *tmpfuncs;
221 /* Never allow newreno to be deregistered. */
222 if (&newreno_cc_algo == remove_cc)
225 /* Remove algo from cc_list so that new connections can't use it. */
227 STAILQ_FOREACH_SAFE(funcs, &cc_list, entries, tmpfuncs) {
228 if (funcs == remove_cc) {
229 cc_checkreset_default(remove_cc);
230 STAILQ_REMOVE(&cc_list, funcs, cc_algo, entries);
240 * - We may need to handle non-zero return values in future.
241 * - If we add CC framework support for protocols other than
242 * TCP, we may want a more generic way to handle this step.
244 tcp_ccalgounload(remove_cc);
250 * Returns 0 on success, non-zero on failure.
253 cc_register_algo(struct cc_algo *add_cc)
255 struct cc_algo *funcs;
261 * Iterate over list of registered CC algorithms and make sure
262 * we're not trying to add a duplicate.
265 STAILQ_FOREACH(funcs, &cc_list, entries) {
266 if (funcs == add_cc || strncmp(funcs->name, add_cc->name,
267 TCP_CA_NAME_MAX) == 0)
272 STAILQ_INSERT_TAIL(&cc_list, add_cc, entries);
280 * Handles kld related events. Returns 0 on success, non-zero on failure.
283 cc_modevent(module_t mod, int event_type, void *data)
285 struct cc_algo *algo;
289 algo = (struct cc_algo *)data;
293 if (algo->mod_init != NULL)
294 err = algo->mod_init();
296 err = cc_register_algo(algo);
302 err = cc_deregister_algo(algo);
303 if (!err && algo->mod_destroy != NULL)
317 SYSINIT(cc, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_FIRST, cc_init, NULL);
319 /* Declare sysctl tree and populate it. */
320 SYSCTL_NODE(_net_inet_tcp, OID_AUTO, cc, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
321 "Congestion control related settings");
323 SYSCTL_PROC(_net_inet_tcp_cc, OID_AUTO, algorithm,
324 CTLFLAG_VNET | CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE,
325 NULL, 0, cc_default_algo, "A",
326 "Default congestion control algorithm");
328 SYSCTL_PROC(_net_inet_tcp_cc, OID_AUTO, available,
329 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
330 NULL, 0, cc_list_available, "A",
331 "List available congestion control algorithms");
333 VNET_DEFINE(int, cc_do_abe) = 0;
334 SYSCTL_INT(_net_inet_tcp_cc, OID_AUTO, abe, CTLFLAG_VNET | CTLFLAG_RW,
335 &VNET_NAME(cc_do_abe), 0,
336 "Enable draft-ietf-tcpm-alternativebackoff-ecn (TCP Alternative Backoff with ECN)");
338 VNET_DEFINE(int, cc_abe_frlossreduce) = 0;
339 SYSCTL_INT(_net_inet_tcp_cc, OID_AUTO, abe_frlossreduce, CTLFLAG_VNET | CTLFLAG_RW,
340 &VNET_NAME(cc_abe_frlossreduce), 0,
341 "Apply standard beta instead of ABE-beta during ECN-signalled congestion "
342 "recovery episodes if loss also needs to be repaired");