55#include <sys/kernel.h>
56#include <sys/libkern.h>
58#include <sys/malloc.h>
59#include <sys/module.h>
62#include <sys/rwlock.h>
64#include <sys/socket.h>
65#include <sys/socketvar.h>
66#include <sys/sysctl.h>
84#define CC_DEFAULT "newreno"
108#define V_newreno_beta VNET(newreno_beta)
155 char default_cc[TCP_CA_NAME_MAX];
164 memset(default_cc, 0, TCP_CA_NAME_MAX);
167 error = sysctl_handle_string(oidp, default_cc,
sizeof(default_cc), req);
170 if (error != 0 || req->newptr == NULL)
176 STAILQ_FOREACH(funcs, &
cc_list, entries) {
177 if (strncmp(default_cc, funcs->
name,
sizeof(default_cc)))
206 STAILQ_FOREACH(algo, &
cc_list, entries) {
213 bufsz = (nalgos+2) * ((TCP_CA_NAME_MAX + 13) + 1);
214 buffer = malloc(bufsz, M_TEMP, M_WAITOK);
217 linesz = snprintf(cp, bufsz,
"\n%-16s%c %s\n",
"CCmod",
'D',
223 STAILQ_FOREACH(algo, &
cc_list, entries) {
224 linesz = snprintf(cp, bufsz,
"%-16s%c %u\n",
228 if (linesz >= bufsz) {
238 error = sysctl_handle_string(oidp, buffer, outsz + 1, req);
239 free(buffer, M_TEMP);
251 VNET_ITERATOR_DECL(vnet_iter);
255 VNET_LIST_RLOCK_NOSLEEP();
256 VNET_FOREACH(vnet_iter) {
257 CURVNET_SET(vnet_iter);
261 TCP_CA_NAME_MAX) == 0) {
266 VNET_LIST_RUNLOCK_NOSLEEP();
293 STAILQ_FOREACH(funcs, &
cc_list, entries) {
294 if (funcs == remove_cc)
304 (
"remove_cc:%p does not have CC_MODULE_BEING_REMOVED flag", remove_cc));
334 STAILQ_FOREACH(funcs, &
cc_list, entries) {
335 if (funcs == add_cc ||
337 TCP_CA_NAME_MAX) == 0) {
351 STAILQ_INSERT_TAIL(&
cc_list, add_cc, entries);
368 if (IS_DEFAULT_VNET(curvnet))
402 if (pipe <
CCV(ccv, snd_ssthresh))
407 CCV(ccv, snd_cwnd) = max(pipe,
CCV(ccv, t_maxseg)) +
410 CCV(ccv, snd_cwnd) =
CCV(ccv, snd_ssthresh);
437 CCV(ccv, snd_ssthresh) = max(
CCV(ccv, snd_ssthresh),
438 CCV(ccv, snd_cwnd)-(
CCV(ccv, snd_cwnd)>>2));
440 CCV(ccv, snd_cwnd) = min(rw,
CCV(ccv, snd_cwnd));
452 cwin =
CCV(ccv, snd_cwnd);
463 (
"%s: congestion signal type 0x%08x is private\n", __func__, type));
465 cwin = max(((uint64_t)cwin * (uint64_t)factor) / (100ULL * (uint64_t)mss),
472 CCV(ccv, snd_ssthresh) = cwin;
478 CCV(ccv, snd_ssthresh) = cwin;
479 CCV(ccv, snd_cwnd) = cwin;
484 CCV(ccv, snd_ssthresh) = max(min(
CCV(ccv, snd_wnd),
485 CCV(ccv, snd_cwnd)) / 2 / mss,
487 CCV(ccv, snd_cwnd) = mss;
497 u_int cw =
CCV(ccv, snd_cwnd);
498 u_int incr =
CCV(ccv, t_maxseg);
527 if (cw >
CCV(ccv, snd_ssthresh)) {
530 ccv->
flags &= ~CCF_ABC_SENTAWND;
534 incr = max((incr * incr / cw), 1);
552 if (
CCV(ccv, snd_nxt) ==
CCV(ccv, snd_max))
554 ccv->
nsegs * abc_val *
562 CCV(ccv, snd_cwnd) = min(cw + incr,
563 TCP_MAXWIN <<
CCV(ccv, snd_scale));
600 printf(
"Module Load Fails, it lacks a cc_data_sz() function but has a cb_init()!\n");
647SYSCTL_NODE(_net_inet_tcp, OID_AUTO, cc, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
648 "Congestion control related settings");
651 CTLFLAG_VNET | CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE,
653 "Default congestion control algorithm");
656 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
658 "List available congestion control algorithms");
661 CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
662 "New Reno related HyStart++ settings");
664SYSCTL_UINT(_net_inet_tcp_cc_hystartplusplus, OID_AUTO, minrtt_thresh,
667 "HyStarts++ minimum RTT thresh used in clamp (in microseconds)");
669SYSCTL_UINT(_net_inet_tcp_cc_hystartplusplus, OID_AUTO, maxrtt_thresh,
672 "HyStarts++ maximum RTT thresh used in clamp (in microseconds)");
674SYSCTL_UINT(_net_inet_tcp_cc_hystartplusplus, OID_AUTO, n_rttsamples,
677 "The number of RTT samples that must be seen to consider HyStart++");
679SYSCTL_UINT(_net_inet_tcp_cc_hystartplusplus, OID_AUTO, css_growth_div,
682 "The divisor to the growth when in Hystart++ CSS");
684SYSCTL_UINT(_net_inet_tcp_cc_hystartplusplus, OID_AUTO, css_rounds,
687 "The number of rounds HyStart++ lasts in CSS before falling to CA");
692 "Do we enable HyStart++ Black Box logs to be generated if BB logging is on");
695SYSCTL_INT(_net_inet_tcp_cc, OID_AUTO, abe, CTLFLAG_VNET | CTLFLAG_RW,
696 &VNET_NAME(cc_do_abe), 0,
697 "Enable draft-ietf-tcpm-alternativebackoff-ecn (TCP Alternative Backoff with ECN)");
700SYSCTL_INT(_net_inet_tcp_cc, OID_AUTO, abe_frlossreduce, CTLFLAG_VNET | CTLFLAG_RW,
701 &VNET_NAME(cc_abe_frlossreduce), 0,
702 "Apply standard beta instead of ABE-beta during ECN-signalled congestion "
703 "recovery episodes if loss also needs to be repaired");
static int cc_check_default(struct cc_algo *remove_cc)
static void vnet_cc_sysinit(void *arg)
uint32_t hystart_css_growth_div
int cc_modevent(module_t mod, int event_type, void *data)
uint32_t hystart_maxrtt_thresh
int cc_deregister_algo(struct cc_algo *remove_cc)
VNET_SYSINIT(vnet_cc_sysinit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, vnet_cc_sysinit, NULL)
void cc_refer(struct cc_algo *algo)
uint32_t hystart_css_rounds
void newreno_cc_post_recovery(struct cc_var *ccv)
void cc_attach(struct tcpcb *tp, struct cc_algo *algo)
SYSCTL_UINT(_net_inet_tcp_cc_hystartplusplus, OID_AUTO, minrtt_thresh, CTLFLAG_RW, &hystart_minrtt_thresh, 4000, "HyStarts++ minimum RTT thresh used in clamp (in microseconds)")
VNET_DEFINE(struct cc_algo *, default_cc_ptr)
int cc_register_algo(struct cc_algo *add_cc)
uint32_t hystart_minrtt_thresh
void newreno_cc_ack_received(struct cc_var *ccv, uint16_t type)
static int cc_stop_new_assignments(struct cc_algo *algo)
void newreno_cc_cong_signal(struct cc_var *ccv, uint32_t type)
SYSCTL_NODE(_net_inet_tcp, OID_AUTO, cc, CTLFLAG_RW|CTLFLAG_MPSAFE, NULL, "Congestion control related settings")
SYSCTL_INT(_net_inet_tcp_cc, OID_AUTO, abe, CTLFLAG_VNET|CTLFLAG_RW, &VNET_NAME(cc_do_abe), 0, "Enable draft-ietf-tcpm-alternativebackoff-ecn (TCP Alternative Backoff with ECN)")
SYSINIT(cc, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_FIRST, cc_init, NULL)
struct rwlock cc_list_lock
void cc_release(struct cc_algo *algo)
uint32_t hystart_n_rttsamples
SYSCTL_PROC(_net_inet_tcp_cc, OID_AUTO, algorithm, CTLFLAG_VNET|CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_MPSAFE, NULL, 0, cc_default_algo, "A", "Default congestion control algorithm")
void newreno_cc_after_idle(struct cc_var *ccv)
static int cc_list_available(SYSCTL_HANDLER_ARGS)
static int cc_default_algo(SYSCTL_HANDLER_ARGS)
MALLOC_DEFINE(M_CC_MEM, "CC Mem", "Congestion Control State memory")
void cc_detach(struct tcpcb *tp)
static void cc_init(void)
#define CC_DEFAULT_ALGO()
#define CC_LIST_LOCK_INIT()
#define CC_LIST_RUNLOCK()
#define CCF_USE_LOCAL_ABC
#define CC_MODULE_BEING_REMOVED
#define CC_LIST_WUNLOCK()
#define CC_LIST_LOCK_ASSERT()
size_t(* cc_data_sz)(void)
char name[TCP_CA_NAME_MAX]
int(* cb_init)(struct cc_var *ccv, void *ptr)
union cc_var::ccv_container ccvc
u_int tcp_maxseg(const struct tcpcb *tp)
u_int tcp_fixed_maxseg(const struct tcpcb *tp)
#define IN_CONGRECOVERY(t_flags)
#define IN_FASTRECOVERY(t_flags)
#define IN_RECOVERY(t_flags)
#define ENTER_RECOVERY(t_flags)
#define ENTER_CONGRECOVERY(t_flags)